@finalai/agent-definition 0.1.2 → 0.1.4
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.
- package/HOSTING.md +234 -0
- package/README.md +7 -0
- package/dist/compiler-assets/{chunk-TATN3PYK.ts → chunk-2ZRYQO4Q.ts} +4 -4
- package/dist/compiler-assets/{chunk-HGW4YHAY.ts → chunk-3K4C4SVG.ts} +9 -0
- package/dist/compiler-assets/{chunk-7VSSVZM4.ts → chunk-4A66SVBJ.ts} +4 -4
- package/dist/compiler-assets/{chunk-CWWRTRWW.ts → chunk-4E5HECVD.ts} +1 -1
- package/dist/compiler-assets/{chunk-7QP2CKPI.ts → chunk-4X2DS5BR.ts} +1 -1
- package/dist/compiler-assets/{chunk-ZDLVA6XF.ts → chunk-5NTKRRMC.ts} +112 -21
- package/dist/compiler-assets/{chunk-2CZRHOLL.ts → chunk-7XUPKRZU.ts} +1 -1
- package/dist/compiler-assets/{chunk-OWC6SFFF.ts → chunk-APU2VKLW.ts} +52 -12
- package/dist/compiler-assets/{chunk-HFS4KLEL.ts → chunk-D3SB4CCB.ts} +1 -1
- package/dist/compiler-assets/{chunk-HNPUTP35.ts → chunk-GCFSHHH2.ts} +2 -2
- package/dist/compiler-assets/{chunk-5BK6FVRE.ts → chunk-IF6MR7JF.ts} +2 -2
- package/dist/compiler-assets/{chunk-LUSAAV4L.ts → chunk-IZGOMT7K.ts} +2 -2
- package/dist/compiler-assets/{chunk-GTUZOATD.ts → chunk-JGQ2KAN7.ts} +1 -1
- package/dist/compiler-assets/{chunk-NYTOYKKF.ts → chunk-K6D7ZK74.ts} +3 -3
- package/dist/compiler-assets/{chunk-WMXMVFHM.ts → chunk-K7V4IMOB.ts} +3 -3
- package/dist/compiler-assets/{chunk-VHXHUU7L.ts → chunk-LHMUAIYJ.ts} +1 -1
- package/dist/compiler-assets/{chunk-SKTNMUO7.ts → chunk-MSE7X5YG.ts} +25 -2
- package/dist/compiler-assets/chunk-PFLSBTJA.ts +39 -0
- package/dist/compiler-assets/{chunk-XHKPWT3G.ts → chunk-QJ26GEUM.ts} +1 -1
- package/dist/compiler-assets/{chunk-JPY4L2UJ.ts → chunk-RIEMTCTV.ts} +12 -8
- package/dist/compiler-assets/chunk-RMIQJHSL.ts +0 -0
- package/dist/compiler-assets/chunk-TJ536HI4.ts +61 -0
- package/dist/compiler-assets/{chunk-QMWTDPNT.ts → chunk-TJZS457N.ts} +3 -3
- package/dist/compiler-assets/{chunk-JIPNTA56.ts → chunk-TM36NO3C.ts} +1 -1
- package/dist/compiler-assets/{chunk-MZMSKIKU.ts → chunk-UBR53WBH.ts} +33 -8
- package/dist/compiler-assets/chunk-ULI5WWRR.ts +40 -0
- package/dist/compiler-assets/chunk-W6DOJA4W.ts +3763 -0
- package/dist/compiler-assets/{chunk-EVQIK62B.ts → chunk-YW7HDGQA.ts} +11 -7
- package/dist/compiler-assets/{chunk-BLB6JGLO.ts → chunk-YWFGIPHD.ts} +27 -24
- package/dist/compiler-assets/{chunk-QMKWAFVZ.ts → chunk-Z5TO7RSJ.ts} +5 -3
- package/dist/compiler-assets/src/authoring/agent.ts +4 -4
- package/dist/compiler-assets/src/authoring/approval.ts +7 -7
- package/dist/compiler-assets/src/authoring/brand.ts +3 -3
- package/dist/compiler-assets/src/authoring/channels.ts +6 -6
- package/dist/compiler-assets/src/authoring/connections.ts +14 -4
- package/dist/compiler-assets/src/authoring/credentials.ts +7 -6
- package/dist/compiler-assets/src/authoring/dynamic.ts +9 -4
- package/dist/compiler-assets/src/authoring/harness.ts +9 -9
- package/dist/compiler-assets/src/authoring/hooks.ts +10 -8
- package/dist/compiler-assets/src/authoring/index.ts +33 -26
- package/dist/compiler-assets/src/authoring/instructions.ts +10 -5
- package/dist/compiler-assets/src/authoring/sandbox.ts +10 -10
- package/dist/compiler-assets/src/authoring/schedules.ts +4 -4
- package/dist/compiler-assets/src/authoring/skills.ts +4 -4
- package/dist/compiler-assets/src/authoring/tools.ts +10 -8
- package/dist/compiler-assets/src/compatibility.ts +11 -11
- package/dist/compiler-assets/src/hosted-bindings.ts +15 -0
- package/dist/compiler-assets/src/index.ts +54 -41
- package/dist/compiler-assets/src/manifest.ts +8 -4
- package/dist/compiler-assets/src/resolve.ts +5 -5
- package/dist/compiler-assets/src/runtime/bundle.ts +22 -20
- package/dist/compiler-assets/src/runtime/describe.ts +14 -12
- package/dist/compiler-assets/src/runtime/described.ts +19 -12
- package/dist/compiler-assets/src/runtime/isolate.ts +18 -16
- package/dist/compiler-assets/src/runtime/lower.ts +13 -11
- package/dist/compiler-assets/src/runtime/schema-validation.ts +4 -4
- package/dist/compiler-assets/src/runtime/values.ts +2 -2
- package/dist/modules/authoring/agent.d.mts +3 -2
- package/dist/modules/authoring/agent.mjs.map +2 -2
- package/dist/modules/authoring/connections.d.mts +15 -2
- package/dist/modules/authoring/connections.mjs +36 -0
- package/dist/modules/authoring/connections.mjs.map +2 -2
- package/dist/modules/authoring/context.d.mts +3 -1
- package/dist/modules/authoring/context.mjs.map +2 -2
- package/dist/modules/authoring/dynamic.d.mts +3 -1
- package/dist/modules/authoring/dynamic.mjs +19 -1
- package/dist/modules/authoring/dynamic.mjs.map +2 -2
- package/dist/modules/authoring/harness.mjs +2 -0
- package/dist/modules/authoring/harness.mjs.map +2 -2
- package/dist/modules/authoring/hooks.d.mts +2 -1
- package/dist/modules/authoring/hooks.mjs.map +2 -2
- package/dist/modules/authoring/index.d.mts +4 -2
- package/dist/modules/authoring/index.mjs +4 -1
- package/dist/modules/authoring/index.mjs.map +2 -2
- package/dist/modules/authoring/sandbox.d.mts +2 -1
- package/dist/modules/authoring/sandbox.mjs.map +2 -2
- package/dist/modules/compiler/assemble.mjs +6 -1
- package/dist/modules/compiler/assemble.mjs.map +2 -2
- package/dist/modules/compiler/index.d.mts +2 -1
- package/dist/modules/compiler/index.mjs +18 -0
- package/dist/modules/compiler/index.mjs.map +2 -2
- package/dist/modules/compiler/local-isolate.d.mts +2 -1
- package/dist/modules/compiler/local-isolate.mjs +6 -1
- package/dist/modules/compiler/local-isolate.mjs.map +2 -2
- package/dist/modules/hosted-bindings.d.mts +10 -0
- package/dist/modules/hosted-bindings.mjs +36 -0
- package/dist/modules/hosted-bindings.mjs.map +7 -0
- package/dist/modules/index.d.mts +2 -0
- package/dist/modules/index.mjs +2 -0
- package/dist/modules/index.mjs.map +2 -2
- package/dist/modules/manifest.d.mts +2 -2
- package/dist/modules/manifest.mjs +4 -0
- package/dist/modules/manifest.mjs.map +2 -2
- package/dist/modules/resolve.mjs +4 -0
- package/dist/modules/resolve.mjs.map +2 -2
- package/dist/modules/runtime/describe.mjs +25 -4
- package/dist/modules/runtime/describe.mjs.map +2 -2
- package/dist/modules/runtime/described.d.mts +40 -4
- package/dist/modules/runtime/described.mjs +7 -2
- package/dist/modules/runtime/described.mjs.map +2 -2
- package/dist/modules/runtime/isolate.d.mts +2 -0
- package/dist/modules/runtime/isolate.mjs +7 -4
- package/dist/modules/runtime/isolate.mjs.map +2 -2
- package/dist/modules/runtime/lower.mjs +76 -14
- package/dist/modules/runtime/lower.mjs.map +2 -2
- package/dist/modules/runtime/schema-validation.mjs +19 -2
- package/dist/modules/runtime/schema-validation.mjs.map +2 -2
- package/fixtures/assistant/agent/agent.ts +7 -0
- package/package.json +4 -3
- package/dist/compiler-assets/chunk-GNR7XBPN.ts +0 -3364
- package/dist/compiler-assets/chunk-JNJE72EH.ts +0 -10
- package/dist/compiler-assets/chunk-T6WG4L4M.ts +0 -19
- /package/dist/compiler-assets/{chunk-6WR3PGNF.ts → chunk-CIWWFQHL.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/authoring/connections.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ApprovalPolicyIface } from \"./approval.mjs\";\nimport { AuthoredKind, stamp } from \"./brand.mjs\";\n\n// An MCP connection. Secrets are references by\n// name: the MCP host injects them, so they never reach the harness. Final's\n// own MCP server is an ordinary connection with `auth: { kind: 'final-session' }`.\n\nexport type McpConnectionAuthIface =\n // Sent as `Authorization: Bearer <secret>` when headerName is null.\n | { readonly secretKey: string; readonly headerName: string | null }\n | { readonly kind: 'final-session' };\n\nexport interface McpConnectionToolsIface {\n // Only these tools are exposed; omit to expose every tool the server lists.\n readonly allow?: readonly
|
|
5
|
-
"mappings": "AACA,SAAS,cAAc,aAAa;
|
|
4
|
+
"sourcesContent": ["import type { ApprovalPolicyIface } from \"./approval.mjs\";\nimport { AuthoredKind, stamp } from \"./brand.mjs\";\nimport { jsonObjectSchema, mcpAuthSchema, requireHostedBinding } from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { defineDynamic, type DynamicSentinelIface } from \"./dynamic.mjs\";\n\n// An MCP connection. Secrets are references by\n// name: the MCP host injects them, so they never reach the harness. Final's\n// own MCP server is an ordinary connection with `auth: { kind: 'final-session' }`.\n\nexport type McpConnectionAuthIface =\n // Sent as `Authorization: Bearer <secret>` when headerName is null.\n | { readonly secretKey: string; readonly headerName: string | null }\n | { readonly kind: 'final-session' };\n\n// Selects tools by the MCP annotations their server reports, reading omitted\n// hints as the spec's defaults: `{ readOnlyHint: true }` matches only tools\n// the server marks read-only. Use with servers you trust to classify tools.\nexport interface McpToolAnnotationSelectorIface {\n readonly readOnlyHint?: boolean;\n readonly destructiveHint?: boolean;\n readonly idempotentHint?: boolean;\n readonly openWorldHint?: boolean;\n}\n\nexport type McpToolSelector = string | McpToolAnnotationSelectorIface;\n\n// Entries and keys are tool names or `*` patterns (`github.*`), and allow and\n// deny entries may also be annotation selectors; the most specific matching\n// key governs a tool.\nexport interface McpConnectionToolsIface {\n // Only these tools are exposed; omit to expose every tool the server lists.\n // Annotation-selected tools run under the connection's default approval.\n readonly allow?: readonly McpToolSelector[];\n // These tools are hidden, whatever `allow` says.\n readonly deny?: readonly McpToolSelector[];\n // Per-tool approval; tools not listed use the connection's `approval`.\n readonly approval?: Readonly<Record<string, ApprovalPolicyIface<never>>>;\n // Exposed tools (names or `*` patterns) the harness lists up front; the rest\n // stay reachable through the host's tool search. Omit to list every exposed tool.\n readonly load?: readonly string[];\n}\n\nexport interface McpClientConnectionDefinitionIface {\n readonly url: string;\n readonly description?: string;\n readonly auth?: McpConnectionAuthIface;\n readonly headers?: Readonly<Record<string, string>>;\n readonly tools?: McpConnectionToolsIface;\n // Default approval for every tool of this connection.\n readonly approval?: ApprovalPolicyIface<never>;\n readonly protocolVersionDiscovery?: boolean;\n readonly instanceKey?: string;\n}\n\nexport const defineMcpClientConnection = <TConnection extends McpClientConnectionDefinitionIface>(\n definition: TConnection,\n): TConnection => stamp({ ...definition }, AuthoredKind.Connection);\n\nexport interface HostedConnectionDefinitionIface extends Omit<\n McpClientConnectionDefinitionIface,\n 'url' | 'auth' | 'headers' | 'protocolVersionDiscovery' | 'instanceKey'\n> {\n readonly binding: string;\n}\n\nconst hostedConnectionSchema = z.strictObject({\n url: z.string().url(),\n auth: mcpAuthSchema.nullable().optional(),\n headers: z.record(z.string(), z.string()).optional(),\n});\n\n// Built-in and third-party bindings use the ordinary dynamic connection path.\nexport const defineHostedConnection = (\n definition: HostedConnectionDefinitionIface,\n): DynamicSentinelIface<McpClientConnectionDefinitionIface> => {\n const { binding, description, tools, approval } = definition;\n if (binding.trim().length === 0) throw new Error('Hosted connection binding must not be empty');\n return defineDynamic({\n description: definition.description ?? `Hosted connection ${binding}`,\n preview: `Resolved by hosting from ${binding}`,\n requiredBindings: [\n { name: binding, schema: jsonObjectSchema.parse(z.toJSONSchema(hostedConnectionSchema)) },\n ],\n events: {\n 'session.started': async (_event, ctx) => {\n const value = await requireHostedBinding({ bindings: ctx.bindings, name: binding });\n const parsed = hostedConnectionSchema.safeParse(value);\n if (!parsed.success)\n throw new Error(`Hosted connection ${binding} has invalid configuration`);\n const { auth, ...transport } = parsed.data;\n return defineMcpClientConnection({\n ...transport,\n description,\n tools,\n approval,\n ...(auth == null ? {} : { auth }),\n });\n },\n },\n });\n};\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,cAAc,aAAa;AACpC,SAAS,kBAAkB,eAAe,4BAA4B;AACtE,YAAY,OAAO;AACnB,SAAS,qBAAgD;AAmDlD,MAAM,4BAA4B,CACvC,eACgB,MAAM,EAAE,GAAG,WAAW,GAAG,aAAa,UAAU;AASlE,MAAM,yBAAyB,EAAE,aAAa;AAAA,EAC5C,KAAK,EAAE,OAAO,EAAE,IAAI;AAAA,EACpB,MAAM,cAAc,SAAS,EAAE,SAAS;AAAA,EACxC,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AACrD,CAAC;AAGM,MAAM,yBAAyB,CACpC,eAC6D;AAC7D,QAAM,EAAE,SAAS,aAAa,OAAO,SAAS,IAAI;AAClD,MAAI,QAAQ,KAAK,EAAE,WAAW,EAAG,OAAM,IAAI,MAAM,6CAA6C;AAC9F,SAAO,cAAc;AAAA,IACnB,aAAa,WAAW,eAAe,qBAAqB,OAAO;AAAA,IACnE,SAAS,4BAA4B,OAAO;AAAA,IAC5C,kBAAkB;AAAA,MAChB,EAAE,MAAM,SAAS,QAAQ,iBAAiB,MAAM,EAAE,aAAa,sBAAsB,CAAC,EAAE;AAAA,IAC1F;AAAA,IACA,QAAQ;AAAA,MACN,mBAAmB,OAAO,QAAQ,QAAQ;AACxC,cAAM,QAAQ,MAAM,qBAAqB,EAAE,UAAU,IAAI,UAAU,MAAM,QAAQ,CAAC;AAClF,cAAM,SAAS,uBAAuB,UAAU,KAAK;AACrD,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,MAAM,qBAAqB,OAAO,4BAA4B;AAC1E,cAAM,EAAE,MAAM,GAAG,UAAU,IAAI,OAAO;AACtC,eAAO,0BAA0B;AAAA,UAC/B,GAAG;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA,GAAI,QAAQ,OAAO,CAAC,IAAI,EAAE,KAAK;AAAA,QACjC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ConversationMessageIface } from '@finalai/agent-protocol/agent-platform';
|
|
2
|
-
import type { ConversationKind, JsonObject, JsonValue, NetworkSandboxSessionIface, ParticipantKind, ProviderRef } from '@finalai/agent-provider';
|
|
2
|
+
import type { ConversationKind, HostedBindingsIface, JsonObject, JsonValue, NetworkSandboxSessionIface, ParticipantKind, ProviderRef } from '@finalai/agent-provider';
|
|
3
3
|
export interface ParticipantInfoIface {
|
|
4
4
|
id: string;
|
|
5
5
|
kind: ParticipantKind;
|
|
@@ -63,6 +63,7 @@ export interface FinalPlatformClientIface {
|
|
|
63
63
|
}): Promise<ConversationMessageIface[]>;
|
|
64
64
|
}
|
|
65
65
|
export interface ToolContextIface {
|
|
66
|
+
readonly bindings?: HostedBindingsIface;
|
|
66
67
|
readonly session: AgentSessionInfoIface;
|
|
67
68
|
readonly callId: string;
|
|
68
69
|
readonly toolName: string;
|
|
@@ -73,6 +74,7 @@ export interface ToolContextIface {
|
|
|
73
74
|
readonly final: FinalPlatformClientIface;
|
|
74
75
|
}
|
|
75
76
|
export interface DynamicResolveContextIface {
|
|
77
|
+
readonly bindings?: HostedBindingsIface;
|
|
76
78
|
readonly previousValue?: JsonValue | null;
|
|
77
79
|
readonly session: AgentSessionInfoIface;
|
|
78
80
|
readonly messages: readonly TranscriptMessageIface[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/authoring/context.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ConversationMessageIface } from '@finalai/agent-protocol/agent-platform';\nimport type {\n ConversationKind,\n JsonObject,\n JsonValue,\n NetworkSandboxSessionIface,\n ParticipantKind,\n ProviderRef,\n} from '@finalai/agent-provider';\n\n// What authored code (tools, hooks, dynamic resolvers, channel routes) sees of\n// the session it runs for. Everything is provided by\n// the session service through the Worker isolate; none of it is harness state.\n//\n// Ids are the public API's wire ids (`<prefix>_<base58>`), the same strings the\n// client SDK and `/api/v1` return: a session is `ases_\u2026`, a conversation\n// `conv_\u2026`, a participant `cpart_\u2026`, a turn `atrn_\u2026`, a user `usr_\u2026`. Pass them\n// back unchanged (`ctx.final.post({ conversationId })`, channel platform\n// calls); raw UUIDs are refused. ACP ids (`toolCallId`, prompt message ids)\n// and provider or model ids are passed through as the harness sent them.\n\nexport interface ParticipantInfoIface {\n // `cpart_\u2026`; `userId` is `usr_\u2026`.\n id: string;\n kind: ParticipantKind;\n displayName: string;\n userId: string | null;\n}\n\nexport interface ConversationInfoIface {\n // `conv_\u2026`, as `client` and `/api/v1/conversations` name it.\n id: string;\n kind: ConversationKind;\n title: string | null;\n metadata: JsonObject;\n participants: ParticipantInfoIface[];\n}\n\nexport interface PromptAuthorIface {\n participantId: string | null;\n userId: string | null;\n displayName: string;\n}\n\nexport interface AgentSessionInfoIface {\n // `ases_\u2026`: what `client.sessions.attach(id)` takes.\n id: string;\n // `org_\u2026`.\n organizationId: string;\n // The agent (`adef_\u2026`) and its published revision (`arev_\u2026`).\n definitionId: string;\n revisionId: string;\n conversation: ConversationInfoIface | null;\n // Who prompted the current turn; null outside a turn and for system input.\n author: PromptAuthorIface | null;\n // `atrn_\u2026`.\n turn: { id: string } | null;\n harness: ProviderRef;\n}\n\nexport enum TranscriptRole {\n User = 'user',\n Assistant = 'assistant',\n Tool = 'tool',\n Thought = 'thought',\n Summary = 'summary',\n}\n\n// One entry of the transcript rebuilt from the session's ACP log. Not the\n// harness's byte-exact model input (no system prompt).\nexport interface TranscriptMessageIface {\n role: TranscriptRole;\n // ACP content blocks.\n content: JsonValue[];\n toolCallId: string | null;\n seq: number;\n}\n\nexport interface SecretsIface {\n get(name: string): Promise<string | null>;\n}\n\nexport interface PostMessageInputIface {\n text?: string;\n // ACP content blocks; appended after `text` when both are given.\n content?: JsonValue[];\n // A `conv_\u2026` id; defaults to the session's conversation.\n conversationId?: string;\n}\n\n// The agent-platform client handed to authored code (a Final addition).\nexport interface FinalPlatformClientIface {\n // Resolves the posted message's `cnmsg_\u2026` id.\n post(input: PostMessageInputIface): Promise<{ messageId: string }>;\n conversation(): Promise<ConversationInfoIface | null>;\n // The current conversation's visible history, oldest first within the page.\n // `before` is a cnmsg_\u2026 id; other conversations are refused by the platform.\n read(options?: {\n conversationId?: string;\n limit?: number;\n before?: string;\n }): Promise<ConversationMessageIface[]>;\n}\n\nexport interface ToolContextIface {\n readonly session: AgentSessionInfoIface;\n // The MCP request id the harness chose; shows up as the ACP toolCallId.\n readonly callId: string;\n // Qualified name as the harness saw it.\n readonly toolName: string;\n readonly abortSignal: AbortSignal;\n // The same handle the sandbox MCP server uses; the first call starts the\n // sandbox. Defaults to the definition's default target.\n getSandbox(target?: string): Promise<NetworkSandboxSessionIface>;\n readonly messages: readonly TranscriptMessageIface[];\n readonly secrets: SecretsIface;\n readonly final: FinalPlatformClientIface;\n}\n\nexport interface DynamicResolveContextIface {\n // The persisted value of this slot at its previous lifecycle boundary.\n readonly previousValue?: JsonValue | null;\n readonly session: AgentSessionInfoIface;\n // The transcript at the boundary (empty at session.started for a new session).\n readonly messages: readonly TranscriptMessageIface[];\n readonly channel: { kind: string | null };\n readonly secrets: SecretsIface;\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { ConversationMessageIface } from '@finalai/agent-protocol/agent-platform';\nimport type {\n ConversationKind,\n HostedBindingsIface,\n JsonObject,\n JsonValue,\n NetworkSandboxSessionIface,\n ParticipantKind,\n ProviderRef,\n} from '@finalai/agent-provider';\n\n// What authored code (tools, hooks, dynamic resolvers, channel routes) sees of\n// the session it runs for. Everything is provided by\n// the session service through the Worker isolate; none of it is harness state.\n//\n// Ids are the public API's wire ids (`<prefix>_<base58>`), the same strings the\n// client SDK and `/api/v1` return: a session is `ases_\u2026`, a conversation\n// `conv_\u2026`, a participant `cpart_\u2026`, a turn `atrn_\u2026`, a user `usr_\u2026`. Pass them\n// back unchanged (`ctx.final.post({ conversationId })`, channel platform\n// calls); raw UUIDs are refused. ACP ids (`toolCallId`, prompt message ids)\n// and provider or model ids are passed through as the harness sent them.\n\nexport interface ParticipantInfoIface {\n // `cpart_\u2026`; `userId` is `usr_\u2026`.\n id: string;\n kind: ParticipantKind;\n displayName: string;\n userId: string | null;\n}\n\nexport interface ConversationInfoIface {\n // `conv_\u2026`, as `client` and `/api/v1/conversations` name it.\n id: string;\n kind: ConversationKind;\n title: string | null;\n metadata: JsonObject;\n participants: ParticipantInfoIface[];\n}\n\nexport interface PromptAuthorIface {\n participantId: string | null;\n userId: string | null;\n displayName: string;\n}\n\nexport interface AgentSessionInfoIface {\n // `ases_\u2026`: what `client.sessions.attach(id)` takes.\n id: string;\n // `org_\u2026`.\n organizationId: string;\n // The agent (`adef_\u2026`) and its published revision (`arev_\u2026`).\n definitionId: string;\n revisionId: string;\n conversation: ConversationInfoIface | null;\n // Who prompted the current turn; null outside a turn and for system input.\n author: PromptAuthorIface | null;\n // `atrn_\u2026`.\n turn: { id: string } | null;\n harness: ProviderRef;\n}\n\nexport enum TranscriptRole {\n User = 'user',\n Assistant = 'assistant',\n Tool = 'tool',\n Thought = 'thought',\n Summary = 'summary',\n}\n\n// One entry of the transcript rebuilt from the session's ACP log. Not the\n// harness's byte-exact model input (no system prompt).\nexport interface TranscriptMessageIface {\n role: TranscriptRole;\n // ACP content blocks.\n content: JsonValue[];\n toolCallId: string | null;\n seq: number;\n}\n\nexport interface SecretsIface {\n get(name: string): Promise<string | null>;\n}\n\nexport interface PostMessageInputIface {\n text?: string;\n // ACP content blocks; appended after `text` when both are given.\n content?: JsonValue[];\n // A `conv_\u2026` id; defaults to the session's conversation.\n conversationId?: string;\n}\n\n// The agent-platform client handed to authored code (a Final addition).\nexport interface FinalPlatformClientIface {\n // Resolves the posted message's `cnmsg_\u2026` id.\n post(input: PostMessageInputIface): Promise<{ messageId: string }>;\n conversation(): Promise<ConversationInfoIface | null>;\n // The current conversation's visible history, oldest first within the page.\n // `before` is a cnmsg_\u2026 id; other conversations are refused by the platform.\n read(options?: {\n conversationId?: string;\n limit?: number;\n before?: string;\n }): Promise<ConversationMessageIface[]>;\n}\n\nexport interface ToolContextIface {\n readonly bindings?: HostedBindingsIface;\n readonly session: AgentSessionInfoIface;\n // The MCP request id the harness chose; shows up as the ACP toolCallId.\n readonly callId: string;\n // Qualified name as the harness saw it.\n readonly toolName: string;\n readonly abortSignal: AbortSignal;\n // The same handle the sandbox MCP server uses; the first call starts the\n // sandbox. Defaults to the definition's default target.\n getSandbox(target?: string): Promise<NetworkSandboxSessionIface>;\n readonly messages: readonly TranscriptMessageIface[];\n readonly secrets: SecretsIface;\n readonly final: FinalPlatformClientIface;\n}\n\nexport interface DynamicResolveContextIface {\n readonly bindings?: HostedBindingsIface;\n // The persisted value of this slot at its previous lifecycle boundary.\n readonly previousValue?: JsonValue | null;\n readonly session: AgentSessionInfoIface;\n // The transcript at the boundary (empty at session.started for a new session).\n readonly messages: readonly TranscriptMessageIface[];\n readonly channel: { kind: string | null };\n readonly secrets: SecretsIface;\n}\n"],
|
|
5
|
+
"mappings": "AA6DO,IAAK,iBAAL,kBAAKA,oBAAL;AACL,EAAAA,gBAAA,UAAO;AACP,EAAAA,gBAAA,eAAY;AACZ,EAAAA,gBAAA,UAAO;AACP,EAAAA,gBAAA,aAAU;AACV,EAAAA,gBAAA,aAAU;AALA,SAAAA;AAAA,GAAA;",
|
|
6
6
|
"names": ["TranscriptRole"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ProviderRef } from '@finalai/agent-provider';
|
|
1
|
+
import type { HostedBindingRequirementIface, ProviderRef } from '@finalai/agent-provider';
|
|
2
2
|
import type { DynamicResolveContextIface } from "./context.mjs";
|
|
3
3
|
export type DynamicHandler<TResult> = (event: DynamicBoundaryEventIface, ctx: DynamicResolveContextIface) => TResult | Promise<TResult>;
|
|
4
4
|
export interface DynamicBoundaryEventIface {
|
|
@@ -19,6 +19,7 @@ export interface DynamicDefinitionIface<TResult> {
|
|
|
19
19
|
readonly description?: string;
|
|
20
20
|
readonly preview?: string;
|
|
21
21
|
readonly provider?: DynamicProviderHint;
|
|
22
|
+
readonly requiredBindings?: readonly HostedBindingRequirementIface[];
|
|
22
23
|
}
|
|
23
24
|
export interface DynamicSentinelIface<TResult = unknown> {
|
|
24
25
|
readonly kind: 'final:dynamic';
|
|
@@ -26,5 +27,6 @@ export interface DynamicSentinelIface<TResult = unknown> {
|
|
|
26
27
|
readonly description?: string;
|
|
27
28
|
readonly preview?: string;
|
|
28
29
|
readonly provider?: DynamicProviderHint;
|
|
30
|
+
readonly requiredBindings?: readonly HostedBindingRequirementIface[];
|
|
29
31
|
}
|
|
30
32
|
export declare const defineDynamic: <TResult>(definition: DynamicDefinitionIface<TResult>) => DynamicSentinelIface<TResult>;
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import { AuthoredKind, stamp } from "./brand.mjs";
|
|
2
|
+
import { validateHostedBindingRequirements } from "../hosted-bindings.mjs";
|
|
2
3
|
const defineDynamic = (definition) => {
|
|
4
|
+
const checked = (handler) => {
|
|
5
|
+
if (handler == null || (definition.requiredBindings?.length ?? 0) === 0) return handler;
|
|
6
|
+
return async (event, ctx) => {
|
|
7
|
+
await validateHostedBindingRequirements({
|
|
8
|
+
requirements: definition.requiredBindings ?? [],
|
|
9
|
+
bindings: ctx.bindings
|
|
10
|
+
});
|
|
11
|
+
const result = await handler(event, ctx);
|
|
12
|
+
if (result == null) throw new Error("Required hosted binding resolver returned no value");
|
|
13
|
+
return result;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
3
16
|
const sentinel = {
|
|
4
17
|
kind: "final:dynamic",
|
|
5
|
-
events:
|
|
18
|
+
events: {
|
|
19
|
+
...definition.events,
|
|
20
|
+
"session.started": checked(definition.events["session.started"]),
|
|
21
|
+
"turn.started": checked(definition.events["turn.started"])
|
|
22
|
+
}
|
|
6
23
|
};
|
|
7
24
|
if (definition.description != null) sentinel.description = definition.description;
|
|
8
25
|
if (definition.preview != null) sentinel.preview = definition.preview;
|
|
9
26
|
if (definition.provider != null) sentinel.provider = definition.provider;
|
|
27
|
+
if (definition.requiredBindings != null) sentinel.requiredBindings = definition.requiredBindings;
|
|
10
28
|
return stamp(sentinel, AuthoredKind.Dynamic);
|
|
11
29
|
};
|
|
12
30
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/authoring/dynamic.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ProviderRef } from '@finalai/agent-provider';\nimport { AuthoredKind, stamp } from \"./brand.mjs\";\nimport type { DynamicResolveContextIface } from \"./context.mjs\";\n\n// defineDynamic: a definition computed at a lifecycle\n// boundary. The directory a file sits in decides what a handler must return.\n// `description` and `preview` are Final additions so Build can render a slot\n// without resolving it.\n\nexport type DynamicHandler<TResult> = (\n event: DynamicBoundaryEventIface,\n ctx: DynamicResolveContextIface,\n) => TResult | Promise<TResult>;\n\nexport interface DynamicBoundaryEventIface {\n type: 'session.started' | 'turn.started';\n // The prompt that started the turn (turn.started only), as ACP content blocks.\n prompt: unknown[] | null;\n}\n\nexport interface DynamicEventsIface<TResult> {\n readonly 'session.started'?: DynamicHandler<TResult>;\n readonly 'turn.started'?: DynamicHandler<TResult>;\n}\n\n// A sandbox target whose environment is dynamic still needs its provider at\n// compile time: an installed provider helper, a provider defined with\n// defineSandboxProvider, or a provider reference.\nexport type DynamicProviderHint =\n | ProviderRef\n | { readonly name: string }\n | { readonly providerRef: ProviderRef };\n\nexport interface DynamicDefinitionIface<TResult> {\n readonly events: DynamicEventsIface<TResult>;\n readonly description?: string;\n readonly preview?: string;\n readonly provider?: DynamicProviderHint;\n}\n\nexport interface DynamicSentinelIface<TResult = unknown> {\n readonly kind: 'final:dynamic';\n readonly events: DynamicEventsIface<TResult>;\n readonly description?: string;\n readonly preview?: string;\n readonly provider?: DynamicProviderHint;\n}\n\ninterface DynamicSentinelFieldsIface<TResult> {\n kind: 'final:dynamic';\n events: DynamicEventsIface<TResult>;\n description?: string;\n preview?: string;\n provider?: DynamicProviderHint;\n}\n\nexport const defineDynamic = <TResult>(\n definition: DynamicDefinitionIface<TResult>,\n): DynamicSentinelIface<TResult> => {\n const sentinel: DynamicSentinelFieldsIface<TResult> = {\n kind: 'final:dynamic',\n events: definition.events,\n };\n if (definition.description != null) sentinel.description = definition.description;\n if (definition.preview != null) sentinel.preview = definition.preview;\n if (definition.provider != null) sentinel.provider = definition.provider;\n return stamp(sentinel, AuthoredKind.Dynamic);\n};\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,cAAc,aAAa;
|
|
4
|
+
"sourcesContent": ["import type { HostedBindingRequirementIface, ProviderRef } from '@finalai/agent-provider';\nimport { AuthoredKind, stamp } from \"./brand.mjs\";\nimport { validateHostedBindingRequirements } from \"../hosted-bindings.mjs\";\nimport type { DynamicResolveContextIface } from \"./context.mjs\";\n\n// defineDynamic: a definition computed at a lifecycle\n// boundary. The directory a file sits in decides what a handler must return.\n// `description` and `preview` are Final additions so Build can render a slot\n// without resolving it.\n\nexport type DynamicHandler<TResult> = (\n event: DynamicBoundaryEventIface,\n ctx: DynamicResolveContextIface,\n) => TResult | Promise<TResult>;\n\nexport interface DynamicBoundaryEventIface {\n type: 'session.started' | 'turn.started';\n // The prompt that started the turn (turn.started only), as ACP content blocks.\n prompt: unknown[] | null;\n}\n\nexport interface DynamicEventsIface<TResult> {\n readonly 'session.started'?: DynamicHandler<TResult>;\n readonly 'turn.started'?: DynamicHandler<TResult>;\n}\n\n// A sandbox target whose environment is dynamic still needs its provider at\n// compile time: an installed provider helper, a provider defined with\n// defineSandboxProvider, or a provider reference.\nexport type DynamicProviderHint =\n | ProviderRef\n | { readonly name: string }\n | { readonly providerRef: ProviderRef };\n\nexport interface DynamicDefinitionIface<TResult> {\n readonly events: DynamicEventsIface<TResult>;\n readonly description?: string;\n readonly preview?: string;\n readonly provider?: DynamicProviderHint;\n readonly requiredBindings?: readonly HostedBindingRequirementIface[];\n}\n\nexport interface DynamicSentinelIface<TResult = unknown> {\n readonly kind: 'final:dynamic';\n readonly events: DynamicEventsIface<TResult>;\n readonly description?: string;\n readonly preview?: string;\n readonly provider?: DynamicProviderHint;\n readonly requiredBindings?: readonly HostedBindingRequirementIface[];\n}\n\ninterface DynamicSentinelFieldsIface<TResult> {\n kind: 'final:dynamic';\n events: DynamicEventsIface<TResult>;\n description?: string;\n preview?: string;\n provider?: DynamicProviderHint;\n requiredBindings?: readonly HostedBindingRequirementIface[];\n}\n\nexport const defineDynamic = <TResult>(\n definition: DynamicDefinitionIface<TResult>,\n): DynamicSentinelIface<TResult> => {\n const checked = (\n handler: DynamicHandler<TResult> | undefined,\n ): DynamicHandler<TResult> | undefined => {\n if (handler == null || (definition.requiredBindings?.length ?? 0) === 0) return handler;\n return async (event, ctx) => {\n await validateHostedBindingRequirements({\n requirements: definition.requiredBindings ?? [],\n bindings: ctx.bindings,\n });\n const result = await handler(event, ctx);\n if (result == null) throw new Error('Required hosted binding resolver returned no value');\n return result;\n };\n };\n const sentinel: DynamicSentinelFieldsIface<TResult> = {\n kind: 'final:dynamic',\n events: {\n ...definition.events,\n 'session.started': checked(definition.events['session.started']),\n 'turn.started': checked(definition.events['turn.started']),\n },\n };\n if (definition.description != null) sentinel.description = definition.description;\n if (definition.preview != null) sentinel.preview = definition.preview;\n if (definition.provider != null) sentinel.provider = definition.provider;\n if (definition.requiredBindings != null) sentinel.requiredBindings = definition.requiredBindings;\n return stamp(sentinel, AuthoredKind.Dynamic);\n};\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,cAAc,aAAa;AACpC,SAAS,yCAAyC;AA0D3C,MAAM,gBAAgB,CAC3B,eACkC;AAClC,QAAM,UAAU,CACd,YACwC;AACxC,QAAI,WAAW,SAAS,WAAW,kBAAkB,UAAU,OAAO,EAAG,QAAO;AAChF,WAAO,OAAO,OAAO,QAAQ;AAC3B,YAAM,kCAAkC;AAAA,QACtC,cAAc,WAAW,oBAAoB,CAAC;AAAA,QAC9C,UAAU,IAAI;AAAA,MAChB,CAAC;AACD,YAAM,SAAS,MAAM,QAAQ,OAAO,GAAG;AACvC,UAAI,UAAU,KAAM,OAAM,IAAI,MAAM,oDAAoD;AACxF,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,WAAgD;AAAA,IACpD,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,GAAG,WAAW;AAAA,MACd,mBAAmB,QAAQ,WAAW,OAAO,iBAAiB,CAAC;AAAA,MAC/D,gBAAgB,QAAQ,WAAW,OAAO,cAAc,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,MAAI,WAAW,eAAe,KAAM,UAAS,cAAc,WAAW;AACtE,MAAI,WAAW,WAAW,KAAM,UAAS,UAAU,WAAW;AAC9D,MAAI,WAAW,YAAY,KAAM,UAAS,WAAW,WAAW;AAChE,MAAI,WAAW,oBAAoB,KAAM,UAAS,mBAAmB,WAAW;AAChF,SAAO,MAAM,UAAU,aAAa,OAAO;AAC7C;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -14,6 +14,8 @@ const completeHarnessDescription = (authored) => {
|
|
|
14
14
|
};
|
|
15
15
|
if (authored.supports?.nativeToolPolicy != null)
|
|
16
16
|
supports.nativeToolPolicy = authored.supports.nativeToolPolicy;
|
|
17
|
+
if (authored.supports?.deferredToolSearch != null)
|
|
18
|
+
supports.deferredToolSearch = authored.supports.deferredToolSearch;
|
|
17
19
|
return harnessDescriptionSchema.parse({
|
|
18
20
|
...authored,
|
|
19
21
|
acp: { transports: authored.acp.transports, mcp: authored.acp.mcp ?? [] },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/authoring/harness.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n bundleRef,\n CredentialDelivery,\n harnessDescriptionSchema,\n InferenceCredentialKind,\n type AcpTransport,\n type DefinedHarnessBindingIface,\n type DescribeHarnessArgsIface,\n type HarnessClientTlsIface,\n type HarnessDescriptionIface,\n type HarnessSessionRefIface,\n type JsonSchema,\n type JsonValue,\n type McpTransportKind,\n type OpenHarnessSessionArgsIface,\n type PromptWhileRunning,\n type ProviderRef,\n type SandboxWire,\n type SecretReaderIface,\n type UserInstructionDelivery,\n} from '@finalai/agent-provider';\nimport { registerPending } from \"./brand.mjs\";\n\n// A harness declared in the definition's bundle. Its\n// methods run in the agent's Worker isolate; the session service dials the\n// endpoints they return like any other harness's.\n\ntype EnumInput<E extends string> = E | `${E}`;\n\n// What `describe` may return: what the session service needs to dial and\n// report on the harness. Omitted fields take the defaults of a third-party\n// harness that owns its model and native tools: no base tools, no sandbox\n// wires, harness-owned inference, and none of observe, resume replay, fork or\n// author metadata.\nexport interface AuthoredHarnessDescriptionIface {\n configSchema: JsonSchema;\n userInstructionDelivery?: EnumInput<UserInstructionDelivery>;\n acp: {\n transports: readonly EnumInput<AcpTransport.Ws | AcpTransport.Http>[];\n mcp?: readonly EnumInput<McpTransportKind>[];\n };\n baseTools?: HarnessDescriptionIface['baseTools'];\n consumes?: readonly EnumInput<SandboxWire>[];\n inference?: {\n vendors?: readonly string[];\n kinds?: readonly EnumInput<InferenceCredentialKind>[];\n delivery?: EnumInput<CredentialDelivery>;\n };\n supports?: Partial<HarnessDescriptionIface['supports']>;\n promptWhileRunning?: EnumInput<PromptWhileRunning>;\n sessionSurvivesDisconnect?: boolean;\n}\n\n// The harness's own session reference; the session service adds which\n// harness it belongs to.\nexport interface AuthoredHarnessSessionRefIface {\n harnessSessionRef: string;\n generation: number;\n}\n\nexport type AuthoredHarnessEndpointIface =\n | {\n ref: AuthoredHarnessSessionRefIface;\n transport: EnumInput<AcpTransport.Ws>;\n url: string;\n headers?: Record<string, string>;\n tls?: HarnessClientTlsIface;\n }\n | {\n ref: AuthoredHarnessSessionRefIface;\n transport: EnumInput<AcpTransport.Http>;\n url: string;\n headers?: Record<string, string>;\n tls?: HarnessClientTlsIface;\n };\n\nexport interface AuthoredHarnessOpenArgsIface<Config> extends Omit<\n OpenHarnessSessionArgsIface,\n 'config' | 'observer'\n> {\n config: Config;\n // The agent session's id (`session.sessionId`), for keying the harness's own state.\n sessionId: string;\n}\n\nexport interface AuthoredHarnessResumeArgsIface<\n Config,\n> extends AuthoredHarnessOpenArgsIface<Config> {\n ref: HarnessSessionRefIface;\n lastSeq: number;\n}\n\n// What the session service sends: the open and resume arguments before\n// `sessionId` is filled in from `session`.\nexport type HarnessOpenCallIface<Config> = Omit<AuthoredHarnessOpenArgsIface<Config>, 'sessionId'>;\nexport type HarnessResumeCallIface<Config> = Omit<\n AuthoredHarnessResumeArgsIface<Config>,\n 'sessionId'\n>;\n\n// park, close and health get the session reference and the definition's\n// secret reader (the isolate's `secrets`, limited to manifest.secrets).\nexport interface AuthoredHarnessRefContextIface {\n secrets: SecretReaderIface;\n}\n\n// close is graceful unless `force` (the contract's close options).\nexport interface AuthoredHarnessCloseContextIface extends AuthoredHarnessRefContextIface {\n force: boolean;\n}\n\n// The first argument of park, close and health: the session reference itself,\n// also under `ref`, with the context's fields, so both `park(ref)` and\n// `park({ ref, secrets })` read naturally.\nexport type AuthoredHarnessRefArgIface<Context extends AuthoredHarnessRefContextIface> =\n HarnessSessionRefIface & Context & { ref: HarnessSessionRefIface };\n\nexport interface AuthoredHarnessHealthIface {\n ok: boolean;\n detail?: string;\n // Defaults to when the check returned.\n checkedAt?: string;\n}\n\nexport interface AuthoredHarnessIface<Config> {\n describe(binding?: DescribeHarnessArgsIface): Promise<AuthoredHarnessDescriptionIface>;\n open(args: AuthoredHarnessOpenArgsIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n resume(args: AuthoredHarnessResumeArgsIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n park(\n ref: AuthoredHarnessRefArgIface<AuthoredHarnessRefContextIface>,\n ctx: AuthoredHarnessRefContextIface,\n ): Promise<void>;\n close(\n ref: AuthoredHarnessRefArgIface<AuthoredHarnessCloseContextIface>,\n ctx: AuthoredHarnessCloseContextIface,\n ): Promise<void>;\n health(\n ref: AuthoredHarnessRefArgIface<AuthoredHarnessRefContextIface>,\n ctx: AuthoredHarnessRefContextIface,\n ): Promise<AuthoredHarnessHealthIface>;\n}\n\nexport interface DefinedAuthoredHarnessIface<Config> {\n (config: Config): DefinedHarnessBindingIface;\n describe(binding?: DescribeHarnessArgsIface): Promise<HarnessDescriptionIface>;\n open(args: HarnessOpenCallIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n resume(args: HarnessResumeCallIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n park(ref: HarnessSessionRefIface, ctx: AuthoredHarnessRefContextIface): Promise<void>;\n close(ref: HarnessSessionRefIface, ctx: AuthoredHarnessCloseContextIface): Promise<void>;\n health(\n ref: HarnessSessionRefIface,\n ctx: AuthoredHarnessRefContextIface,\n ): Promise<{ ok: boolean; detail?: string; checkedAt: string }>;\n}\n\n// Fills the omitted description fields (see AuthoredHarnessDescriptionIface)\n// and validates the result against the contract's schema, which also applies\n// its own defaults and turns enum literals into members.\nexport const completeHarnessDescription = (\n authored: AuthoredHarnessDescriptionIface,\n): HarnessDescriptionIface => {\n const supports: HarnessDescriptionIface['supports'] = {\n observe: authored.supports?.observe ?? false,\n resumeReplay: authored.supports?.resumeReplay ?? false,\n fork: authored.supports?.fork ?? false,\n authorMeta: authored.supports?.authorMeta ?? false,\n };\n if (authored.supports?.nativeToolPolicy != null)\n supports.nativeToolPolicy = authored.supports.nativeToolPolicy;\n return harnessDescriptionSchema.parse({\n ...authored,\n acp: { transports: authored.acp.transports, mcp: authored.acp.mcp ?? [] },\n baseTools: authored.baseTools ?? {},\n consumes: authored.consumes ?? [],\n inference: {\n vendors: authored.inference?.vendors ?? [],\n kinds: authored.inference?.kinds ?? [InferenceCredentialKind.HarnessOwned],\n delivery: authored.inference?.delivery ?? CredentialDelivery.AtOpen,\n },\n supports,\n });\n};\n\n// The contract's binding shape, with the bundle export placeholder made\n// unique per harness so the compiler can bind it to a synthesized bundle\n// export even when the harness is not exported.\nexport const defineHarness = <Config extends JsonValue = JsonValue>(\n implementation: AuthoredHarnessIface<Config>,\n): DefinedAuthoredHarnessIface<Config> => {\n let placeholder: ProviderRef | null = null;\n const binding = (config: Config): DefinedHarnessBindingIface => ({\n harness: placeholder ?? bundleRef('<pending>'),\n config,\n definedHarness: true,\n });\n const defined = Object.assign(binding, {\n describe: async (args?: DescribeHarnessArgsIface): Promise<HarnessDescriptionIface> =>\n completeHarnessDescription(await implementation.describe(args)),\n open: (args: HarnessOpenCallIface<Config>) =>\n implementation.open({ ...args, sessionId: args.session.sessionId }),\n resume: (args: HarnessResumeCallIface<Config>) =>\n implementation.resume({ ...args, sessionId: args.session.sessionId }),\n park: (ref: HarnessSessionRefIface, ctx: AuthoredHarnessRefContextIface) =>\n implementation.park({ ...ref, ...ctx, ref }, ctx),\n close: (ref: HarnessSessionRefIface, ctx: AuthoredHarnessCloseContextIface) =>\n implementation.close({ ...ref, ...ctx, ref }, ctx),\n health: async (ref: HarnessSessionRefIface, ctx: AuthoredHarnessRefContextIface) => {\n const health = await implementation.health({ ...ref, ...ctx, ref }, ctx);\n return { ...health, checkedAt: health.checkedAt ?? new Date().toISOString() };\n },\n });\n placeholder = bundleRef(registerPending(defined));\n return defined;\n};\n"],
|
|
5
|
-
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAgBK;AACP,SAAS,uBAAuB;AAyIzB,MAAM,6BAA6B,CACxC,aAC4B;AAC5B,QAAM,WAAgD;AAAA,IACpD,SAAS,SAAS,UAAU,WAAW;AAAA,IACvC,cAAc,SAAS,UAAU,gBAAgB;AAAA,IACjD,MAAM,SAAS,UAAU,QAAQ;AAAA,IACjC,YAAY,SAAS,UAAU,cAAc;AAAA,EAC/C;AACA,MAAI,SAAS,UAAU,oBAAoB;AACzC,aAAS,mBAAmB,SAAS,SAAS;AAChD,SAAO,yBAAyB,MAAM;AAAA,IACpC,GAAG;AAAA,IACH,KAAK,EAAE,YAAY,SAAS,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE;AAAA,IACxE,WAAW,SAAS,aAAa,CAAC;AAAA,IAClC,UAAU,SAAS,YAAY,CAAC;AAAA,IAChC,WAAW;AAAA,MACT,SAAS,SAAS,WAAW,WAAW,CAAC;AAAA,MACzC,OAAO,SAAS,WAAW,SAAS,CAAC,wBAAwB,YAAY;AAAA,MACzE,UAAU,SAAS,WAAW,YAAY,mBAAmB;AAAA,IAC/D;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAKO,MAAM,gBAAgB,CAC3B,mBACwC;AACxC,MAAI,cAAkC;AACtC,QAAM,UAAU,CAAC,YAAgD;AAAA,IAC/D,SAAS,eAAe,UAAU,WAAW;AAAA,IAC7C;AAAA,IACA,gBAAgB;AAAA,EAClB;AACA,QAAM,UAAU,OAAO,OAAO,SAAS;AAAA,IACrC,UAAU,OAAO,SACf,2BAA2B,MAAM,eAAe,SAAS,IAAI,CAAC;AAAA,IAChE,MAAM,CAAC,SACL,eAAe,KAAK,EAAE,GAAG,MAAM,WAAW,KAAK,QAAQ,UAAU,CAAC;AAAA,IACpE,QAAQ,CAAC,SACP,eAAe,OAAO,EAAE,GAAG,MAAM,WAAW,KAAK,QAAQ,UAAU,CAAC;AAAA,IACtE,MAAM,CAAC,KAA6B,QAClC,eAAe,KAAK,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG;AAAA,IAClD,OAAO,CAAC,KAA6B,QACnC,eAAe,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG;AAAA,IACnD,QAAQ,OAAO,KAA6B,QAAwC;AAClF,YAAM,SAAS,MAAM,eAAe,OAAO,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG;AACvE,aAAO,EAAE,GAAG,QAAQ,WAAW,OAAO,cAAa,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,IAC9E;AAAA,EACF,CAAC;AACD,gBAAc,UAAU,gBAAgB,OAAO,CAAC;AAChD,SAAO;AACT;",
|
|
4
|
+
"sourcesContent": ["import {\n bundleRef,\n CredentialDelivery,\n harnessDescriptionSchema,\n InferenceCredentialKind,\n type AcpTransport,\n type DefinedHarnessBindingIface,\n type DescribeHarnessArgsIface,\n type HarnessClientTlsIface,\n type HarnessDescriptionIface,\n type HarnessSessionRefIface,\n type JsonSchema,\n type JsonValue,\n type McpTransportKind,\n type OpenHarnessSessionArgsIface,\n type PromptWhileRunning,\n type ProviderRef,\n type SandboxWire,\n type SecretReaderIface,\n type UserInstructionDelivery,\n} from '@finalai/agent-provider';\nimport { registerPending } from \"./brand.mjs\";\n\n// A harness declared in the definition's bundle. Its\n// methods run in the agent's Worker isolate; the session service dials the\n// endpoints they return like any other harness's.\n\ntype EnumInput<E extends string> = E | `${E}`;\n\n// What `describe` may return: what the session service needs to dial and\n// report on the harness. Omitted fields take the defaults of a third-party\n// harness that owns its model and native tools: no base tools, no sandbox\n// wires, harness-owned inference, and none of observe, resume replay, fork or\n// author metadata.\nexport interface AuthoredHarnessDescriptionIface {\n configSchema: JsonSchema;\n userInstructionDelivery?: EnumInput<UserInstructionDelivery>;\n acp: {\n transports: readonly EnumInput<AcpTransport.Ws | AcpTransport.Http>[];\n mcp?: readonly EnumInput<McpTransportKind>[];\n };\n baseTools?: HarnessDescriptionIface['baseTools'];\n consumes?: readonly EnumInput<SandboxWire>[];\n inference?: {\n vendors?: readonly string[];\n kinds?: readonly EnumInput<InferenceCredentialKind>[];\n delivery?: EnumInput<CredentialDelivery>;\n };\n supports?: Partial<HarnessDescriptionIface['supports']>;\n promptWhileRunning?: EnumInput<PromptWhileRunning>;\n sessionSurvivesDisconnect?: boolean;\n}\n\n// The harness's own session reference; the session service adds which\n// harness it belongs to.\nexport interface AuthoredHarnessSessionRefIface {\n harnessSessionRef: string;\n generation: number;\n}\n\nexport type AuthoredHarnessEndpointIface =\n | {\n ref: AuthoredHarnessSessionRefIface;\n transport: EnumInput<AcpTransport.Ws>;\n url: string;\n headers?: Record<string, string>;\n tls?: HarnessClientTlsIface;\n }\n | {\n ref: AuthoredHarnessSessionRefIface;\n transport: EnumInput<AcpTransport.Http>;\n url: string;\n headers?: Record<string, string>;\n tls?: HarnessClientTlsIface;\n };\n\nexport interface AuthoredHarnessOpenArgsIface<Config> extends Omit<\n OpenHarnessSessionArgsIface,\n 'config' | 'observer'\n> {\n config: Config;\n // The agent session's id (`session.sessionId`), for keying the harness's own state.\n sessionId: string;\n}\n\nexport interface AuthoredHarnessResumeArgsIface<\n Config,\n> extends AuthoredHarnessOpenArgsIface<Config> {\n ref: HarnessSessionRefIface;\n lastSeq: number;\n}\n\n// What the session service sends: the open and resume arguments before\n// `sessionId` is filled in from `session`.\nexport type HarnessOpenCallIface<Config> = Omit<AuthoredHarnessOpenArgsIface<Config>, 'sessionId'>;\nexport type HarnessResumeCallIface<Config> = Omit<\n AuthoredHarnessResumeArgsIface<Config>,\n 'sessionId'\n>;\n\n// park, close and health get the session reference and the definition's\n// secret reader (the isolate's `secrets`, limited to manifest.secrets).\nexport interface AuthoredHarnessRefContextIface {\n secrets: SecretReaderIface;\n}\n\n// close is graceful unless `force` (the contract's close options).\nexport interface AuthoredHarnessCloseContextIface extends AuthoredHarnessRefContextIface {\n force: boolean;\n}\n\n// The first argument of park, close and health: the session reference itself,\n// also under `ref`, with the context's fields, so both `park(ref)` and\n// `park({ ref, secrets })` read naturally.\nexport type AuthoredHarnessRefArgIface<Context extends AuthoredHarnessRefContextIface> =\n HarnessSessionRefIface & Context & { ref: HarnessSessionRefIface };\n\nexport interface AuthoredHarnessHealthIface {\n ok: boolean;\n detail?: string;\n // Defaults to when the check returned.\n checkedAt?: string;\n}\n\nexport interface AuthoredHarnessIface<Config> {\n describe(binding?: DescribeHarnessArgsIface): Promise<AuthoredHarnessDescriptionIface>;\n open(args: AuthoredHarnessOpenArgsIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n resume(args: AuthoredHarnessResumeArgsIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n park(\n ref: AuthoredHarnessRefArgIface<AuthoredHarnessRefContextIface>,\n ctx: AuthoredHarnessRefContextIface,\n ): Promise<void>;\n close(\n ref: AuthoredHarnessRefArgIface<AuthoredHarnessCloseContextIface>,\n ctx: AuthoredHarnessCloseContextIface,\n ): Promise<void>;\n health(\n ref: AuthoredHarnessRefArgIface<AuthoredHarnessRefContextIface>,\n ctx: AuthoredHarnessRefContextIface,\n ): Promise<AuthoredHarnessHealthIface>;\n}\n\nexport interface DefinedAuthoredHarnessIface<Config> {\n (config: Config): DefinedHarnessBindingIface;\n describe(binding?: DescribeHarnessArgsIface): Promise<HarnessDescriptionIface>;\n open(args: HarnessOpenCallIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n resume(args: HarnessResumeCallIface<Config>): Promise<AuthoredHarnessEndpointIface>;\n park(ref: HarnessSessionRefIface, ctx: AuthoredHarnessRefContextIface): Promise<void>;\n close(ref: HarnessSessionRefIface, ctx: AuthoredHarnessCloseContextIface): Promise<void>;\n health(\n ref: HarnessSessionRefIface,\n ctx: AuthoredHarnessRefContextIface,\n ): Promise<{ ok: boolean; detail?: string; checkedAt: string }>;\n}\n\n// Fills the omitted description fields (see AuthoredHarnessDescriptionIface)\n// and validates the result against the contract's schema, which also applies\n// its own defaults and turns enum literals into members.\nexport const completeHarnessDescription = (\n authored: AuthoredHarnessDescriptionIface,\n): HarnessDescriptionIface => {\n const supports: HarnessDescriptionIface['supports'] = {\n observe: authored.supports?.observe ?? false,\n resumeReplay: authored.supports?.resumeReplay ?? false,\n fork: authored.supports?.fork ?? false,\n authorMeta: authored.supports?.authorMeta ?? false,\n };\n if (authored.supports?.nativeToolPolicy != null)\n supports.nativeToolPolicy = authored.supports.nativeToolPolicy;\n if (authored.supports?.deferredToolSearch != null)\n supports.deferredToolSearch = authored.supports.deferredToolSearch;\n return harnessDescriptionSchema.parse({\n ...authored,\n acp: { transports: authored.acp.transports, mcp: authored.acp.mcp ?? [] },\n baseTools: authored.baseTools ?? {},\n consumes: authored.consumes ?? [],\n inference: {\n vendors: authored.inference?.vendors ?? [],\n kinds: authored.inference?.kinds ?? [InferenceCredentialKind.HarnessOwned],\n delivery: authored.inference?.delivery ?? CredentialDelivery.AtOpen,\n },\n supports,\n });\n};\n\n// The contract's binding shape, with the bundle export placeholder made\n// unique per harness so the compiler can bind it to a synthesized bundle\n// export even when the harness is not exported.\nexport const defineHarness = <Config extends JsonValue = JsonValue>(\n implementation: AuthoredHarnessIface<Config>,\n): DefinedAuthoredHarnessIface<Config> => {\n let placeholder: ProviderRef | null = null;\n const binding = (config: Config): DefinedHarnessBindingIface => ({\n harness: placeholder ?? bundleRef('<pending>'),\n config,\n definedHarness: true,\n });\n const defined = Object.assign(binding, {\n describe: async (args?: DescribeHarnessArgsIface): Promise<HarnessDescriptionIface> =>\n completeHarnessDescription(await implementation.describe(args)),\n open: (args: HarnessOpenCallIface<Config>) =>\n implementation.open({ ...args, sessionId: args.session.sessionId }),\n resume: (args: HarnessResumeCallIface<Config>) =>\n implementation.resume({ ...args, sessionId: args.session.sessionId }),\n park: (ref: HarnessSessionRefIface, ctx: AuthoredHarnessRefContextIface) =>\n implementation.park({ ...ref, ...ctx, ref }, ctx),\n close: (ref: HarnessSessionRefIface, ctx: AuthoredHarnessCloseContextIface) =>\n implementation.close({ ...ref, ...ctx, ref }, ctx),\n health: async (ref: HarnessSessionRefIface, ctx: AuthoredHarnessRefContextIface) => {\n const health = await implementation.health({ ...ref, ...ctx, ref }, ctx);\n return { ...health, checkedAt: health.checkedAt ?? new Date().toISOString() };\n },\n });\n placeholder = bundleRef(registerPending(defined));\n return defined;\n};\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAgBK;AACP,SAAS,uBAAuB;AAyIzB,MAAM,6BAA6B,CACxC,aAC4B;AAC5B,QAAM,WAAgD;AAAA,IACpD,SAAS,SAAS,UAAU,WAAW;AAAA,IACvC,cAAc,SAAS,UAAU,gBAAgB;AAAA,IACjD,MAAM,SAAS,UAAU,QAAQ;AAAA,IACjC,YAAY,SAAS,UAAU,cAAc;AAAA,EAC/C;AACA,MAAI,SAAS,UAAU,oBAAoB;AACzC,aAAS,mBAAmB,SAAS,SAAS;AAChD,MAAI,SAAS,UAAU,sBAAsB;AAC3C,aAAS,qBAAqB,SAAS,SAAS;AAClD,SAAO,yBAAyB,MAAM;AAAA,IACpC,GAAG;AAAA,IACH,KAAK,EAAE,YAAY,SAAS,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE;AAAA,IACxE,WAAW,SAAS,aAAa,CAAC;AAAA,IAClC,UAAU,SAAS,YAAY,CAAC;AAAA,IAChC,WAAW;AAAA,MACT,SAAS,SAAS,WAAW,WAAW,CAAC;AAAA,MACzC,OAAO,SAAS,WAAW,SAAS,CAAC,wBAAwB,YAAY;AAAA,MACzE,UAAU,SAAS,WAAW,YAAY,mBAAmB;AAAA,IAC/D;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAKO,MAAM,gBAAgB,CAC3B,mBACwC;AACxC,MAAI,cAAkC;AACtC,QAAM,UAAU,CAAC,YAAgD;AAAA,IAC/D,SAAS,eAAe,UAAU,WAAW;AAAA,IAC7C;AAAA,IACA,gBAAgB;AAAA,EAClB;AACA,QAAM,UAAU,OAAO,OAAO,SAAS;AAAA,IACrC,UAAU,OAAO,SACf,2BAA2B,MAAM,eAAe,SAAS,IAAI,CAAC;AAAA,IAChE,MAAM,CAAC,SACL,eAAe,KAAK,EAAE,GAAG,MAAM,WAAW,KAAK,QAAQ,UAAU,CAAC;AAAA,IACpE,QAAQ,CAAC,SACP,eAAe,OAAO,EAAE,GAAG,MAAM,WAAW,KAAK,QAAQ,UAAU,CAAC;AAAA,IACtE,MAAM,CAAC,KAA6B,QAClC,eAAe,KAAK,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG;AAAA,IAClD,OAAO,CAAC,KAA6B,QACnC,eAAe,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG;AAAA,IACnD,QAAQ,OAAO,KAA6B,QAAwC;AAClF,YAAM,SAAS,MAAM,eAAe,OAAO,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,GAAG;AACvE,aAAO,EAAE,GAAG,QAAQ,WAAW,OAAO,cAAa,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,IAC9E;AAAA,EACF,CAAC;AACD,gBAAc,UAAU,gBAAgB,OAAO,CAAC;AAChD,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { JsonValue, NetworkSandboxSessionIface } from '@finalai/agent-provider';
|
|
1
|
+
import type { HostedBindingsIface, JsonValue, NetworkSandboxSessionIface } from '@finalai/agent-provider';
|
|
2
2
|
import { type AuthoredValue } from "../runtime/values.mjs";
|
|
3
3
|
import type { AgentSessionInfoIface, FinalPlatformClientIface, SecretsIface, TranscriptMessageIface } from "./context.mjs";
|
|
4
4
|
import type { ToolCallEventDataIface } from "./tools.mjs";
|
|
@@ -101,6 +101,7 @@ export interface HookContextIface {
|
|
|
101
101
|
getSandbox(target?: string): Promise<NetworkSandboxSessionIface>;
|
|
102
102
|
cancel(): void;
|
|
103
103
|
readonly secrets: SecretsIface;
|
|
104
|
+
readonly bindings?: HostedBindingsIface;
|
|
104
105
|
readonly final: FinalPlatformClientIface;
|
|
105
106
|
}
|
|
106
107
|
export type HookHandler<TKey extends string> = (event: HookEventFor<TKey>, ctx: HookContextIface) => void | Promise<void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/authoring/hooks.ts"],
|
|
4
|
-
"sourcesContent": ["import type {
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type {\n HostedBindingsIface,\n JsonValue,\n NetworkSandboxSessionIface,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport { authoredRecordSchema, isCallable, type AuthoredValue } from \"../runtime/values.mjs\";\nimport { AuthoredKind, stamp } from \"./brand.mjs\";\nimport type {\n AgentSessionInfoIface,\n FinalPlatformClientIface,\n SecretsIface,\n TranscriptMessageIface,\n} from \"./context.mjs\";\nimport type { ToolCallEventDataIface } from \"./tools.mjs\";\n\nexport { toolResultFrom } from \"./tools.mjs\";\n\n// Observe-only subscribers to the session's ACP log. Event\n// names are ACP update kinds and request methods plus a few session-service\n// lifecycle events. Only these canonical names are accepted.\n\nexport enum HookEvent {\n SessionOpened = 'session.opened',\n TurnStarted = 'turn.started',\n TurnEnded = 'turn.ended',\n UserMessageChunk = 'user_message_chunk',\n AgentMessageChunk = 'agent_message_chunk',\n AgentMessage = 'agent_message',\n AgentThoughtChunk = 'agent_thought_chunk',\n ToolCall = 'tool_call',\n ToolCallUpdate = 'tool_call_update',\n ToolCallContentChunk = 'tool_call_content_chunk',\n Plan = 'plan',\n PendingCreated = 'pending.created',\n PendingResolved = 'pending.resolved',\n StateUpdate = 'state_update',\n SessionFailed = 'session.failed',\n SessionClosed = 'session.closed',\n CompactionUpdate = 'compaction_update',\n UsageUpdate = 'usage_update',\n AvailableCommandsUpdate = 'available_commands_update',\n CurrentModeUpdate = 'current_mode_update',\n ConfigOptionUpdate = 'config_option_update',\n SessionInfoUpdate = 'session_info_update',\n Notice = 'notice',\n}\n\nexport const HOOK_WILDCARD = '*';\n\nconst CANONICAL_EVENTS: ReadonlySet<string> = new Set(Object.values(HookEvent));\n\nexport enum HookEventKeyKind {\n Canonical = 'canonical',\n Wildcard = 'wildcard',\n Unknown = 'unknown',\n}\n\nexport interface NormalizedHookKeyIface {\n key: string;\n kind: HookEventKeyKind;\n // Canonical event names this key subscribes to ('*' for the wildcard).\n events: string[];\n}\n\nexport const normalizeHookKey = (key: string): NormalizedHookKeyIface => {\n if (key === HOOK_WILDCARD)\n return { key, kind: HookEventKeyKind.Wildcard, events: [HOOK_WILDCARD] };\n if (CANONICAL_EVENTS.has(key) || key.startsWith('_final/')) {\n return { key, kind: HookEventKeyKind.Canonical, events: [key] };\n }\n return { key, kind: HookEventKeyKind.Unknown, events: [] };\n};\n\nexport interface HookEventMetaIface {\n // '<sessionId>:<seq>' with the session's wire id (`ases_\u2026:12`): sortable\n // within a session and stable across redelivery.\n id: string;\n at: string;\n seq: number;\n}\n\nexport interface HookEventIface<TType extends string = string, TData = AuthoredValue> {\n type: TType;\n data: TData;\n meta: HookEventMetaIface;\n}\n\n// Lifecycle event data names platform objects by their wire ids, as the public\n// API does: sessions `ases_\u2026`, turns `atrn_\u2026`, participants `cpart_\u2026`, pending\n// requests `apnd_\u2026`. `promptMessageId` is the harness's ACP message id. ACP\n// update events (tool_call, agent_message_chunk, \u2026) carry the ACP payload as is.\nexport interface HookEventDataMapIface {\n 'session.opened': { sessionId: string };\n 'turn.started': {\n turnId: string;\n promptMessageId: string | null;\n authorParticipantId: string | null;\n };\n 'turn.ended': { turnId: string; stopReason: string | null };\n tool_call: ToolCallEventDataIface;\n tool_call_update: ToolCallEventDataIface;\n tool_call_content_chunk: ToolCallEventDataIface;\n 'pending.created': {\n pendingId: string;\n kind: 'permission' | 'elicitation' | 'authorization';\n request: JsonValue;\n };\n 'pending.resolved': { pendingId: string; outcome: JsonValue };\n 'session.failed': { reason: string | null };\n 'session.closed': { reason: string | null };\n}\n\ntype CanonicalData<TKey extends string> = TKey extends keyof HookEventDataMapIface\n ? HookEventDataMapIface[TKey]\n : Record<string, JsonValue>;\n\nexport type HookEventKey = `${HookEvent}` | typeof HOOK_WILDCARD | `_final/${string}`;\n\nexport type HookEventFor<TKey extends string> = TKey extends typeof HOOK_WILDCARD\n ? HookEventIface\n : HookEventIface<TKey, CanonicalData<TKey>>;\n\nexport interface HookSessionInfoIface extends AgentSessionInfoIface {\n readonly messages: readonly TranscriptMessageIface[];\n}\n\nexport interface HookContextIface {\n readonly session: HookSessionInfoIface;\n readonly agent: {\n readonly definitionId: string;\n readonly name: string;\n readonly revisionId: string;\n };\n readonly channel: { readonly kind: string | null };\n getSandbox(target?: string): Promise<NetworkSandboxSessionIface>;\n // Sends session/cancel for the running turn.\n cancel(): void;\n readonly secrets: SecretsIface;\n readonly bindings?: HostedBindingsIface;\n readonly final: FinalPlatformClientIface;\n}\n\nexport type HookHandler<TKey extends string> = (\n event: HookEventFor<TKey>,\n ctx: HookContextIface,\n) => void | Promise<void>;\n\nexport type HookHandlersIface = { readonly [TKey in HookEventKey]?: HookHandler<TKey> };\n\nexport interface HookDefinitionIface {\n readonly events?: HookHandlersIface;\n}\n\nexport const defineHook = (definition: HookDefinitionIface): HookDefinitionIface =>\n stamp({ ...definition }, AuthoredKind.Hook);\n\nexport interface HookDispatchEventIface {\n type: string;\n data: AuthoredValue;\n meta: HookEventMetaIface;\n}\n\nconst keyMatches = (key: string, event: HookDispatchEventIface): boolean =>\n key === event.type && (CANONICAL_EVENTS.has(key) || key.startsWith('_final/'));\n\nexport type HookInvocable = (event: HookDispatchEventIface, ctx: HookContextIface) => AuthoredValue;\n\nconst hookEventsSchema = z.looseObject({ events: authoredRecordSchema });\n\n// Handlers for one event: typed handlers in declaration order, then the\n// wildcard.\nexport const hookHandlersFor = (\n hook: AuthoredValue,\n event: HookDispatchEventIface,\n): HookInvocable[] => {\n const parsed = hookEventsSchema.safeParse(hook);\n if (!parsed.success) return [];\n const typed: HookInvocable[] = [];\n let wildcard: HookInvocable | null = null;\n for (const [key, handler] of Object.entries(parsed.data.events)) {\n if (!isCallable(handler)) continue;\n const invoke: HookInvocable = (dispatched, ctx) => handler(dispatched, ctx);\n if (key === HOOK_WILDCARD) wildcard = invoke;\n else if (keyMatches(key, event)) typed.push(invoke);\n }\n return wildcard == null ? typed : [...typed, wildcard];\n};\n"],
|
|
5
|
+
"mappings": "AAKA,YAAY,OAAO;AACnB,SAAS,sBAAsB,kBAAsC;AACrE,SAAS,cAAc,aAAa;AASpC,SAAS,sBAAsB;AAMxB,IAAK,YAAL,kBAAKA,eAAL;AACL,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,eAAY;AACZ,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,cAAW;AACX,EAAAA,WAAA,oBAAiB;AACjB,EAAAA,WAAA,0BAAuB;AACvB,EAAAA,WAAA,UAAO;AACP,EAAAA,WAAA,oBAAiB;AACjB,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,mBAAgB;AAChB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,6BAA0B;AAC1B,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,wBAAqB;AACrB,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,YAAS;AAvBC,SAAAA;AAAA,GAAA;AA0BL,MAAM,gBAAgB;AAE7B,MAAM,mBAAwC,IAAI,IAAI,OAAO,OAAO,SAAS,CAAC;AAEvE,IAAK,mBAAL,kBAAKC,sBAAL;AACL,EAAAA,kBAAA,eAAY;AACZ,EAAAA,kBAAA,cAAW;AACX,EAAAA,kBAAA,aAAU;AAHA,SAAAA;AAAA,GAAA;AAaL,MAAM,mBAAmB,CAAC,QAAwC;AACvE,MAAI,QAAQ;AACV,WAAO,EAAE,KAAK,MAAM,2BAA2B,QAAQ,CAAC,aAAa,EAAE;AACzE,MAAI,iBAAiB,IAAI,GAAG,KAAK,IAAI,WAAW,SAAS,GAAG;AAC1D,WAAO,EAAE,KAAK,MAAM,6BAA4B,QAAQ,CAAC,GAAG,EAAE;AAAA,EAChE;AACA,SAAO,EAAE,KAAK,MAAM,yBAA0B,QAAQ,CAAC,EAAE;AAC3D;AAkFO,MAAM,aAAa,CAAC,eACzB,MAAM,EAAE,GAAG,WAAW,GAAG,aAAa,IAAI;AAQ5C,MAAM,aAAa,CAAC,KAAa,UAC/B,QAAQ,MAAM,SAAS,iBAAiB,IAAI,GAAG,KAAK,IAAI,WAAW,SAAS;AAI9E,MAAM,mBAAmB,EAAE,YAAY,EAAE,QAAQ,qBAAqB,CAAC;AAIhE,MAAM,kBAAkB,CAC7B,MACA,UACoB;AACpB,QAAM,SAAS,iBAAiB,UAAU,IAAI;AAC9C,MAAI,CAAC,OAAO,QAAS,QAAO,CAAC;AAC7B,QAAM,QAAyB,CAAC;AAChC,MAAI,WAAiC;AACrC,aAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,OAAO,KAAK,MAAM,GAAG;AAC/D,QAAI,CAAC,WAAW,OAAO,EAAG;AAC1B,UAAM,SAAwB,CAAC,YAAY,QAAQ,QAAQ,YAAY,GAAG;AAC1E,QAAI,QAAQ,cAAe,YAAW;AAAA,aAC7B,WAAW,KAAK,KAAK,EAAG,OAAM,KAAK,MAAM;AAAA,EACpD;AACA,SAAO,YAAY,OAAO,QAAQ,CAAC,GAAG,OAAO,QAAQ;AACvD;",
|
|
6
6
|
"names": ["HookEvent", "HookEventKeyKind"]
|
|
7
7
|
}
|
|
@@ -4,9 +4,11 @@ export { always, never, whenInput } from "./approval.mjs";
|
|
|
4
4
|
export type { ApprovalPolicyIface } from "./approval.mjs";
|
|
5
5
|
export { DELETE, GET, POST, PUT, WS, defineChannel, defineProviderChannel, disableChannel, } from "./channels.mjs";
|
|
6
6
|
export type { AuthoredChannelDefinitionIface, RouteHandler, RouteHandlerArgsIface, } from "./channels.mjs";
|
|
7
|
-
export { defineMcpClientConnection } from "./connections.mjs";
|
|
8
|
-
export type { McpClientConnectionDefinitionIface, McpConnectionAuthIface } from "./connections.mjs";
|
|
7
|
+
export { defineHostedConnection, defineMcpClientConnection } from "./connections.mjs";
|
|
8
|
+
export type { HostedConnectionDefinitionIface, McpClientConnectionDefinitionIface, McpConnectionAuthIface, McpConnectionToolsIface, McpToolAnnotationSelectorIface, McpToolSelector, } from "./connections.mjs";
|
|
9
9
|
export * from "./context.mjs";
|
|
10
|
+
export { requireHostedBinding } from '@finalai/agent-provider';
|
|
11
|
+
export type { HostedBindingsIface } from '@finalai/agent-provider';
|
|
10
12
|
export { CredentialOwner, CredentialPayer, credentials } from "./credentials.mjs";
|
|
11
13
|
export type { CredentialNode, CredentialPolicyIface } from "./credentials.mjs";
|
|
12
14
|
export { defineDynamic } from "./dynamic.mjs";
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
defineProviderChannel,
|
|
11
11
|
disableChannel
|
|
12
12
|
} from "./channels.mjs";
|
|
13
|
-
import { defineMcpClientConnection } from "./connections.mjs";
|
|
13
|
+
import { defineHostedConnection, defineMcpClientConnection } from "./connections.mjs";
|
|
14
14
|
export * from "./context.mjs";
|
|
15
|
+
import { requireHostedBinding } from "@finalai/agent-provider";
|
|
15
16
|
import { CredentialOwner, CredentialPayer, credentials } from "./credentials.mjs";
|
|
16
17
|
import { defineDynamic } from "./dynamic.mjs";
|
|
17
18
|
import { completeHarnessDescription, defineHarness } from "./harness.mjs";
|
|
@@ -46,6 +47,7 @@ export {
|
|
|
46
47
|
defineDynamic,
|
|
47
48
|
defineHarness,
|
|
48
49
|
defineHook,
|
|
50
|
+
defineHostedConnection,
|
|
49
51
|
defineInstructions,
|
|
50
52
|
defineMcpClientConnection,
|
|
51
53
|
defineProviderChannel,
|
|
@@ -57,6 +59,7 @@ export {
|
|
|
57
59
|
disableChannel,
|
|
58
60
|
harnessHost,
|
|
59
61
|
never,
|
|
62
|
+
requireHostedBinding,
|
|
60
63
|
toolResultFrom,
|
|
61
64
|
whenInput
|
|
62
65
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/authoring/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { defineAgent } from \"./agent.mjs\";\nexport type {\n AgentDefinitionInputIface,\n ChannelBindingValueIface,\n HarnessBindingValueIface,\n} from \"./agent.mjs\";\nexport { always, never, whenInput } from \"./approval.mjs\";\nexport type { ApprovalPolicyIface } from \"./approval.mjs\";\nexport {\n DELETE,\n GET,\n POST,\n PUT,\n WS,\n defineChannel,\n defineProviderChannel,\n disableChannel,\n} from \"./channels.mjs\";\nexport type {\n AuthoredChannelDefinitionIface,\n RouteHandler,\n RouteHandlerArgsIface,\n} from \"./channels.mjs\";\nexport { defineMcpClientConnection } from \"./connections.mjs\";\nexport type {
|
|
5
|
-
"mappings": "AAAA,SAAS,mBAAmB;AAM5B,SAAS,QAAQ,OAAO,iBAAiB;AAEzC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAMP,SAAS,iCAAiC;
|
|
4
|
+
"sourcesContent": ["export { defineAgent } from \"./agent.mjs\";\nexport type {\n AgentDefinitionInputIface,\n ChannelBindingValueIface,\n HarnessBindingValueIface,\n} from \"./agent.mjs\";\nexport { always, never, whenInput } from \"./approval.mjs\";\nexport type { ApprovalPolicyIface } from \"./approval.mjs\";\nexport {\n DELETE,\n GET,\n POST,\n PUT,\n WS,\n defineChannel,\n defineProviderChannel,\n disableChannel,\n} from \"./channels.mjs\";\nexport type {\n AuthoredChannelDefinitionIface,\n RouteHandler,\n RouteHandlerArgsIface,\n} from \"./channels.mjs\";\nexport { defineHostedConnection, defineMcpClientConnection } from \"./connections.mjs\";\nexport type {\n HostedConnectionDefinitionIface,\n McpClientConnectionDefinitionIface,\n McpConnectionAuthIface,\n McpConnectionToolsIface,\n McpToolAnnotationSelectorIface,\n McpToolSelector,\n} from \"./connections.mjs\";\nexport * from \"./context.mjs\";\nexport { requireHostedBinding } from '@finalai/agent-provider';\nexport type { HostedBindingsIface } from '@finalai/agent-provider';\nexport { CredentialOwner, CredentialPayer, credentials } from \"./credentials.mjs\";\nexport type { CredentialNode, CredentialPolicyIface } from \"./credentials.mjs\";\nexport { defineDynamic } from \"./dynamic.mjs\";\nexport type { DynamicDefinitionIface, DynamicEventsIface, DynamicSentinelIface } from \"./dynamic.mjs\";\nexport { completeHarnessDescription, defineHarness } from \"./harness.mjs\";\nexport type {\n AuthoredHarnessCloseContextIface,\n AuthoredHarnessDescriptionIface,\n AuthoredHarnessEndpointIface,\n AuthoredHarnessHealthIface,\n AuthoredHarnessIface,\n AuthoredHarnessOpenArgsIface,\n AuthoredHarnessRefContextIface,\n AuthoredHarnessResumeArgsIface,\n AuthoredHarnessSessionRefIface,\n DefinedAuthoredHarnessIface,\n} from \"./harness.mjs\";\nexport { HookEvent, defineHook } from \"./hooks.mjs\";\nexport type {\n HookContextIface,\n HookDefinitionIface,\n HookEventFor,\n HookEventIface,\n HookEventKey,\n} from \"./hooks.mjs\";\nexport { defineInstructions } from \"./instructions.mjs\";\nexport type { DefinedInstructionsIface, InstructionsDefinitionIface } from \"./instructions.mjs\";\nexport {\n SandboxWire,\n baseTools,\n defineSandbox,\n defineSandboxProvider,\n harnessHost,\n} from \"./sandbox.mjs\";\nexport type {\n BaseToolsValueIface,\n HarnessHostIface,\n SandboxSelector,\n SandboxSelectorContextIface,\n SandboxTargetValue,\n} from \"./sandbox.mjs\";\nexport { defineSchedule } from \"./schedules.mjs\";\nexport type { ScheduleInputIface } from \"./schedules.mjs\";\nexport { defineSkill } from \"./skills.mjs\";\nexport type { SkillDefinitionIface } from \"./skills.mjs\";\nexport { defineTool, toolResultFrom } from \"./tools.mjs\";\nexport type {\n DefinedToolIface,\n StandardSchemaLikeIface,\n ToolCallEventDataIface,\n ToolDefinitionIface,\n ToolInputSchema,\n} from \"./tools.mjs\";\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,mBAAmB;AAM5B,SAAS,QAAQ,OAAO,iBAAiB;AAEzC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAMP,SAAS,wBAAwB,iCAAiC;AASlE,cAAc;AACd,SAAS,4BAA4B;AAErC,SAAS,iBAAiB,iBAAiB,mBAAmB;AAE9D,SAAS,qBAAqB;AAE9B,SAAS,4BAA4B,qBAAqB;AAa1D,SAAS,WAAW,kBAAkB;AAQtC,SAAS,0BAA0B;AAEnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAQP,SAAS,sBAAsB;AAE/B,SAAS,mBAAmB;AAE5B,SAAS,YAAY,sBAAsB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { BaseCapability, NetworkSandboxSessionIface, SandboxEnvironmentIface, SandboxOpenRequestIface } from '@finalai/agent-provider';
|
|
1
|
+
import type { BaseCapability, HostedBindingsIface, NetworkSandboxSessionIface, SandboxEnvironmentIface, SandboxOpenRequestIface } from '@finalai/agent-provider';
|
|
2
2
|
import type { AgentSessionInfoIface, SecretsIface } from "./context.mjs";
|
|
3
3
|
import type { DynamicSentinelIface } from "./dynamic.mjs";
|
|
4
4
|
export { defineSandboxProvider, SandboxWire } from '@finalai/agent-provider';
|
|
5
5
|
export interface SandboxSelectorContextIface {
|
|
6
6
|
readonly session: AgentSessionInfoIface;
|
|
7
7
|
readonly secrets: SecretsIface;
|
|
8
|
+
readonly bindings?: HostedBindingsIface;
|
|
8
9
|
open(request: SandboxOpenRequestIface<unknown, unknown>): Promise<NetworkSandboxSessionIface>;
|
|
9
10
|
}
|
|
10
11
|
export type SandboxSelector = (ctx: SandboxSelectorContextIface) => NetworkSandboxSessionIface | SandboxOpenRequestIface<unknown, unknown> | Promise<NetworkSandboxSessionIface | SandboxOpenRequestIface<unknown, unknown>>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/authoring/sandbox.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n BaseCapability,\n NetworkSandboxSessionIface,\n SandboxEnvironmentIface,\n SandboxOpenRequestIface,\n} from '@finalai/agent-provider';\nimport { AuthoredKind, stamp } from \"./brand.mjs\";\nimport type { AgentSessionInfoIface, SecretsIface } from \"./context.mjs\";\nimport type { DynamicSentinelIface } from \"./dynamic.mjs\";\n\nexport { defineSandboxProvider, SandboxWire } from '@finalai/agent-provider';\n\n// sandbox.ts: named exports are sandbox targets (an\n// environment such as `computerSetupGuide({...})`, or a defineDynamic resolving\n// to one); the default export is the default target, either an environment\n// or a selector that opens it per session.\n\nexport interface SandboxSelectorContextIface {\n readonly session: AgentSessionInfoIface;\n readonly secrets: SecretsIface;\n // Starts (or reattaches to) the requested environment and returns the live\n // session, so a selector can prepare it before the agent uses it.\n open(request: SandboxOpenRequestIface<unknown, unknown>): Promise<NetworkSandboxSessionIface>;\n}\n\nexport type SandboxSelector = (\n ctx: SandboxSelectorContextIface,\n) =>\n | NetworkSandboxSessionIface\n | SandboxOpenRequestIface<unknown, unknown>\n | Promise<NetworkSandboxSessionIface | SandboxOpenRequestIface<unknown, unknown>>;\n\n// The harness's own host as a base-tool binding: the capability is the\n// harness's native one where it runs, with no sandbox target. Only\n// harnesses that provide it natively (host-disableable, host-fixed) can serve it.\nexport interface HarnessHostIface {\n readonly harnessHost: true;\n}\n\nexport const harnessHost: HarnessHostIface = stamp({ harnessHost: true }, AuthoredKind.HarnessHost);\n\nexport type SandboxTargetValue =\n | HarnessHostIface\n | SandboxEnvironmentIface<unknown, unknown>\n | SandboxOpenRequestIface<unknown, unknown>\n | DynamicSentinelIface\n | SandboxSelector\n // A target name, for targets that are not imported (Build forms).\n | string;\n\nexport const defineSandbox = <\n T extends SandboxSelector | SandboxEnvironmentIface<unknown, unknown>,\n>(\n value: T,\n): T => (value instanceof Function ? stamp(value, AuthoredKind.SandboxSelector) : value);\n\nexport type BaseToolsInputIface = Partial<\n Record<BaseCapability | `${BaseCapability}`, SandboxTargetValue>\n>;\n\nexport interface BaseToolsValueIface {\n readonly base: BaseToolsInputIface;\n}\n\n// Declares base tool capabilities, each bound to a sandbox target exported\n// from sandbox.ts or to `harnessHost`. Targets are\n// resolved by identity to their export name at compile time.\nexport const baseTools = (base: BaseToolsInputIface): BaseToolsValueIface =>\n stamp({ base: { ...base } }, AuthoredKind.BaseTools);\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type {\n BaseCapability,\n HostedBindingsIface,\n NetworkSandboxSessionIface,\n SandboxEnvironmentIface,\n SandboxOpenRequestIface,\n} from '@finalai/agent-provider';\nimport { AuthoredKind, stamp } from \"./brand.mjs\";\nimport type { AgentSessionInfoIface, SecretsIface } from \"./context.mjs\";\nimport type { DynamicSentinelIface } from \"./dynamic.mjs\";\n\nexport { defineSandboxProvider, SandboxWire } from '@finalai/agent-provider';\n\n// sandbox.ts: named exports are sandbox targets (an\n// environment such as `computerSetupGuide({...})`, or a defineDynamic resolving\n// to one); the default export is the default target, either an environment\n// or a selector that opens it per session.\n\nexport interface SandboxSelectorContextIface {\n readonly session: AgentSessionInfoIface;\n readonly secrets: SecretsIface;\n readonly bindings?: HostedBindingsIface;\n // Starts (or reattaches to) the requested environment and returns the live\n // session, so a selector can prepare it before the agent uses it.\n open(request: SandboxOpenRequestIface<unknown, unknown>): Promise<NetworkSandboxSessionIface>;\n}\n\nexport type SandboxSelector = (\n ctx: SandboxSelectorContextIface,\n) =>\n | NetworkSandboxSessionIface\n | SandboxOpenRequestIface<unknown, unknown>\n | Promise<NetworkSandboxSessionIface | SandboxOpenRequestIface<unknown, unknown>>;\n\n// The harness's own host as a base-tool binding: the capability is the\n// harness's native one where it runs, with no sandbox target. Only\n// harnesses that provide it natively (host-disableable, host-fixed) can serve it.\nexport interface HarnessHostIface {\n readonly harnessHost: true;\n}\n\nexport const harnessHost: HarnessHostIface = stamp({ harnessHost: true }, AuthoredKind.HarnessHost);\n\nexport type SandboxTargetValue =\n | HarnessHostIface\n | SandboxEnvironmentIface<unknown, unknown>\n | SandboxOpenRequestIface<unknown, unknown>\n | DynamicSentinelIface\n | SandboxSelector\n // A target name, for targets that are not imported (Build forms).\n | string;\n\nexport const defineSandbox = <\n T extends SandboxSelector | SandboxEnvironmentIface<unknown, unknown>,\n>(\n value: T,\n): T => (value instanceof Function ? stamp(value, AuthoredKind.SandboxSelector) : value);\n\nexport type BaseToolsInputIface = Partial<\n Record<BaseCapability | `${BaseCapability}`, SandboxTargetValue>\n>;\n\nexport interface BaseToolsValueIface {\n readonly base: BaseToolsInputIface;\n}\n\n// Declares base tool capabilities, each bound to a sandbox target exported\n// from sandbox.ts or to `harnessHost`. Targets are\n// resolved by identity to their export name at compile time.\nexport const baseTools = (base: BaseToolsInputIface): BaseToolsValueIface =>\n stamp({ base: { ...base } }, AuthoredKind.BaseTools);\n"],
|
|
5
|
+
"mappings": "AAOA,SAAS,cAAc,aAAa;AAIpC,SAAS,uBAAuB,mBAAmB;AA8B5C,MAAM,cAAgC,MAAM,EAAE,aAAa,KAAK,GAAG,aAAa,WAAW;AAW3F,MAAM,gBAAgB,CAG3B,UACO,iBAAiB,WAAW,MAAM,OAAO,aAAa,eAAe,IAAI;AAa3E,MAAM,YAAY,CAAC,SACxB,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,aAAa,SAAS;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -118,6 +118,8 @@ const assemble = (input) => {
|
|
|
118
118
|
const slot = { $dynamic: { resolver, events } };
|
|
119
119
|
if (dynamic.description != null) slot.$dynamic.description = dynamic.description;
|
|
120
120
|
if (dynamic.preview != null) slot.$dynamic.preview = dynamic.preview;
|
|
121
|
+
if ((dynamic.requiredBindings?.length ?? 0) > 0)
|
|
122
|
+
slot.$dynamic.requiredBindings = dynamic.requiredBindings;
|
|
121
123
|
if (dynamic.description == null && dynamic.preview == null) {
|
|
122
124
|
report(
|
|
123
125
|
DiagnosticSeverity.Note,
|
|
@@ -399,6 +401,9 @@ ${text}`;
|
|
|
399
401
|
mcpServers = {
|
|
400
402
|
$dynamic: {
|
|
401
403
|
resolver: COMBINED_MCP_SERVERS_EXPORT,
|
|
404
|
+
requiredBindings: [...ofSlot(SlotKind.Connection), ...ofSlot(SlotKind.Tool)].flatMap(
|
|
405
|
+
(module) => module.value?.type === "dynamic" ? module.value.requiredBindings ?? [] : []
|
|
406
|
+
),
|
|
402
407
|
events: anyTurnStartedServer ? [DynamicEvent.SessionStarted, DynamicEvent.TurnStarted] : [DynamicEvent.SessionStarted],
|
|
403
408
|
description: "Authored tools and connections, including the dynamic ones, resolved when the session starts."
|
|
404
409
|
}
|
|
@@ -852,7 +857,7 @@ ${text}`;
|
|
|
852
857
|
identity: {
|
|
853
858
|
name: agent?.name ?? input.fallbackName,
|
|
854
859
|
description: agent?.description ?? null,
|
|
855
|
-
|
|
860
|
+
...agent?.avatar == null ? {} : { avatar: agent.avatar }
|
|
856
861
|
},
|
|
857
862
|
harness: { harness: harnessRef, config },
|
|
858
863
|
mcpServers,
|