@zhin.js/agent 1.1.39 → 1.1.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/lib/assistant/job-storage.d.ts +238 -0
  2. package/lib/assistant/job-storage.js +143 -0
  3. package/lib/assistant/job-storage.js.map +1 -0
  4. package/lib/assistant/job-store.d.ts +7 -0
  5. package/lib/assistant/job-store.js +41 -3
  6. package/lib/assistant/job-store.js.map +1 -1
  7. package/lib/config/perception-config.d.ts +9 -0
  8. package/lib/config/perception-config.js +27 -0
  9. package/lib/config/perception-config.js.map +1 -1
  10. package/lib/context/context-system.d.ts +1 -0
  11. package/lib/context/context-system.js +8 -8
  12. package/lib/context/context-system.js.map +1 -1
  13. package/lib/context/im-turn-context-adapter.js +2 -0
  14. package/lib/context/im-turn-context-adapter.js.map +1 -1
  15. package/lib/context/skill-context.d.ts +3 -0
  16. package/lib/context/skill-context.js +6 -0
  17. package/lib/context/skill-context.js.map +1 -0
  18. package/lib/context/turn-envelope.d.ts +4 -0
  19. package/lib/context/turn-envelope.js +24 -7
  20. package/lib/context/turn-envelope.js.map +1 -1
  21. package/lib/context/turn-user-message.d.ts +3 -1
  22. package/lib/context/turn-user-message.js +14 -1
  23. package/lib/context/turn-user-message.js.map +1 -1
  24. package/lib/core/agent-core-run.d.ts +1 -0
  25. package/lib/core/agent-core-run.js +47 -20
  26. package/lib/core/agent-core-run.js.map +1 -1
  27. package/lib/core/structured-reply-recovery.d.ts +6 -2
  28. package/lib/core/structured-reply-recovery.js +22 -8
  29. package/lib/core/structured-reply-recovery.js.map +1 -1
  30. package/lib/core/turn-completion-usage.d.ts +2 -1
  31. package/lib/core/turn-completion-usage.js +14 -5
  32. package/lib/core/turn-completion-usage.js.map +1 -1
  33. package/lib/core/turn-event-mapper.d.ts +1 -1
  34. package/lib/core/turn-event-mapper.js +8 -5
  35. package/lib/core/turn-event-mapper.js.map +1 -1
  36. package/lib/event/turn-event.d.ts +7 -1
  37. package/lib/event/turn-event.js.map +1 -1
  38. package/lib/index.d.ts +4 -1
  39. package/lib/index.js +2 -0
  40. package/lib/index.js.map +1 -1
  41. package/lib/media/perception.d.ts +3 -4
  42. package/lib/media/perception.js +59 -37
  43. package/lib/media/perception.js.map +1 -1
  44. package/lib/memory/compaction-runtime.d.ts +3 -2
  45. package/lib/memory/compaction-runtime.js +22 -14
  46. package/lib/memory/compaction-runtime.js.map +1 -1
  47. package/lib/outbound/agent-output.js +2 -0
  48. package/lib/outbound/agent-output.js.map +1 -1
  49. package/lib/outbound/chat-failure.d.ts +27 -0
  50. package/lib/outbound/chat-failure.js +53 -0
  51. package/lib/outbound/chat-failure.js.map +1 -0
  52. package/lib/outbound/structured-reply.d.ts +7 -0
  53. package/lib/outbound/structured-reply.js +52 -16
  54. package/lib/outbound/structured-reply.js.map +1 -1
  55. package/lib/plugin-runtime/agent-runtime.js +49 -8
  56. package/lib/plugin-runtime/agent-runtime.js.map +1 -1
  57. package/lib/plugin-runtime/ai-completion.d.ts +4 -3
  58. package/lib/plugin-runtime/ai-completion.js +64 -10
  59. package/lib/plugin-runtime/ai-completion.js.map +1 -1
  60. package/lib/plugin-runtime/capability-ingress.js +3 -1
  61. package/lib/plugin-runtime/capability-ingress.js.map +1 -1
  62. package/lib/plugin-runtime/deferred-capability-plan.d.ts +4 -1
  63. package/lib/plugin-runtime/deferred-capability-plan.js +25 -9
  64. package/lib/plugin-runtime/deferred-capability-plan.js.map +1 -1
  65. package/lib/plugin-runtime/full-agent-turn-engine.js +1 -0
  66. package/lib/plugin-runtime/full-agent-turn-engine.js.map +1 -1
  67. package/lib/plugin-runtime/index.d.ts +2 -0
  68. package/lib/plugin-runtime/index.js +2 -0
  69. package/lib/plugin-runtime/index.js.map +1 -1
  70. package/lib/prompt/assembly.js +0 -9
  71. package/lib/prompt/assembly.js.map +1 -1
  72. package/lib/prompt/git-context.js +1 -1
  73. package/lib/prompt/git-context.js.map +1 -1
  74. package/lib/prompt/rules/chat-rules.js +8 -9
  75. package/lib/prompt/rules/chat-rules.js.map +1 -1
  76. package/lib/prompt/rules/critical-rules.js +10 -10
  77. package/lib/prompt/rules/critical-rules.js.map +1 -1
  78. package/lib/prompt/system-prompt.js +4 -5
  79. package/lib/prompt/system-prompt.js.map +1 -1
  80. package/lib/security/file-role-policy.js +6 -6
  81. package/lib/security/file-role-policy.js.map +1 -1
  82. package/lib/security/policy-facade.js +1 -1
  83. package/lib/security/policy-facade.js.map +1 -1
  84. package/lib/security/usage-quota.d.ts +4 -0
  85. package/lib/security/usage-quota.js +23 -2
  86. package/lib/security/usage-quota.js.map +1 -1
  87. package/lib/session/approval-port.d.ts +2 -0
  88. package/lib/session/approval-port.js.map +1 -1
  89. package/lib/session/approval-review-agent.d.ts +1 -1
  90. package/lib/session/approval-review-agent.js +19 -4
  91. package/lib/session/approval-review-agent.js.map +1 -1
  92. package/lib/session/turn-ingress-session.js +7 -1
  93. package/lib/session/turn-ingress-session.js.map +1 -1
  94. package/lib/tool/tool-approval-gate.js +4 -2
  95. package/lib/tool/tool-approval-gate.js.map +1 -1
  96. package/lib/tool/turn-tool-runtime.js +24 -5
  97. package/lib/tool/turn-tool-runtime.js.map +1 -1
  98. package/lib/tool-catalog/deferred-turn-controller.js +1 -4
  99. package/lib/tool-catalog/deferred-turn-controller.js.map +1 -1
  100. package/lib/trace/context-budget.d.ts +4 -3
  101. package/lib/trace/context-budget.js +28 -8
  102. package/lib/trace/context-budget.js.map +1 -1
  103. package/lib/trace/turn-trace-format.js +4 -1
  104. package/lib/trace/turn-trace-format.js.map +1 -1
  105. package/lib/trace/turn-trace.d.ts +6 -0
  106. package/lib/trace/turn-trace.js +8 -2
  107. package/lib/trace/turn-trace.js.map +1 -1
  108. package/lib/trace/turn-usage-log.d.ts +14 -0
  109. package/lib/trace/turn-usage-log.js +83 -0
  110. package/lib/trace/turn-usage-log.js.map +1 -0
  111. package/lib/usage/usage-store.d.ts +199 -0
  112. package/lib/usage/usage-store.js +121 -0
  113. package/lib/usage/usage-store.js.map +1 -0
  114. package/package.json +12 -12
@@ -1 +1 @@
1
- {"version":3,"file":"agent-runtime.js","sourceRoot":"","sources":["../../src/plugin-runtime/agent-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { createToken, type PluginId, type SnapshotLease, type SnapshotReader } from '@zhin.js/plugin-runtime';\nimport { applyTurnTrust } from '../security/trust-level.js';\nimport type { JournalStore } from '@zhin.js/ai/journal-store';\nimport { PersistentTurnJournal } from '../journal/persistent-turn-journal.js';\nimport { TurnTraceCollector } from '../trace/turn-trace.js';\nimport { createTracingJournal, registerTurnTrace } from '../trace/turn-trace-registry.js';\nimport { createJournalFeed } from '../turn/journal-feed.js';\nimport type { TurnTraceStore } from '../trace/turn-trace-store.js';\nimport { executeAgentTurn, type TurnEventObserver } from '../turn/execute-agent-turn.js';\nimport {\n createTurnIngress,\n type TurnOutcome,\n type TurnRequest,\n} from '../turn/turn-ingress.js';\nimport {\n CapabilityIngress,\n type AgentCapabilities,\n type ToolCapability,\n} from './capability-ingress.js';\nimport { TurnToolRuntime, type TurnToolOutcome } from '../tool/turn-tool-runtime.js';\nimport { requireToolInputSchema, type ToolDescriptor } from '@zhin.js/tool';\nimport type { ResolvedAgentBinding } from '../config/types.js';\nimport { runWithAgentTurnConfiguration } from '../turn/agent-turn-context.js';\nimport { TurnSupersededError } from '../turn/prompt-controller.js';\nimport { createConversationReferenceCapability } from '../tool/conversation-reference-tool.js';\nimport { drainAgentTurnDecisionObservations, runWithAgentDecisionTurn } from './decision-runtime.js';\nimport type { AgentDecisionRuntime } from '../decision/types.js';\n\nabstract class SnapshotAttachedRuntime {\n protected snapshots?: SnapshotReader;\n\n attach(snapshots: SnapshotReader): void {\n if (this.snapshots && this.snapshots !== snapshots) {\n throw new Error(`${this.constructor.name} is already attached to another Root`);\n }\n this.snapshots = snapshots;\n }\n\n protected requireSnapshots(): SnapshotReader {\n if (!this.snapshots) throw new Error(`${this.constructor.name} is not attached to a Root`);\n return this.snapshots;\n }\n}\n\nexport const turnJournalStoreToken = createToken<JournalStore>(\n 'zhin.agent.turn-journal-store',\n 'Durable Agent turn event journal store',\n);\n\nexport interface ExternalToolCapability extends ToolDescriptor {\n execute(input: Readonly<Record<string, unknown>>, toolUseId: string): Promise<TurnToolOutcome>;\n}\n\n/** Canonical fixed-generation execution authority for external tool protocols. */\nexport class ToolIngressRuntime extends SnapshotAttachedRuntime {\n readonly #ingress = new CapabilityIngress();\n\n async withTools<TResult>(\n owner: PluginId,\n request: TurnRequest,\n operation: (tools: readonly ExternalToolCapability[]) => TResult | Promise<TResult>,\n ): Promise<TResult> {\n const lease = this.requireSnapshots().acquire();\n let active = true;\n try {\n const capabilities = await this.#ingress.read(lease.value, owner, () => active, request);\n let invocationSequence = 0;\n const tools = Object.freeze(capabilities.tools\n .filter((tool) => !tool.hidden)\n .map(({ execute: _execute, ...descriptor }) => Object.freeze({\n ...descriptor,\n execute: async (input: Readonly<Record<string, unknown>>, toolUseId: string) => {\n if (!active) throw new Error('External Tool capability scope has ended');\n invocationSequence += 1;\n const invocationRequest: TurnRequest = {\n ...request,\n identity: {\n traceId: request.identity.traceId,\n turnId: `${request.identity.turnId}:${invocationSequence}`,\n },\n };\n const turn = createIngressTurn(lease.value, invocationRequest, capabilities);\n const runtime = new TurnToolRuntime(turn, capabilities.tools);\n const outcome = await runtime.execute(descriptor.name, input, toolUseId);\n await appendExternalToolTerminal(turn, outcome);\n return outcome;\n },\n })));\n return await operation(tools);\n } finally {\n active = false;\n lease.release();\n }\n }\n}\n\nasync function appendExternalToolTerminal(\n turn: import('../turn/turn-ingress.js').TurnIngress,\n outcome: TurnToolOutcome,\n): Promise<void> {\n if (outcome.status === 'completed') {\n await turn.ports.journal.append({\n type: 'turn_end',\n output: [],\n usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },\n });\n return;\n }\n if (outcome.status === 'cancelled') {\n await turn.ports.journal.append({\n type: 'turn_cancelled',\n code: 'cancelled',\n reason: outcome.reason,\n });\n return;\n }\n const message = outcome.status === 'failed' ? outcome.error : outcome.reason;\n await turn.ports.journal.append({\n type: 'error',\n error: new Error(message),\n recoverable: false,\n });\n}\n\n/** Single Agent execution authority: snapshot + capabilities + terminal algebra. */\nexport interface AgentTurnExecutionContext {\n readonly decision?: AgentDecisionRuntime;\n readonly turn: import('../turn/turn-ingress.js').TurnIngress;\n readonly capabilities: Omit<AgentCapabilities, 'tools'> & {\n readonly tools: readonly ToolDescriptor[];\n };\n readonly tools: TurnToolRuntime;\n /** Executable descriptors bound to the same active generation lease. */\n readonly toolCapabilities: readonly ToolCapability[];\n readonly selection: AgentCapabilitySelection;\n /** Signals that this ingress has reached the ordered PromptController boundary. */\n readonly admit?: () => void;\n}\n\n/** Root-owned serialization authority shared by every Agent generation. */\nexport class AgentTurnCoordinator {\n readonly #tails = new Map<string, Promise<void>>();\n readonly #admissions = new Map<string, Promise<void>>();\n readonly #active = new Map<string, AbortController>();\n\n async run<TResult>(\n sessionKey: string,\n signal: AbortSignal,\n operation: () => Promise<TResult>,\n ): Promise<TResult> {\n const previous = this.#tails.get(sessionKey) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => { release = resolve; });\n const tail = previous.catch(() => undefined).then(() => current);\n this.#tails.set(sessionKey, tail);\n try {\n await waitForTurn(previous.catch(() => undefined), signal);\n return await operation();\n } finally {\n release();\n if (this.#tails.get(sessionKey) === tail) this.#tails.delete(sessionKey);\n }\n }\n\n async runIntent<TResult>(\n sessionKey: string,\n signal: AbortSignal,\n intent: import('../turn/turn-ingress.js').TurnIntent,\n _principal: import('../turn/turn-ingress.js').TurnPrincipal,\n operation: (admit: () => void, signal: AbortSignal) => Promise<TResult>,\n ): Promise<TResult> {\n const previous = this.#tails.get(sessionKey) ?? Promise.resolve();\n const previousAdmission = this.#admissions.get(sessionKey);\n let admit!: () => void;\n let complete!: () => void;\n const admitted = new Promise<void>((resolve) => { admit = once(resolve); });\n const completed = new Promise<void>((resolve) => { complete = once(resolve); });\n const cumulative = Promise.all([previous.catch(() => undefined), completed]).then(() => undefined);\n const controller = new AbortController();\n const abortFromCaller = () => controller.abort(signal.reason);\n if (signal.aborted) abortFromCaller();\n else signal.addEventListener('abort', abortFromCaller, { once: true });\n this.#tails.set(sessionKey, cumulative);\n void cumulative.finally(() => {\n if (this.#tails.get(sessionKey) === cumulative) this.#tails.delete(sessionKey);\n });\n this.#admissions.set(sessionKey, admitted);\n try {\n if (intent.kind === 'new') {\n await waitForTurn(previous.catch(() => undefined), signal);\n this.#active.set(sessionKey, controller);\n } else if (intent.kind === 'supersede') {\n await waitForAdmission(previousAdmission, signal);\n this.#active.get(sessionKey)?.abort(new TurnSupersededError(sessionKey));\n await waitForTurn(previous.catch(() => undefined), signal);\n this.#active.set(sessionKey, controller);\n } else {\n await waitForAdmission(previousAdmission, signal);\n }\n return await operation(admit, controller.signal);\n } finally {\n signal.removeEventListener('abort', abortFromCaller);\n admit();\n complete();\n if (this.#active.get(sessionKey) === controller) this.#active.delete(sessionKey);\n if (this.#admissions.get(sessionKey) === admitted) this.#admissions.delete(sessionKey);\n }\n }\n}\n\nexport type AgentTurnExecutor = (\n context: AgentTurnExecutionContext,\n) => AsyncGenerator<\n import('../event/turn-event.js').TurnEvent,\n import('../turn/execute-agent-turn.js').TurnTerminalProjection | void\n>;\n\n/** Generation-owned complete Turn engine resolved from the held snapshot. */\nexport interface AgentTurnEngine {\n run: AgentTurnExecutor;\n}\n\nexport const agentTurnEngineToken = createToken<AgentTurnEngine>(\n 'zhin.agent.turn-engine',\n 'Complete Agent Turn engine owned by one Root generation',\n);\n\nexport interface AgentRuntimeOptions {\n /** Root-owned queue shared by every AgentRuntime generation of that Root. */\n readonly coordinator: AgentTurnCoordinator;\n /** Where finished TurnTraces go (`zhin trace`). Omit to disable tracing. */\n readonly turnTraceStore?: TurnTraceStore;\n}\n\nexport interface AgentCapabilitySelection {\n /** Immutable model/provider binding selected for this turn. */\n readonly binding: ResolvedAgentBinding;\n /** Binding-local MCP names. Empty means no MCP capability is exposed. */\n readonly mcpServers: readonly string[];\n /** Optional owner-visible specialist selected by the ingress router. */\n readonly agent?: string;\n}\n\nexport class AgentRuntime extends SnapshotAttachedRuntime {\n readonly #ingress = new CapabilityIngress();\n\n constructor(private readonly options: AgentRuntimeOptions) {\n super();\n }\n\n async execute(\n owner: PluginId,\n request: TurnRequest,\n selection: AgentCapabilitySelection,\n observe?: TurnEventObserver,\n ): Promise<TurnOutcome> {\n const lease = this.requireSnapshots().acquire();\n try {\n return await this.executeLeased(lease, owner, request, selection, observe);\n } finally {\n lease.release();\n }\n }\n\n /** Executes under the fixed-generation lease owned by the ingress operation. */\n async executeLeased(\n lease: SnapshotLease,\n owner: PluginId,\n request: TurnRequest,\n selection: AgentCapabilitySelection,\n observe?: TurnEventObserver,\n ): Promise<TurnOutcome> {\n const snapshots = this.requireSnapshots();\n if (!snapshots.owns(lease)) throw new Error('AgentRuntime rejected a lease owned by another Root');\n if (!lease.active) throw new Error('AgentRuntime requires an active generation lease');\n if (!request.intent) throw new TypeError('AgentRuntime requires an explicit Turn intent');\n const intent = request.intent;\n return this.options.coordinator.runIntent(\n request.session.key,\n request.signal,\n intent,\n request.principal,\n (admit, signal) => this.#executeLeased(\n lease,\n owner,\n { ...request, signal },\n selection,\n observe,\n admit,\n ),\n );\n }\n\n async #executeLeased(\n lease: SnapshotLease,\n owner: PluginId,\n request: TurnRequest,\n selection: AgentCapabilitySelection,\n observe?: TurnEventObserver,\n admit: () => void = () => undefined,\n ): Promise<TurnOutcome> {\n let active = true;\n let activeTrace: TurnTraceCollector | undefined;\n let releaseTrace: (() => void) | undefined;\n try {\n if (!active) throw new Error('Agent generation operation is not active');\n const discovered = await this.#ingress.read(\n lease.value,\n owner,\n () => active && lease.active,\n request,\n selection.agent,\n );\n const referenceCapability = createConversationReferenceCapability(owner, request);\n // #726: the initiator's trust level caps the turn (group members: no shell, writes or outbound).\n const allTools = [\n ...discovered.tools,\n ...(referenceCapability ? [referenceCapability] : []),\n ...await expandMcpTools(discovered, selection.mcpServers),\n ];\n const trust = applyTurnTrust(request, allTools);\n const capabilities = Object.freeze({\n ...discovered,\n tools: Object.freeze([...trust.tools]),\n });\n const turnRequest = trust.restricted\n ? Object.freeze({ ...request, policy: trust.policy })\n : request;\n const trace = this.options.turnTraceStore\n ? new TurnTraceCollector({\n turnId: request.identity.turnId,\n sessionKey: request.session.key,\n principal: { ...request.principal, trustLevel: trust.level },\n })\n : undefined;\n releaseTrace = trace ? registerTurnTrace(trace) : undefined;\n activeTrace = trace;\n const turn = createIngressTurn(lease.value, turnRequest, capabilities, trace);\n const catalog = Object.freeze({\n ...capabilities,\n tools: Object.freeze(capabilities.tools.map(({ execute: _execute, ...tool }) => Object.freeze(tool))),\n });\n const tools = new TurnToolRuntime(turn, capabilities.tools);\n const engine = resolveTurnEngine(lease.value);\n const disabled = Boolean(request.session.key.startsWith('workroom:') || request.input.metadata?.workroom\n || request.principal.roles.includes('workroom_assignment') || request.execution?.kind === 'schedule');\n return await runWithAgentDecisionTurn(lease.value, request.identity.turnId, decision => runWithAgentTurnConfiguration(\n { activeBinding: selection.binding },\n () => executeAgentTurn(turn, async function* () {\n const stream = engine.run({\n turn,\n capabilities: catalog,\n tools,\n toolCapabilities: capabilities.tools,\n selection,\n decision,\n admit,\n });\n try {\n while (true) {\n const next = await stream.next();\n for (const observation of drainAgentTurnDecisionObservations()) {\n yield { type: 'decision_evaluation', ...observation };\n }\n if (next.done) return next.value;\n yield next.value;\n }\n } catch (error) {\n // A later engine failure must not erase already completed decisions.\n for (const observation of drainAgentTurnDecisionObservations()) {\n yield { type: 'decision_evaluation', ...observation };\n }\n throw error;\n } finally {\n await stream.return(undefined);\n }\n }, observe),\n ), { disabled });\n } finally {\n active = false;\n releaseTrace?.();\n if (activeTrace) this.#saveTrace(activeTrace);\n }\n }\n\n #saveTrace(trace: TurnTraceCollector): void {\n trace.finalize();\n // Fire-and-forget: a slow or failing trace write must not delay the reply.\n void this.options.turnTraceStore?.save(trace.snapshot()).catch(() => undefined);\n }\n}\n\nfunction resolveTurnEngine(snapshot: import('@zhin.js/plugin-runtime').RuntimeSnapshot): AgentTurnEngine {\n const candidate = snapshot.resources.get(snapshot.root)?.get(agentTurnEngineToken.id);\n if (!candidate || typeof (candidate as AgentTurnEngine).run !== 'function') {\n throw new Error('Active generation does not provide an Agent Turn Engine');\n }\n return candidate as AgentTurnEngine;\n}\n\nasync function waitForTurn(previous: Promise<void>, signal: AbortSignal): Promise<void> {\n if (signal.aborted) throw signal.reason ?? new Error('Agent turn cancelled while queued');\n let rejectAbort!: (reason: unknown) => void;\n const aborted = new Promise<never>((_resolve, reject) => { rejectAbort = reject; });\n const onAbort = () => rejectAbort(signal.reason ?? new Error('Agent turn cancelled while queued'));\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n await Promise.race([previous, aborted]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\nasync function waitForAdmission(previous: Promise<void> | undefined, signal: AbortSignal): Promise<void> {\n if (!previous) return;\n await waitForTurn(previous.catch(() => undefined), signal);\n}\n\nfunction once(callback: () => void): () => void {\n let called = false;\n return () => {\n if (called) return;\n called = true;\n callback();\n };\n}\n\nexport async function expandMcpTools(\n capabilities: AgentCapabilities,\n allowedServers: readonly string[],\n): Promise<ToolCapability[]> {\n const expanded: ToolCapability[] = [];\n const occupied = new Set(capabilities.tools.map((tool) => tool.name));\n for (const connection of capabilities.mcp) {\n if (!allowedServers.includes(connection.name)) continue;\n for (const tool of await connection.listTools()) {\n const name = `${connection.qualifiedName}__${tool.name}`;\n if (occupied.has(name)) {\n throw new Error(`Duplicate Agent Tool capability: ${name}`);\n }\n occupied.add(name);\n expanded.push(Object.freeze({\n owner: connection.owner,\n name,\n qualifiedName: name,\n description: tool.description?.trim() || `${connection.name} MCP tool ${tool.name}`,\n inputSchema: tool.inputSchema === undefined\n ? undefined\n : requireToolInputSchema(tool.inputSchema, `MCP Tool ${name} inputSchema`),\n requiresApproval: 'on-risk' as const,\n source: connection.source,\n execute: <TInput = unknown, TResult = unknown>(input: TInput) =>\n connection.callTool<TResult>(tool.name, input),\n }));\n }\n }\n return expanded;\n}\n\nfunction createIngressTurn(\n snapshot: import('@zhin.js/plugin-runtime').RuntimeSnapshot,\n request: TurnRequest,\n capabilities: AgentCapabilities,\n trace?: TurnTraceCollector,\n) {\n const journal = new PersistentTurnJournal({\n sessionId: request.session.key,\n turnId: request.identity.turnId,\n }, resolveJournalStore(snapshot), request.principal);\n return createTurnIngress({\n ...request,\n identity: {\n rootId: String(snapshot.root),\n generation: snapshot.generation,\n traceId: request.identity.traceId,\n turnId: request.identity.turnId,\n },\n capabilities: {\n tools: capabilities.tools.map((tool) => tool.name),\n skills: capabilities.skills.map((skill) => skill.name),\n },\n ports: {\n ...request.ports,\n journal: createJournalFeed(trace ? createTracingJournal(journal, trace) : journal, {\n turnId: request.identity.turnId,\n }),\n },\n });\n}\n\nfunction resolveJournalStore(snapshot: import('@zhin.js/plugin-runtime').RuntimeSnapshot): JournalStore {\n const store = snapshot.resources.get(snapshot.root)?.get(turnJournalStoreToken.id);\n if (!store\n || typeof (store as JournalStore).append !== 'function'\n || typeof (store as JournalStore).replay !== 'function') {\n throw new Error('Agent Turn JournalStore is not installed for this generation');\n }\n return store as JournalStore;\n}\n"]}
1
+ {"version":3,"file":"agent-runtime.js","sourceRoot":"","sources":["../../src/plugin-runtime/agent-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TurnEvent } from '../event/turn-event.js';\nimport { AgentUsageCollector, agentUsageStoreToken, type AgentUsageStore } from '../usage/usage-store.js';\nimport { getLogger } from '@zhin.js/logger';\nimport { logTurnUsage, type UsageLogContext } from '../trace/turn-usage-log.js';\nimport { createToken, type PluginId, type SnapshotLease, type SnapshotReader } from '@zhin.js/plugin-runtime';\nimport { applyTurnTrust } from '../security/trust-level.js';\nimport type { JournalStore } from '@zhin.js/ai/journal-store';\nimport { PersistentTurnJournal } from '../journal/persistent-turn-journal.js';\nimport { TurnTraceCollector } from '../trace/turn-trace.js';\nimport { createTracingJournal, registerTurnTrace } from '../trace/turn-trace-registry.js';\nimport { createJournalFeed } from '../turn/journal-feed.js';\nimport type { TurnTraceStore } from '../trace/turn-trace-store.js';\nimport { executeAgentTurn, type TurnEventObserver } from '../turn/execute-agent-turn.js';\nimport {\n createTurnIngress,\n type TurnOutcome,\n type TurnRequest,\n} from '../turn/turn-ingress.js';\nimport {\n CapabilityIngress,\n type AgentCapabilities,\n type ToolCapability,\n} from './capability-ingress.js';\nimport { TurnToolRuntime, type TurnToolOutcome } from '../tool/turn-tool-runtime.js';\nimport { requireToolInputSchema, type ToolDescriptor } from '@zhin.js/tool';\nimport type { ResolvedAgentBinding } from '../config/types.js';\nimport { runWithAgentTurnConfiguration } from '../turn/agent-turn-context.js';\nimport { TurnSupersededError } from '../turn/prompt-controller.js';\nimport { createConversationReferenceCapability } from '../tool/conversation-reference-tool.js';\nimport { drainAgentTurnDecisionObservations, runWithAgentDecisionTurn } from './decision-runtime.js';\nimport type { AgentDecisionRuntime } from '../decision/types.js';\n\nabstract class SnapshotAttachedRuntime {\n protected snapshots?: SnapshotReader;\n\n attach(snapshots: SnapshotReader): void {\n if (this.snapshots && this.snapshots !== snapshots) {\n throw new Error(`${this.constructor.name} is already attached to another Root`);\n }\n this.snapshots = snapshots;\n }\n\n protected requireSnapshots(): SnapshotReader {\n if (!this.snapshots) throw new Error(`${this.constructor.name} is not attached to a Root`);\n return this.snapshots;\n }\n}\n\nexport const turnJournalStoreToken = createToken<JournalStore>(\n 'zhin.agent.turn-journal-store',\n 'Durable Agent turn event journal store',\n);\n\nexport interface ExternalToolCapability extends ToolDescriptor {\n execute(input: Readonly<Record<string, unknown>>, toolUseId: string): Promise<TurnToolOutcome>;\n}\n\n/** Canonical fixed-generation execution authority for external tool protocols. */\nexport class ToolIngressRuntime extends SnapshotAttachedRuntime {\n readonly #ingress = new CapabilityIngress();\n\n async withTools<TResult>(\n owner: PluginId,\n request: TurnRequest,\n operation: (tools: readonly ExternalToolCapability[]) => TResult | Promise<TResult>,\n ): Promise<TResult> {\n const lease = this.requireSnapshots().acquire();\n let active = true;\n try {\n const capabilities = await this.#ingress.read(lease.value, owner, () => active, request);\n let invocationSequence = 0;\n const tools = Object.freeze(capabilities.tools\n .filter((tool) => !tool.hidden)\n .map(({ execute: _execute, ...descriptor }) => Object.freeze({\n ...descriptor,\n execute: async (input: Readonly<Record<string, unknown>>, toolUseId: string) => {\n if (!active) throw new Error('External Tool capability scope has ended');\n invocationSequence += 1;\n const invocationRequest: TurnRequest = {\n ...request,\n identity: {\n traceId: request.identity.traceId,\n turnId: `${request.identity.turnId}:${invocationSequence}`,\n },\n };\n const turn = createIngressTurn(lease.value, invocationRequest, capabilities);\n const runtime = new TurnToolRuntime(turn, capabilities.tools);\n const outcome = await runtime.execute(descriptor.name, input, toolUseId);\n await appendExternalToolTerminal(turn, outcome);\n return outcome;\n },\n })));\n return await operation(tools);\n } finally {\n active = false;\n lease.release();\n }\n }\n}\n\nasync function appendExternalToolTerminal(\n turn: import('../turn/turn-ingress.js').TurnIngress,\n outcome: TurnToolOutcome,\n): Promise<void> {\n if (outcome.status === 'completed') {\n await turn.ports.journal.append({\n type: 'turn_end',\n output: [],\n usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },\n });\n return;\n }\n if (outcome.status === 'cancelled') {\n await turn.ports.journal.append({\n type: 'turn_cancelled',\n code: 'cancelled',\n reason: outcome.reason,\n });\n return;\n }\n const message = outcome.status === 'failed' ? outcome.error : outcome.reason;\n await turn.ports.journal.append({\n type: 'error',\n error: new Error(message),\n recoverable: false,\n });\n}\n\n/** Single Agent execution authority: snapshot + capabilities + terminal algebra. */\nexport interface AgentTurnExecutionContext {\n readonly decision?: AgentDecisionRuntime;\n readonly turn: import('../turn/turn-ingress.js').TurnIngress;\n readonly capabilities: Omit<AgentCapabilities, 'tools'> & {\n readonly tools: readonly ToolDescriptor[];\n };\n readonly tools: TurnToolRuntime;\n /** Executable descriptors bound to the same active generation lease. */\n readonly toolCapabilities: readonly ToolCapability[];\n readonly selection: AgentCapabilitySelection;\n /** Signals that this ingress has reached the ordered PromptController boundary. */\n readonly admit?: () => void;\n}\n\n/** Root-owned serialization authority shared by every Agent generation. */\nexport class AgentTurnCoordinator {\n readonly #tails = new Map<string, Promise<void>>();\n readonly #admissions = new Map<string, Promise<void>>();\n readonly #active = new Map<string, AbortController>();\n\n async run<TResult>(\n sessionKey: string,\n signal: AbortSignal,\n operation: () => Promise<TResult>,\n ): Promise<TResult> {\n const previous = this.#tails.get(sessionKey) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => { release = resolve; });\n const tail = previous.catch(() => undefined).then(() => current);\n this.#tails.set(sessionKey, tail);\n try {\n await waitForTurn(previous.catch(() => undefined), signal);\n return await operation();\n } finally {\n release();\n if (this.#tails.get(sessionKey) === tail) this.#tails.delete(sessionKey);\n }\n }\n\n async runIntent<TResult>(\n sessionKey: string,\n signal: AbortSignal,\n intent: import('../turn/turn-ingress.js').TurnIntent,\n _principal: import('../turn/turn-ingress.js').TurnPrincipal,\n operation: (admit: () => void, signal: AbortSignal) => Promise<TResult>,\n ): Promise<TResult> {\n const previous = this.#tails.get(sessionKey) ?? Promise.resolve();\n const previousAdmission = this.#admissions.get(sessionKey);\n let admit!: () => void;\n let complete!: () => void;\n const admitted = new Promise<void>((resolve) => { admit = once(resolve); });\n const completed = new Promise<void>((resolve) => { complete = once(resolve); });\n const cumulative = Promise.all([previous.catch(() => undefined), completed]).then(() => undefined);\n const controller = new AbortController();\n const abortFromCaller = () => controller.abort(signal.reason);\n if (signal.aborted) abortFromCaller();\n else signal.addEventListener('abort', abortFromCaller, { once: true });\n this.#tails.set(sessionKey, cumulative);\n void cumulative.finally(() => {\n if (this.#tails.get(sessionKey) === cumulative) this.#tails.delete(sessionKey);\n });\n this.#admissions.set(sessionKey, admitted);\n try {\n if (intent.kind === 'new') {\n await waitForTurn(previous.catch(() => undefined), signal);\n this.#active.set(sessionKey, controller);\n } else if (intent.kind === 'supersede') {\n await waitForAdmission(previousAdmission, signal);\n this.#active.get(sessionKey)?.abort(new TurnSupersededError(sessionKey));\n await waitForTurn(previous.catch(() => undefined), signal);\n this.#active.set(sessionKey, controller);\n } else {\n await waitForAdmission(previousAdmission, signal);\n }\n return await operation(admit, controller.signal);\n } finally {\n signal.removeEventListener('abort', abortFromCaller);\n admit();\n complete();\n if (this.#active.get(sessionKey) === controller) this.#active.delete(sessionKey);\n if (this.#admissions.get(sessionKey) === admitted) this.#admissions.delete(sessionKey);\n }\n }\n}\n\nexport type AgentTurnExecutor = (\n context: AgentTurnExecutionContext,\n) => AsyncGenerator<\n import('../event/turn-event.js').TurnEvent,\n import('../turn/execute-agent-turn.js').TurnTerminalProjection | void\n>;\n\n/** Generation-owned complete Turn engine resolved from the held snapshot. */\nexport interface AgentTurnEngine {\n run: AgentTurnExecutor;\n}\n\nexport const agentTurnEngineToken = createToken<AgentTurnEngine>(\n 'zhin.agent.turn-engine',\n 'Complete Agent Turn engine owned by one Root generation',\n);\n\nexport interface AgentRuntimeOptions {\n /** Root-owned queue shared by every AgentRuntime generation of that Root. */\n readonly coordinator: AgentTurnCoordinator;\n /** Where finished TurnTraces go (`zhin trace`). Omit to disable tracing. */\n readonly turnTraceStore?: TurnTraceStore;\n}\n\nexport interface AgentCapabilitySelection {\n /** Immutable model/provider binding selected for this turn. */\n readonly binding: ResolvedAgentBinding;\n /** Binding-local MCP names. Empty means no MCP capability is exposed. */\n readonly mcpServers: readonly string[];\n /** Optional owner-visible specialist selected by the ingress router. */\n readonly agent?: string;\n}\n\nexport class AgentRuntime extends SnapshotAttachedRuntime {\n readonly #ingress = new CapabilityIngress();\n readonly #usageLogger = getLogger('ai.usage');\n\n constructor(private readonly options: AgentRuntimeOptions) {\n super();\n }\n\n async execute(\n owner: PluginId,\n request: TurnRequest,\n selection: AgentCapabilitySelection,\n observe?: TurnEventObserver,\n ): Promise<TurnOutcome> {\n const lease = this.requireSnapshots().acquire();\n try {\n return await this.executeLeased(lease, owner, request, selection, observe);\n } finally {\n lease.release();\n }\n }\n\n /** Executes under the fixed-generation lease owned by the ingress operation. */\n async executeLeased(\n lease: SnapshotLease,\n owner: PluginId,\n request: TurnRequest,\n selection: AgentCapabilitySelection,\n observe?: TurnEventObserver,\n ): Promise<TurnOutcome> {\n const snapshots = this.requireSnapshots();\n if (!snapshots.owns(lease)) throw new Error('AgentRuntime rejected a lease owned by another Root');\n if (!lease.active) throw new Error('AgentRuntime requires an active generation lease');\n if (!request.intent) throw new TypeError('AgentRuntime requires an explicit Turn intent');\n const intent = request.intent;\n return this.options.coordinator.runIntent(\n request.session.key,\n request.signal,\n intent,\n request.principal,\n (admit, signal) => this.#executeLeased(\n lease,\n owner,\n { ...request, signal },\n selection,\n observe,\n admit,\n ),\n );\n }\n\n async #executeLeased(\n lease: SnapshotLease,\n owner: PluginId,\n request: TurnRequest,\n selection: AgentCapabilitySelection,\n observe?: TurnEventObserver,\n admit: () => void = () => undefined,\n ): Promise<TurnOutcome> {\n let active = true;\n const usageStore = lease.value.resources.get(lease.value.root)?.get(agentUsageStoreToken.id) as AgentUsageStore | undefined;\n const usage = usageStore ? new AgentUsageCollector(String(owner), request, {\n provider: selection.binding.providerAlias, model: selection.binding.model,\n }) : undefined;\n let usageStatus = 'failed';\n let activeTrace: TurnTraceCollector | undefined;\n let releaseTrace: (() => void) | undefined;\n let outcome: TurnOutcome | undefined;\n const logContext: UsageLogContext = {\n traceId: request.identity.traceId,\n scene: request.origin.kind === 'im' ? `${request.origin.platform}/${request.origin.scope}` : request.origin.kind,\n selectedModel: `${selection.binding.providerAlias}/${selection.binding.model}`,\n };\n try {\n if (!active) throw new Error('Agent generation operation is not active');\n const discovered = await this.#ingress.read(\n lease.value,\n owner,\n () => active && lease.active,\n request,\n selection.agent,\n );\n const referenceCapability = createConversationReferenceCapability(owner, request);\n // #726: the initiator's trust level caps the turn (group members: no shell, writes or outbound).\n const allTools = [\n ...discovered.tools,\n ...(referenceCapability ? [referenceCapability] : []),\n ...await expandMcpTools(discovered, selection.mcpServers),\n ];\n const trust = applyTurnTrust(request, allTools);\n const capabilities = Object.freeze({\n ...discovered,\n tools: Object.freeze([...trust.tools]),\n });\n const turnRequest = trust.restricted\n ? Object.freeze({ ...request, policy: trust.policy })\n : request;\n const trace = this.options.turnTraceStore || this.#usageLogger.isLevelEnabled('info')\n ? new TurnTraceCollector({\n turnId: request.identity.turnId,\n sessionKey: request.session.key,\n principal: { ...request.principal, trustLevel: trust.level },\n })\n : undefined;\n releaseTrace = trace ? registerTurnTrace(trace) : undefined;\n activeTrace = trace;\n const turn = createIngressTurn(lease.value, turnRequest, capabilities, trace, usage);\n const catalog = Object.freeze({\n ...capabilities,\n tools: Object.freeze(capabilities.tools.map(({ execute: _execute, ...tool }) => Object.freeze(tool))),\n });\n const tools = new TurnToolRuntime(turn, capabilities.tools);\n const engine = resolveTurnEngine(lease.value);\n const disabled = Boolean(request.session.key.startsWith('workroom:') || request.input.metadata?.workroom\n || request.principal.roles.includes('workroom_assignment') || request.execution?.kind === 'schedule');\n outcome = await runWithAgentDecisionTurn(lease.value, request.identity.turnId, decision => runWithAgentTurnConfiguration(\n { activeBinding: selection.binding },\n () => executeAgentTurn(turn, async function* () {\n const stream = engine.run({\n turn,\n capabilities: catalog,\n tools,\n toolCapabilities: capabilities.tools,\n selection,\n decision,\n admit,\n });\n try {\n while (true) {\n const next = await stream.next();\n for (const observation of drainAgentTurnDecisionObservations()) {\n yield { type: 'decision_evaluation', ...observation };\n }\n if (next.done) return next.value;\n yield next.value;\n }\n } catch (error) {\n // A later engine failure must not erase already completed decisions.\n for (const observation of drainAgentTurnDecisionObservations()) {\n yield { type: 'decision_evaluation', ...observation };\n }\n throw error;\n } finally {\n await stream.return(undefined);\n }\n }, observe),\n ), { disabled });\n usageStatus = outcome.status;\n return outcome;\n } catch (error) {\n usageStatus = request.signal.aborted ? 'cancelled' : 'failed';\n if (!activeTrace && this.#usageLogger.isLevelEnabled('info')) {\n activeTrace = new TurnTraceCollector({ turnId: request.identity.turnId, sessionKey: request.session.key });\n }\n activeTrace?.finalize({ status: request.signal.aborted ? 'cancelled' : 'failed' });\n throw error;\n } finally {\n active = false;\n releaseTrace?.();\n if (activeTrace) this.#saveTrace(activeTrace, { ...logContext, status: outcome?.status });\n if (usage && usageStore) {\n try { await usageStore.save(usage.finish(usageStatus)); }\n catch {\n // No model response, prompt or database error text enters this diagnostic.\n try { this.#usageLogger.error('op=usage_persist status=failed; 本轮用量未写入数据库'); } catch { /* Transport failure cannot change delivery. */ }\n }\n }\n }\n }\n\n #saveTrace(trace: TurnTraceCollector, context: UsageLogContext): void {\n trace.finalize();\n const snapshot = trace.snapshot();\n logTurnUsage(this.#usageLogger, snapshot, context);\n // Fire-and-forget: a slow or failing trace write must not delay the reply.\n void this.options.turnTraceStore?.save(snapshot).catch(() => undefined);\n }\n}\n\nfunction resolveTurnEngine(snapshot: import('@zhin.js/plugin-runtime').RuntimeSnapshot): AgentTurnEngine {\n const candidate = snapshot.resources.get(snapshot.root)?.get(agentTurnEngineToken.id);\n if (!candidate || typeof (candidate as AgentTurnEngine).run !== 'function') {\n throw new Error('Active generation does not provide an Agent Turn Engine');\n }\n return candidate as AgentTurnEngine;\n}\n\nasync function waitForTurn(previous: Promise<void>, signal: AbortSignal): Promise<void> {\n if (signal.aborted) throw signal.reason ?? new Error('Agent turn cancelled while queued');\n let rejectAbort!: (reason: unknown) => void;\n const aborted = new Promise<never>((_resolve, reject) => { rejectAbort = reject; });\n const onAbort = () => rejectAbort(signal.reason ?? new Error('Agent turn cancelled while queued'));\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n await Promise.race([previous, aborted]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\nasync function waitForAdmission(previous: Promise<void> | undefined, signal: AbortSignal): Promise<void> {\n if (!previous) return;\n await waitForTurn(previous.catch(() => undefined), signal);\n}\n\nfunction once(callback: () => void): () => void {\n let called = false;\n return () => {\n if (called) return;\n called = true;\n callback();\n };\n}\n\nexport async function expandMcpTools(\n capabilities: AgentCapabilities,\n allowedServers: readonly string[],\n): Promise<ToolCapability[]> {\n const expanded: ToolCapability[] = [];\n const occupied = new Set(capabilities.tools.map((tool) => tool.name));\n for (const connection of capabilities.mcp) {\n if (!allowedServers.includes(connection.name)) continue;\n for (const tool of await connection.listTools()) {\n const name = `${connection.qualifiedName}__${tool.name}`;\n if (occupied.has(name)) {\n throw new Error(`Duplicate Agent Tool capability: ${name}`);\n }\n occupied.add(name);\n expanded.push(Object.freeze({\n owner: connection.owner,\n name,\n qualifiedName: name,\n description: tool.description?.trim() || `${connection.name} MCP tool ${tool.name}`,\n inputSchema: tool.inputSchema === undefined\n ? undefined\n : requireToolInputSchema(tool.inputSchema, `MCP Tool ${name} inputSchema`),\n requiresApproval: 'on-risk' as const,\n source: connection.source,\n execute: <TInput = unknown, TResult = unknown>(input: TInput) =>\n connection.callTool<TResult>(tool.name, input),\n }));\n }\n }\n return expanded;\n}\n\nfunction createIngressTurn(\n snapshot: import('@zhin.js/plugin-runtime').RuntimeSnapshot,\n request: TurnRequest,\n capabilities: AgentCapabilities,\n trace?: TurnTraceCollector,\n usage?: AgentUsageCollector,\n) {\n const journal = new PersistentTurnJournal({\n sessionId: request.session.key,\n turnId: request.identity.turnId,\n }, resolveJournalStore(snapshot), request.principal);\n const traced = trace ? createTracingJournal(journal, trace) : journal;\n const observed = usage ? { append(event: TurnEvent) { usage.record(event); return traced.append(event); } } : traced;\n return createTurnIngress({\n ...request,\n identity: {\n rootId: String(snapshot.root),\n generation: snapshot.generation,\n traceId: request.identity.traceId,\n turnId: request.identity.turnId,\n },\n capabilities: {\n tools: capabilities.tools.map((tool) => tool.name),\n skills: capabilities.skills.map((skill) => skill.name),\n },\n ports: {\n ...request.ports,\n journal: createJournalFeed(observed, {\n turnId: request.identity.turnId,\n }),\n },\n });\n}\n\nfunction resolveJournalStore(snapshot: import('@zhin.js/plugin-runtime').RuntimeSnapshot): JournalStore {\n const store = snapshot.resources.get(snapshot.root)?.get(turnJournalStoreToken.id);\n if (!store\n || typeof (store as JournalStore).append !== 'function'\n || typeof (store as JournalStore).replay !== 'function') {\n throw new Error('Agent Turn JournalStore is not installed for this generation');\n }\n return store as JournalStore;\n}\n"]}
@@ -6,17 +6,18 @@ import type { UsageQuota } from '../security/usage-quota.js';
6
6
  * `zhin.js` main entry without this package; re-exported here unchanged (same token object and id).
7
7
  */
8
8
  export { aiCompletionToken } from '@zhin.js/core';
9
- export type { AiCompletion, AiCompletionInput, AiCompletionResult, AiCompletionUntrustedInput, UsageSubject, } from '@zhin.js/core';
9
+ export type { AiCompletion, AiCompletionInput, AiCompletionResult, AiCompletionUntrustedInput, AiCompletionUsageShare, UsageSubject, } from '@zhin.js/core';
10
10
  /** Thrown when the `onBehalfOf` user or group is over its usage quota; `message` is user-facing. Recognise it with `isAiCompletionQuotaError`. */
11
11
  export declare class AiCompletionQuotaError extends Error {
12
12
  readonly name: "AiCompletionQuotaError";
13
13
  readonly scope: 'user' | 'group';
14
14
  readonly retryAfterSeconds: number;
15
- constructor(message: string, scope: 'user' | 'group', retryAfterSeconds: number);
15
+ readonly deniedUserIds?: readonly string[];
16
+ constructor(message: string, scope: 'user' | 'group', retryAfterSeconds: number, deniedUserIds?: readonly string[]);
16
17
  }
17
18
  export interface AiCompletionOptions {
18
19
  readonly service: Pick<AIService, 'getBindingRegistry' | 'getProvider' | 'getAgentConfig'> & Partial<Pick<AIService, 'getModelRegistry'>>;
19
- readonly usageQuota?: Pick<UsageQuota, 'check' | 'record'>;
20
+ readonly usageQuota?: Pick<UsageQuota, 'check' | 'record'> & Partial<Pick<UsageQuota, 'checkBatch'>>;
20
21
  readonly now?: () => number;
21
22
  }
22
23
  export declare function createAiCompletion(options: AiCompletionOptions): AiCompletion;
@@ -29,28 +29,37 @@ export class AiCompletionQuotaError extends Error {
29
29
  name = 'AiCompletionQuotaError';
30
30
  scope;
31
31
  retryAfterSeconds;
32
- constructor(message, scope, retryAfterSeconds) {
32
+ deniedUserIds;
33
+ constructor(message, scope, retryAfterSeconds, deniedUserIds) {
33
34
  super(message);
34
35
  this.scope = scope;
35
36
  this.retryAfterSeconds = retryAfterSeconds;
37
+ this.deniedUserIds = deniedUserIds;
36
38
  }
37
39
  }
38
40
  export function createAiCompletion(options) {
39
41
  const now = options.now ?? Date.now;
40
42
  return Object.freeze({
43
+ ...(options.usageQuota && !options.usageQuota.checkBatch ? {} : { supportsUsageShares: true }),
41
44
  async completeText(input) {
42
45
  const purpose = requiredText(input.purpose, 'purpose');
43
46
  const prompt = requiredText(input.prompt, 'prompt');
47
+ const shares = usageShares(input);
44
48
  const registry = options.service.getBindingRegistry();
45
49
  const binding = input.agent ? registry.getBinding(input.agent) : registry.requireZhinBinding();
46
50
  if (!binding)
47
51
  throw new Error(`AI completion: agent binding "${input.agent}" not found`);
48
52
  const provider = options.service.getProvider(binding.providerAlias);
49
53
  const model = input.model?.trim() || binding.model || provider.models[0] || '';
50
- if (input.onBehalfOf && options.usageQuota) {
51
- const decision = options.usageQuota.check(input.onBehalfOf);
54
+ input.signal?.throwIfAborted();
55
+ if (shares.length && options.usageQuota) {
56
+ if (input.usageShares && !options.usageQuota.checkBatch)
57
+ throw new Error('AI completion: quota does not support shared attribution');
58
+ const decision = input.usageShares
59
+ ? options.usageQuota.checkBatch(shares.map(share => share.subject))
60
+ : options.usageQuota.check(shares[0].subject);
52
61
  if (!decision.allowed) {
53
- throw new AiCompletionQuotaError(decision.message, decision.scope, decision.retryAfterSeconds);
62
+ throw new AiCompletionQuotaError(decision.message, decision.scope, decision.retryAfterSeconds, 'deniedUserIds' in decision ? decision.deniedUserIds : undefined);
54
63
  }
55
64
  }
56
65
  const user = [
@@ -70,10 +79,18 @@ export function createAiCompletion(options) {
70
79
  };
71
80
  // Reserve the prompt estimate before the call: concurrent calls then see each other's
72
81
  // spend at `check`, and a call that fails after reaching the provider is still billed.
73
- const quotaSubject = input.onBehalfOf && options.usageQuota ? input.onBehalfOf : undefined;
74
- const reserved = quotaSubject ? estimatePromptTokens(`${input.system ?? ''}\n${user}`) : 0;
75
- if (quotaSubject && reserved > 0)
76
- options.usageQuota.record(quotaSubject, reserved);
82
+ const reserved = shares.length && options.usageQuota ? estimatePromptTokens(`${input.system ?? ''}\n${user}`) : 0;
83
+ let billed = shares.map(() => 0);
84
+ const record = (tokens) => {
85
+ if (!options.usageQuota || tokens <= 0)
86
+ return;
87
+ const allocated = allocateTokens(tokens, shares.map(share => share.weight));
88
+ shares.forEach((share, index) => {
89
+ options.usageQuota.record(share.subject, allocated[index] - billed[index]);
90
+ });
91
+ billed = allocated;
92
+ };
93
+ record(reserved);
77
94
  const started = now();
78
95
  let result;
79
96
  try {
@@ -96,11 +113,11 @@ export function createAiCompletion(options) {
96
113
  const durationMs = now() - started;
97
114
  const reportedTokens = result.usage?.totalTokens;
98
115
  const totalTokens = reportedTokens || undefined;
99
- if (quotaSubject) {
116
+ if (shares.length && options.usageQuota) {
100
117
  // Reported usage settles the reservation; without it, estimate the answer on top of the prompt.
101
118
  const settled = totalTokens ?? reserved + estimatePromptTokens(result.text);
102
119
  if (settled > reserved)
103
- options.usageQuota.record(quotaSubject, settled - reserved);
120
+ record(settled);
104
121
  }
105
122
  logger.info(formatCompact({
106
123
  op: 'ai_completion',
@@ -121,6 +138,43 @@ export function createAiCompletion(options) {
121
138
  },
122
139
  });
123
140
  }
141
+ function usageShares(input) {
142
+ if (!input.usageShares)
143
+ return input.onBehalfOf ? [{ subject: { ...input.onBehalfOf }, weight: 1 }] : [];
144
+ if (input.onBehalfOf || !input.usageShares.length)
145
+ throw new TypeError('AI completion: choose nonempty usageShares or onBehalfOf');
146
+ const shares = new Map();
147
+ for (const { subject, text } of input.usageShares) {
148
+ if (!subject.userId || typeof text !== 'string' || !text.trim())
149
+ throw new TypeError('AI completion: invalid usage share');
150
+ const weight = Math.max(1, estimatePromptTokens(text));
151
+ const key = JSON.stringify([subject.userId, subject.groupId]);
152
+ const previous = shares.get(key);
153
+ if (previous && previous.subject.owner !== subject.owner)
154
+ throw new TypeError('AI completion: conflicting usage subjects');
155
+ shares.set(key, { subject: { ...subject }, weight: weight + (previous?.weight ?? 0) });
156
+ }
157
+ if (!Number.isFinite([...shares.values()].reduce((sum, share) => sum + share.weight, 0)))
158
+ throw new TypeError('AI completion: invalid total weight');
159
+ return [...shares.values()];
160
+ }
161
+ /** Highest-averages rounding is monotone: settling a larger total never needs to refund a user. */
162
+ function allocateTokens(tokens, weights) {
163
+ const total = weights.reduce((sum, weight) => sum + weight, 0);
164
+ const allocated = weights.map(weight => Math.floor(tokens * (weight / total)));
165
+ let remaining = tokens - allocated.reduce((sum, value) => sum + value, 0);
166
+ while (remaining > 0 && weights.length) {
167
+ let next = 0;
168
+ for (let index = 1; index < weights.length; index++) {
169
+ if (weights[index] / (allocated[index] + 1) > weights[next] / (allocated[next] + 1))
170
+ next = index;
171
+ }
172
+ const amount = Math.min(1, remaining);
173
+ allocated[next] += amount;
174
+ remaining -= amount;
175
+ }
176
+ return allocated;
177
+ }
124
178
  function requiredText(value, name) {
125
179
  if (typeof value !== 'string' || !value.trim())
126
180
  throw new TypeError(`AI completion: ${name} is required`);
@@ -1 +1 @@
1
- {"version":3,"file":"ai-completion.js","sourceRoot":"","sources":["../../src/plugin-runtime/ai-completion.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Plain text completion for plugins (#804).\n *\n * Plugins that only need text (summarise a chat, classify a message, rewrite a\n * reply) should not borrow a whole Agent turn: that is slow, and the model gets\n * tools such as file access while it reads untrusted group chat. This port does\n * one completion with **no tools at all** — the request carries no tool\n * definitions, so nothing the model writes can be executed — and reuses the\n * provider resilience chain (retry, backoff, timeout). There is no automatic model\n * fallback: a plugin call must never silently fail over to a pricier model, and no\n * per-binding fallback list exists to opt in to.\n *\n * Untrusted text is rendered as `external_content` data blocks (#726), and a\n * call made on behalf of an IM user counts against that user's / group's usage\n * quota (#727).\n */\nimport { resolveModelCandidates } from '../context/model-resolver.js';\nimport type { AIProvider, ProviderResilienceConfig, TextCompleteResult } from '@zhin.js/ai';\nimport type { AiCompletion, AiCompletionInput, AiCompletionResult } from '@zhin.js/core';\nimport { formatCompact, getLogger } from '@zhin.js/logger';\nimport type { AIService } from '../service.js';\nimport { renderExternalContent } from '../security/trust-level.js';\nimport type { UsageQuota } from '../security/usage-quota.js';\nimport { estimatePromptTokens } from '../prompt/estimate-tokens.js';\n\n/**\n * The contract (types and token) lives in `@zhin.js/core` (#877) so plugins can import it from the\n * `zhin.js` main entry without this package; re-exported here unchanged (same token object and id).\n */\nexport { aiCompletionToken } from '@zhin.js/core';\nexport type {\n AiCompletion,\n AiCompletionInput,\n AiCompletionResult,\n AiCompletionUntrustedInput,\n UsageSubject,\n} from '@zhin.js/core';\n\nconst logger = getLogger('agent');\n\n/** Thrown when the `onBehalfOf` user or group is over its usage quota; `message` is user-facing. Recognise it with `isAiCompletionQuotaError`. */\nexport class AiCompletionQuotaError extends Error {\n override readonly name = 'AiCompletionQuotaError' as const;\n readonly scope: 'user' | 'group';\n readonly retryAfterSeconds: number;\n\n constructor(message: string, scope: 'user' | 'group', retryAfterSeconds: number) {\n super(message);\n this.scope = scope;\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\nexport interface AiCompletionOptions {\n readonly service: Pick<AIService, 'getBindingRegistry' | 'getProvider' | 'getAgentConfig'>\n & Partial<Pick<AIService, 'getModelRegistry'>>;\n readonly usageQuota?: Pick<UsageQuota, 'check' | 'record'>;\n readonly now?: () => number;\n}\n\nexport function createAiCompletion(options: AiCompletionOptions): AiCompletion {\n const now = options.now ?? Date.now;\n return Object.freeze({\n async completeText(input: AiCompletionInput): Promise<AiCompletionResult> {\n const purpose = requiredText(input.purpose, 'purpose');\n const prompt = requiredText(input.prompt, 'prompt');\n const registry = options.service.getBindingRegistry();\n const binding = input.agent ? registry.getBinding(input.agent) : registry.requireZhinBinding();\n if (!binding) throw new Error(`AI completion: agent binding \"${input.agent}\" not found`);\n const provider: AIProvider = options.service.getProvider(binding.providerAlias);\n const model = input.model?.trim() || binding.model || provider.models[0] || '';\n\n if (input.onBehalfOf && options.usageQuota) {\n const decision = options.usageQuota.check(input.onBehalfOf);\n if (!decision.allowed) {\n throw new AiCompletionQuotaError(decision.message, decision.scope, decision.retryAfterSeconds);\n }\n }\n\n const user = [\n prompt,\n ...(input.untrusted ?? []).map(item => renderExternalContent(sourceLabel(item.source), neutralizeBlockMarkers(String(item.text ?? '')))),\n ].join('\\n\\n');\n const opts = {\n model,\n temperature: input.temperature,\n maxTokens: input.maxTokens,\n timeoutMs: input.timeoutMs,\n signal: input.signal,\n // Same candidates as the conversation path (bound model, registry picks, then the\n // provider's models); whether they are tried is up to `providerResilience.fallback`.\n fallbackModels: resolveModelCandidates(\n provider.models,\n options.service.getModelRegistry?.() ?? null,\n binding.providerAlias,\n { chatModel: binding.model },\n 'chat',\n model,\n ).filter(id => id && id !== model),\n resilience: options.service.getAgentConfig()?.providerResilience as ProviderResilienceConfig | undefined,\n };\n // Reserve the prompt estimate before the call: concurrent calls then see each other's\n // spend at `check`, and a call that fails after reaching the provider is still billed.\n const quotaSubject = input.onBehalfOf && options.usageQuota ? input.onBehalfOf : undefined;\n const reserved = quotaSubject ? estimatePromptTokens(`${input.system ?? ''}\\n${user}`) : 0;\n if (quotaSubject && reserved > 0) options.usageQuota!.record(quotaSubject, reserved);\n const started = now();\n let result: TextCompleteResult;\n try {\n result = provider.completeTextResult\n ? await provider.completeTextResult(input.system ?? '', user, opts)\n : { text: await provider.completeText(input.system ?? '', user, opts), model };\n } catch (error) {\n logger.warn(formatCompact({\n op: 'ai_completion',\n purpose,\n provider: binding.providerAlias,\n model,\n outcome: 'error',\n durationMs: now() - started,\n error: error instanceof Error ? error.message : String(error),\n }));\n throw error;\n }\n const durationMs = now() - started;\n const reportedTokens = result.usage?.totalTokens;\n const totalTokens = reportedTokens || undefined;\n if (quotaSubject) {\n // Reported usage settles the reservation; without it, estimate the answer on top of the prompt.\n const settled = totalTokens ?? reserved + estimatePromptTokens(result.text);\n if (settled > reserved) options.usageQuota!.record(quotaSubject, settled - reserved);\n }\n logger.info(formatCompact({\n op: 'ai_completion',\n purpose,\n provider: binding.providerAlias,\n model: result.model,\n outcome: 'ok',\n durationMs,\n ...(totalTokens ? { tokens: totalTokens } : {}),\n untrusted: input.untrusted?.length ?? 0,\n }));\n return Object.freeze({\n text: result.text,\n model: result.model,\n durationMs,\n ...(result.usage ? { usage: result.usage } : {}),\n });\n },\n });\n}\n\nfunction requiredText(value: unknown, name: string): string {\n if (typeof value !== 'string' || !value.trim()) throw new TypeError(`AI completion: ${name} is required`);\n return value;\n}\n\n/** Untrusted text must not be able to close its data block early and continue as instructions. */\nfunction neutralizeBlockMarkers(text: string): string {\n return text.replace(/\\[(\\s*(?:end\\s+)?external_content)/giu, '[$1');\n}\n\n/** Keeps the source label from closing the data block or injecting quotes. */\nfunction sourceLabel(source: unknown): string {\n const text = String(source ?? '').replace(/[^\\p{L}\\p{N}_.:/-]+/gu, '-').slice(0, 64);\n return text || 'untrusted';\n}\n"]}
1
+ {"version":3,"file":"ai-completion.js","sourceRoot":"","sources":["../../src/plugin-runtime/ai-completion.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Plain text completion for plugins (#804).\n *\n * Plugins that only need text (summarise a chat, classify a message, rewrite a\n * reply) should not borrow a whole Agent turn: that is slow, and the model gets\n * tools such as file access while it reads untrusted group chat. This port does\n * one completion with **no tools at all** — the request carries no tool\n * definitions, so nothing the model writes can be executed — and reuses the\n * provider resilience chain (retry, backoff, timeout). There is no automatic model\n * fallback: a plugin call must never silently fail over to a pricier model, and no\n * per-binding fallback list exists to opt in to.\n *\n * Untrusted text is rendered as `external_content` data blocks (#726), and a\n * call made on behalf of an IM user counts against that user's / group's usage\n * quota (#727).\n */\nimport { resolveModelCandidates } from '../context/model-resolver.js';\nimport type { AIProvider, ProviderResilienceConfig, TextCompleteResult } from '@zhin.js/ai';\nimport type { AiCompletion, AiCompletionInput, AiCompletionResult, UsageSubject } from '@zhin.js/core';\nimport { formatCompact, getLogger } from '@zhin.js/logger';\nimport type { AIService } from '../service.js';\nimport { renderExternalContent } from '../security/trust-level.js';\nimport type { UsageQuota } from '../security/usage-quota.js';\nimport { estimatePromptTokens } from '../prompt/estimate-tokens.js';\n\n/**\n * The contract (types and token) lives in `@zhin.js/core` (#877) so plugins can import it from the\n * `zhin.js` main entry without this package; re-exported here unchanged (same token object and id).\n */\nexport { aiCompletionToken } from '@zhin.js/core';\nexport type {\n AiCompletion,\n AiCompletionInput,\n AiCompletionResult,\n AiCompletionUntrustedInput,\n AiCompletionUsageShare,\n UsageSubject,\n} from '@zhin.js/core';\n\nconst logger = getLogger('agent');\n\n/** Thrown when the `onBehalfOf` user or group is over its usage quota; `message` is user-facing. Recognise it with `isAiCompletionQuotaError`. */\nexport class AiCompletionQuotaError extends Error {\n override readonly name = 'AiCompletionQuotaError' as const;\n readonly scope: 'user' | 'group';\n readonly retryAfterSeconds: number;\n readonly deniedUserIds?: readonly string[];\n\n constructor(message: string, scope: 'user' | 'group', retryAfterSeconds: number, deniedUserIds?: readonly string[]) {\n super(message);\n this.scope = scope;\n this.retryAfterSeconds = retryAfterSeconds;\n this.deniedUserIds = deniedUserIds;\n }\n}\n\nexport interface AiCompletionOptions {\n readonly service: Pick<AIService, 'getBindingRegistry' | 'getProvider' | 'getAgentConfig'>\n & Partial<Pick<AIService, 'getModelRegistry'>>;\n readonly usageQuota?: Pick<UsageQuota, 'check' | 'record'> & Partial<Pick<UsageQuota, 'checkBatch'>>;\n readonly now?: () => number;\n}\n\nexport function createAiCompletion(options: AiCompletionOptions): AiCompletion {\n const now = options.now ?? Date.now;\n return Object.freeze({\n ...(options.usageQuota && !options.usageQuota.checkBatch ? {} : { supportsUsageShares: true as const }),\n async completeText(input: AiCompletionInput): Promise<AiCompletionResult> {\n const purpose = requiredText(input.purpose, 'purpose');\n const prompt = requiredText(input.prompt, 'prompt');\n const shares = usageShares(input);\n const registry = options.service.getBindingRegistry();\n const binding = input.agent ? registry.getBinding(input.agent) : registry.requireZhinBinding();\n if (!binding) throw new Error(`AI completion: agent binding \"${input.agent}\" not found`);\n const provider: AIProvider = options.service.getProvider(binding.providerAlias);\n const model = input.model?.trim() || binding.model || provider.models[0] || '';\n\n input.signal?.throwIfAborted();\n if (shares.length && options.usageQuota) {\n if (input.usageShares && !options.usageQuota.checkBatch) throw new Error('AI completion: quota does not support shared attribution');\n const decision = input.usageShares\n ? options.usageQuota.checkBatch!(shares.map(share => share.subject))\n : options.usageQuota.check(shares[0]!.subject);\n if (!decision.allowed) {\n throw new AiCompletionQuotaError(decision.message, decision.scope, decision.retryAfterSeconds,\n 'deniedUserIds' in decision ? decision.deniedUserIds as readonly string[] : undefined);\n }\n }\n\n const user = [\n prompt,\n ...(input.untrusted ?? []).map(item => renderExternalContent(sourceLabel(item.source), neutralizeBlockMarkers(String(item.text ?? '')))),\n ].join('\\n\\n');\n const opts = {\n model,\n temperature: input.temperature,\n maxTokens: input.maxTokens,\n timeoutMs: input.timeoutMs,\n signal: input.signal,\n // Same candidates as the conversation path (bound model, registry picks, then the\n // provider's models); whether they are tried is up to `providerResilience.fallback`.\n fallbackModels: resolveModelCandidates(\n provider.models,\n options.service.getModelRegistry?.() ?? null,\n binding.providerAlias,\n { chatModel: binding.model },\n 'chat',\n model,\n ).filter(id => id && id !== model),\n resilience: options.service.getAgentConfig()?.providerResilience as ProviderResilienceConfig | undefined,\n };\n // Reserve the prompt estimate before the call: concurrent calls then see each other's\n // spend at `check`, and a call that fails after reaching the provider is still billed.\n const reserved = shares.length && options.usageQuota ? estimatePromptTokens(`${input.system ?? ''}\\n${user}`) : 0;\n let billed = shares.map(() => 0);\n const record = (tokens: number) => {\n if (!options.usageQuota || tokens <= 0) return;\n const allocated = allocateTokens(tokens, shares.map(share => share.weight));\n shares.forEach((share, index) => {\n options.usageQuota!.record(share.subject, allocated[index]! - billed[index]!);\n });\n billed = allocated;\n };\n record(reserved);\n const started = now();\n let result: TextCompleteResult;\n try {\n result = provider.completeTextResult\n ? await provider.completeTextResult(input.system ?? '', user, opts)\n : { text: await provider.completeText(input.system ?? '', user, opts), model };\n } catch (error) {\n logger.warn(formatCompact({\n op: 'ai_completion',\n purpose,\n provider: binding.providerAlias,\n model,\n outcome: 'error',\n durationMs: now() - started,\n error: error instanceof Error ? error.message : String(error),\n }));\n throw error;\n }\n const durationMs = now() - started;\n const reportedTokens = result.usage?.totalTokens;\n const totalTokens = reportedTokens || undefined;\n if (shares.length && options.usageQuota) {\n // Reported usage settles the reservation; without it, estimate the answer on top of the prompt.\n const settled = totalTokens ?? reserved + estimatePromptTokens(result.text);\n if (settled > reserved) record(settled);\n }\n logger.info(formatCompact({\n op: 'ai_completion',\n purpose,\n provider: binding.providerAlias,\n model: result.model,\n outcome: 'ok',\n durationMs,\n ...(totalTokens ? { tokens: totalTokens } : {}),\n untrusted: input.untrusted?.length ?? 0,\n }));\n return Object.freeze({\n text: result.text,\n model: result.model,\n durationMs,\n ...(result.usage ? { usage: result.usage } : {}),\n });\n },\n });\n}\n\nfunction usageShares(input: AiCompletionInput): readonly { subject: UsageSubject; weight: number }[] {\n if (!input.usageShares) return input.onBehalfOf ? [{ subject: { ...input.onBehalfOf }, weight: 1 }] : [];\n if (input.onBehalfOf || !input.usageShares.length) throw new TypeError('AI completion: choose nonempty usageShares or onBehalfOf');\n const shares = new Map<string, { subject: UsageSubject; weight: number }>();\n for (const { subject, text } of input.usageShares) {\n if (!subject.userId || typeof text !== 'string' || !text.trim()) throw new TypeError('AI completion: invalid usage share');\n const weight = Math.max(1, estimatePromptTokens(text));\n const key = JSON.stringify([subject.userId, subject.groupId]);\n const previous = shares.get(key);\n if (previous && previous.subject.owner !== subject.owner) throw new TypeError('AI completion: conflicting usage subjects');\n shares.set(key, { subject: { ...subject }, weight: weight + (previous?.weight ?? 0) });\n }\n if (!Number.isFinite([...shares.values()].reduce((sum, share) => sum + share.weight, 0))) throw new TypeError('AI completion: invalid total weight');\n return [...shares.values()];\n}\n\n/** Highest-averages rounding is monotone: settling a larger total never needs to refund a user. */\nfunction allocateTokens(tokens: number, weights: readonly number[]): number[] {\n const total = weights.reduce((sum, weight) => sum + weight, 0);\n const allocated = weights.map(weight => Math.floor(tokens * (weight / total)));\n let remaining = tokens - allocated.reduce((sum, value) => sum + value, 0);\n while (remaining > 0 && weights.length) {\n let next = 0;\n for (let index = 1; index < weights.length; index++) {\n if (weights[index]! / (allocated[index]! + 1) > weights[next]! / (allocated[next]! + 1)) next = index;\n }\n const amount = Math.min(1, remaining);\n allocated[next]! += amount; remaining -= amount;\n }\n return allocated;\n}\n\nfunction requiredText(value: unknown, name: string): string {\n if (typeof value !== 'string' || !value.trim()) throw new TypeError(`AI completion: ${name} is required`);\n return value;\n}\n\n/** Untrusted text must not be able to close its data block early and continue as instructions. */\nfunction neutralizeBlockMarkers(text: string): string {\n return text.replace(/\\[(\\s*(?:end\\s+)?external_content)/giu, '[$1');\n}\n\n/** Keeps the source label from closing the data block or injecting quotes. */\nfunction sourceLabel(source: unknown): string {\n const text = String(source ?? '').replace(/[^\\p{L}\\p{N}_.:/-]+/gu, '-').slice(0, 64);\n return text || 'untrusted';\n}\n"]}
@@ -36,7 +36,9 @@ export class CapabilityIngress {
36
36
  mcp: bindMcp(mcp, owner, isActive),
37
37
  promptSections: Object.freeze([...(promptSections?.visible(owner, promptProfile) ?? [])]
38
38
  .filter((section) => !section.platforms
39
- || (turn?.origin.kind === 'im' && section.platforms.includes(turn.origin.platform)))),
39
+ || (turn?.origin.kind === 'im' && section.platforms.includes(turn.origin.platform)))
40
+ .filter((section) => !section.scopes
41
+ || (turn?.origin.kind === 'im' && section.scopes.includes(turn.origin.scope)))),
40
42
  });
41
43
  }
42
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"capability-ingress.js","sourceRoot":"","sources":["../../src/plugin-runtime/capability-ingress.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FeatureId, PluginId, RuntimeSnapshot } from '@zhin.js/plugin-runtime';\nimport { permissionHostToken, type PermissionHost } from '@zhin.js/permission';\nimport { turnPermissionSubject, type TurnAccessContext } from '../turn/turn-ingress.js';\nimport {\n type AgentIndex,\n isAgentIndex,\n agentFeatureId,\n type AgentDescriptor,\n} from '@zhin.js/agent-feature';\nimport {\n type McpIndex,\n isMcpIndex,\n mcpFeatureId,\n type McpDescriptor,\n type McpToolDescriptor,\n} from '@zhin.js/mcp-feature';\nimport {\n type SkillIndex,\n isSkillIndex,\n skillFeatureId,\n type SkillDescriptor,\n} from '@zhin.js/skill';\nimport {\n type ToolIndex,\n isToolIndex,\n toolFeatureId,\n type ToolDescriptor,\n type ToolInvocationContext,\n} from '@zhin.js/tool';\nimport {\n isPromptSectionIndex,\n promptSectionFeatureId,\n type PromptSectionDescriptor,\n type PromptProfile,\n} from '@zhin.js/prompt-section';\nimport { capabilitySeamToken } from '../seam/tokens.js';\nimport type { SeamIntegration } from '../seam/seam-integration.js';\n\nexport interface ToolCapability extends ToolDescriptor {\n execute<TInput = unknown, TResult = unknown>(\n input: TInput,\n invocation: ToolInvocationContext,\n ): Promise<TResult>;\n}\n\nexport interface McpCapability extends McpDescriptor {\n listTools(): Promise<readonly McpToolDescriptor[]>;\n callTool<TResult = unknown>(tool: string, input: unknown): Promise<TResult>;\n}\n\nexport interface AgentCapabilities {\n readonly generation: number;\n readonly owner: PluginId;\n readonly tools: readonly ToolCapability[];\n readonly skills: readonly SkillDescriptor[];\n readonly agents: readonly AgentDescriptor[];\n readonly mcp: readonly McpCapability[];\n readonly promptSections: readonly PromptSectionDescriptor[];\n}\n\nexport class CapabilityIngress {\n async read(\n snapshot: RuntimeSnapshot,\n owner: PluginId,\n isActive: () => boolean = () => true,\n turn?: TurnAccessContext,\n selectedAgent?: string,\n ): Promise<AgentCapabilities> {\n if (!snapshot.tree.has(owner)) throw new Error(`Unknown Agent capability owner: ${owner}`);\n const tools = projection(snapshot, toolFeatureId, isToolIndex);\n const mcp = projection(snapshot, mcpFeatureId, isMcpIndex);\n const promptProjection = snapshot.projections.get(promptSectionFeatureId);\n const promptSections = isPromptSectionIndex(promptProjection) ? promptProjection : undefined;\n const promptProfile: PromptProfile = turn?.origin.kind === 'schedule' ? 'schedule' : 'interactive';\n const featureTools = await bindTools(\n tools,\n owner,\n isActive,\n turn,\n resolvePermissionHost(snapshot),\n selectedAgent,\n snapshot,\n );\n const featureSkills = await bindSkills(\n projection(snapshot, skillFeatureId, isSkillIndex),\n turn,\n resolvePermissionHost(snapshot),\n selectedAgent,\n );\n const seam = resolveSeamIntegration(snapshot);\n const seamTools = seam\n ? await bindSeamTools(seam, owner, isActive, turn, resolvePermissionHost(snapshot))\n : [];\n const seamSkills = seam\n ? await bindSeamSkills(seam, owner, turn, resolvePermissionHost(snapshot))\n : [];\n assertDistinctCapabilities('Tool', [...featureTools, ...seamTools]);\n assertDistinctCapabilities(\n 'Skill',\n [...featureSkills, ...seamSkills].map((skill) => ({ name: skill.qualifiedName })),\n );\n const featureAgents = await bindAgents(\n projection(snapshot, agentFeatureId, isAgentIndex),\n owner,\n turn,\n resolvePermissionHost(snapshot),\n );\n return Object.freeze({\n generation: snapshot.generation,\n owner,\n tools: Object.freeze([...featureTools, ...seamTools]),\n skills: Object.freeze([...featureSkills, ...seamSkills]),\n agents: featureAgents,\n mcp: bindMcp(mcp, owner, isActive),\n promptSections: Object.freeze([...(promptSections?.visible(owner, promptProfile) ?? [])]\n .filter((section) => !section.platforms\n || (turn?.origin.kind === 'im' && section.platforms.includes(turn.origin.platform)))),\n });\n }\n}\n\nasync function bindAgents(\n index: AgentIndex | undefined,\n owner: PluginId,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n): Promise<readonly AgentDescriptor[]> {\n if (!index) return Object.freeze([]);\n const access = await Promise.all(index.visible(owner).map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nfunction resolveSeamIntegration(snapshot: RuntimeSnapshot): SeamIntegration | undefined {\n const value = snapshot.resources.get(snapshot.root)?.get(capabilitySeamToken.id);\n return value\n && typeof (value as SeamIntegration).projectTools === 'function'\n && typeof (value as SeamIntegration).projectSkills === 'function'\n ? value as SeamIntegration\n : undefined;\n}\n\nasync function bindSeamTools(\n seam: SeamIntegration,\n owner: PluginId,\n isActive: () => boolean,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n): Promise<readonly ToolCapability[]> {\n const projected = seam.projectTools(String(owner)).map((entry) => Object.freeze({\n owner,\n name: entry.schema.function.name,\n qualifiedName: entry.schema.function.name,\n description: entry.schema.function.description,\n inputSchema: entry.schema.function.parameters,\n requiresApproval: entry.schema.requiresApproval ?? 'on-risk',\n platforms: entry.schema.platforms,\n scopes: entry.schema.scopes,\n permissions: entry.schema.permissions,\n hidden: entry.schema.hidden,\n source: entry.schema.source ?? `seam:${entry.providerId}`,\n execute: async <TInput = unknown, TResult = unknown>(\n input: TInput,\n invocation: ToolInvocationContext,\n ): Promise<TResult> => {\n assertActive(isActive);\n const result = await entry.execute(input, invocation);\n if (!result.success) throw new Error(result.error ?? `Seam Tool failed: ${entry.schema.function.name}`);\n return result.output as TResult;\n },\n } satisfies ToolCapability));\n const access = await Promise.all(projected.map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nasync function bindSeamSkills(\n seam: SeamIntegration,\n owner: PluginId,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n): Promise<readonly SkillDescriptor[]> {\n const projected = (await seam.projectSkills(String(owner))).map((entry) => Object.freeze({\n $feature: 'zhin.skill/1' as const,\n owner,\n name: entry.metadata.name,\n qualifiedName: entry.metadata.name,\n description: entry.metadata.description,\n instructions: entry.instructions,\n toolNames: entry.metadata.toolNames,\n platforms: entry.metadata.platforms,\n scopes: entry.metadata.scopes,\n permissions: entry.metadata.permissions,\n keywords: entry.metadata.keywords,\n tags: entry.metadata.tags,\n always: entry.metadata.always,\n source: `seam:${entry.providerId}`,\n } satisfies SkillDescriptor));\n const access = await Promise.all(projected.map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nasync function bindSkills(\n index: SkillIndex | undefined,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n selectedAgent?: string,\n): Promise<readonly SkillDescriptor[]> {\n if (!index) return Object.freeze([]);\n const access = await Promise.all(index.list().map(async (descriptor) => ({\n descriptor,\n allowed: belongsToSelectedAgent(descriptor.agentName, selectedAgent)\n && await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nfunction belongsToSelectedAgent(agentName: string | undefined, selectedAgent: string | undefined): boolean {\n if (!agentName) return true;\n return selectedAgent === agentName || selectedAgent?.endsWith(`__${agentName}`) === true;\n}\n\nfunction assertDistinctCapabilities(\n kind: 'Tool' | 'Skill',\n capabilities: readonly { name: string }[],\n): void {\n const names = new Set<string>();\n for (const capability of capabilities) {\n if (names.has(capability.name)) throw new Error(`Duplicate Agent ${kind} capability: ${capability.name}`);\n names.add(capability.name);\n }\n}\n\nasync function bindTools(\n index: ToolIndex | undefined,\n owner: PluginId,\n isActive: () => boolean,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n selectedAgent?: string,\n operationSnapshot?: RuntimeSnapshot,\n): Promise<readonly ToolCapability[]> {\n if (!index) return Object.freeze([]);\n const descriptors = index.list();\n const accessResults = await Promise.all(\n descriptors.map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })),\n );\n return Object.freeze(accessResults\n .filter((r) => r.allowed)\n .map((r) => Object.freeze({\n ...r.descriptor,\n hidden: isSelectedAgentTool(r.descriptor.placement, selectedAgent)\n ? false\n : r.descriptor.hidden,\n name: r.descriptor.qualifiedName,\n execute: <TInput, TResult>(input: TInput, invocation: ToolInvocationContext) => {\n assertActive(isActive);\n return index.execute<TInput, TResult>(r.descriptor.owner, r.descriptor.name, input, invocation, operationSnapshot);\n },\n })));\n}\n\nfunction isSelectedAgentTool(\n placement: ToolDescriptor['placement'],\n selectedAgent: string | undefined,\n): boolean {\n return placement?.kind === 'agent'\n && belongsToSelectedAgent(placement.agent, selectedAgent);\n}\n\nasync function canAccessDescriptor(\n descriptor: Pick<ToolDescriptor, 'platforms' | 'scopes' | 'permissions'>,\n turn: TurnAccessContext | undefined,\n host?: PermissionHost,\n): Promise<boolean> {\n if (descriptor.platforms?.length) {\n if (turn?.origin.kind !== 'im' || !descriptor.platforms.includes(turn.origin.platform)) {\n return false;\n }\n }\n if (descriptor.scopes?.length) {\n if (turn?.origin.kind !== 'im' || !descriptor.scopes.includes(turn.origin.scope)) {\n return false;\n }\n }\n if (!descriptor.permissions?.length) return true;\n if (!turn || !host) return false;\n return host.checkAll(descriptor.permissions, turnPermissionSubject(turn));\n}\n\n/** Root resources 上的 PermissionHost(command-index 同款解析;未安装时 fail-closed)。 */\nfunction resolvePermissionHost(snapshot: RuntimeSnapshot): PermissionHost | undefined {\n try {\n const resources = snapshot.resources.get(snapshot.root);\n const host = resources?.get(permissionHostToken.id);\n return host && typeof (host as PermissionHost).check === 'function'\n ? host as PermissionHost\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction bindMcp(\n index: McpIndex | undefined,\n owner: PluginId,\n isActive: () => boolean,\n): readonly McpCapability[] {\n if (!index) return Object.freeze([]);\n return Object.freeze(index.visible(owner).map((descriptor) => Object.freeze({\n ...descriptor,\n listTools: () => {\n assertActive(isActive);\n return index.listTools(owner, descriptor.name);\n },\n callTool: <TResult>(tool: string, input: unknown) => {\n assertActive(isActive);\n return index.callTool<TResult>(owner, descriptor.name, tool, input);\n },\n })));\n}\n\nfunction assertActive(isActive: () => boolean): void {\n if (!isActive()) throw new Error('Agent capability turn scope has ended');\n}\n\nfunction projection<T>(\n snapshot: RuntimeSnapshot,\n id: FeatureId,\n guard: (value: unknown) => value is T,\n): T | undefined {\n const value = snapshot.projections.get(id);\n return guard(value) ? value : undefined;\n}\n"]}
1
+ {"version":3,"file":"capability-ingress.js","sourceRoot":"","sources":["../../src/plugin-runtime/capability-ingress.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAA0B,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAEL,YAAY,EACZ,cAAc,GAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,UAAU,EACV,YAAY,GAGb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,YAAY,EACZ,cAAc,GAEf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,WAAW,EACX,aAAa,GAGd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GAGvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAyBxD,MAAM,OAAO,iBAAiB;IAC5B,KAAK,CAAC,IAAI,CACR,QAAyB,EACzB,KAAe,EACf,WAA0B,GAAG,EAAE,CAAC,IAAI,EACpC,IAAwB,EACxB,aAAsB;QAEtB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,KAAK,EAAE,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QAC3D,MAAM,gBAAgB,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QAC1E,MAAM,cAAc,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7F,MAAM,aAAa,GAAkB,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC;QACnG,MAAM,YAAY,GAAG,MAAM,SAAS,CAClC,KAAK,EACL,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,aAAa,EACb,QAAQ,CACT,CAAC;QACF,MAAM,aAAa,GAAG,MAAM,UAAU,CACpC,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,YAAY,CAAC,EAClD,IAAI,EACJ,qBAAqB,CAAC,QAAQ,CAAC,EAC/B,aAAa,CACd,CAAC;QACF,MAAM,IAAI,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI;YACpB,CAAC,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YACnF,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,UAAU,GAAG,IAAI;YACrB,CAAC,CAAC,MAAM,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YAC1E,CAAC,CAAC,EAAE,CAAC;QACP,0BAA0B,CAAC,MAAM,EAAE,CAAC,GAAG,YAAY,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;QACpE,0BAA0B,CACxB,OAAO,EACP,CAAC,GAAG,aAAa,EAAE,GAAG,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAClF,CAAC;QACF,MAAM,aAAa,GAAG,MAAM,UAAU,CACpC,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,YAAY,CAAC,EAClD,KAAK,EACL,IAAI,EACJ,qBAAqB,CAAC,QAAQ,CAAC,CAChC,CAAC;QACF,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,KAAK;YACL,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,SAAS,CAAC,CAAC;YACrD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,EAAE,GAAG,UAAU,CAAC,CAAC;YACxD,MAAM,EAAE,aAAa;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC;YAClC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;iBACrF,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS;mBAClC,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;iBACrF,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM;mBAC/B,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACpF,CAAC,CAAC;IACL,CAAC;CACF;AAED,KAAK,UAAU,UAAU,CACvB,KAA6B,EAC7B,KAAe,EACf,IAAwB,EACxB,IAAqB;IAErB,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAC/E,UAAU;QACV,OAAO,EAAE,MAAM,mBAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC;KAC3D,CAAC,CAAC,CAAC,CAAC;IACL,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,SAAS,sBAAsB,CAAC,QAAyB;IACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACjF,OAAO,KAAK;WACP,OAAQ,KAAyB,CAAC,YAAY,KAAK,UAAU;WAC7D,OAAQ,KAAyB,CAAC,aAAa,KAAK,UAAU;QACjE,CAAC,CAAC,KAAwB;QAC1B,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,IAAqB,EACrB,KAAe,EACf,QAAuB,EACvB,IAAwB,EACxB,IAAqB;IAErB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QAC9E,KAAK;QACL,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI;QAChC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI;QACzC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW;QAC9C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU;QAC7C,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,gBAAgB,IAAI,SAAS;QAC5D,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS;QACjC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;QAC3B,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW;QACrC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;QAC3B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,QAAQ,KAAK,CAAC,UAAU,EAAE;QACzD,OAAO,EAAE,KAAK,EACZ,KAAa,EACb,UAAiC,EACf,EAAE;YACpB,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YACtD,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,qBAAqB,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YACxG,OAAO,MAAM,CAAC,MAAiB,CAAC;QAClC,CAAC;KACuB,CAAC,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QACpE,UAAU;QACV,OAAO,EAAE,MAAM,mBAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC;KAC3D,CAAC,CAAC,CAAC,CAAC;IACL,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,IAAqB,EACrB,KAAe,EACf,IAAwB,EACxB,IAAqB;IAErB,MAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QACvF,QAAQ,EAAE,cAAuB;QACjC,KAAK;QACL,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;QACzB,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;QAClC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW;QACvC,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS;QACnC,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS;QACnC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;QAC7B,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW;QACvC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ;QACjC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;QACzB,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;QAC7B,MAAM,EAAE,QAAQ,KAAK,CAAC,UAAU,EAAE;KACT,CAAC,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QACpE,UAAU;QACV,OAAO,EAAE,MAAM,mBAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC;KAC3D,CAAC,CAAC,CAAC,CAAC;IACL,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,KAA6B,EAC7B,IAAwB,EACxB,IAAqB,EACrB,aAAsB;IAEtB,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QACvE,UAAU;QACV,OAAO,EAAE,sBAAsB,CAAC,UAAU,CAAC,SAAS,EAAE,aAAa,CAAC;eAC/D,MAAM,mBAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC;KACvD,CAAC,CAAC,CAAC,CAAC;IACL,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,SAAS,sBAAsB,CAAC,SAA6B,EAAE,aAAiC;IAC9F,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,aAAa,KAAK,SAAS,IAAI,aAAa,EAAE,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC,KAAK,IAAI,CAAC;AAC3F,CAAC;AAED,SAAS,0BAA0B,CACjC,IAAsB,EACtB,YAAyC;IAEzC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,gBAAgB,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1G,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,KAA4B,EAC5B,KAAe,EACf,QAAuB,EACvB,IAAwB,EACxB,IAAqB,EACrB,aAAsB,EACtB,iBAAmC;IAEnC,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACjC,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,GAAG,CACrC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QACrC,UAAU;QACV,OAAO,EAAE,MAAM,mBAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC;KAC3D,CAAC,CAAC,CACJ,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa;SAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QACxB,GAAG,CAAC,CAAC,UAAU;QACf,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,EAAE,aAAa,CAAC;YAChE,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM;QACvB,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,aAAa;QAChC,OAAO,EAAE,CAAkB,KAAa,EAAE,UAAiC,EAAE,EAAE;YAC7E,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvB,OAAO,KAAK,CAAC,OAAO,CAAkB,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;QACrH,CAAC;KACF,CAAC,CAAC,CAAC,CAAC;AACT,CAAC;AAED,SAAS,mBAAmB,CAC1B,SAAsC,EACtC,aAAiC;IAEjC,OAAO,SAAS,EAAE,IAAI,KAAK,OAAO;WAC7B,sBAAsB,CAAC,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;AAC9D,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,UAAwE,EACxE,IAAmC,EACnC,IAAqB;IAErB,IAAI,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QACjC,IAAI,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAC9B,IAAI,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACjF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,EAAE,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,6EAA6E;AAC7E,SAAS,qBAAqB,CAAC,QAAyB;IACtD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,SAAS,EAAE,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;QACpD,OAAO,IAAI,IAAI,OAAQ,IAAuB,CAAC,KAAK,KAAK,UAAU;YACjE,CAAC,CAAC,IAAsB;YACxB,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CACd,KAA2B,EAC3B,KAAe,EACf,QAAuB;IAEvB,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QAC1E,GAAG,UAAU;QACb,SAAS,EAAE,GAAG,EAAE;YACd,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvB,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QACD,QAAQ,EAAE,CAAU,IAAY,EAAE,KAAc,EAAE,EAAE;YAClD,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvB,OAAO,KAAK,CAAC,QAAQ,CAAU,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACtE,CAAC;KACF,CAAC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,YAAY,CAAC,QAAuB;IAC3C,IAAI,CAAC,QAAQ,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,UAAU,CACjB,QAAyB,EACzB,EAAa,EACb,KAAqC;IAErC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC","sourcesContent":["import type { FeatureId, PluginId, RuntimeSnapshot } from '@zhin.js/plugin-runtime';\nimport { permissionHostToken, type PermissionHost } from '@zhin.js/permission';\nimport { turnPermissionSubject, type TurnAccessContext } from '../turn/turn-ingress.js';\nimport {\n type AgentIndex,\n isAgentIndex,\n agentFeatureId,\n type AgentDescriptor,\n} from '@zhin.js/agent-feature';\nimport {\n type McpIndex,\n isMcpIndex,\n mcpFeatureId,\n type McpDescriptor,\n type McpToolDescriptor,\n} from '@zhin.js/mcp-feature';\nimport {\n type SkillIndex,\n isSkillIndex,\n skillFeatureId,\n type SkillDescriptor,\n} from '@zhin.js/skill';\nimport {\n type ToolIndex,\n isToolIndex,\n toolFeatureId,\n type ToolDescriptor,\n type ToolInvocationContext,\n} from '@zhin.js/tool';\nimport {\n isPromptSectionIndex,\n promptSectionFeatureId,\n type PromptSectionDescriptor,\n type PromptProfile,\n} from '@zhin.js/prompt-section';\nimport { capabilitySeamToken } from '../seam/tokens.js';\nimport type { SeamIntegration } from '../seam/seam-integration.js';\n\nexport interface ToolCapability extends ToolDescriptor {\n execute<TInput = unknown, TResult = unknown>(\n input: TInput,\n invocation: ToolInvocationContext,\n ): Promise<TResult>;\n}\n\nexport interface McpCapability extends McpDescriptor {\n listTools(): Promise<readonly McpToolDescriptor[]>;\n callTool<TResult = unknown>(tool: string, input: unknown): Promise<TResult>;\n}\n\nexport interface AgentCapabilities {\n readonly generation: number;\n readonly owner: PluginId;\n readonly tools: readonly ToolCapability[];\n readonly skills: readonly SkillDescriptor[];\n readonly agents: readonly AgentDescriptor[];\n readonly mcp: readonly McpCapability[];\n readonly promptSections: readonly PromptSectionDescriptor[];\n}\n\nexport class CapabilityIngress {\n async read(\n snapshot: RuntimeSnapshot,\n owner: PluginId,\n isActive: () => boolean = () => true,\n turn?: TurnAccessContext,\n selectedAgent?: string,\n ): Promise<AgentCapabilities> {\n if (!snapshot.tree.has(owner)) throw new Error(`Unknown Agent capability owner: ${owner}`);\n const tools = projection(snapshot, toolFeatureId, isToolIndex);\n const mcp = projection(snapshot, mcpFeatureId, isMcpIndex);\n const promptProjection = snapshot.projections.get(promptSectionFeatureId);\n const promptSections = isPromptSectionIndex(promptProjection) ? promptProjection : undefined;\n const promptProfile: PromptProfile = turn?.origin.kind === 'schedule' ? 'schedule' : 'interactive';\n const featureTools = await bindTools(\n tools,\n owner,\n isActive,\n turn,\n resolvePermissionHost(snapshot),\n selectedAgent,\n snapshot,\n );\n const featureSkills = await bindSkills(\n projection(snapshot, skillFeatureId, isSkillIndex),\n turn,\n resolvePermissionHost(snapshot),\n selectedAgent,\n );\n const seam = resolveSeamIntegration(snapshot);\n const seamTools = seam\n ? await bindSeamTools(seam, owner, isActive, turn, resolvePermissionHost(snapshot))\n : [];\n const seamSkills = seam\n ? await bindSeamSkills(seam, owner, turn, resolvePermissionHost(snapshot))\n : [];\n assertDistinctCapabilities('Tool', [...featureTools, ...seamTools]);\n assertDistinctCapabilities(\n 'Skill',\n [...featureSkills, ...seamSkills].map((skill) => ({ name: skill.qualifiedName })),\n );\n const featureAgents = await bindAgents(\n projection(snapshot, agentFeatureId, isAgentIndex),\n owner,\n turn,\n resolvePermissionHost(snapshot),\n );\n return Object.freeze({\n generation: snapshot.generation,\n owner,\n tools: Object.freeze([...featureTools, ...seamTools]),\n skills: Object.freeze([...featureSkills, ...seamSkills]),\n agents: featureAgents,\n mcp: bindMcp(mcp, owner, isActive),\n promptSections: Object.freeze([...(promptSections?.visible(owner, promptProfile) ?? [])]\n .filter((section) => !section.platforms\n || (turn?.origin.kind === 'im' && section.platforms.includes(turn.origin.platform)))\n .filter((section) => !section.scopes\n || (turn?.origin.kind === 'im' && section.scopes.includes(turn.origin.scope)))),\n });\n }\n}\n\nasync function bindAgents(\n index: AgentIndex | undefined,\n owner: PluginId,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n): Promise<readonly AgentDescriptor[]> {\n if (!index) return Object.freeze([]);\n const access = await Promise.all(index.visible(owner).map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nfunction resolveSeamIntegration(snapshot: RuntimeSnapshot): SeamIntegration | undefined {\n const value = snapshot.resources.get(snapshot.root)?.get(capabilitySeamToken.id);\n return value\n && typeof (value as SeamIntegration).projectTools === 'function'\n && typeof (value as SeamIntegration).projectSkills === 'function'\n ? value as SeamIntegration\n : undefined;\n}\n\nasync function bindSeamTools(\n seam: SeamIntegration,\n owner: PluginId,\n isActive: () => boolean,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n): Promise<readonly ToolCapability[]> {\n const projected = seam.projectTools(String(owner)).map((entry) => Object.freeze({\n owner,\n name: entry.schema.function.name,\n qualifiedName: entry.schema.function.name,\n description: entry.schema.function.description,\n inputSchema: entry.schema.function.parameters,\n requiresApproval: entry.schema.requiresApproval ?? 'on-risk',\n platforms: entry.schema.platforms,\n scopes: entry.schema.scopes,\n permissions: entry.schema.permissions,\n hidden: entry.schema.hidden,\n source: entry.schema.source ?? `seam:${entry.providerId}`,\n execute: async <TInput = unknown, TResult = unknown>(\n input: TInput,\n invocation: ToolInvocationContext,\n ): Promise<TResult> => {\n assertActive(isActive);\n const result = await entry.execute(input, invocation);\n if (!result.success) throw new Error(result.error ?? `Seam Tool failed: ${entry.schema.function.name}`);\n return result.output as TResult;\n },\n } satisfies ToolCapability));\n const access = await Promise.all(projected.map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nasync function bindSeamSkills(\n seam: SeamIntegration,\n owner: PluginId,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n): Promise<readonly SkillDescriptor[]> {\n const projected = (await seam.projectSkills(String(owner))).map((entry) => Object.freeze({\n $feature: 'zhin.skill/1' as const,\n owner,\n name: entry.metadata.name,\n qualifiedName: entry.metadata.name,\n description: entry.metadata.description,\n instructions: entry.instructions,\n toolNames: entry.metadata.toolNames,\n platforms: entry.metadata.platforms,\n scopes: entry.metadata.scopes,\n permissions: entry.metadata.permissions,\n keywords: entry.metadata.keywords,\n tags: entry.metadata.tags,\n always: entry.metadata.always,\n source: `seam:${entry.providerId}`,\n } satisfies SkillDescriptor));\n const access = await Promise.all(projected.map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nasync function bindSkills(\n index: SkillIndex | undefined,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n selectedAgent?: string,\n): Promise<readonly SkillDescriptor[]> {\n if (!index) return Object.freeze([]);\n const access = await Promise.all(index.list().map(async (descriptor) => ({\n descriptor,\n allowed: belongsToSelectedAgent(descriptor.agentName, selectedAgent)\n && await canAccessDescriptor(descriptor, turn, host),\n })));\n return Object.freeze(access.filter(({ allowed }) => allowed).map(({ descriptor }) => descriptor));\n}\n\nfunction belongsToSelectedAgent(agentName: string | undefined, selectedAgent: string | undefined): boolean {\n if (!agentName) return true;\n return selectedAgent === agentName || selectedAgent?.endsWith(`__${agentName}`) === true;\n}\n\nfunction assertDistinctCapabilities(\n kind: 'Tool' | 'Skill',\n capabilities: readonly { name: string }[],\n): void {\n const names = new Set<string>();\n for (const capability of capabilities) {\n if (names.has(capability.name)) throw new Error(`Duplicate Agent ${kind} capability: ${capability.name}`);\n names.add(capability.name);\n }\n}\n\nasync function bindTools(\n index: ToolIndex | undefined,\n owner: PluginId,\n isActive: () => boolean,\n turn?: TurnAccessContext,\n host?: PermissionHost,\n selectedAgent?: string,\n operationSnapshot?: RuntimeSnapshot,\n): Promise<readonly ToolCapability[]> {\n if (!index) return Object.freeze([]);\n const descriptors = index.list();\n const accessResults = await Promise.all(\n descriptors.map(async (descriptor) => ({\n descriptor,\n allowed: await canAccessDescriptor(descriptor, turn, host),\n })),\n );\n return Object.freeze(accessResults\n .filter((r) => r.allowed)\n .map((r) => Object.freeze({\n ...r.descriptor,\n hidden: isSelectedAgentTool(r.descriptor.placement, selectedAgent)\n ? false\n : r.descriptor.hidden,\n name: r.descriptor.qualifiedName,\n execute: <TInput, TResult>(input: TInput, invocation: ToolInvocationContext) => {\n assertActive(isActive);\n return index.execute<TInput, TResult>(r.descriptor.owner, r.descriptor.name, input, invocation, operationSnapshot);\n },\n })));\n}\n\nfunction isSelectedAgentTool(\n placement: ToolDescriptor['placement'],\n selectedAgent: string | undefined,\n): boolean {\n return placement?.kind === 'agent'\n && belongsToSelectedAgent(placement.agent, selectedAgent);\n}\n\nasync function canAccessDescriptor(\n descriptor: Pick<ToolDescriptor, 'platforms' | 'scopes' | 'permissions'>,\n turn: TurnAccessContext | undefined,\n host?: PermissionHost,\n): Promise<boolean> {\n if (descriptor.platforms?.length) {\n if (turn?.origin.kind !== 'im' || !descriptor.platforms.includes(turn.origin.platform)) {\n return false;\n }\n }\n if (descriptor.scopes?.length) {\n if (turn?.origin.kind !== 'im' || !descriptor.scopes.includes(turn.origin.scope)) {\n return false;\n }\n }\n if (!descriptor.permissions?.length) return true;\n if (!turn || !host) return false;\n return host.checkAll(descriptor.permissions, turnPermissionSubject(turn));\n}\n\n/** Root resources 上的 PermissionHost(command-index 同款解析;未安装时 fail-closed)。 */\nfunction resolvePermissionHost(snapshot: RuntimeSnapshot): PermissionHost | undefined {\n try {\n const resources = snapshot.resources.get(snapshot.root);\n const host = resources?.get(permissionHostToken.id);\n return host && typeof (host as PermissionHost).check === 'function'\n ? host as PermissionHost\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction bindMcp(\n index: McpIndex | undefined,\n owner: PluginId,\n isActive: () => boolean,\n): readonly McpCapability[] {\n if (!index) return Object.freeze([]);\n return Object.freeze(index.visible(owner).map((descriptor) => Object.freeze({\n ...descriptor,\n listTools: () => {\n assertActive(isActive);\n return index.listTools(owner, descriptor.name);\n },\n callTool: <TResult>(tool: string, input: unknown) => {\n assertActive(isActive);\n return index.callTool<TResult>(owner, descriptor.name, tool, input);\n },\n })));\n}\n\nfunction assertActive(isActive: () => boolean): void {\n if (!isActive()) throw new Error('Agent capability turn scope has ended');\n}\n\nfunction projection<T>(\n snapshot: RuntimeSnapshot,\n id: FeatureId,\n guard: (value: unknown) => value is T,\n): T | undefined {\n const value = snapshot.projections.get(id);\n return guard(value) ? value : undefined;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type AgentTool, type DeferredToolSessionSnapshot } from '@zhin.js/ai';
1
+ import { type AgentTool, type TextContentBlock, type DeferredToolSessionSnapshot } from '@zhin.js/ai';
2
2
  import type { SkillDescriptor } from '@zhin.js/skill';
3
3
  import type { AgentDecisionRuntime } from '../decision/types.js';
4
4
  import { resolveDeferredToolsConfig } from '../tool-catalog/resolve-config.js';
@@ -25,6 +25,9 @@ export declare function isReservedControlToolName(name: string): boolean;
25
25
  export interface DeferredCapabilityController {
26
26
  loadedToolNames(): string[];
27
27
  loadedSkillInstructions(): string[];
28
+ loadedSkillBlocks(): TextContentBlock[];
29
+ /** Marks only a successful, unmodified runtime load_skill result. */
30
+ modelOutputBlocks(name: string, args: unknown, text: string): TextContentBlock[] | undefined;
28
31
  /** Load a public catalog tool into the session. Returns false when it is not in this turn's catalog. */
29
32
  load(name: string): Promise<boolean>;
30
33
  }