mirror of
https://github.com/langgenius/dify.git
synced 2026-09-05 08:48:10 +08:00
Workflow KnowledgeFS retrieval nodes ran through `retrieval-tests`, which never wrote an AnswerTrace or an overview event, so their queries were missing from the retrieval history and from the space overview; the history also only ever showed each member their own traces. - AnswerTrace gains a `source` (retrieval_test | workflow | service_api | agent | mcp; migration 0051_answer_trace_source) derived from the Capability v2 caller kind. The retrieval-tests route records one trace per run (stages, evidence bundle, profile metadata), returns its id as `answerTraceId`, and the workflow node's failed-retrieval capture attaches to that trace instead of creating a second record. - The quality trace list exposes and filters by `source`; traces from other caller kinds are visible to any current reader of the space, and counts and scores fall back to the evidence embedded in the trace when no bundle row exists. - Overview accounting: retrieval-tests and Research tasks now emit `query.requested`, and the Research job state machine emits `query.completed` / `query.failed` on terminal stages (wired for both the in-process gateway and the durable runtime), so query volume, answer rate and outcomes include every caller. Activity details keep `source` and `taskKind`. - Console and service trace routes accept a `source` filter; the retrieval test page shows a source badge and an all / retrieval tests / workflow filter, with translations for every locale. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
2756 lines
98 KiB
Python
2756 lines
98 KiB
Python
"""Typed KnowledgeFS BFF facade over operation capabilities and internal transports."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable, Iterable
|
|
from datetime import UTC, datetime, timedelta
|
|
from typing import Literal
|
|
|
|
from pydantic import BaseModel, JsonValue
|
|
|
|
from services.knowledge_fs.buffered_upload_admission import (
|
|
DEFAULT_KNOWLEDGE_FS_BUFFERED_UPLOAD_ADMISSION,
|
|
KnowledgeFSBufferedUploadAdmissionPort,
|
|
)
|
|
from services.knowledge_fs.capability_broker import (
|
|
KnowledgeFSCapabilityBroker,
|
|
KnowledgeFSIssuedProductCapability,
|
|
)
|
|
from services.knowledge_fs.product_dto import (
|
|
KnowledgeFSAdmittedQueryRequest,
|
|
KnowledgeFSAnswerTraceResponse,
|
|
KnowledgeFSBackgroundTaskListResponse,
|
|
KnowledgeFSBackgroundTaskResponse,
|
|
KnowledgeFSBadCaseCreatePayload,
|
|
KnowledgeFSBadCaseListResponse,
|
|
KnowledgeFSBadCaseResponse,
|
|
KnowledgeFSBadCaseTraceReferenceResponse,
|
|
KnowledgeFSBadCaseUpdatePayload,
|
|
KnowledgeFSBulkDeletionAcceptedResponse,
|
|
KnowledgeFSBulkDocumentAvailabilityPayload,
|
|
KnowledgeFSBulkDocumentAvailabilityResponse,
|
|
KnowledgeFSBulkDocumentDeletePayload,
|
|
KnowledgeFSBulkJobResponse,
|
|
KnowledgeFSBulkLogicalDocumentDeletePayload,
|
|
KnowledgeFSCatQuery,
|
|
KnowledgeFSCatResponse,
|
|
KnowledgeFSCrawlImportPayload,
|
|
KnowledgeFSCrawlPreviewPageListResponse,
|
|
KnowledgeFSCrawlPreviewSelectionPayload,
|
|
KnowledgeFSDiffQuery,
|
|
KnowledgeFSDiffResponse,
|
|
KnowledgeFSDocumentAvailabilityPayload,
|
|
KnowledgeFSDocumentChunkListResponse,
|
|
KnowledgeFSDocumentChunkResponse,
|
|
KnowledgeFSDocumentCompilationJobResponse,
|
|
KnowledgeFSDocumentDeletePayload,
|
|
KnowledgeFSDocumentDownloadDescriptor,
|
|
KnowledgeFSDocumentListResponse,
|
|
KnowledgeFSDocumentMetadataPayload,
|
|
KnowledgeFSDocumentMultimodalManifest,
|
|
KnowledgeFSDocumentOutlineResponse,
|
|
KnowledgeFSDocumentReindexPayload,
|
|
KnowledgeFSDocumentReindexResponse,
|
|
KnowledgeFSDocumentResponse,
|
|
KnowledgeFSDocumentRevisionListResponse,
|
|
KnowledgeFSDocumentUploadAcceptedResponse,
|
|
KnowledgeFSDurableDeletionAcceptedResponse,
|
|
KnowledgeFSEmbeddingSettingsResponse,
|
|
KnowledgeFSFindQuery,
|
|
KnowledgeFSGoldenQuestionBulkImportPayload,
|
|
KnowledgeFSGoldenQuestionBulkImportRemotePayload,
|
|
KnowledgeFSGoldenQuestionBulkImportRemoteRowPayload,
|
|
KnowledgeFSGoldenQuestionBulkImportResponse,
|
|
KnowledgeFSGoldenQuestionEvidenceMatchPayload,
|
|
KnowledgeFSGoldenQuestionEvidenceMatchRemotePayload,
|
|
KnowledgeFSGoldenQuestionEvidenceMatchResponse,
|
|
KnowledgeFSGoldenQuestionListResponse,
|
|
KnowledgeFSGoldenQuestionPayload,
|
|
KnowledgeFSGoldenQuestionRemotePayload,
|
|
KnowledgeFSGoldenQuestionResponse,
|
|
KnowledgeFSGoldenQuestionUpdateRemotePayload,
|
|
KnowledgeFSGrepQuery,
|
|
KnowledgeFSGrepResponse,
|
|
KnowledgeFSListQuery,
|
|
KnowledgeFSListResponse,
|
|
KnowledgeFSLogicalDocumentDeletePayload,
|
|
KnowledgeFSLogicalDocumentListResponse,
|
|
KnowledgeFSLogicalDocumentResponse,
|
|
KnowledgeFSMetadataFieldCreatePayload,
|
|
KnowledgeFSMetadataFieldDeleteResponse,
|
|
KnowledgeFSMetadataFieldListResponse,
|
|
KnowledgeFSMetadataFieldResponse,
|
|
KnowledgeFSMetadataFieldUpdatePayload,
|
|
KnowledgeFSNamespacePreviewConsumePayload,
|
|
KnowledgeFSNamespacePreviewCreatePayload,
|
|
KnowledgeFSNamespacePreviewImportResponse,
|
|
KnowledgeFSNamespacePreviewJobResponse,
|
|
KnowledgeFSOverviewActivityListResponse,
|
|
KnowledgeFSOverviewAttentionListResponse,
|
|
KnowledgeFSOverviewBaseStatsResponse,
|
|
KnowledgeFSOverviewHealthResponse,
|
|
KnowledgeFSOverviewInventoryResponse,
|
|
KnowledgeFSOverviewQueryOutcomesResponse,
|
|
KnowledgeFSPresignedUploadResponse,
|
|
KnowledgeFSProfileMigrationResponse,
|
|
KnowledgeFSQualityReplayListResponse,
|
|
KnowledgeFSQualityReplayPayload,
|
|
KnowledgeFSQualityReplayResponse,
|
|
KnowledgeFSQueryCreatePayload,
|
|
KnowledgeFSQueryImageResponse,
|
|
KnowledgeFSQueryResponse,
|
|
KnowledgeFSResearchTaskCreatePayload,
|
|
KnowledgeFSResearchTaskListResponse,
|
|
KnowledgeFSResearchTaskPartialListResponse,
|
|
KnowledgeFSResearchTaskPlanPayload,
|
|
KnowledgeFSResearchTaskPlanResponse,
|
|
KnowledgeFSResearchTaskResponse,
|
|
KnowledgeFSRetrievalProfileUpdatePayload,
|
|
KnowledgeFSRetrievalSettingsResponse,
|
|
KnowledgeFSSettingsPayload,
|
|
KnowledgeFSSettingsResponse,
|
|
KnowledgeFSSettingsUpdateResponse,
|
|
KnowledgeFSSmallFileUploadResponse,
|
|
KnowledgeFSSourceConnectionCreatePayload,
|
|
KnowledgeFSSourceConnectionListResponse,
|
|
KnowledgeFSSourceConnectionRefreshPayload,
|
|
KnowledgeFSSourceConnectionResponse,
|
|
KnowledgeFSSourceCrawlResponse,
|
|
KnowledgeFSSourceCreatePayload,
|
|
KnowledgeFSSourceCredentialTestResponse,
|
|
KnowledgeFSSourceDeletePayload,
|
|
KnowledgeFSSourceFilesResponse,
|
|
KnowledgeFSSourceImportFilesPayload,
|
|
KnowledgeFSSourceImportPagesPayload,
|
|
KnowledgeFSSourceImportResponse,
|
|
KnowledgeFSSourceListResponse,
|
|
KnowledgeFSSourcePagesResponse,
|
|
KnowledgeFSSourceProviderListResponse,
|
|
KnowledgeFSSourceResponse,
|
|
KnowledgeFSSourceSyncPolicyPayload,
|
|
KnowledgeFSSourceSyncPolicyResponse,
|
|
KnowledgeFSSourceUpdatePayload,
|
|
KnowledgeFSSourceWorkflowCancelPayload,
|
|
KnowledgeFSSourceWorkflowImportPayload,
|
|
KnowledgeFSSourceWorkflowResponse,
|
|
KnowledgeFSSpaceUpdatePayload,
|
|
KnowledgeFSStatQuery,
|
|
KnowledgeFSStatResponse,
|
|
KnowledgeFSTraceEntryListResponse,
|
|
KnowledgeFSTraceListResponse,
|
|
KnowledgeFSTreeQuery,
|
|
KnowledgeFSTreeResponse,
|
|
KnowledgeFSUploadPartPresignPayload,
|
|
KnowledgeFSUploadSessionAbortPayload,
|
|
KnowledgeFSUploadSessionCompletePayload,
|
|
KnowledgeFSUploadSessionCreatePayload,
|
|
KnowledgeFSUploadSessionCreateRemotePayload,
|
|
KnowledgeFSUploadSessionCreateResponse,
|
|
KnowledgeFSUploadSessionMutationResponse,
|
|
)
|
|
from services.knowledge_fs.product_operations import KNOWLEDGE_FS_PRODUCT_OPERATIONS, is_product_operation_ready
|
|
from services.knowledge_fs.product_remote import (
|
|
KnowledgeFSOperationUnavailableError,
|
|
KnowledgeFSProductRemoteError,
|
|
KnowledgeFSProductRemotePort,
|
|
KnowledgeFSProductRequestRejectedError,
|
|
KnowledgeFSProductResourceNotFoundError,
|
|
KnowledgeFSRemoteBinaryRequest,
|
|
KnowledgeFSRemoteJSONRequest,
|
|
KnowledgeFSRemoteMultipartFile,
|
|
KnowledgeFSRemoteMultipartRequest,
|
|
KnowledgeFSRemoteSSERequest,
|
|
KnowledgeFSRemoteSSEResponse,
|
|
)
|
|
from services.knowledge_fs.query_images import (
|
|
KnowledgeFSQueryImagePreviewPort,
|
|
load_query_image_previews,
|
|
)
|
|
from services.knowledge_fs.service_api_authorization import KnowledgeFSServiceApiProfile
|
|
|
|
_BUFFERED_UPLOAD_CAPABILITY_MIN_REMAINING = timedelta(seconds=15)
|
|
|
|
|
|
def _utc_now() -> datetime:
|
|
return datetime.now(UTC)
|
|
|
|
|
|
class KnowledgeFSDataFacade:
|
|
def __init__(
|
|
self,
|
|
*,
|
|
broker: KnowledgeFSCapabilityBroker,
|
|
remote: KnowledgeFSProductRemotePort,
|
|
buffered_upload_admission: KnowledgeFSBufferedUploadAdmissionPort = (
|
|
DEFAULT_KNOWLEDGE_FS_BUFFERED_UPLOAD_ADMISSION
|
|
),
|
|
clock: Callable[[], datetime] = _utc_now,
|
|
query_image_previews: KnowledgeFSQueryImagePreviewPort = load_query_image_previews,
|
|
) -> None:
|
|
self._broker = broker
|
|
self._remote = remote
|
|
self._buffered_upload_admission = buffered_upload_admission
|
|
self._clock = clock
|
|
self._query_image_previews = query_image_previews
|
|
|
|
@staticmethod
|
|
def _query_images_of(*responses: object) -> list[KnowledgeFSQueryImageResponse]:
|
|
# Responses are validated DTOs in production; unit tests may substitute opaque objects for
|
|
# the validated value, which simply carry no query images.
|
|
return [image for response in responses for image in (getattr(response, "query_images", None) or ())]
|
|
|
|
def _attach_query_image_previews(
|
|
self, *, tenant_id: str, account_id: str, images: Iterable[KnowledgeFSQueryImageResponse]
|
|
) -> None:
|
|
"""Fill in file names and signed preview URLs for the query images a run was asked with."""
|
|
|
|
pending = list(images)
|
|
if not pending:
|
|
return
|
|
previews = self._query_image_previews(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
upload_file_ids=[image.upload_file_id for image in pending],
|
|
)
|
|
for image in pending:
|
|
preview = previews.get(image.upload_file_id)
|
|
if preview is None:
|
|
continue
|
|
image.name = preview.name
|
|
image.mime_type = image.mime_type or preview.mime_type
|
|
image.byte_size = image.byte_size if image.byte_size is not None else preview.byte_size
|
|
image.preview_url = preview.preview_url
|
|
|
|
def _ensure_fresh_buffered_upload_capability(
|
|
self,
|
|
*,
|
|
issued: KnowledgeFSIssuedProductCapability,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
operation_id: str,
|
|
resource_id: str | None = None,
|
|
) -> KnowledgeFSIssuedProductCapability:
|
|
if issued.expires_at - self._clock() > _BUFFERED_UPLOAD_CAPABILITY_MIN_REMAINING:
|
|
return issued
|
|
return self._broker.issue_interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
resource_id=resource_id,
|
|
trace_id=issued.trace_id,
|
|
)
|
|
|
|
def stream_query(
|
|
self,
|
|
*,
|
|
capability_token: str,
|
|
trace_id: str,
|
|
payload: KnowledgeFSAdmittedQueryRequest,
|
|
) -> KnowledgeFSRemoteSSEResponse:
|
|
operation_id = "createQuery"
|
|
_assert_sse_bff_ready(operation_id)
|
|
operation = KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id]
|
|
if operation.kfs_path is None:
|
|
raise KnowledgeFSOperationUnavailableError("KnowledgeFS query stream path is unavailable")
|
|
return self._remote.execute_sse(
|
|
KnowledgeFSRemoteSSERequest(
|
|
operation_id=operation_id,
|
|
method=operation.method,
|
|
path=operation.kfs_path,
|
|
capability_token=capability_token,
|
|
trace_id=trace_id,
|
|
payload=payload.model_dump(mode="json", by_alias=True, exclude_none=True),
|
|
)
|
|
)
|
|
|
|
def stream_research_task(
|
|
self,
|
|
*,
|
|
capability_token: str,
|
|
trace_id: str,
|
|
task_id: str,
|
|
knowledge_space_id: str,
|
|
cursor: str | None,
|
|
limit: int,
|
|
) -> KnowledgeFSRemoteSSEResponse:
|
|
operation_id = "streamResearchTask"
|
|
_assert_sse_bff_ready(operation_id)
|
|
operation = KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id]
|
|
if operation.kfs_path is None:
|
|
raise KnowledgeFSOperationUnavailableError("KnowledgeFS research stream path is unavailable")
|
|
path = _resolve_product_path(
|
|
template=operation.kfs_path,
|
|
knowledge_space_id=knowledge_space_id,
|
|
resource_id=task_id,
|
|
resource_resolver=operation.resource_resolver,
|
|
path_parameters=(),
|
|
)
|
|
query: tuple[tuple[str, str], ...] = (("knowledgeSpaceId", knowledge_space_id), ("limit", str(limit)))
|
|
if cursor is not None:
|
|
query = (*query, ("cursor", cursor))
|
|
return self._remote.execute_sse(
|
|
KnowledgeFSRemoteSSERequest(
|
|
operation_id=operation_id,
|
|
method=operation.method,
|
|
path=path,
|
|
capability_token=capability_token,
|
|
trace_id=trace_id,
|
|
payload=None,
|
|
query=query,
|
|
)
|
|
)
|
|
|
|
def get_settings(self, *, tenant_id: str, account_id: str, control_space_id: str) -> KnowledgeFSSettingsResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getSettings",
|
|
)
|
|
return KnowledgeFSSettingsResponse.model_validate(raw)
|
|
|
|
def list_knowledge_fs(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
query: KnowledgeFSListQuery,
|
|
) -> KnowledgeFSListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listKnowledgeFs",
|
|
query=_knowledge_fs_query(
|
|
("path", query.path),
|
|
("limit", query.limit),
|
|
("cursor", query.cursor),
|
|
("consistencyClass", query.consistency_class),
|
|
),
|
|
)
|
|
return KnowledgeFSListResponse.model_validate(raw)
|
|
|
|
def tree_knowledge_fs(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
query: KnowledgeFSTreeQuery,
|
|
) -> KnowledgeFSTreeResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="treeKnowledgeFs",
|
|
query=_knowledge_fs_query(
|
|
("path", query.path),
|
|
("limit", query.limit),
|
|
("cursor", query.cursor),
|
|
("depth", query.depth),
|
|
("consistencyClass", query.consistency_class),
|
|
),
|
|
)
|
|
return KnowledgeFSTreeResponse.model_validate(raw)
|
|
|
|
def grep_knowledge_fs(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
query: KnowledgeFSGrepQuery,
|
|
) -> KnowledgeFSGrepResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="grepKnowledgeFs",
|
|
query=_knowledge_fs_query(
|
|
("path", query.path),
|
|
("limit", query.limit),
|
|
("cursor", query.cursor),
|
|
("q", query.query),
|
|
("timeoutMs", query.timeout_ms),
|
|
("consistencyClass", query.consistency_class),
|
|
),
|
|
)
|
|
return KnowledgeFSGrepResponse.model_validate(raw)
|
|
|
|
def find_knowledge_fs(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
query: KnowledgeFSFindQuery,
|
|
) -> KnowledgeFSListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="findKnowledgeFs",
|
|
query=_knowledge_fs_query(
|
|
("path", query.path),
|
|
("limit", query.limit),
|
|
("cursor", query.cursor),
|
|
("metadataKey", query.metadata_key),
|
|
("metadataValue", query.metadata_value),
|
|
("nameContains", query.name_contains),
|
|
("resourceType", query.resource_type),
|
|
("consistencyClass", query.consistency_class),
|
|
),
|
|
)
|
|
return KnowledgeFSListResponse.model_validate(raw)
|
|
|
|
def diff_knowledge_fs(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
query: KnowledgeFSDiffQuery,
|
|
) -> KnowledgeFSDiffResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="diffKnowledgeFs",
|
|
query=_knowledge_fs_query(
|
|
("oldPath", query.old_path),
|
|
("newPath", query.new_path),
|
|
("mode", query.mode),
|
|
("semantic", query.semantic),
|
|
("consistencyClass", query.consistency_class),
|
|
),
|
|
)
|
|
return KnowledgeFSDiffResponse.model_validate(raw)
|
|
|
|
def cat_knowledge_fs(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
query: KnowledgeFSCatQuery,
|
|
) -> KnowledgeFSCatResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="catKnowledgeFs",
|
|
query=_knowledge_fs_query(
|
|
("path", query.path),
|
|
("limit", query.limit),
|
|
("cursor", query.cursor),
|
|
("consistencyClass", query.consistency_class),
|
|
),
|
|
)
|
|
return KnowledgeFSCatResponse.model_validate(raw)
|
|
|
|
def stat_knowledge_fs(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
query: KnowledgeFSStatQuery,
|
|
) -> KnowledgeFSStatResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="statKnowledgeFs",
|
|
query=_knowledge_fs_query(
|
|
("path", query.path),
|
|
("consistencyClass", query.consistency_class),
|
|
),
|
|
)
|
|
return KnowledgeFSStatResponse.model_validate(raw)
|
|
|
|
def get_overview_stats(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str
|
|
) -> KnowledgeFSOverviewBaseStatsResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getOverviewStats",
|
|
)
|
|
return KnowledgeFSOverviewBaseStatsResponse.model_validate(raw)
|
|
|
|
def get_overview_query_outcomes(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
window: Literal["24h", "7d", "30d"],
|
|
) -> KnowledgeFSOverviewQueryOutcomesResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getOverviewQueryOutcomes",
|
|
query=(("window", window),),
|
|
)
|
|
return KnowledgeFSOverviewQueryOutcomesResponse.model_validate(raw)
|
|
|
|
def get_overview_inventory(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str
|
|
) -> KnowledgeFSOverviewInventoryResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getOverviewInventory",
|
|
)
|
|
return KnowledgeFSOverviewInventoryResponse.model_validate(raw)
|
|
|
|
def list_overview_attention(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
include_dismissed: bool,
|
|
limit: int,
|
|
) -> KnowledgeFSOverviewAttentionListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listOverviewAttention",
|
|
query=(("includeDismissed", str(include_dismissed).lower()), ("limit", str(limit))),
|
|
)
|
|
return KnowledgeFSOverviewAttentionListResponse.model_validate(raw)
|
|
|
|
def list_overview_activity(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
action: str | None,
|
|
actor_id: str | None,
|
|
actor_type: str | None,
|
|
cursor: str | None,
|
|
from_at: str | None,
|
|
limit: int,
|
|
resource_type: str | None,
|
|
result: str | None,
|
|
to_at: str | None,
|
|
) -> KnowledgeFSOverviewActivityListResponse:
|
|
query = tuple(
|
|
(key, value)
|
|
for key, value in (
|
|
("action", action),
|
|
("actorId", actor_id),
|
|
("actorType", actor_type),
|
|
("cursor", cursor),
|
|
("from", from_at),
|
|
("limit", str(limit)),
|
|
("resourceType", resource_type),
|
|
("result", result),
|
|
("to", to_at),
|
|
)
|
|
if value is not None
|
|
)
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listOverviewActivity",
|
|
query=query,
|
|
)
|
|
return KnowledgeFSOverviewActivityListResponse.model_validate(raw)
|
|
|
|
def get_overview_health(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str
|
|
) -> KnowledgeFSOverviewHealthResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getOverviewHealth",
|
|
)
|
|
return KnowledgeFSOverviewHealthResponse.model_validate(raw)
|
|
|
|
def update_space(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSSpaceUpdatePayload,
|
|
) -> JsonValue:
|
|
return self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateSpace",
|
|
payload=payload,
|
|
)
|
|
|
|
def update_settings(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSSettingsPayload,
|
|
) -> KnowledgeFSSettingsUpdateResponse:
|
|
current = self.get_settings(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
)
|
|
has_existing_profile = bool(
|
|
current.active_profile_revisions.embedding is not None
|
|
or current.active_profile_revisions.retrieval is not None
|
|
)
|
|
if has_existing_profile:
|
|
if current.revision != payload.expected_revision:
|
|
raise KnowledgeFSProductRequestRejectedError(status_code=409)
|
|
if payload.embedding is not None and payload.retrieval is not None:
|
|
raise KnowledgeFSProductRequestRejectedError(status_code=422)
|
|
if payload.embedding is not None:
|
|
migration_raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateEmbeddingProfile",
|
|
payload=payload.embedding,
|
|
)
|
|
elif payload.retrieval is not None:
|
|
retrieval_revision = current.active_profile_revisions.retrieval
|
|
if retrieval_revision is None:
|
|
raise KnowledgeFSOperationUnavailableError(
|
|
"KnowledgeFS active retrieval profile revision is unavailable"
|
|
)
|
|
migration_raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateRetrievalProfile",
|
|
payload=KnowledgeFSRetrievalProfileUpdatePayload(
|
|
expectedRevision=retrieval_revision,
|
|
profile=payload.retrieval,
|
|
),
|
|
)
|
|
else:
|
|
raise KnowledgeFSProductRequestRejectedError(status_code=422)
|
|
if isinstance(migration_raw, dict) and ("runState" in migration_raw or "run_state" in migration_raw):
|
|
return KnowledgeFSSettingsUpdateResponse(
|
|
migration=KnowledgeFSProfileMigrationResponse.model_validate(migration_raw),
|
|
settings=current,
|
|
)
|
|
if payload.embedding is not None:
|
|
KnowledgeFSEmbeddingSettingsResponse.model_validate(migration_raw)
|
|
else:
|
|
KnowledgeFSRetrievalSettingsResponse.model_validate(migration_raw)
|
|
refreshed = self.get_settings(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
)
|
|
return KnowledgeFSSettingsUpdateResponse(settings=refreshed)
|
|
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateSettings",
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSettingsUpdateResponse(settings=KnowledgeFSSettingsResponse.model_validate(raw))
|
|
|
|
def get_profile_migration(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
migration_id: str,
|
|
) -> KnowledgeFSProfileMigrationResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getProfileMigration",
|
|
path_parameters=(("migrationId", migration_id),),
|
|
)
|
|
return KnowledgeFSProfileMigrationResponse.model_validate(raw)
|
|
|
|
def list_documents(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None,
|
|
) -> KnowledgeFSDocumentListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listDocuments",
|
|
query=(("cursor", cursor),) if cursor else (),
|
|
)
|
|
return KnowledgeFSDocumentListResponse.model_validate(raw)
|
|
|
|
def list_logical_documents(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None,
|
|
) -> KnowledgeFSLogicalDocumentListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listLogicalDocuments",
|
|
query=(("cursor", cursor),) if cursor else (),
|
|
)
|
|
return KnowledgeFSLogicalDocumentListResponse.model_validate(raw)
|
|
|
|
def get_logical_document(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, document_id: str
|
|
) -> KnowledgeFSLogicalDocumentResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getLogicalDocument",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
)
|
|
return KnowledgeFSLogicalDocumentResponse.model_validate(raw)
|
|
|
|
def prepare_logical_document_download(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, document_id: str
|
|
) -> KnowledgeFSDocumentDownloadDescriptor:
|
|
"""Resolve a logical document's active or latest failed revision to its stored asset."""
|
|
logical_document = self.get_logical_document(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
document_id=document_id,
|
|
)
|
|
downloadable_revision = logical_document.active
|
|
if downloadable_revision is None:
|
|
if logical_document.status != "failed":
|
|
raise KnowledgeFSProductResourceNotFoundError("Logical document has no downloadable revision")
|
|
revisions = self.list_document_revisions(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
document_id=document_id,
|
|
limit=1,
|
|
)
|
|
downloadable_revision = revisions.data[0] if revisions.data else None
|
|
if downloadable_revision is None or downloadable_revision.state != "failed":
|
|
raise KnowledgeFSProductResourceNotFoundError("Logical document has no downloadable revision")
|
|
asset = self.get_document(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
document_id=downloadable_revision.document_asset_id,
|
|
)
|
|
if asset.version != downloadable_revision.document_asset_version:
|
|
raise KnowledgeFSProductResourceNotFoundError("Logical document revision asset version is unavailable")
|
|
return KnowledgeFSDocumentDownloadDescriptor(
|
|
document_id=logical_document.id,
|
|
filename=asset.filename,
|
|
mime_type=asset.mime_type,
|
|
object_key=asset.object_key,
|
|
sha256=asset.sha256,
|
|
size_bytes=asset.size_bytes,
|
|
)
|
|
|
|
def update_logical_document_availability(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
document_id: str,
|
|
payload: KnowledgeFSDocumentAvailabilityPayload,
|
|
) -> KnowledgeFSLogicalDocumentResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateLogicalDocumentAvailability",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSLogicalDocumentResponse.model_validate(raw)
|
|
|
|
def bulk_update_logical_document_availability(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSBulkDocumentAvailabilityPayload,
|
|
) -> KnowledgeFSBulkDocumentAvailabilityResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="bulkUpdateLogicalDocumentAvailability",
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSBulkDocumentAvailabilityResponse.model_validate(raw)
|
|
|
|
def delete_logical_document(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
document_id: str,
|
|
payload: KnowledgeFSLogicalDocumentDeletePayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSDurableDeletionAcceptedResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="deleteLogicalDocument",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSDurableDeletionAcceptedResponse.model_validate(raw)
|
|
|
|
def bulk_delete_logical_documents(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSBulkLogicalDocumentDeletePayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSBulkDeletionAcceptedResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="bulkDeleteLogicalDocuments",
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSBulkDeletionAcceptedResponse.model_validate(raw)
|
|
|
|
def create_document(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
body_reader: Callable[[int], KnowledgeFSRemoteMultipartFile],
|
|
) -> KnowledgeFSDocumentUploadAcceptedResponse:
|
|
operation_id = "createDocument"
|
|
_assert_multipart_bff_ready(operation_id)
|
|
issued = self._broker.issue_interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
)
|
|
operation = KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id]
|
|
if operation.kfs_path is None:
|
|
raise KnowledgeFSOperationUnavailableError(f"KnowledgeFS operation is unavailable: {operation_id}")
|
|
with self._buffered_upload_admission.admit(reserved_bytes=operation.max_request_bytes):
|
|
issued = self._ensure_fresh_buffered_upload_capability(
|
|
issued=issued,
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
)
|
|
upload = body_reader(operation.max_request_bytes)
|
|
if not upload.filename or not upload.content_type or not isinstance(upload.body, bytes) or not upload.body:
|
|
raise KnowledgeFSProductRequestRejectedError(status_code=422)
|
|
if len(upload.body) > operation.max_request_bytes:
|
|
raise KnowledgeFSProductRequestRejectedError(status_code=413)
|
|
issued = self._ensure_fresh_buffered_upload_capability(
|
|
issued=issued,
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
)
|
|
path = _resolve_product_path(
|
|
template=operation.kfs_path,
|
|
knowledge_space_id=issued.knowledge_space_id,
|
|
resource_id=None,
|
|
resource_resolver=operation.resource_resolver,
|
|
path_parameters=(),
|
|
)
|
|
raw = self._remote.execute_multipart(
|
|
KnowledgeFSRemoteMultipartRequest(
|
|
operation_id=operation_id,
|
|
method=operation.method,
|
|
path=path,
|
|
namespace_id=tenant_id,
|
|
knowledge_space_id=issued.knowledge_space_id,
|
|
capability_token=issued.token,
|
|
trace_id=issued.trace_id,
|
|
file=upload,
|
|
)
|
|
)
|
|
return KnowledgeFSDocumentUploadAcceptedResponse.model_validate(raw)
|
|
|
|
def create_upload_session(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSUploadSessionCreatePayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSUploadSessionCreateResponse:
|
|
remote_payload = KnowledgeFSUploadSessionCreateRemotePayload(
|
|
**payload.model_dump(mode="python"),
|
|
idempotencyKey=idempotency_key,
|
|
)
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createUploadSession",
|
|
payload=remote_payload,
|
|
)
|
|
return KnowledgeFSUploadSessionCreateResponse.model_validate(raw)
|
|
|
|
def presign_upload_session_part(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
upload_session_id: str,
|
|
part_number: int,
|
|
payload: KnowledgeFSUploadPartPresignPayload,
|
|
) -> KnowledgeFSPresignedUploadResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="presignUploadSessionPart",
|
|
resource_id=upload_session_id,
|
|
payload=payload,
|
|
bind_space_in_body=True,
|
|
path_parameters=(("partNumber", str(part_number)),),
|
|
)
|
|
return KnowledgeFSPresignedUploadResponse.model_validate(raw)
|
|
|
|
def complete_upload_session(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
upload_session_id: str,
|
|
payload: KnowledgeFSUploadSessionCompletePayload,
|
|
) -> KnowledgeFSUploadSessionMutationResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="completeUploadSession",
|
|
resource_id=upload_session_id,
|
|
payload=payload,
|
|
bind_space_in_body=True,
|
|
)
|
|
return KnowledgeFSUploadSessionMutationResponse.model_validate(raw)
|
|
|
|
def abort_upload_session(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
upload_session_id: str,
|
|
payload: KnowledgeFSUploadSessionAbortPayload,
|
|
) -> KnowledgeFSUploadSessionMutationResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="abortUploadSession",
|
|
resource_id=upload_session_id,
|
|
payload=payload,
|
|
bind_space_in_body=True,
|
|
)
|
|
return KnowledgeFSUploadSessionMutationResponse.model_validate(raw)
|
|
|
|
def upload_small_file(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
upload_session_id: str,
|
|
body_reader: Callable[[int], bytes],
|
|
) -> KnowledgeFSSmallFileUploadResponse:
|
|
operation_id = "uploadSmallFile"
|
|
_assert_binary_bff_ready(operation_id)
|
|
issued = self._broker.issue_interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
resource_id=upload_session_id,
|
|
)
|
|
operation = KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id]
|
|
if operation.kfs_path is None:
|
|
raise KnowledgeFSOperationUnavailableError(f"KnowledgeFS operation is unavailable: {operation_id}")
|
|
with self._buffered_upload_admission.admit(reserved_bytes=operation.max_request_bytes):
|
|
issued = self._ensure_fresh_buffered_upload_capability(
|
|
issued=issued,
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
resource_id=upload_session_id,
|
|
)
|
|
body = body_reader(operation.max_request_bytes)
|
|
if not isinstance(body, bytes) or not body:
|
|
raise KnowledgeFSProductRequestRejectedError(status_code=422)
|
|
if len(body) > operation.max_request_bytes:
|
|
raise KnowledgeFSProductRequestRejectedError(status_code=413)
|
|
issued = self._ensure_fresh_buffered_upload_capability(
|
|
issued=issued,
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
resource_id=upload_session_id,
|
|
)
|
|
path = _resolve_product_path(
|
|
template=operation.kfs_path,
|
|
knowledge_space_id=issued.knowledge_space_id,
|
|
resource_id=upload_session_id,
|
|
resource_resolver=operation.resource_resolver,
|
|
path_parameters=(),
|
|
)
|
|
raw = self._remote.execute_binary(
|
|
KnowledgeFSRemoteBinaryRequest(
|
|
operation_id=operation_id,
|
|
method=operation.method,
|
|
path=path,
|
|
namespace_id=tenant_id,
|
|
knowledge_space_id=issued.knowledge_space_id,
|
|
capability_token=issued.token,
|
|
trace_id=issued.trace_id,
|
|
body=body,
|
|
query=(("knowledgeSpaceId", issued.knowledge_space_id),),
|
|
)
|
|
)
|
|
return KnowledgeFSSmallFileUploadResponse.model_validate(raw)
|
|
|
|
def get_document(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, document_id: str
|
|
) -> KnowledgeFSDocumentResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getDocument",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
)
|
|
return KnowledgeFSDocumentResponse.model_validate(raw)
|
|
|
|
def get_document_outline(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, document_id: str
|
|
) -> KnowledgeFSDocumentOutlineResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getDocumentOutline",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
)
|
|
return KnowledgeFSDocumentOutlineResponse.model_validate(raw)
|
|
|
|
def get_document_multimodal_manifest(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, document_id: str
|
|
) -> KnowledgeFSDocumentMultimodalManifest:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getDocumentMultimodalManifest",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
)
|
|
return KnowledgeFSDocumentMultimodalManifest.model_validate(raw)
|
|
|
|
def list_document_revisions(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
document_id: str,
|
|
cursor: str | None = None,
|
|
limit: int | None = None,
|
|
) -> KnowledgeFSDocumentRevisionListResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listDocumentRevisions",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
query=_knowledge_fs_query(("cursor", cursor), ("limit", limit)),
|
|
)
|
|
return KnowledgeFSDocumentRevisionListResponse.model_validate(raw)
|
|
|
|
def update_document_metadata(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
document_id: str,
|
|
payload: KnowledgeFSDocumentMetadataPayload,
|
|
) -> KnowledgeFSLogicalDocumentResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateDocumentMetadata",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSLogicalDocumentResponse.model_validate(raw)
|
|
|
|
def list_metadata_fields(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 100,
|
|
) -> KnowledgeFSMetadataFieldListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listMetadataFields",
|
|
query=_knowledge_fs_query(("cursor", cursor), ("limit", limit)),
|
|
)
|
|
return KnowledgeFSMetadataFieldListResponse.model_validate(raw)
|
|
|
|
def create_metadata_field(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSMetadataFieldCreatePayload,
|
|
) -> KnowledgeFSMetadataFieldResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createMetadataField",
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSMetadataFieldResponse.model_validate(raw)
|
|
|
|
def update_metadata_field(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
field_id: str,
|
|
payload: KnowledgeFSMetadataFieldUpdatePayload,
|
|
) -> KnowledgeFSMetadataFieldResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateMetadataField",
|
|
path_parameters=(("fieldId", field_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSMetadataFieldResponse.model_validate(raw)
|
|
|
|
def delete_metadata_field(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
field_id: str,
|
|
expected_row_version: int,
|
|
) -> KnowledgeFSMetadataFieldDeleteResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="deleteMetadataField",
|
|
path_parameters=(("fieldId", field_id),),
|
|
query=(("expectedRowVersion", str(expected_row_version)),),
|
|
)
|
|
return KnowledgeFSMetadataFieldDeleteResponse.model_validate(raw)
|
|
|
|
def list_document_chunks(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
document_id: str,
|
|
revision: int,
|
|
cursor: str | None = None,
|
|
query_text: str | None = None,
|
|
) -> KnowledgeFSDocumentChunkListResponse:
|
|
query = tuple((name, value) for name, value in (("cursor", cursor), ("query", query_text)) if value)
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listDocumentChunks",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id), ("revision", str(revision))),
|
|
query=query,
|
|
)
|
|
return KnowledgeFSDocumentChunkListResponse.model_validate(raw)
|
|
|
|
def get_document_chunk(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
document_id: str,
|
|
revision: int,
|
|
chunk_id: str,
|
|
) -> KnowledgeFSDocumentChunkResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getDocumentChunk",
|
|
resource_id=document_id,
|
|
path_parameters=(
|
|
("documentId", document_id),
|
|
("revision", str(revision)),
|
|
("chunkId", chunk_id),
|
|
),
|
|
)
|
|
return KnowledgeFSDocumentChunkResponse.model_validate(raw)
|
|
|
|
def delete_document(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
document_id: str,
|
|
payload: KnowledgeFSDocumentDeletePayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSDurableDeletionAcceptedResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="deleteDocument",
|
|
resource_id=document_id,
|
|
path_parameters=(("documentId", document_id),),
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSDurableDeletionAcceptedResponse.model_validate(raw)
|
|
|
|
def bulk_delete_documents(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSBulkDocumentDeletePayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSBulkDeletionAcceptedResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="bulkDeleteDocuments",
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSBulkDeletionAcceptedResponse.model_validate(raw)
|
|
|
|
def reindex_documents(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSDocumentReindexPayload,
|
|
) -> KnowledgeFSDocumentReindexResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="reindexDocuments",
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSDocumentReindexResponse.model_validate(raw)
|
|
|
|
def get_compilation_job(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, job_id: str
|
|
) -> KnowledgeFSDocumentCompilationJobResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getCompilationJob",
|
|
resource_id=job_id,
|
|
)
|
|
return KnowledgeFSDocumentCompilationJobResponse.model_validate(raw)
|
|
|
|
def cancel_compilation_job(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, job_id: str
|
|
) -> KnowledgeFSDocumentCompilationJobResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="cancelCompilationJob",
|
|
resource_id=job_id,
|
|
)
|
|
return KnowledgeFSDocumentCompilationJobResponse.model_validate(raw)
|
|
|
|
def retry_compilation_job(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, job_id: str
|
|
) -> KnowledgeFSDocumentCompilationJobResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="retryCompilationJob",
|
|
resource_id=job_id,
|
|
)
|
|
return KnowledgeFSDocumentCompilationJobResponse.model_validate(raw)
|
|
|
|
def get_bulk_job(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, job_id: str
|
|
) -> KnowledgeFSBulkJobResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getBulkJob",
|
|
resource_id=job_id,
|
|
)
|
|
return KnowledgeFSBulkJobResponse.model_validate(raw)
|
|
|
|
def list_background_tasks(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 50,
|
|
) -> KnowledgeFSBackgroundTaskListResponse:
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listBackgroundTasks",
|
|
query=query,
|
|
)
|
|
return KnowledgeFSBackgroundTaskListResponse.model_validate(raw)
|
|
|
|
def cancel_background_task(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
task_kind: Literal["document", "document_bulk", "source"],
|
|
task_id: str,
|
|
) -> KnowledgeFSBackgroundTaskResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="cancelBackgroundTask",
|
|
resource_id=task_id,
|
|
path_parameters=(("taskKind", task_kind), ("taskId", task_id)),
|
|
)
|
|
return KnowledgeFSBackgroundTaskResponse.model_validate(raw)
|
|
|
|
def retry_background_task(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
task_kind: Literal["document", "document_bulk", "source"],
|
|
task_id: str,
|
|
) -> KnowledgeFSBackgroundTaskResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="retryBackgroundTask",
|
|
resource_id=task_id,
|
|
path_parameters=(("taskKind", task_kind), ("taskId", task_id)),
|
|
)
|
|
return KnowledgeFSBackgroundTaskResponse.model_validate(raw)
|
|
|
|
def list_sources(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 50,
|
|
) -> KnowledgeFSSourceListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listSources",
|
|
query=(
|
|
*((("cursor", cursor),) if cursor else ()),
|
|
("limit", str(limit)),
|
|
),
|
|
)
|
|
return KnowledgeFSSourceListResponse.model_validate(raw)
|
|
|
|
def create_source(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSSourceCreatePayload,
|
|
) -> KnowledgeFSSourceResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createSource",
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSourceResponse.model_validate(raw)
|
|
|
|
def get_source(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, source_id: str
|
|
) -> KnowledgeFSSourceResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getSource",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
)
|
|
return KnowledgeFSSourceResponse.model_validate(raw)
|
|
|
|
def update_source(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSSourceUpdatePayload,
|
|
) -> KnowledgeFSSourceResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateSource",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSourceResponse.model_validate(raw)
|
|
|
|
def delete_source(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSSourceDeletePayload,
|
|
documents: Literal["cascade", "keep"],
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSDurableDeletionAcceptedResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="deleteSource",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
query=(("documents", documents),),
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSDurableDeletionAcceptedResponse.model_validate(raw)
|
|
|
|
def test_source(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, source_id: str
|
|
) -> KnowledgeFSSourceCredentialTestResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="testSource",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
)
|
|
return KnowledgeFSSourceCredentialTestResponse.model_validate(raw)
|
|
|
|
def sync_source(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="syncSource",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def list_source_providers(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str
|
|
) -> KnowledgeFSSourceProviderListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listSourceProviders",
|
|
)
|
|
return KnowledgeFSSourceProviderListResponse.model_validate(raw)
|
|
|
|
def create_source_connection(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSSourceConnectionCreatePayload,
|
|
) -> KnowledgeFSSourceConnectionResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createSourceConnection",
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSourceConnectionResponse.model_validate(raw)
|
|
|
|
def list_source_connections(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None,
|
|
limit: int,
|
|
) -> KnowledgeFSSourceConnectionListResponse:
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listSourceConnections",
|
|
query=query,
|
|
)
|
|
return KnowledgeFSSourceConnectionListResponse.model_validate(raw)
|
|
|
|
def refresh_source_connection(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
connection_id: str,
|
|
payload: KnowledgeFSSourceConnectionRefreshPayload,
|
|
) -> KnowledgeFSSourceConnectionResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="refreshSourceConnection",
|
|
payload=payload,
|
|
path_parameters=(("connectionId", connection_id),),
|
|
)
|
|
return KnowledgeFSSourceConnectionResponse.model_validate(raw)
|
|
|
|
def preview_source_crawl(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="previewSourceCrawl",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def import_selected_source_crawl(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSCrawlImportPayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="importSelectedSourceCrawl",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def create_namespace_source_preview(
|
|
self, *, tenant_id: str, account_id: str, payload: KnowledgeFSNamespacePreviewCreatePayload
|
|
) -> KnowledgeFSNamespacePreviewJobResponse:
|
|
return KnowledgeFSNamespacePreviewJobResponse.model_validate(
|
|
self._namespace_interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
operation_id="createNamespaceSourcePreview",
|
|
payload=payload,
|
|
)
|
|
)
|
|
|
|
def get_namespace_source_preview(
|
|
self, *, tenant_id: str, account_id: str, job_id: str
|
|
) -> KnowledgeFSNamespacePreviewJobResponse:
|
|
return KnowledgeFSNamespacePreviewJobResponse.model_validate(
|
|
self._namespace_interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
operation_id="getNamespaceSourcePreview",
|
|
path_parameters=(("jobId", job_id),),
|
|
)
|
|
)
|
|
|
|
def cancel_namespace_source_preview(
|
|
self, *, tenant_id: str, account_id: str, job_id: str
|
|
) -> KnowledgeFSNamespacePreviewJobResponse:
|
|
return KnowledgeFSNamespacePreviewJobResponse.model_validate(
|
|
self._namespace_interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
operation_id="cancelNamespaceSourcePreview",
|
|
path_parameters=(("jobId", job_id),),
|
|
)
|
|
)
|
|
|
|
def consume_namespace_source_preview(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSNamespacePreviewConsumePayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSNamespacePreviewImportResponse:
|
|
return KnowledgeFSNamespacePreviewImportResponse.model_validate(
|
|
self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="consumeNamespaceSourcePreview",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
)
|
|
|
|
def import_source_workflow(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSSourceWorkflowImportPayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="importSourceWorkflow",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def get_source_sync_policy(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, source_id: str
|
|
) -> KnowledgeFSSourceSyncPolicyResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getSourceSyncPolicy",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
)
|
|
return KnowledgeFSSourceSyncPolicyResponse.model_validate(raw)
|
|
|
|
def update_source_sync_policy(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSSourceSyncPolicyPayload,
|
|
) -> KnowledgeFSSourceSyncPolicyResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateSourceSyncPolicy",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSourceSyncPolicyResponse.model_validate(raw)
|
|
|
|
def get_source_workflow(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, run_id: str
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getSourceWorkflow",
|
|
resource_id=run_id,
|
|
path_parameters=(("runId", run_id),),
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def cancel_source_workflow(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
run_id: str,
|
|
payload: KnowledgeFSSourceWorkflowCancelPayload,
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="cancelSourceWorkflow",
|
|
resource_id=run_id,
|
|
path_parameters=(("runId", run_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def retry_source_workflow(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, run_id: str
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="retrySourceWorkflow",
|
|
resource_id=run_id,
|
|
path_parameters=(("runId", run_id),),
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def list_crawl_preview_pages(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
run_id: str,
|
|
cursor: str | None,
|
|
limit: int,
|
|
) -> KnowledgeFSCrawlPreviewPageListResponse:
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listCrawlPreviewPages",
|
|
resource_id=run_id,
|
|
path_parameters=(("runId", run_id),),
|
|
query=query,
|
|
)
|
|
return KnowledgeFSCrawlPreviewPageListResponse.model_validate(raw)
|
|
|
|
def select_crawl_preview_pages(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
run_id: str,
|
|
payload: KnowledgeFSCrawlPreviewSelectionPayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSSourceWorkflowResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="selectCrawlPreviewPages",
|
|
resource_id=run_id,
|
|
path_parameters=(("runId", run_id),),
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSSourceWorkflowResponse.model_validate(raw)
|
|
|
|
def crawl_source(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, source_id: str
|
|
) -> KnowledgeFSSourceCrawlResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="crawlSource",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
)
|
|
return KnowledgeFSSourceCrawlResponse.model_validate(raw)
|
|
|
|
def list_source_pages(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 50,
|
|
) -> KnowledgeFSSourcePagesResponse:
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listSourcePages",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
query=query,
|
|
)
|
|
return KnowledgeFSSourcePagesResponse.model_validate(raw)
|
|
|
|
def import_source_pages(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSSourceImportPagesPayload,
|
|
) -> KnowledgeFSSourceImportResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="importSourcePages",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSourceImportResponse.model_validate(raw)
|
|
|
|
def list_source_files(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
query: tuple[tuple[str, str], ...] = (),
|
|
) -> KnowledgeFSSourceFilesResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listSourceFiles",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
query=query,
|
|
)
|
|
return KnowledgeFSSourceFilesResponse.model_validate(raw)
|
|
|
|
def import_source_files(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
source_id: str,
|
|
payload: KnowledgeFSSourceImportFilesPayload,
|
|
) -> KnowledgeFSSourceImportResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="importSourceFiles",
|
|
resource_id=source_id,
|
|
path_parameters=(("sourceId", source_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSSourceImportResponse.model_validate(raw)
|
|
|
|
def create_query(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSQueryCreatePayload,
|
|
) -> KnowledgeFSQueryResponse:
|
|
_ = (tenant_id, account_id, control_space_id, payload)
|
|
raise KnowledgeFSOperationUnavailableError(
|
|
"Buffered KnowledgeFS query creation is deprecated; use the queries/admission direct flow"
|
|
)
|
|
|
|
def create_research_task(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSResearchTaskCreatePayload,
|
|
) -> KnowledgeFSResearchTaskResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createResearchTask",
|
|
payload=payload,
|
|
bind_space_in_body=True,
|
|
)
|
|
task = KnowledgeFSResearchTaskResponse.model_validate(raw)
|
|
self._attach_query_image_previews(
|
|
tenant_id=tenant_id, account_id=account_id, images=self._query_images_of(task)
|
|
)
|
|
return task
|
|
|
|
def plan_research_task(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSResearchTaskPlanPayload,
|
|
) -> KnowledgeFSResearchTaskPlanResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="planResearchTask",
|
|
payload=payload,
|
|
bind_space_in_body=True,
|
|
)
|
|
return KnowledgeFSResearchTaskPlanResponse.model_validate(raw)
|
|
|
|
def get_research_task(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, task_id: str
|
|
) -> KnowledgeFSResearchTaskResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getResearchTask",
|
|
resource_id=task_id,
|
|
)
|
|
task = KnowledgeFSResearchTaskResponse.model_validate(raw)
|
|
self._attach_query_image_previews(
|
|
tenant_id=tenant_id, account_id=account_id, images=self._query_images_of(task)
|
|
)
|
|
return task
|
|
|
|
def list_research_task_partials(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
task_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 25,
|
|
) -> KnowledgeFSResearchTaskPartialListResponse:
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listResearchTaskPartials",
|
|
resource_id=task_id,
|
|
query=query,
|
|
)
|
|
return KnowledgeFSResearchTaskPartialListResponse.model_validate(raw)
|
|
|
|
def cancel_research_task(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, task_id: str
|
|
) -> KnowledgeFSResearchTaskResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="cancelResearchTask",
|
|
resource_id=task_id,
|
|
)
|
|
return KnowledgeFSResearchTaskResponse.model_validate(raw)
|
|
|
|
def list_research_tasks(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, cursor: str | None = None
|
|
) -> KnowledgeFSResearchTaskListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listResearchTasks",
|
|
query=(("cursor", cursor),) if cursor else (),
|
|
)
|
|
tasks = KnowledgeFSResearchTaskListResponse.model_validate(raw)
|
|
self._attach_query_image_previews(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
images=self._query_images_of(*tasks.data),
|
|
)
|
|
return tasks
|
|
|
|
def list_traces(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None = None,
|
|
source: str | None = None,
|
|
) -> KnowledgeFSTraceListResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listTraces",
|
|
query=_trace_list_query(cursor=cursor, source=source),
|
|
)
|
|
traces = KnowledgeFSTraceListResponse.model_validate(raw)
|
|
self._attach_query_image_previews(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
images=self._query_images_of(*traces.data),
|
|
)
|
|
return traces
|
|
|
|
def list_golden_questions(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 50,
|
|
) -> KnowledgeFSGoldenQuestionListResponse:
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listGoldenQuestions",
|
|
query=query,
|
|
)
|
|
return KnowledgeFSGoldenQuestionListResponse.model_validate(raw)
|
|
|
|
def create_golden_question(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSGoldenQuestionPayload,
|
|
) -> KnowledgeFSGoldenQuestionResponse:
|
|
metadata: dict[str, object] = {
|
|
"annotation": payload.annotation,
|
|
"evidenceText": payload.evidence_text,
|
|
"matchPolicy": payload.match_policy,
|
|
}
|
|
if payload.source_bad_case_id is not None:
|
|
metadata["sourceBadCaseId"] = payload.source_bad_case_id
|
|
remote_payload = KnowledgeFSGoldenQuestionRemotePayload(
|
|
expected_evidence_ids=payload.expected_evidence_ids,
|
|
metadata=metadata,
|
|
question=payload.question,
|
|
tags=payload.tags,
|
|
)
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createGoldenQuestion",
|
|
payload=remote_payload,
|
|
)
|
|
return KnowledgeFSGoldenQuestionResponse.model_validate(raw)
|
|
|
|
def update_golden_question(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
question_id: str,
|
|
payload: KnowledgeFSGoldenQuestionPayload,
|
|
) -> KnowledgeFSGoldenQuestionResponse:
|
|
metadata: dict[str, object] = {"annotation": payload.annotation}
|
|
if "evidence_text" in payload.model_fields_set:
|
|
metadata["evidenceText"] = payload.evidence_text
|
|
if "match_policy" in payload.model_fields_set:
|
|
metadata["matchPolicy"] = payload.match_policy
|
|
if payload.source_bad_case_id is not None:
|
|
metadata["sourceBadCaseId"] = payload.source_bad_case_id
|
|
remote_payload = KnowledgeFSGoldenQuestionUpdateRemotePayload(
|
|
expected_evidence_ids=(
|
|
payload.expected_evidence_ids if "expected_evidence_ids" in payload.model_fields_set else None
|
|
),
|
|
metadata=metadata,
|
|
question=payload.question,
|
|
tags=payload.tags,
|
|
)
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateGoldenQuestion",
|
|
resource_id=question_id,
|
|
path_parameters=(("questionId", question_id),),
|
|
payload=remote_payload,
|
|
)
|
|
return KnowledgeFSGoldenQuestionResponse.model_validate(raw)
|
|
|
|
def match_golden_question_evidence(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSGoldenQuestionEvidenceMatchPayload,
|
|
) -> KnowledgeFSGoldenQuestionEvidenceMatchResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="matchGoldenQuestionEvidence",
|
|
payload=KnowledgeFSGoldenQuestionEvidenceMatchRemotePayload(
|
|
evidence_texts=[payload.evidence] if payload.evidence else None,
|
|
minimum_similarity=payload.minimum_similarity,
|
|
node_ids=payload.node_ids or None,
|
|
top_k=payload.top_k,
|
|
),
|
|
)
|
|
if not isinstance(raw, dict):
|
|
raise KnowledgeFSProductRemoteError("KnowledgeFS returned an invalid evidence match response")
|
|
if payload.node_ids:
|
|
return KnowledgeFSGoldenQuestionEvidenceMatchResponse.model_validate(
|
|
{
|
|
"candidates": raw.get("resolvedEvidence", []),
|
|
"evidence": "",
|
|
"matched": False,
|
|
}
|
|
)
|
|
items = raw.get("items")
|
|
if not isinstance(items, list) or len(items) != 1 or not isinstance(items[0], dict):
|
|
raise KnowledgeFSProductRemoteError("KnowledgeFS returned an invalid evidence match response")
|
|
item = items[0]
|
|
return KnowledgeFSGoldenQuestionEvidenceMatchResponse.model_validate(
|
|
{
|
|
"candidates": item.get("candidates", []),
|
|
"evidence": item.get("evidenceText", payload.evidence or ""),
|
|
"matched": item.get("matched", False),
|
|
}
|
|
)
|
|
|
|
def bulk_import_golden_questions(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSGoldenQuestionBulkImportPayload,
|
|
) -> KnowledgeFSGoldenQuestionBulkImportResponse:
|
|
remote_payload = KnowledgeFSGoldenQuestionBulkImportRemotePayload(
|
|
match_policy=payload.match_policy,
|
|
minimum_similarity=payload.minimum_similarity,
|
|
rows=[
|
|
KnowledgeFSGoldenQuestionBulkImportRemoteRowPayload(
|
|
evidence=row.evidence,
|
|
metadata={"evidenceText": row.evidence, "importSource": "csv"},
|
|
question=row.question,
|
|
tags=row.tags,
|
|
)
|
|
for row in payload.rows
|
|
],
|
|
)
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="bulkImportGoldenQuestions",
|
|
payload=remote_payload,
|
|
)
|
|
return KnowledgeFSGoldenQuestionBulkImportResponse.model_validate(raw)
|
|
|
|
def delete_golden_question(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
question_id: str,
|
|
) -> None:
|
|
self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="deleteGoldenQuestion",
|
|
resource_id=question_id,
|
|
path_parameters=(("questionId", question_id),),
|
|
)
|
|
|
|
def list_bad_cases(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 50,
|
|
) -> KnowledgeFSBadCaseListResponse:
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listQualityBadCases",
|
|
query=query,
|
|
)
|
|
return KnowledgeFSBadCaseListResponse.model_validate(raw)
|
|
|
|
def create_bad_case(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSBadCaseCreatePayload,
|
|
) -> KnowledgeFSBadCaseResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createQualityBadCase",
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSBadCaseResponse.model_validate(raw)
|
|
|
|
def get_bad_case(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
bad_case_id: str,
|
|
) -> KnowledgeFSBadCaseResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getQualityBadCase",
|
|
resource_id=bad_case_id,
|
|
path_parameters=(("badCaseId", bad_case_id),),
|
|
)
|
|
return KnowledgeFSBadCaseResponse.model_validate(raw)
|
|
|
|
def update_bad_case(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
bad_case_id: str,
|
|
payload: KnowledgeFSBadCaseUpdatePayload,
|
|
) -> KnowledgeFSBadCaseResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="updateQualityBadCase",
|
|
resource_id=bad_case_id,
|
|
path_parameters=(("badCaseId", bad_case_id),),
|
|
payload=payload,
|
|
)
|
|
return KnowledgeFSBadCaseResponse.model_validate(raw)
|
|
|
|
def get_bad_case_trace_reference(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
bad_case_id: str,
|
|
) -> KnowledgeFSBadCaseTraceReferenceResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getQualityBadCaseTraceReference",
|
|
resource_id=bad_case_id,
|
|
path_parameters=(("badCaseId", bad_case_id),),
|
|
)
|
|
return KnowledgeFSBadCaseTraceReferenceResponse.model_validate(raw)
|
|
|
|
def create_quality_replay(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
payload: KnowledgeFSQualityReplayPayload,
|
|
idempotency_key: str,
|
|
) -> KnowledgeFSQualityReplayResponse:
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="createQualityReplay",
|
|
payload=payload,
|
|
headers=(("Idempotency-Key", idempotency_key),),
|
|
)
|
|
return KnowledgeFSQualityReplayResponse.model_validate(raw)
|
|
|
|
def list_quality_replays(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
cursor: str | None = None,
|
|
limit: int = 20,
|
|
mode: Literal["deep", "fast", "research"] | None = None,
|
|
state: Literal["queued", "running", "passed", "failed", "canceled"] | None = None,
|
|
) -> KnowledgeFSQualityReplayListResponse:
|
|
query: tuple[tuple[str, str], ...] = (("limit", str(limit)),)
|
|
if cursor:
|
|
query += (("cursor", cursor),)
|
|
if mode:
|
|
query += (("mode", mode),)
|
|
if state:
|
|
query += (("state", state),)
|
|
raw = self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="listQualityReplays",
|
|
query=query,
|
|
)
|
|
return KnowledgeFSQualityReplayListResponse.model_validate(raw)
|
|
|
|
def get_quality_replay(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
run_id: str,
|
|
evidence_item_id: str | None = None,
|
|
) -> KnowledgeFSQualityReplayResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getQualityReplay",
|
|
resource_id=run_id,
|
|
path_parameters=(("runId", run_id),),
|
|
query=(("evidenceItemId", evidence_item_id),) if evidence_item_id else (),
|
|
)
|
|
return KnowledgeFSQualityReplayResponse.model_validate(raw)
|
|
|
|
def get_trace(
|
|
self, *, tenant_id: str, account_id: str, control_space_id: str, trace_id: str
|
|
) -> KnowledgeFSAnswerTraceResponse:
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id="getTrace",
|
|
resource_id=trace_id,
|
|
path_parameters=(("traceId", trace_id),),
|
|
)
|
|
trace = KnowledgeFSAnswerTraceResponse.model_validate(raw)
|
|
self._attach_query_image_previews(
|
|
tenant_id=tenant_id, account_id=account_id, images=self._query_images_of(trace)
|
|
)
|
|
return trace
|
|
|
|
def list_trace_entries(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
trace_id: str,
|
|
kind: Literal["conflicts", "evidence", "missing"],
|
|
cursor: str | None = None,
|
|
limit: int = 100,
|
|
) -> KnowledgeFSTraceEntryListResponse:
|
|
operation_id = {
|
|
"conflicts": "listTraceConflicts",
|
|
"evidence": "listTraceEvidence",
|
|
"missing": "listTraceMissing",
|
|
}[kind]
|
|
query = (("limit", str(limit)),) + ((("cursor", cursor),) if cursor else ())
|
|
raw = self._interactive_child(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
resource_id=trace_id,
|
|
path_parameters=(("traceId", trace_id),),
|
|
query=query,
|
|
)
|
|
return KnowledgeFSTraceEntryListResponse.model_validate(raw)
|
|
|
|
def execute_service(
|
|
self,
|
|
*,
|
|
profile: KnowledgeFSServiceApiProfile,
|
|
operation_id: str,
|
|
payload: BaseModel | None = None,
|
|
query: tuple[tuple[str, str], ...] = (),
|
|
bind_space_in_body: bool = False,
|
|
resource_id: str | None = None,
|
|
path_parameters: tuple[tuple[str, str], ...] = (),
|
|
headers: tuple[tuple[str, str], ...] = (),
|
|
) -> JsonValue:
|
|
_assert_json_bff_ready(operation_id)
|
|
issued = self._broker.issue_service(profile=profile, operation_id=operation_id, resource_id=resource_id)
|
|
return self._execute(
|
|
operation_id=operation_id,
|
|
namespace_id=profile.tenant_id,
|
|
knowledge_space_id=profile.knowledge_space_id,
|
|
knowledge_space_revision=profile.knowledge_space_revision,
|
|
capability_token=issued.token,
|
|
trace_id=issued.trace_id,
|
|
payload=payload,
|
|
query=query,
|
|
bind_space_in_body=bind_space_in_body,
|
|
resource_id=resource_id,
|
|
path_parameters=path_parameters,
|
|
headers=headers,
|
|
)
|
|
|
|
def _interactive(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
operation_id: str,
|
|
payload: BaseModel | None = None,
|
|
query: tuple[tuple[str, str], ...] = (),
|
|
bind_space_in_body: bool = False,
|
|
resource_id: str | None = None,
|
|
path_parameters: tuple[tuple[str, str], ...] = (),
|
|
headers: tuple[tuple[str, str], ...] = (),
|
|
) -> JsonValue:
|
|
_assert_json_bff_ready(operation_id)
|
|
issued = self._broker.issue_interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
resource_id=resource_id,
|
|
)
|
|
return self._execute(
|
|
operation_id=operation_id,
|
|
namespace_id=tenant_id,
|
|
knowledge_space_id=issued.knowledge_space_id,
|
|
knowledge_space_revision=issued.knowledge_space_revision,
|
|
capability_token=issued.token,
|
|
trace_id=issued.trace_id,
|
|
payload=payload,
|
|
query=query,
|
|
bind_space_in_body=bind_space_in_body,
|
|
resource_id=resource_id,
|
|
path_parameters=path_parameters,
|
|
headers=headers,
|
|
)
|
|
|
|
def _namespace_interactive(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
operation_id: str,
|
|
payload: BaseModel | None = None,
|
|
path_parameters: tuple[tuple[str, str], ...] = (),
|
|
) -> JsonValue:
|
|
_assert_json_bff_ready(operation_id)
|
|
issued = self._broker.issue_namespace_interactive(
|
|
tenant_id=tenant_id, account_id=account_id, operation_id=operation_id
|
|
)
|
|
return self._execute(
|
|
operation_id=operation_id,
|
|
namespace_id=tenant_id,
|
|
knowledge_space_id=tenant_id,
|
|
knowledge_space_revision=0,
|
|
capability_token=issued.token,
|
|
trace_id=issued.trace_id,
|
|
payload=payload,
|
|
query=(),
|
|
bind_space_in_body=False,
|
|
resource_id=None,
|
|
path_parameters=path_parameters,
|
|
headers=(),
|
|
)
|
|
|
|
def _interactive_child(
|
|
self,
|
|
*,
|
|
tenant_id: str,
|
|
account_id: str,
|
|
control_space_id: str,
|
|
operation_id: str,
|
|
resource_id: str,
|
|
payload: BaseModel | None = None,
|
|
query: tuple[tuple[str, str], ...] = (),
|
|
bind_space_in_body: bool = False,
|
|
path_parameters: tuple[tuple[str, str], ...] = (),
|
|
headers: tuple[tuple[str, str], ...] = (),
|
|
) -> JsonValue:
|
|
return self._interactive(
|
|
tenant_id=tenant_id,
|
|
account_id=account_id,
|
|
control_space_id=control_space_id,
|
|
operation_id=operation_id,
|
|
resource_id=resource_id,
|
|
payload=payload,
|
|
query=query,
|
|
bind_space_in_body=bind_space_in_body,
|
|
path_parameters=path_parameters,
|
|
headers=headers,
|
|
)
|
|
|
|
def _execute(
|
|
self,
|
|
*,
|
|
operation_id: str,
|
|
namespace_id: str,
|
|
knowledge_space_id: str,
|
|
knowledge_space_revision: int,
|
|
capability_token: str,
|
|
trace_id: str,
|
|
payload: BaseModel | None,
|
|
query: tuple[tuple[str, str], ...],
|
|
bind_space_in_body: bool,
|
|
resource_id: str | None,
|
|
path_parameters: tuple[tuple[str, str], ...],
|
|
headers: tuple[tuple[str, str], ...],
|
|
) -> JsonValue:
|
|
operation = KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id]
|
|
if operation.kfs_path is None:
|
|
raise KnowledgeFSOperationUnavailableError(f"KnowledgeFS operation is unavailable: {operation_id}")
|
|
path = _resolve_product_path(
|
|
template=operation.kfs_path,
|
|
knowledge_space_id=knowledge_space_id,
|
|
resource_id=resource_id,
|
|
resource_resolver=operation.resource_resolver,
|
|
path_parameters=path_parameters,
|
|
)
|
|
remote_payload: JsonValue | None = (
|
|
payload.model_dump(mode="json", exclude_none=True, by_alias=True) if payload is not None else None
|
|
)
|
|
if operation_id == "updateSpace":
|
|
if knowledge_space_revision <= 0 or not isinstance(payload, KnowledgeFSSpaceUpdatePayload):
|
|
raise KnowledgeFSOperationUnavailableError("KnowledgeFS metadata revision is not available")
|
|
remote_payload = {"expectedRevision": knowledge_space_revision}
|
|
if payload.name is not None:
|
|
remote_payload["name"] = payload.name
|
|
if payload.icon is not None:
|
|
remote_payload["iconRef"] = payload.icon
|
|
if payload.description is not None:
|
|
remote_payload["description"] = payload.description
|
|
if bind_space_in_body:
|
|
if not isinstance(remote_payload, dict):
|
|
raise KnowledgeFSOperationUnavailableError("KnowledgeFS request body binding is unavailable")
|
|
remote_payload["knowledgeSpaceId"] = knowledge_space_id
|
|
if operation.resource_resolver in {"job", "query", "research_task"} and not path.startswith(
|
|
"/knowledge-spaces/"
|
|
):
|
|
query = (*query, ("knowledgeSpaceId", knowledge_space_id))
|
|
return self._remote.execute_json(
|
|
KnowledgeFSRemoteJSONRequest(
|
|
operation_id=operation_id,
|
|
method=operation.method,
|
|
path=path,
|
|
namespace_id=namespace_id,
|
|
knowledge_space_id=knowledge_space_id,
|
|
capability_token=capability_token,
|
|
trace_id=trace_id,
|
|
payload=remote_payload,
|
|
query=query,
|
|
headers=headers,
|
|
)
|
|
)
|
|
|
|
|
|
def _resolve_product_path(
|
|
*,
|
|
template: str,
|
|
knowledge_space_id: str,
|
|
resource_id: str | None,
|
|
resource_resolver: str,
|
|
path_parameters: tuple[tuple[str, str], ...],
|
|
) -> str:
|
|
bindings = {name: _path_segment(value) for name, value in path_parameters}
|
|
if template.startswith("/knowledge-spaces/{id}") or resource_resolver in {"knowledge_space", "namespace"}:
|
|
bindings["id"] = _path_segment(knowledge_space_id)
|
|
elif "{id}" in template:
|
|
if resource_id is None:
|
|
raise KnowledgeFSOperationUnavailableError("KnowledgeFS child resource is required")
|
|
bindings["id"] = _path_segment(resource_id)
|
|
path = template
|
|
for name, value in bindings.items():
|
|
path = path.replace(f"{{{name}}}", value)
|
|
if "{" in path or "}" in path:
|
|
raise KnowledgeFSOperationUnavailableError("KnowledgeFS product path resolver is not registered")
|
|
return path
|
|
|
|
|
|
def _path_segment(value: str) -> str:
|
|
normalized = value.strip()
|
|
if (
|
|
not normalized
|
|
or len(normalized) > 1_000
|
|
or normalized in {".", ".."}
|
|
or any(character in normalized for character in ("/", "%", "?", "#", "\\"))
|
|
):
|
|
raise KnowledgeFSOperationUnavailableError("KnowledgeFS product path parameter is invalid")
|
|
return normalized
|
|
|
|
|
|
def _knowledge_fs_query(*items: tuple[str, object | None]) -> tuple[tuple[str, str], ...]:
|
|
def serialize(value: object) -> str:
|
|
if isinstance(value, bool):
|
|
return "true" if value else "false"
|
|
return str(value)
|
|
|
|
return tuple((name, serialize(value)) for name, value in items if value is not None)
|
|
|
|
|
|
def _assert_ready(operation_id: str) -> None:
|
|
if not is_product_operation_ready(operation_id):
|
|
raise KnowledgeFSOperationUnavailableError(f"KnowledgeFS operation is unavailable: {operation_id}")
|
|
|
|
|
|
def _assert_json_bff_ready(operation_id: str) -> None:
|
|
_assert_ready(operation_id)
|
|
if KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id].transport != "json":
|
|
raise KnowledgeFSOperationUnavailableError(
|
|
f"KnowledgeFS operation does not allow the buffered JSON BFF: {operation_id}"
|
|
)
|
|
|
|
|
|
def _assert_binary_bff_ready(operation_id: str) -> None:
|
|
_assert_ready(operation_id)
|
|
if KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id].transport != "binary":
|
|
raise KnowledgeFSOperationUnavailableError(
|
|
f"KnowledgeFS operation does not allow the bounded binary BFF: {operation_id}"
|
|
)
|
|
|
|
|
|
def _assert_multipart_bff_ready(operation_id: str) -> None:
|
|
_assert_ready(operation_id)
|
|
if KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id].transport != "multipart":
|
|
raise KnowledgeFSOperationUnavailableError(
|
|
f"KnowledgeFS operation does not allow the bounded multipart BFF: {operation_id}"
|
|
)
|
|
|
|
|
|
def _assert_sse_bff_ready(operation_id: str) -> None:
|
|
_assert_ready(operation_id)
|
|
if KNOWLEDGE_FS_PRODUCT_OPERATIONS[operation_id].transport != "sse":
|
|
raise KnowledgeFSOperationUnavailableError(
|
|
f"KnowledgeFS operation does not allow the streaming BFF: {operation_id}"
|
|
)
|
|
|
|
|
|
__all__ = ["KnowledgeFSDataFacade"]
|
|
|
|
|
|
def _trace_list_query(*, cursor: str | None, source: str | None) -> tuple[tuple[str, str], ...]:
|
|
query: list[tuple[str, str]] = []
|
|
if cursor:
|
|
query.append(("cursor", cursor))
|
|
if source:
|
|
query.append(("source", source))
|
|
return tuple(query)
|