forked from bai/curriculum-project-hub
8df8156969
Introduces the External Capability abstraction: platform-registered, org-enabled document/media transform services invoked as side effects of an AgentRun. The first concrete capability is pdf_to_md_bundle backed by MinerU. This lands the contract, schema, adapter interface, and a fully mock-tested adapter; the real MinerU HTTP client is deferred until credentials and pricing are confirmed. Contract: - spec/Spec/System/Agent/Capability.lean pins ExternalCapability, OrganizationCapabilityConnection (reuses ADR-0024 envelope, distinct from model-provider connection), and CapabilityInvocation.Authorized (workspace containment predicate, ADR-0018). lake build green (41 jobs). - ADR-0027 records why capability credentials are a separate connection type (MinerU/Whisper have their own auth shape, not OpenRouter /v1/models), the adapter seam, and what is deferred (capability invocation record, pricebook, agent-facing tool discovery). Schema: - OrganizationCapabilityConnection + CapabilityCredentialVersion, mirroring the Feishu Application Connection shape. Unique by (organizationId, capabilityId). Migration 20260718130000 applied. Adapter (hub/src/capability): - types.ts: CapabilityId, CapabilityAdapter interface, secret payload, CapabilityConnectionUnavailable. - mineruClient.ts: MineruClient interface + MineruParseResult + errors. Real HTTP client deferred; the interface is the seam. - capabilityConnections.ts: resolveCapabilityCredential — org-scoped, fail-closed, reuses LocalSecretEnvelope with purpose="capability". - pdfToMdBundle.ts: adapter that resolves credential, confines input/output to the run workspace (ADR-0018), calls MineruClient, writes md + images into workspace, and writes a UsageFact (kind=external_capability, quantity=pages, costSource=provider_reported|unknown per ADR-0022). Tests (7, all green): - md + images written to workspace, UsageFact attributes pages + cost - costUsd null -> costSource=unknown (missing cost != zero, ADR-0022) - no ACTIVE connection -> fail-closed, no fact written - input/output path escape -> CapabilityPathEscape - MinerU client error propagates, no fact written - empty markdown -> parse failure Deferred (needs operator): MinerU account/API key/pricing, real MineruClient HTTP implementation, org admin UI for capability connection management, agent-facing tool exposure (MCP vs built-in).
70 lines
3.5 KiB
SQL
70 lines
3.5 KiB
SQL
-- ADR-0027: org-scoped capability connections for external document/media
|
|
-- transforms (PDF→MD, audio/video→text, …). Mirrors the Feishu Application
|
|
-- Connection shape: reuses the ADR-0024 envelope machinery with its own
|
|
-- payload schema and readiness probe, distinct from the model-provider
|
|
-- connection.
|
|
|
|
CREATE TABLE "OrganizationCapabilityConnection" (
|
|
"id" TEXT NOT NULL,
|
|
"organizationId" TEXT NOT NULL,
|
|
"capabilityId" TEXT NOT NULL,
|
|
"status" "OrganizationConnectionStatus" NOT NULL DEFAULT 'DRAFT',
|
|
"activeSecretVersionId" TEXT,
|
|
"activatedAt" TIMESTAMP(3),
|
|
"disabledAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "OrganizationCapabilityConnection_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE UNIQUE INDEX "OrganizationCapabilityConnection_organizationId_capabilityId_key"
|
|
ON "OrganizationCapabilityConnection"("organizationId", "capabilityId");
|
|
CREATE UNIQUE INDEX "OrganizationCapabilityConnection_activeSecretVersionId_key"
|
|
ON "OrganizationCapabilityConnection"("activeSecretVersionId");
|
|
CREATE INDEX "OrganizationCapabilityConnection_organizationId_status_idx"
|
|
ON "OrganizationCapabilityConnection"("organizationId", "status");
|
|
CREATE INDEX "OrganizationCapabilityConnection_capabilityId_status_idx"
|
|
ON "OrganizationCapabilityConnection"("capabilityId", "status");
|
|
|
|
CREATE TABLE "CapabilityCredentialVersion" (
|
|
"id" TEXT NOT NULL,
|
|
"connectionId" TEXT NOT NULL,
|
|
"version" INTEGER NOT NULL,
|
|
"envelopeVersion" INTEGER NOT NULL DEFAULT 1,
|
|
"keyId" TEXT NOT NULL,
|
|
"envelope" JSONB NOT NULL,
|
|
"createdByUserId" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"retiredAt" TIMESTAMP(3),
|
|
CONSTRAINT "CapabilityCredentialVersion_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE UNIQUE INDEX "CapabilityCredentialVersion_connectionId_version_key"
|
|
ON "CapabilityCredentialVersion"("connectionId", "version");
|
|
CREATE INDEX "CapabilityCredentialVersion_connectionId_retiredAt_idx"
|
|
ON "CapabilityCredentialVersion"("connectionId", "retiredAt");
|
|
CREATE INDEX "CapabilityCredentialVersion_keyId_idx"
|
|
ON "CapabilityCredentialVersion"("keyId");
|
|
CREATE INDEX "CapabilityCredentialVersion_createdByUserId_idx"
|
|
ON "CapabilityCredentialVersion"("createdByUserId");
|
|
|
|
ALTER TABLE "OrganizationCapabilityConnection"
|
|
ADD CONSTRAINT "OrganizationCapabilityConnection_organizationId_fkey"
|
|
FOREIGN KEY ("organizationId") REFERENCES "Organization"("id")
|
|
ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
ALTER TABLE "OrganizationCapabilityConnection"
|
|
ADD CONSTRAINT "OrganizationCapabilityConnection_activeSecretVersionId_fkey"
|
|
FOREIGN KEY ("activeSecretVersionId") REFERENCES "CapabilityCredentialVersion"("id")
|
|
ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
|
|
ALTER TABLE "CapabilityCredentialVersion"
|
|
ADD CONSTRAINT "CapabilityCredentialVersion_connectionId_fkey"
|
|
FOREIGN KEY ("connectionId") REFERENCES "OrganizationCapabilityConnection"("id")
|
|
ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
ALTER TABLE "CapabilityCredentialVersion"
|
|
ADD CONSTRAINT "CapabilityCredentialVersion_createdByUserId_fkey"
|
|
FOREIGN KEY ("createdByUserId") REFERENCES "User"("id")
|
|
ON DELETE SET NULL ON UPDATE CASCADE;
|