@truefoundry/trueforge-core 0.2.0-rc.6 → 0.2.0
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/dist/agent-session/SessionHandle.d.ts +1 -0
- package/dist/agent-session/SessionHandle.d.ts.map +1 -1
- package/dist/agent-session/SessionHandle.js +1 -0
- package/dist/agent-session/SessionHandle.js.map +1 -1
- package/dist/agent-session/SessionHandle.mjs +1 -0
- package/dist/agent-session/SessionHandle.mjs.map +1 -1
- package/dist/agent-session/models/TurnRecord.d.ts +1 -0
- package/dist/agent-session/models/TurnRecord.d.ts.map +1 -1
- package/dist/agent-session/models/TurnRecord.js.map +1 -1
- package/dist/agent-session/models/TurnRecord.mjs.map +1 -1
- package/dist/core/capabilities/builtins/OpenUI.d.ts.map +1 -1
- package/dist/core/capabilities/builtins/OpenUI.js +4 -2
- package/dist/core/capabilities/builtins/OpenUI.js.map +1 -1
- package/dist/core/capabilities/builtins/OpenUI.mjs +4 -2
- package/dist/core/capabilities/builtins/OpenUI.mjs.map +1 -1
- package/dist/core/runtime/DeferredTool.d.ts.map +1 -1
- package/dist/core/runtime/DeferredTool.js +3 -1
- package/dist/core/runtime/DeferredTool.js.map +1 -1
- package/dist/core/runtime/DeferredTool.mjs +3 -1
- package/dist/core/runtime/DeferredTool.mjs.map +1 -1
- package/dist/core/sandbox/Sandbox.d.ts.map +1 -1
- package/dist/core/sandbox/Sandbox.js +4 -1
- package/dist/core/sandbox/Sandbox.js.map +1 -1
- package/dist/core/sandbox/Sandbox.mjs +4 -1
- package/dist/core/sandbox/Sandbox.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -40,6 +40,7 @@ export declare class SessionHandle<TSessionCustom extends object = Record<string
|
|
|
40
40
|
*/
|
|
41
41
|
createTurn(input: {
|
|
42
42
|
turn_id: string;
|
|
43
|
+
active_executor_id: string;
|
|
43
44
|
input?: TurnInputItem[] | undefined;
|
|
44
45
|
/** 'auto'/omitted → session.last_turn_id; 'none' → new root; id → fork from that turn. */
|
|
45
46
|
previous_turn_id?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionHandle.d.ts","sourceRoot":"","sources":["../../src/agent-session/SessionHandle.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,qBAAqB,EAA2B,MAAM,yBAAyB,CAAC;AAC9F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAkB,KAAK,UAAU,EAAqB,MAAM,qBAAqB,CAAC;AAEzF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAoC,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACxH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAyF1C,qBAAa,aAAa,CACxB,cAAc,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACrD,WAAW,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAElD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6C;IACnE,OAAO,CAAC,OAAO,CAAgC;IAE/C,YAAY,OAAO,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAAC,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;KAAE,EAGjH;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,KAAK,IAAI,YAAY,CAExB;IAED,IAAI,MAAM,IAAI,cAAc,GAAG,IAAI,CAElC;IAED,IAAI,QAAQ,IAAI,aAAa,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,CAExD;IAED,IAAI,MAAM,IAAI,aAAa,CAAC,cAAc,CAAC,CAE1C;IAED;;;;;;;;;;;;;;;;OAgBG;IACG,UAAU,CAAC,KAAK,EAAE;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC;QACpC,0FAA0F;QAC1F,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACtC,MAAM,EAAE,WAAW,CAAC;QACpB,QAAQ,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAC7C,yFAAyF;QACzF,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,WAAW,KAAK,WAAW,CAAC,GAAG,SAAS,CAAC;QAC7E;;;;WAIG;QACH,iCAAiC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACxD,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"SessionHandle.d.ts","sourceRoot":"","sources":["../../src/agent-session/SessionHandle.ts"],"names":[],"mappings":"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"}
|
|
@@ -224,6 +224,7 @@ var SessionHandle = class {
|
|
|
224
224
|
first_turn_id: previous?.first_turn_id ?? turnId,
|
|
225
225
|
ancestor_ids: previous ? [...previous.ancestor_ids, previous.turn_id].slice(-MAX_TURN_ANCESTORS) : [],
|
|
226
226
|
previous_turn_id: previousTurnId,
|
|
227
|
+
active_executor_id: input.active_executor_id,
|
|
227
228
|
state: { status: "running" },
|
|
228
229
|
input: input.input ?? [],
|
|
229
230
|
created_at: now,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/agent-session/SessionHandle.ts"],"sourcesContent":["/**\n * Bound session handle: starts turns via {@link SessionHandle.createTurn}.\n */\nimport { newEventId } from '../core/events/schema';\nimport type { AgentDefinition } from '../core/runtime/AgentDefinition';\nimport { AgentThread } from '../core/runtime/AgentThread';\nimport type {\n AgentThreadAppendContext,\n AgentThreadSendBatch,\n AgentThreadSnapshot,\n} from '../core/runtime/AgentThread.types';\nimport { AgentThreadOrchestrator } from '../core/runtime/AgentThreadOrchestrator';\nimport {\n isApprovalDecisionMessage,\n isClientSideToolResponseMessage,\n isInputUserMessage,\n} from '../core/runtime/contextUtils';\nimport type { CreateDynamicSubAgentThread } from '../core/runtime/CreateDynamicSubAgentThread';\nimport type { Sandbox } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { builtinsFromSpec } from './builtinsFromSpec';\nimport type { ITurnResourceResolver, ResolvedAgentDefinition } from './ITurnResourceResolver';\nimport type { SessionRecord } from './models/SessionRecord';\nimport { MAIN_THREAD_ID, type TurnRecord, type TurnSnapshot } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\nimport type { SessionEventItem } from './schemas/events';\nimport { EventType, type TurnDoneEvent } from './schemas/events';\nimport type { TokenPagination } from './schemas/pagination';\nimport type { SessionAgent } from './schemas/session';\nimport type { TurnInputItem } from './schemas/turn';\nimport { CancellationReason } from './schemas/turn';\nimport type { ISessionStore, NewThreadInit, TurnContextAppend, TurnRecordWithoutSnapshot } from './store/ISessionStore';\nimport { TurnHandle } from './TurnHandle';\n\n/** How many recent ancestors SessionHandle persists on each turn. Store-local. */\nconst MAX_TURN_ANCESTORS = 20;\n\nfunction resolvePreviousTurnId(requested: string | undefined, lastTurnId: string | null | undefined): string | null {\n if (requested === 'none') {\n return null;\n }\n if (requested === undefined || requested === 'auto') {\n return lastTurnId ?? null;\n }\n return requested;\n}\n\nfunction toSendBatch(input: TurnInputItem[] | undefined): AgentThreadSendBatch {\n if (!input || input.length === 0) {\n return [];\n }\n if (input.every(msg => isApprovalDecisionMessage(msg) || isClientSideToolResponseMessage(msg))) {\n return input;\n }\n if (input.every(isInputUserMessage)) {\n return input;\n }\n throw new Error('input must be homogeneous: all user messages, or all approval/tool-response messages');\n}\n\nfunction toNewThreadInit(snapshot: AgentThreadSnapshot): NewThreadInit {\n const { context, current_context_usage, completion, capability_state, ...rest } = snapshot;\n void context;\n void current_context_usage;\n void completion;\n void capability_state;\n return rest;\n}\n\nfunction collectContextAppends(\n events: AsyncGenerator<AgentThreadAppendContext, void, unknown>,\n): Promise<TurnContextAppend[]> {\n return (async () => {\n const appendMap = new Map<string, TurnContextAppend>();\n for await (const event of events) {\n const existing = appendMap.get(event.thread_id);\n if (existing) {\n existing.context.push(...event.context);\n if (event.current_context_usage !== undefined) {\n existing.current_context_usage = event.current_context_usage;\n }\n } else {\n appendMap.set(event.thread_id, {\n thread_id: event.thread_id,\n context: [...event.context],\n current_context_usage: event.current_context_usage ?? null,\n });\n }\n }\n return [...appendMap.values()];\n })();\n}\n\nfunction cancelledTurnDoneEvent(reason: CancellationReason): TurnDoneEvent {\n return {\n type: EventType.TURN_DONE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n state: {\n status: 'cancelled',\n reason,\n completed_at: new Date().toISOString(),\n },\n thread_id: null,\n };\n}\n\nfunction threadsRecordFromMap(threads: Map<string, AgentThread>): Record<string, AgentThreadSnapshot> {\n const out: Record<string, AgentThreadSnapshot> = {};\n for (const [id, thread] of threads) {\n out[id] = thread.toSnapshot();\n }\n return out;\n}\n\n// Current-turn thread ids. Main (`MAIN_THREAD_ID`) is always present — first turn\n// synthesizes it; later turns always carry it in the previous snapshot.\nfunction threadIdsForCurrentTurn(snapshot: TurnSnapshot | undefined): string[] {\n return snapshot ? Object.keys(snapshot.threads) : [MAIN_THREAD_ID];\n}\n\nexport class SessionHandle<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> {\n private readonly store: ISessionStore<TSessionCustom, TTurnCustom>;\n private session: SessionRecord<TSessionCustom>;\n\n constructor(options: { store: ISessionStore<TSessionCustom, TTurnCustom>; session: SessionRecord<TSessionCustom> }) {\n this.store = options.store;\n this.session = options.session;\n }\n\n get session_id(): string {\n return this.session.session_id;\n }\n\n get tenant_id(): string {\n return this.session.tenant_id;\n }\n\n get agent(): SessionAgent {\n return this.session.agent;\n }\n\n get custom(): TSessionCustom | null {\n return this.session.custom;\n }\n\n get metadata(): SessionRecord<TSessionCustom>['metadata'] {\n return this.session.metadata;\n }\n\n get record(): SessionRecord<TSessionCustom> {\n return this.session;\n }\n\n /**\n * Prepares and commits a new turn — NO execution happens here (execution =\n * TurnHandle.stream()). Builds threads from the previous turn's snapshot, then\n * sends the input through the orchestrator fully drained (validation +\n * context append; empty input still preflights threads awaiting user input),\n * then persists via one atomic store.createTurn LAST. A send/validation\n * failure therefore persists nothing. The returned turn is durable with\n * state { status: 'running' }.\n *\n * On any failure, createTurn() closes the resolver (best-effort) before rethrowing,\n * so resources acquired here (e.g. a sandbox VM) never outlive a failed run.\n * On success, ownership of resolver.close() passes to TurnHandle.stream().\n *\n * `previous_turn_id`: omitted/`'auto'` → session tip; `'none'` → new root\n * (no parent, even on a non-empty session); string → fork from that turn\n * (must exist). Concurrent `'auto'` forks both succeed.\n */\n async createTurn(input: {\n turn_id: string;\n input?: TurnInputItem[] | undefined;\n /** 'auto'/omitted → session.last_turn_id; 'none' → new root; id → fork from that turn. */\n previous_turn_id?: string | undefined;\n signal: AbortSignal;\n resolver: ITurnResourceResolver<TTurnCustom>;\n /** Value = stored as-is. Fn = merge over previous turn's custom. Omitted = undefined. */\n custom?: TTurnCustom | ((previous?: TTurnCustom) => TTurnCustom) | undefined;\n /**\n * Forwarded to store.createTurn: sets session.title in the same atomic\n * unit IF the session has none; never overwrites. The caller derives the\n * value (e.g. from the first user message) — the library does not.\n */\n update_session_title_if_not_exist?: string | undefined;\n }): Promise<TurnHandle<TTurnCustom>> {\n const previousTurnId = resolvePreviousTurnId(input.previous_turn_id, this.session.last_turn_id);\n const previous = previousTurnId\n ? await this.freezeTurn({\n turn_id: previousTurnId,\n reason: CancellationReason.CancelledForNextTurn,\n })\n : undefined;\n\n const custom = typeof input.custom === 'function' ? input.custom(previous?.custom ?? undefined) : input.custom;\n\n // Dispose-on-early-failure: any resource acquired below (sandbox handle,\n // MCP connections) is owned by createTurn() until the TurnHandle is returned; from then\n // on TurnHandle.stream()'s finally owns resolver.close(). On any throw in this\n // acquisition phase we close the resolver (best-effort, error swallowed)\n // and rethrow — same pattern as the gateway's sessionTurnHandler, which\n // wraps getAgent/handler.init and calls gatewayStore.dispose() on failure.\n try {\n const tracing = input.resolver.createTracing();\n const agent = this.session.agent;\n const spec = agent.type === 'inline' ? agent.spec : await input.resolver.resolveAgentSpec({ agent_id: agent.id });\n const sandbox = await input.resolver.resolveSandbox({\n spec,\n existing: previous?.snapshot.sandbox_info ?? undefined,\n previousTurn: previous,\n signal: input.signal,\n tracing,\n });\n\n const definitionsByThreadId = await this.resolveAgentDefinitions({\n previous,\n resolver: input.resolver,\n spec,\n tracing,\n signal: input.signal,\n });\n\n // Wire Code Mode once from main toolSets before threads share the sandbox.\n const mainDefinition = definitionsByThreadId.get(MAIN_THREAD_ID);\n if (!mainDefinition) {\n throw new Error('Unreachable: missing resolved agent definition for main thread');\n }\n if (sandbox) {\n sandbox.configureCodeMode(mainDefinition.definition.toolSets ?? []);\n }\n\n const agentThreads = this.buildThreads({\n previous,\n resolver: input.resolver,\n spec,\n sandbox,\n tracing,\n definitionsByThreadId,\n });\n\n const createDynamicSubAgentThread = this.makeCreateDynamicSubAgentThread({\n resolver: input.resolver,\n previous,\n spec,\n sandbox,\n tracing,\n });\n\n const orchestrator = new AgentThreadOrchestrator({\n agentThreads,\n createDynamicSubAgentThread,\n tracing,\n logger: input.resolver.logger,\n });\n\n // SEND BEFORE COMMIT — validate + append; throw ⇒ nothing persisted.\n const sendBatch = toSendBatch(input.input);\n const new_context_appends = await collectContextAppends(orchestrator.send(sendBatch));\n\n const turnId = input.turn_id;\n const now = new Date();\n\n const new_threads: NewThreadInit[] = [];\n if (!previous) {\n const root = agentThreads.get(MAIN_THREAD_ID);\n if (root) {\n new_threads.push(toNewThreadInit(root.toSnapshot()));\n }\n } else {\n for (const [threadId, thread] of agentThreads) {\n if (previous.snapshot.threads[threadId] === undefined) {\n new_threads.push(toNewThreadInit(thread.toSnapshot()));\n }\n }\n }\n\n const turnInit: TurnRecordWithoutSnapshot<TTurnCustom> = {\n turn_id: turnId,\n session_id: this.session.session_id,\n first_turn_id: previous?.first_turn_id ?? turnId,\n ancestor_ids: previous ? [...previous.ancestor_ids, previous.turn_id].slice(-MAX_TURN_ANCESTORS) : [],\n previous_turn_id: previousTurnId,\n state: { status: 'running' },\n input: input.input ?? [],\n created_at: now,\n updated_at: now,\n custom: custom ?? null,\n };\n\n const turnRecord: TurnRecord<TTurnCustom> = {\n ...turnInit,\n snapshot: {\n threads: threadsRecordFromMap(agentThreads),\n mcp_servers: previous?.snapshot.mcp_servers ?? null,\n sandbox_info: previous?.snapshot.sandbox_info ?? null,\n },\n };\n\n await this.store.createTurn({\n turn: turnInit,\n new_threads,\n new_context_appends,\n capability_states: [...agentThreads].map(([thread_id, thread]) => ({\n thread_id,\n capability_state: thread.toSnapshot().capability_state,\n })),\n update_session_title_if_not_exist: input.update_session_title_if_not_exist ?? null,\n });\n\n const refreshed = await this.store.getSession({\n tenant_id: this.tenant_id,\n session_id: this.session.session_id,\n });\n if (refreshed) {\n this.session = refreshed;\n }\n\n return new TurnHandle({\n store: this.store,\n turn: turnRecord,\n orchestrator,\n resolver: input.resolver,\n signal: input.signal,\n });\n } catch (error) {\n await input.resolver.close().catch((closeError: unknown) => {\n input.resolver.logger.warn('TurnResourceResolver.close() failed after createTurn() error', {\n err: closeError,\n });\n });\n throw error;\n }\n }\n\n /**\n * Conditionally cancel a running turn in this session and return the\n * now-immutable record. Already-terminal turns are returned unchanged.\n * Missing turn → {@link TurnNotFoundError}.\n */\n async freezeTurn(input: { turn_id: string; reason: CancellationReason }): Promise<TurnRecord<TTurnCustom>> {\n return this.store.freezeAndGetTurn({\n session_id: this.session.session_id,\n turn_id: input.turn_id,\n reason: input.reason,\n turn_done_event: cancelledTurnDoneEvent(input.reason),\n });\n }\n\n /** Returns the turn handle (store-backed; not executable), or undefined if not found. */\n async getTurn(turn_id: string): Promise<TurnHandle<TTurnCustom> | undefined> {\n return TurnHandle.get({\n store: this.store,\n session_id: this.session.session_id,\n turn_id,\n });\n }\n\n /** Paginated list of this session's turn rows (no snapshot). */\n async listTurns(input: {\n limit: number;\n page_token?: string | undefined;\n }): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }> {\n return this.store.listTurns({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n });\n }\n\n /**\n * Paginated session-wide feed of persisted events across turns, including\n * turn.created / turn.done lifecycle events. Reads from the store only —\n * nothing is synthesized on read.\n */\n async listEvents(input: {\n limit: number;\n page_token?: string | undefined;\n last_turn_id?: string | undefined;\n }): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }> {\n return this.store.listSessionEvents({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n last_turn_id: input.last_turn_id,\n });\n }\n\n private async resolveAgentDefinitions(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n tracing: AgentTracing;\n signal: AbortSignal;\n }): Promise<Map<string, ResolvedAgentDefinition>> {\n const snapshots = input.previous?.snapshot.threads;\n const threadIds = threadIdsForCurrentTurn(input.previous?.snapshot);\n const definitionsByThreadId = new Map<string, ResolvedAgentDefinition>();\n await Promise.all(\n threadIds.map(async threadId => {\n const previousThreadSnapshot = snapshots?.[threadId];\n const resolved = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: previousThreadSnapshot?.agent_info ?? undefined,\n previousTurn: input.previous,\n signal: input.signal,\n tracing: input.tracing,\n });\n definitionsByThreadId.set(threadId, resolved);\n }),\n );\n return definitionsByThreadId;\n }\n\n private buildThreads(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n definitionsByThreadId: ReadonlyMap<string, ResolvedAgentDefinition>;\n }): Map<string, AgentThread> {\n const snapshots = input.previous?.snapshot.threads;\n const map = new Map<string, AgentThread>();\n for (const threadId of threadIdsForCurrentTurn(input.previous?.snapshot)) {\n const resolvedDefinition = input.definitionsByThreadId.get(threadId);\n if (!resolvedDefinition) {\n throw new Error(`Unreachable: missing resolved agent definition for thread '${threadId}'`);\n }\n map.set(\n threadId,\n this.buildThread({\n threadId,\n previousThreadSnapshot: snapshots?.[threadId],\n resolver: input.resolver,\n spec: input.spec,\n sandbox: input.sandbox,\n tracing: input.tracing,\n resolvedDefinition,\n }),\n );\n }\n return map;\n }\n\n private buildThread(input: {\n threadId: string;\n previousThreadSnapshot?: AgentThreadSnapshot | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n resolvedDefinition: ResolvedAgentDefinition;\n }): AgentThread {\n const { definition, extraCapabilities } = input.resolvedDefinition;\n const isChild = Boolean(input.previousThreadSnapshot?.parent);\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition,\n isChild,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition,\n threadId: input.threadId,\n title: input.previousThreadSnapshot?.agent_info?.name ?? (isChild ? input.threadId : 'main'),\n sandbox: input.sandbox,\n context: input.previousThreadSnapshot?.context,\n currentContextUsage: input.previousThreadSnapshot?.current_context_usage,\n parent: input.previousThreadSnapshot?.parent ?? undefined,\n agentInfo: input.previousThreadSnapshot?.agent_info ?? undefined,\n preComputedCompletion: input.previousThreadSnapshot?.completion ?? undefined,\n capabilities,\n capabilityState: input.previousThreadSnapshot?.capability_state ?? undefined,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n }\n\n private makeCreateDynamicSubAgentThread(input: {\n resolver: ITurnResourceResolver<TTurnCustom>;\n previous: TurnRecord<TTurnCustom> | undefined;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n }): CreateDynamicSubAgentThread {\n return async params => {\n const { definition, extraCapabilities } = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: params.request,\n previousTurn: input.previous,\n signal: params.signal,\n tracing: input.tracing,\n });\n // Model override (request.model) is resolved inside resolveAgentDefinition\n // into modelClient — do not re-label a stale client here.\n const childDefinition: AgentDefinition = {\n ...definition,\n toolSets: params.parentDefinition.toolSets ?? definition.toolSets,\n // The delegated task goes in as the initial user message; the sub-agent\n // system prompt is SUB_AGENT_IDENTITY (added by AgentThread.buildInstruction).\n instruction: undefined,\n messages: [{ role: 'user', content: params.request.input }],\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: undefined,\n };\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition: childDefinition,\n isChild: true,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition: childDefinition,\n threadId: params.threadId,\n title: params.request.name,\n sandbox: input.sandbox,\n parent: params.parent,\n agentInfo: params.request,\n capabilities,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/agent-session/SessionHandle.ts"],"sourcesContent":["/**\n * Bound session handle: starts turns via {@link SessionHandle.createTurn}.\n */\nimport { newEventId } from '../core/events/schema';\nimport type { AgentDefinition } from '../core/runtime/AgentDefinition';\nimport { AgentThread } from '../core/runtime/AgentThread';\nimport type {\n AgentThreadAppendContext,\n AgentThreadSendBatch,\n AgentThreadSnapshot,\n} from '../core/runtime/AgentThread.types';\nimport { AgentThreadOrchestrator } from '../core/runtime/AgentThreadOrchestrator';\nimport {\n isApprovalDecisionMessage,\n isClientSideToolResponseMessage,\n isInputUserMessage,\n} from '../core/runtime/contextUtils';\nimport type { CreateDynamicSubAgentThread } from '../core/runtime/CreateDynamicSubAgentThread';\nimport type { Sandbox } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { builtinsFromSpec } from './builtinsFromSpec';\nimport type { ITurnResourceResolver, ResolvedAgentDefinition } from './ITurnResourceResolver';\nimport type { SessionRecord } from './models/SessionRecord';\nimport { MAIN_THREAD_ID, type TurnRecord, type TurnSnapshot } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\nimport type { SessionEventItem } from './schemas/events';\nimport { EventType, type TurnDoneEvent } from './schemas/events';\nimport type { TokenPagination } from './schemas/pagination';\nimport type { SessionAgent } from './schemas/session';\nimport type { TurnInputItem } from './schemas/turn';\nimport { CancellationReason } from './schemas/turn';\nimport type { ISessionStore, NewThreadInit, TurnContextAppend, TurnRecordWithoutSnapshot } from './store/ISessionStore';\nimport { TurnHandle } from './TurnHandle';\n\n/** How many recent ancestors SessionHandle persists on each turn. Store-local. */\nconst MAX_TURN_ANCESTORS = 20;\n\nfunction resolvePreviousTurnId(requested: string | undefined, lastTurnId: string | null | undefined): string | null {\n if (requested === 'none') {\n return null;\n }\n if (requested === undefined || requested === 'auto') {\n return lastTurnId ?? null;\n }\n return requested;\n}\n\nfunction toSendBatch(input: TurnInputItem[] | undefined): AgentThreadSendBatch {\n if (!input || input.length === 0) {\n return [];\n }\n if (input.every(msg => isApprovalDecisionMessage(msg) || isClientSideToolResponseMessage(msg))) {\n return input;\n }\n if (input.every(isInputUserMessage)) {\n return input;\n }\n throw new Error('input must be homogeneous: all user messages, or all approval/tool-response messages');\n}\n\nfunction toNewThreadInit(snapshot: AgentThreadSnapshot): NewThreadInit {\n const { context, current_context_usage, completion, capability_state, ...rest } = snapshot;\n void context;\n void current_context_usage;\n void completion;\n void capability_state;\n return rest;\n}\n\nfunction collectContextAppends(\n events: AsyncGenerator<AgentThreadAppendContext, void, unknown>,\n): Promise<TurnContextAppend[]> {\n return (async () => {\n const appendMap = new Map<string, TurnContextAppend>();\n for await (const event of events) {\n const existing = appendMap.get(event.thread_id);\n if (existing) {\n existing.context.push(...event.context);\n if (event.current_context_usage !== undefined) {\n existing.current_context_usage = event.current_context_usage;\n }\n } else {\n appendMap.set(event.thread_id, {\n thread_id: event.thread_id,\n context: [...event.context],\n current_context_usage: event.current_context_usage ?? null,\n });\n }\n }\n return [...appendMap.values()];\n })();\n}\n\nfunction cancelledTurnDoneEvent(reason: CancellationReason): TurnDoneEvent {\n return {\n type: EventType.TURN_DONE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n state: {\n status: 'cancelled',\n reason,\n completed_at: new Date().toISOString(),\n },\n thread_id: null,\n };\n}\n\nfunction threadsRecordFromMap(threads: Map<string, AgentThread>): Record<string, AgentThreadSnapshot> {\n const out: Record<string, AgentThreadSnapshot> = {};\n for (const [id, thread] of threads) {\n out[id] = thread.toSnapshot();\n }\n return out;\n}\n\n// Current-turn thread ids. Main (`MAIN_THREAD_ID`) is always present — first turn\n// synthesizes it; later turns always carry it in the previous snapshot.\nfunction threadIdsForCurrentTurn(snapshot: TurnSnapshot | undefined): string[] {\n return snapshot ? Object.keys(snapshot.threads) : [MAIN_THREAD_ID];\n}\n\nexport class SessionHandle<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> {\n private readonly store: ISessionStore<TSessionCustom, TTurnCustom>;\n private session: SessionRecord<TSessionCustom>;\n\n constructor(options: { store: ISessionStore<TSessionCustom, TTurnCustom>; session: SessionRecord<TSessionCustom> }) {\n this.store = options.store;\n this.session = options.session;\n }\n\n get session_id(): string {\n return this.session.session_id;\n }\n\n get tenant_id(): string {\n return this.session.tenant_id;\n }\n\n get agent(): SessionAgent {\n return this.session.agent;\n }\n\n get custom(): TSessionCustom | null {\n return this.session.custom;\n }\n\n get metadata(): SessionRecord<TSessionCustom>['metadata'] {\n return this.session.metadata;\n }\n\n get record(): SessionRecord<TSessionCustom> {\n return this.session;\n }\n\n /**\n * Prepares and commits a new turn — NO execution happens here (execution =\n * TurnHandle.stream()). Builds threads from the previous turn's snapshot, then\n * sends the input through the orchestrator fully drained (validation +\n * context append; empty input still preflights threads awaiting user input),\n * then persists via one atomic store.createTurn LAST. A send/validation\n * failure therefore persists nothing. The returned turn is durable with\n * state { status: 'running' }.\n *\n * On any failure, createTurn() closes the resolver (best-effort) before rethrowing,\n * so resources acquired here (e.g. a sandbox VM) never outlive a failed run.\n * On success, ownership of resolver.close() passes to TurnHandle.stream().\n *\n * `previous_turn_id`: omitted/`'auto'` → session tip; `'none'` → new root\n * (no parent, even on a non-empty session); string → fork from that turn\n * (must exist). Concurrent `'auto'` forks both succeed.\n */\n async createTurn(input: {\n turn_id: string;\n active_executor_id: string;\n input?: TurnInputItem[] | undefined;\n /** 'auto'/omitted → session.last_turn_id; 'none' → new root; id → fork from that turn. */\n previous_turn_id?: string | undefined;\n signal: AbortSignal;\n resolver: ITurnResourceResolver<TTurnCustom>;\n /** Value = stored as-is. Fn = merge over previous turn's custom. Omitted = undefined. */\n custom?: TTurnCustom | ((previous?: TTurnCustom) => TTurnCustom) | undefined;\n /**\n * Forwarded to store.createTurn: sets session.title in the same atomic\n * unit IF the session has none; never overwrites. The caller derives the\n * value (e.g. from the first user message) — the library does not.\n */\n update_session_title_if_not_exist?: string | undefined;\n }): Promise<TurnHandle<TTurnCustom>> {\n const previousTurnId = resolvePreviousTurnId(input.previous_turn_id, this.session.last_turn_id);\n const previous = previousTurnId\n ? await this.freezeTurn({\n turn_id: previousTurnId,\n reason: CancellationReason.CancelledForNextTurn,\n })\n : undefined;\n\n const custom = typeof input.custom === 'function' ? input.custom(previous?.custom ?? undefined) : input.custom;\n\n // Dispose-on-early-failure: any resource acquired below (sandbox handle,\n // MCP connections) is owned by createTurn() until the TurnHandle is returned; from then\n // on TurnHandle.stream()'s finally owns resolver.close(). On any throw in this\n // acquisition phase we close the resolver (best-effort, error swallowed)\n // and rethrow — same pattern as the gateway's sessionTurnHandler, which\n // wraps getAgent/handler.init and calls gatewayStore.dispose() on failure.\n try {\n const tracing = input.resolver.createTracing();\n const agent = this.session.agent;\n const spec = agent.type === 'inline' ? agent.spec : await input.resolver.resolveAgentSpec({ agent_id: agent.id });\n const sandbox = await input.resolver.resolveSandbox({\n spec,\n existing: previous?.snapshot.sandbox_info ?? undefined,\n previousTurn: previous,\n signal: input.signal,\n tracing,\n });\n\n const definitionsByThreadId = await this.resolveAgentDefinitions({\n previous,\n resolver: input.resolver,\n spec,\n tracing,\n signal: input.signal,\n });\n\n // Wire Code Mode once from main toolSets before threads share the sandbox.\n const mainDefinition = definitionsByThreadId.get(MAIN_THREAD_ID);\n if (!mainDefinition) {\n throw new Error('Unreachable: missing resolved agent definition for main thread');\n }\n if (sandbox) {\n sandbox.configureCodeMode(mainDefinition.definition.toolSets ?? []);\n }\n\n const agentThreads = this.buildThreads({\n previous,\n resolver: input.resolver,\n spec,\n sandbox,\n tracing,\n definitionsByThreadId,\n });\n\n const createDynamicSubAgentThread = this.makeCreateDynamicSubAgentThread({\n resolver: input.resolver,\n previous,\n spec,\n sandbox,\n tracing,\n });\n\n const orchestrator = new AgentThreadOrchestrator({\n agentThreads,\n createDynamicSubAgentThread,\n tracing,\n logger: input.resolver.logger,\n });\n\n // SEND BEFORE COMMIT — validate + append; throw ⇒ nothing persisted.\n const sendBatch = toSendBatch(input.input);\n const new_context_appends = await collectContextAppends(orchestrator.send(sendBatch));\n\n const turnId = input.turn_id;\n const now = new Date();\n\n const new_threads: NewThreadInit[] = [];\n if (!previous) {\n const root = agentThreads.get(MAIN_THREAD_ID);\n if (root) {\n new_threads.push(toNewThreadInit(root.toSnapshot()));\n }\n } else {\n for (const [threadId, thread] of agentThreads) {\n if (previous.snapshot.threads[threadId] === undefined) {\n new_threads.push(toNewThreadInit(thread.toSnapshot()));\n }\n }\n }\n\n const turnInit: TurnRecordWithoutSnapshot<TTurnCustom> = {\n turn_id: turnId,\n session_id: this.session.session_id,\n first_turn_id: previous?.first_turn_id ?? turnId,\n ancestor_ids: previous ? [...previous.ancestor_ids, previous.turn_id].slice(-MAX_TURN_ANCESTORS) : [],\n previous_turn_id: previousTurnId,\n active_executor_id: input.active_executor_id,\n state: { status: 'running' },\n input: input.input ?? [],\n created_at: now,\n updated_at: now,\n custom: custom ?? null,\n };\n\n const turnRecord: TurnRecord<TTurnCustom> = {\n ...turnInit,\n snapshot: {\n threads: threadsRecordFromMap(agentThreads),\n mcp_servers: previous?.snapshot.mcp_servers ?? null,\n sandbox_info: previous?.snapshot.sandbox_info ?? null,\n },\n };\n\n await this.store.createTurn({\n turn: turnInit,\n new_threads,\n new_context_appends,\n capability_states: [...agentThreads].map(([thread_id, thread]) => ({\n thread_id,\n capability_state: thread.toSnapshot().capability_state,\n })),\n update_session_title_if_not_exist: input.update_session_title_if_not_exist ?? null,\n });\n\n const refreshed = await this.store.getSession({\n tenant_id: this.tenant_id,\n session_id: this.session.session_id,\n });\n if (refreshed) {\n this.session = refreshed;\n }\n\n return new TurnHandle({\n store: this.store,\n turn: turnRecord,\n orchestrator,\n resolver: input.resolver,\n signal: input.signal,\n });\n } catch (error) {\n await input.resolver.close().catch((closeError: unknown) => {\n input.resolver.logger.warn('TurnResourceResolver.close() failed after createTurn() error', {\n err: closeError,\n });\n });\n throw error;\n }\n }\n\n /**\n * Conditionally cancel a running turn in this session and return the\n * now-immutable record. Already-terminal turns are returned unchanged.\n * Missing turn → {@link TurnNotFoundError}.\n */\n async freezeTurn(input: { turn_id: string; reason: CancellationReason }): Promise<TurnRecord<TTurnCustom>> {\n return this.store.freezeAndGetTurn({\n session_id: this.session.session_id,\n turn_id: input.turn_id,\n reason: input.reason,\n turn_done_event: cancelledTurnDoneEvent(input.reason),\n });\n }\n\n /** Returns the turn handle (store-backed; not executable), or undefined if not found. */\n async getTurn(turn_id: string): Promise<TurnHandle<TTurnCustom> | undefined> {\n return TurnHandle.get({\n store: this.store,\n session_id: this.session.session_id,\n turn_id,\n });\n }\n\n /** Paginated list of this session's turn rows (no snapshot). */\n async listTurns(input: {\n limit: number;\n page_token?: string | undefined;\n }): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }> {\n return this.store.listTurns({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n });\n }\n\n /**\n * Paginated session-wide feed of persisted events across turns, including\n * turn.created / turn.done lifecycle events. Reads from the store only —\n * nothing is synthesized on read.\n */\n async listEvents(input: {\n limit: number;\n page_token?: string | undefined;\n last_turn_id?: string | undefined;\n }): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }> {\n return this.store.listSessionEvents({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n last_turn_id: input.last_turn_id,\n });\n }\n\n private async resolveAgentDefinitions(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n tracing: AgentTracing;\n signal: AbortSignal;\n }): Promise<Map<string, ResolvedAgentDefinition>> {\n const snapshots = input.previous?.snapshot.threads;\n const threadIds = threadIdsForCurrentTurn(input.previous?.snapshot);\n const definitionsByThreadId = new Map<string, ResolvedAgentDefinition>();\n await Promise.all(\n threadIds.map(async threadId => {\n const previousThreadSnapshot = snapshots?.[threadId];\n const resolved = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: previousThreadSnapshot?.agent_info ?? undefined,\n previousTurn: input.previous,\n signal: input.signal,\n tracing: input.tracing,\n });\n definitionsByThreadId.set(threadId, resolved);\n }),\n );\n return definitionsByThreadId;\n }\n\n private buildThreads(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n definitionsByThreadId: ReadonlyMap<string, ResolvedAgentDefinition>;\n }): Map<string, AgentThread> {\n const snapshots = input.previous?.snapshot.threads;\n const map = new Map<string, AgentThread>();\n for (const threadId of threadIdsForCurrentTurn(input.previous?.snapshot)) {\n const resolvedDefinition = input.definitionsByThreadId.get(threadId);\n if (!resolvedDefinition) {\n throw new Error(`Unreachable: missing resolved agent definition for thread '${threadId}'`);\n }\n map.set(\n threadId,\n this.buildThread({\n threadId,\n previousThreadSnapshot: snapshots?.[threadId],\n resolver: input.resolver,\n spec: input.spec,\n sandbox: input.sandbox,\n tracing: input.tracing,\n resolvedDefinition,\n }),\n );\n }\n return map;\n }\n\n private buildThread(input: {\n threadId: string;\n previousThreadSnapshot?: AgentThreadSnapshot | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n resolvedDefinition: ResolvedAgentDefinition;\n }): AgentThread {\n const { definition, extraCapabilities } = input.resolvedDefinition;\n const isChild = Boolean(input.previousThreadSnapshot?.parent);\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition,\n isChild,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition,\n threadId: input.threadId,\n title: input.previousThreadSnapshot?.agent_info?.name ?? (isChild ? input.threadId : 'main'),\n sandbox: input.sandbox,\n context: input.previousThreadSnapshot?.context,\n currentContextUsage: input.previousThreadSnapshot?.current_context_usage,\n parent: input.previousThreadSnapshot?.parent ?? undefined,\n agentInfo: input.previousThreadSnapshot?.agent_info ?? undefined,\n preComputedCompletion: input.previousThreadSnapshot?.completion ?? undefined,\n capabilities,\n capabilityState: input.previousThreadSnapshot?.capability_state ?? undefined,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n }\n\n private makeCreateDynamicSubAgentThread(input: {\n resolver: ITurnResourceResolver<TTurnCustom>;\n previous: TurnRecord<TTurnCustom> | undefined;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n }): CreateDynamicSubAgentThread {\n return async params => {\n const { definition, extraCapabilities } = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: params.request,\n previousTurn: input.previous,\n signal: params.signal,\n tracing: input.tracing,\n });\n // Model override (request.model) is resolved inside resolveAgentDefinition\n // into modelClient — do not re-label a stale client here.\n const childDefinition: AgentDefinition = {\n ...definition,\n toolSets: params.parentDefinition.toolSets ?? definition.toolSets,\n // The delegated task goes in as the initial user message; the sub-agent\n // system prompt is SUB_AGENT_IDENTITY (added by AgentThread.buildInstruction).\n instruction: undefined,\n messages: [{ role: 'user', content: params.request.input }],\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: undefined,\n };\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition: childDefinition,\n isChild: true,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition: childDefinition,\n threadId: params.threadId,\n title: params.request.name,\n sandbox: input.sandbox,\n parent: params.parent,\n agentInfo: params.request,\n capabilities,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -204,6 +204,7 @@ var SessionHandle = class {
|
|
|
204
204
|
first_turn_id: previous?.first_turn_id ?? turnId,
|
|
205
205
|
ancestor_ids: previous ? [...previous.ancestor_ids, previous.turn_id].slice(-MAX_TURN_ANCESTORS) : [],
|
|
206
206
|
previous_turn_id: previousTurnId,
|
|
207
|
+
active_executor_id: input.active_executor_id,
|
|
207
208
|
state: { status: "running" },
|
|
208
209
|
input: input.input ?? [],
|
|
209
210
|
created_at: now,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/agent-session/SessionHandle.ts"],"sourcesContent":["/**\n * Bound session handle: starts turns via {@link SessionHandle.createTurn}.\n */\nimport { newEventId } from '../core/events/schema';\nimport type { AgentDefinition } from '../core/runtime/AgentDefinition';\nimport { AgentThread } from '../core/runtime/AgentThread';\nimport type {\n AgentThreadAppendContext,\n AgentThreadSendBatch,\n AgentThreadSnapshot,\n} from '../core/runtime/AgentThread.types';\nimport { AgentThreadOrchestrator } from '../core/runtime/AgentThreadOrchestrator';\nimport {\n isApprovalDecisionMessage,\n isClientSideToolResponseMessage,\n isInputUserMessage,\n} from '../core/runtime/contextUtils';\nimport type { CreateDynamicSubAgentThread } from '../core/runtime/CreateDynamicSubAgentThread';\nimport type { Sandbox } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { builtinsFromSpec } from './builtinsFromSpec';\nimport type { ITurnResourceResolver, ResolvedAgentDefinition } from './ITurnResourceResolver';\nimport type { SessionRecord } from './models/SessionRecord';\nimport { MAIN_THREAD_ID, type TurnRecord, type TurnSnapshot } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\nimport type { SessionEventItem } from './schemas/events';\nimport { EventType, type TurnDoneEvent } from './schemas/events';\nimport type { TokenPagination } from './schemas/pagination';\nimport type { SessionAgent } from './schemas/session';\nimport type { TurnInputItem } from './schemas/turn';\nimport { CancellationReason } from './schemas/turn';\nimport type { ISessionStore, NewThreadInit, TurnContextAppend, TurnRecordWithoutSnapshot } from './store/ISessionStore';\nimport { TurnHandle } from './TurnHandle';\n\n/** How many recent ancestors SessionHandle persists on each turn. Store-local. */\nconst MAX_TURN_ANCESTORS = 20;\n\nfunction resolvePreviousTurnId(requested: string | undefined, lastTurnId: string | null | undefined): string | null {\n if (requested === 'none') {\n return null;\n }\n if (requested === undefined || requested === 'auto') {\n return lastTurnId ?? null;\n }\n return requested;\n}\n\nfunction toSendBatch(input: TurnInputItem[] | undefined): AgentThreadSendBatch {\n if (!input || input.length === 0) {\n return [];\n }\n if (input.every(msg => isApprovalDecisionMessage(msg) || isClientSideToolResponseMessage(msg))) {\n return input;\n }\n if (input.every(isInputUserMessage)) {\n return input;\n }\n throw new Error('input must be homogeneous: all user messages, or all approval/tool-response messages');\n}\n\nfunction toNewThreadInit(snapshot: AgentThreadSnapshot): NewThreadInit {\n const { context, current_context_usage, completion, capability_state, ...rest } = snapshot;\n void context;\n void current_context_usage;\n void completion;\n void capability_state;\n return rest;\n}\n\nfunction collectContextAppends(\n events: AsyncGenerator<AgentThreadAppendContext, void, unknown>,\n): Promise<TurnContextAppend[]> {\n return (async () => {\n const appendMap = new Map<string, TurnContextAppend>();\n for await (const event of events) {\n const existing = appendMap.get(event.thread_id);\n if (existing) {\n existing.context.push(...event.context);\n if (event.current_context_usage !== undefined) {\n existing.current_context_usage = event.current_context_usage;\n }\n } else {\n appendMap.set(event.thread_id, {\n thread_id: event.thread_id,\n context: [...event.context],\n current_context_usage: event.current_context_usage ?? null,\n });\n }\n }\n return [...appendMap.values()];\n })();\n}\n\nfunction cancelledTurnDoneEvent(reason: CancellationReason): TurnDoneEvent {\n return {\n type: EventType.TURN_DONE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n state: {\n status: 'cancelled',\n reason,\n completed_at: new Date().toISOString(),\n },\n thread_id: null,\n };\n}\n\nfunction threadsRecordFromMap(threads: Map<string, AgentThread>): Record<string, AgentThreadSnapshot> {\n const out: Record<string, AgentThreadSnapshot> = {};\n for (const [id, thread] of threads) {\n out[id] = thread.toSnapshot();\n }\n return out;\n}\n\n// Current-turn thread ids. Main (`MAIN_THREAD_ID`) is always present — first turn\n// synthesizes it; later turns always carry it in the previous snapshot.\nfunction threadIdsForCurrentTurn(snapshot: TurnSnapshot | undefined): string[] {\n return snapshot ? Object.keys(snapshot.threads) : [MAIN_THREAD_ID];\n}\n\nexport class SessionHandle<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> {\n private readonly store: ISessionStore<TSessionCustom, TTurnCustom>;\n private session: SessionRecord<TSessionCustom>;\n\n constructor(options: { store: ISessionStore<TSessionCustom, TTurnCustom>; session: SessionRecord<TSessionCustom> }) {\n this.store = options.store;\n this.session = options.session;\n }\n\n get session_id(): string {\n return this.session.session_id;\n }\n\n get tenant_id(): string {\n return this.session.tenant_id;\n }\n\n get agent(): SessionAgent {\n return this.session.agent;\n }\n\n get custom(): TSessionCustom | null {\n return this.session.custom;\n }\n\n get metadata(): SessionRecord<TSessionCustom>['metadata'] {\n return this.session.metadata;\n }\n\n get record(): SessionRecord<TSessionCustom> {\n return this.session;\n }\n\n /**\n * Prepares and commits a new turn — NO execution happens here (execution =\n * TurnHandle.stream()). Builds threads from the previous turn's snapshot, then\n * sends the input through the orchestrator fully drained (validation +\n * context append; empty input still preflights threads awaiting user input),\n * then persists via one atomic store.createTurn LAST. A send/validation\n * failure therefore persists nothing. The returned turn is durable with\n * state { status: 'running' }.\n *\n * On any failure, createTurn() closes the resolver (best-effort) before rethrowing,\n * so resources acquired here (e.g. a sandbox VM) never outlive a failed run.\n * On success, ownership of resolver.close() passes to TurnHandle.stream().\n *\n * `previous_turn_id`: omitted/`'auto'` → session tip; `'none'` → new root\n * (no parent, even on a non-empty session); string → fork from that turn\n * (must exist). Concurrent `'auto'` forks both succeed.\n */\n async createTurn(input: {\n turn_id: string;\n input?: TurnInputItem[] | undefined;\n /** 'auto'/omitted → session.last_turn_id; 'none' → new root; id → fork from that turn. */\n previous_turn_id?: string | undefined;\n signal: AbortSignal;\n resolver: ITurnResourceResolver<TTurnCustom>;\n /** Value = stored as-is. Fn = merge over previous turn's custom. Omitted = undefined. */\n custom?: TTurnCustom | ((previous?: TTurnCustom) => TTurnCustom) | undefined;\n /**\n * Forwarded to store.createTurn: sets session.title in the same atomic\n * unit IF the session has none; never overwrites. The caller derives the\n * value (e.g. from the first user message) — the library does not.\n */\n update_session_title_if_not_exist?: string | undefined;\n }): Promise<TurnHandle<TTurnCustom>> {\n const previousTurnId = resolvePreviousTurnId(input.previous_turn_id, this.session.last_turn_id);\n const previous = previousTurnId\n ? await this.freezeTurn({\n turn_id: previousTurnId,\n reason: CancellationReason.CancelledForNextTurn,\n })\n : undefined;\n\n const custom = typeof input.custom === 'function' ? input.custom(previous?.custom ?? undefined) : input.custom;\n\n // Dispose-on-early-failure: any resource acquired below (sandbox handle,\n // MCP connections) is owned by createTurn() until the TurnHandle is returned; from then\n // on TurnHandle.stream()'s finally owns resolver.close(). On any throw in this\n // acquisition phase we close the resolver (best-effort, error swallowed)\n // and rethrow — same pattern as the gateway's sessionTurnHandler, which\n // wraps getAgent/handler.init and calls gatewayStore.dispose() on failure.\n try {\n const tracing = input.resolver.createTracing();\n const agent = this.session.agent;\n const spec = agent.type === 'inline' ? agent.spec : await input.resolver.resolveAgentSpec({ agent_id: agent.id });\n const sandbox = await input.resolver.resolveSandbox({\n spec,\n existing: previous?.snapshot.sandbox_info ?? undefined,\n previousTurn: previous,\n signal: input.signal,\n tracing,\n });\n\n const definitionsByThreadId = await this.resolveAgentDefinitions({\n previous,\n resolver: input.resolver,\n spec,\n tracing,\n signal: input.signal,\n });\n\n // Wire Code Mode once from main toolSets before threads share the sandbox.\n const mainDefinition = definitionsByThreadId.get(MAIN_THREAD_ID);\n if (!mainDefinition) {\n throw new Error('Unreachable: missing resolved agent definition for main thread');\n }\n if (sandbox) {\n sandbox.configureCodeMode(mainDefinition.definition.toolSets ?? []);\n }\n\n const agentThreads = this.buildThreads({\n previous,\n resolver: input.resolver,\n spec,\n sandbox,\n tracing,\n definitionsByThreadId,\n });\n\n const createDynamicSubAgentThread = this.makeCreateDynamicSubAgentThread({\n resolver: input.resolver,\n previous,\n spec,\n sandbox,\n tracing,\n });\n\n const orchestrator = new AgentThreadOrchestrator({\n agentThreads,\n createDynamicSubAgentThread,\n tracing,\n logger: input.resolver.logger,\n });\n\n // SEND BEFORE COMMIT — validate + append; throw ⇒ nothing persisted.\n const sendBatch = toSendBatch(input.input);\n const new_context_appends = await collectContextAppends(orchestrator.send(sendBatch));\n\n const turnId = input.turn_id;\n const now = new Date();\n\n const new_threads: NewThreadInit[] = [];\n if (!previous) {\n const root = agentThreads.get(MAIN_THREAD_ID);\n if (root) {\n new_threads.push(toNewThreadInit(root.toSnapshot()));\n }\n } else {\n for (const [threadId, thread] of agentThreads) {\n if (previous.snapshot.threads[threadId] === undefined) {\n new_threads.push(toNewThreadInit(thread.toSnapshot()));\n }\n }\n }\n\n const turnInit: TurnRecordWithoutSnapshot<TTurnCustom> = {\n turn_id: turnId,\n session_id: this.session.session_id,\n first_turn_id: previous?.first_turn_id ?? turnId,\n ancestor_ids: previous ? [...previous.ancestor_ids, previous.turn_id].slice(-MAX_TURN_ANCESTORS) : [],\n previous_turn_id: previousTurnId,\n state: { status: 'running' },\n input: input.input ?? [],\n created_at: now,\n updated_at: now,\n custom: custom ?? null,\n };\n\n const turnRecord: TurnRecord<TTurnCustom> = {\n ...turnInit,\n snapshot: {\n threads: threadsRecordFromMap(agentThreads),\n mcp_servers: previous?.snapshot.mcp_servers ?? null,\n sandbox_info: previous?.snapshot.sandbox_info ?? null,\n },\n };\n\n await this.store.createTurn({\n turn: turnInit,\n new_threads,\n new_context_appends,\n capability_states: [...agentThreads].map(([thread_id, thread]) => ({\n thread_id,\n capability_state: thread.toSnapshot().capability_state,\n })),\n update_session_title_if_not_exist: input.update_session_title_if_not_exist ?? null,\n });\n\n const refreshed = await this.store.getSession({\n tenant_id: this.tenant_id,\n session_id: this.session.session_id,\n });\n if (refreshed) {\n this.session = refreshed;\n }\n\n return new TurnHandle({\n store: this.store,\n turn: turnRecord,\n orchestrator,\n resolver: input.resolver,\n signal: input.signal,\n });\n } catch (error) {\n await input.resolver.close().catch((closeError: unknown) => {\n input.resolver.logger.warn('TurnResourceResolver.close() failed after createTurn() error', {\n err: closeError,\n });\n });\n throw error;\n }\n }\n\n /**\n * Conditionally cancel a running turn in this session and return the\n * now-immutable record. Already-terminal turns are returned unchanged.\n * Missing turn → {@link TurnNotFoundError}.\n */\n async freezeTurn(input: { turn_id: string; reason: CancellationReason }): Promise<TurnRecord<TTurnCustom>> {\n return this.store.freezeAndGetTurn({\n session_id: this.session.session_id,\n turn_id: input.turn_id,\n reason: input.reason,\n turn_done_event: cancelledTurnDoneEvent(input.reason),\n });\n }\n\n /** Returns the turn handle (store-backed; not executable), or undefined if not found. */\n async getTurn(turn_id: string): Promise<TurnHandle<TTurnCustom> | undefined> {\n return TurnHandle.get({\n store: this.store,\n session_id: this.session.session_id,\n turn_id,\n });\n }\n\n /** Paginated list of this session's turn rows (no snapshot). */\n async listTurns(input: {\n limit: number;\n page_token?: string | undefined;\n }): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }> {\n return this.store.listTurns({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n });\n }\n\n /**\n * Paginated session-wide feed of persisted events across turns, including\n * turn.created / turn.done lifecycle events. Reads from the store only —\n * nothing is synthesized on read.\n */\n async listEvents(input: {\n limit: number;\n page_token?: string | undefined;\n last_turn_id?: string | undefined;\n }): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }> {\n return this.store.listSessionEvents({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n last_turn_id: input.last_turn_id,\n });\n }\n\n private async resolveAgentDefinitions(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n tracing: AgentTracing;\n signal: AbortSignal;\n }): Promise<Map<string, ResolvedAgentDefinition>> {\n const snapshots = input.previous?.snapshot.threads;\n const threadIds = threadIdsForCurrentTurn(input.previous?.snapshot);\n const definitionsByThreadId = new Map<string, ResolvedAgentDefinition>();\n await Promise.all(\n threadIds.map(async threadId => {\n const previousThreadSnapshot = snapshots?.[threadId];\n const resolved = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: previousThreadSnapshot?.agent_info ?? undefined,\n previousTurn: input.previous,\n signal: input.signal,\n tracing: input.tracing,\n });\n definitionsByThreadId.set(threadId, resolved);\n }),\n );\n return definitionsByThreadId;\n }\n\n private buildThreads(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n definitionsByThreadId: ReadonlyMap<string, ResolvedAgentDefinition>;\n }): Map<string, AgentThread> {\n const snapshots = input.previous?.snapshot.threads;\n const map = new Map<string, AgentThread>();\n for (const threadId of threadIdsForCurrentTurn(input.previous?.snapshot)) {\n const resolvedDefinition = input.definitionsByThreadId.get(threadId);\n if (!resolvedDefinition) {\n throw new Error(`Unreachable: missing resolved agent definition for thread '${threadId}'`);\n }\n map.set(\n threadId,\n this.buildThread({\n threadId,\n previousThreadSnapshot: snapshots?.[threadId],\n resolver: input.resolver,\n spec: input.spec,\n sandbox: input.sandbox,\n tracing: input.tracing,\n resolvedDefinition,\n }),\n );\n }\n return map;\n }\n\n private buildThread(input: {\n threadId: string;\n previousThreadSnapshot?: AgentThreadSnapshot | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n resolvedDefinition: ResolvedAgentDefinition;\n }): AgentThread {\n const { definition, extraCapabilities } = input.resolvedDefinition;\n const isChild = Boolean(input.previousThreadSnapshot?.parent);\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition,\n isChild,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition,\n threadId: input.threadId,\n title: input.previousThreadSnapshot?.agent_info?.name ?? (isChild ? input.threadId : 'main'),\n sandbox: input.sandbox,\n context: input.previousThreadSnapshot?.context,\n currentContextUsage: input.previousThreadSnapshot?.current_context_usage,\n parent: input.previousThreadSnapshot?.parent ?? undefined,\n agentInfo: input.previousThreadSnapshot?.agent_info ?? undefined,\n preComputedCompletion: input.previousThreadSnapshot?.completion ?? undefined,\n capabilities,\n capabilityState: input.previousThreadSnapshot?.capability_state ?? undefined,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n }\n\n private makeCreateDynamicSubAgentThread(input: {\n resolver: ITurnResourceResolver<TTurnCustom>;\n previous: TurnRecord<TTurnCustom> | undefined;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n }): CreateDynamicSubAgentThread {\n return async params => {\n const { definition, extraCapabilities } = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: params.request,\n previousTurn: input.previous,\n signal: params.signal,\n tracing: input.tracing,\n });\n // Model override (request.model) is resolved inside resolveAgentDefinition\n // into modelClient — do not re-label a stale client here.\n const childDefinition: AgentDefinition = {\n ...definition,\n toolSets: params.parentDefinition.toolSets ?? definition.toolSets,\n // The delegated task goes in as the initial user message; the sub-agent\n // system prompt is SUB_AGENT_IDENTITY (added by AgentThread.buildInstruction).\n instruction: undefined,\n messages: [{ role: 'user', content: params.request.input }],\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: undefined,\n };\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition: childDefinition,\n isChild: true,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition: childDefinition,\n threadId: params.threadId,\n title: params.request.name,\n sandbox: input.sandbox,\n parent: params.parent,\n agentInfo: params.request,\n capabilities,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n };\n }\n}\n"],"mappings":";AAGA,SAAS,kBAAkB;AAE3B,SAAS,mBAAmB;AAM5B,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,SAAS,wBAAwB;AAGjC,SAAS,sBAA0D;AAGnE,SAAS,iBAAqC;AAI9C,SAAS,0BAA0B;AAEnC,SAAS,kBAAkB;AAG3B,IAAM,qBAAqB;AAE3B,SAAS,sBAAsB,WAA+B,YAAsD;AAClH,MAAI,cAAc,QAAQ;AACxB,WAAO;AAAA,EACT;AACA,MAAI,cAAc,UAAa,cAAc,QAAQ;AACnD,WAAO,cAAc;AAAA,EACvB;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAA0D;AAC7E,MAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,WAAO,CAAC;AAAA,EACV;AACA,MAAI,MAAM,MAAM,SAAO,0BAA0B,GAAG,KAAK,gCAAgC,GAAG,CAAC,GAAG;AAC9F,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM,kBAAkB,GAAG;AACnC,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,sFAAsF;AACxG;AAEA,SAAS,gBAAgB,UAA8C;AACrE,QAAM,EAAE,SAAS,uBAAuB,YAAY,kBAAkB,GAAG,KAAK,IAAI;AAClF,OAAK;AACL,OAAK;AACL,OAAK;AACL,OAAK;AACL,SAAO;AACT;AAEA,SAAS,sBACP,QAC8B;AAC9B,UAAQ,YAAY;AAClB,UAAM,YAAY,oBAAI,IAA+B;AACrD,qBAAiB,SAAS,QAAQ;AAChC,YAAM,WAAW,UAAU,IAAI,MAAM,SAAS;AAC9C,UAAI,UAAU;AACZ,iBAAS,QAAQ,KAAK,GAAG,MAAM,OAAO;AACtC,YAAI,MAAM,0BAA0B,QAAW;AAC7C,mBAAS,wBAAwB,MAAM;AAAA,QACzC;AAAA,MACF,OAAO;AACL,kBAAU,IAAI,MAAM,WAAW;AAAA,UAC7B,WAAW,MAAM;AAAA,UACjB,SAAS,CAAC,GAAG,MAAM,OAAO;AAAA,UAC1B,uBAAuB,MAAM,yBAAyB;AAAA,QACxD,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,CAAC,GAAG,UAAU,OAAO,CAAC;AAAA,EAC/B,GAAG;AACL;AAEA,SAAS,uBAAuB,QAA2C;AACzE,SAAO;AAAA,IACL,MAAM,UAAU;AAAA,IAChB,IAAI,WAAW;AAAA,IACf,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACnC,OAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,IACvC;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAEA,SAAS,qBAAqB,SAAwE;AACpG,QAAM,MAA2C,CAAC;AAClD,aAAW,CAAC,IAAI,MAAM,KAAK,SAAS;AAClC,QAAI,EAAE,IAAI,OAAO,WAAW;AAAA,EAC9B;AACA,SAAO;AACT;AAIA,SAAS,wBAAwB,UAA8C;AAC7E,SAAO,WAAW,OAAO,KAAK,SAAS,OAAO,IAAI,CAAC,cAAc;AACnE;AAEO,IAAM,gBAAN,MAGL;AAAA,EACiB;AAAA,EACT;AAAA,EAER,YAAY,SAAwG;AAClH,SAAK,QAAQ,QAAQ;AACrB,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAEA,IAAI,aAAqB;AACvB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,QAAsB;AACxB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,SAAgC;AAClC,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,WAAsD;AACxD,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,SAAwC;AAC1C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,WAAW,OAeoB;AACnC,UAAM,iBAAiB,sBAAsB,MAAM,kBAAkB,KAAK,QAAQ,YAAY;AAC9F,UAAM,WAAW,iBACb,MAAM,KAAK,WAAW;AAAA,MACpB,SAAS;AAAA,MACT,QAAQ,mBAAmB;AAAA,IAC7B,CAAC,IACD;AAEJ,UAAM,SAAS,OAAO,MAAM,WAAW,aAAa,MAAM,OAAO,UAAU,UAAU,MAAS,IAAI,MAAM;AAQxG,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,cAAc;AAC7C,YAAM,QAAQ,KAAK,QAAQ;AAC3B,YAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO,MAAM,MAAM,SAAS,iBAAiB,EAAE,UAAU,MAAM,GAAG,CAAC;AAChH,YAAM,UAAU,MAAM,MAAM,SAAS,eAAe;AAAA,QAClD;AAAA,QACA,UAAU,UAAU,SAAS,gBAAgB;AAAA,QAC7C,cAAc;AAAA,QACd,QAAQ,MAAM;AAAA,QACd;AAAA,MACF,CAAC;AAED,YAAM,wBAAwB,MAAM,KAAK,wBAAwB;AAAA,QAC/D;AAAA,QACA,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA,QAAQ,MAAM;AAAA,MAChB,CAAC;AAGD,YAAM,iBAAiB,sBAAsB,IAAI,cAAc;AAC/D,UAAI,CAAC,gBAAgB;AACnB,cAAM,IAAI,MAAM,gEAAgE;AAAA,MAClF;AACA,UAAI,SAAS;AACX,gBAAQ,kBAAkB,eAAe,WAAW,YAAY,CAAC,CAAC;AAAA,MACpE;AAEA,YAAM,eAAe,KAAK,aAAa;AAAA,QACrC;AAAA,QACA,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,8BAA8B,KAAK,gCAAgC;AAAA,QACvE,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,eAAe,IAAI,wBAAwB;AAAA,QAC/C;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,MAAM,SAAS;AAAA,MACzB,CAAC;AAGD,YAAM,YAAY,YAAY,MAAM,KAAK;AACzC,YAAM,sBAAsB,MAAM,sBAAsB,aAAa,KAAK,SAAS,CAAC;AAEpF,YAAM,SAAS,MAAM;AACrB,YAAM,MAAM,oBAAI,KAAK;AAErB,YAAM,cAA+B,CAAC;AACtC,UAAI,CAAC,UAAU;AACb,cAAM,OAAO,aAAa,IAAI,cAAc;AAC5C,YAAI,MAAM;AACR,sBAAY,KAAK,gBAAgB,KAAK,WAAW,CAAC,CAAC;AAAA,QACrD;AAAA,MACF,OAAO;AACL,mBAAW,CAAC,UAAU,MAAM,KAAK,cAAc;AAC7C,cAAI,SAAS,SAAS,QAAQ,QAAQ,MAAM,QAAW;AACrD,wBAAY,KAAK,gBAAgB,OAAO,WAAW,CAAC,CAAC;AAAA,UACvD;AAAA,QACF;AAAA,MACF;AAEA,YAAM,WAAmD;AAAA,QACvD,SAAS;AAAA,QACT,YAAY,KAAK,QAAQ;AAAA,QACzB,eAAe,UAAU,iBAAiB;AAAA,QAC1C,cAAc,WAAW,CAAC,GAAG,SAAS,cAAc,SAAS,OAAO,EAAE,MAAM,CAAC,kBAAkB,IAAI,CAAC;AAAA,QACpG,kBAAkB;AAAA,QAClB,OAAO,EAAE,QAAQ,UAAU;AAAA,QAC3B,OAAO,MAAM,SAAS,CAAC;AAAA,QACvB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,QAAQ,UAAU;AAAA,MACpB;AAEA,YAAM,aAAsC;AAAA,QAC1C,GAAG;AAAA,QACH,UAAU;AAAA,UACR,SAAS,qBAAqB,YAAY;AAAA,UAC1C,aAAa,UAAU,SAAS,eAAe;AAAA,UAC/C,cAAc,UAAU,SAAS,gBAAgB;AAAA,QACnD;AAAA,MACF;AAEA,YAAM,KAAK,MAAM,WAAW;AAAA,QAC1B,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,mBAAmB,CAAC,GAAG,YAAY,EAAE,IAAI,CAAC,CAAC,WAAW,MAAM,OAAO;AAAA,UACjE;AAAA,UACA,kBAAkB,OAAO,WAAW,EAAE;AAAA,QACxC,EAAE;AAAA,QACF,mCAAmC,MAAM,qCAAqC;AAAA,MAChF,CAAC;AAED,YAAM,YAAY,MAAM,KAAK,MAAM,WAAW;AAAA,QAC5C,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK,QAAQ;AAAA,MAC3B,CAAC;AACD,UAAI,WAAW;AACb,aAAK,UAAU;AAAA,MACjB;AAEA,aAAO,IAAI,WAAW;AAAA,QACpB,OAAO,KAAK;AAAA,QACZ,MAAM;AAAA,QACN;AAAA,QACA,UAAU,MAAM;AAAA,QAChB,QAAQ,MAAM;AAAA,MAChB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,MAAM,SAAS,MAAM,EAAE,MAAM,CAAC,eAAwB;AAC1D,cAAM,SAAS,OAAO,KAAK,gEAAgE;AAAA,UACzF,KAAK;AAAA,QACP,CAAC;AAAA,MACH,CAAC;AACD,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,OAA0F;AACzG,WAAO,KAAK,MAAM,iBAAiB;AAAA,MACjC,YAAY,KAAK,QAAQ;AAAA,MACzB,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,iBAAiB,uBAAuB,MAAM,MAAM;AAAA,IACtD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAQ,SAA+D;AAC3E,WAAO,WAAW,IAAI;AAAA,MACpB,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK,QAAQ;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,UAAU,OAG6E;AAC3F,WAAO,KAAK,MAAM,UAAU;AAAA,MAC1B,YAAY,KAAK,QAAQ;AAAA,MACzB,OAAO,MAAM;AAAA,MACb,YAAY,MAAM;AAAA,IACpB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,OAOd;AACD,WAAO,KAAK,MAAM,kBAAkB;AAAA,MAClC,YAAY,KAAK,QAAQ;AAAA,MACzB,OAAO,MAAM;AAAA,MACb,YAAY,MAAM;AAAA,MAClB,cAAc,MAAM;AAAA,IACtB,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,wBAAwB,OAMY;AAChD,UAAM,YAAY,MAAM,UAAU,SAAS;AAC3C,UAAM,YAAY,wBAAwB,MAAM,UAAU,QAAQ;AAClE,UAAM,wBAAwB,oBAAI,IAAqC;AACvE,UAAM,QAAQ;AAAA,MACZ,UAAU,IAAI,OAAM,aAAY;AAC9B,cAAM,yBAAyB,YAAY,QAAQ;AACnD,cAAM,WAAW,MAAM,MAAM,SAAS,uBAAuB;AAAA,UAC3D,MAAM,MAAM;AAAA,UACZ,YAAY,wBAAwB,cAAc;AAAA,UAClD,cAAc,MAAM;AAAA,UACpB,QAAQ,MAAM;AAAA,UACd,SAAS,MAAM;AAAA,QACjB,CAAC;AACD,8BAAsB,IAAI,UAAU,QAAQ;AAAA,MAC9C,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,OAOQ;AAC3B,UAAM,YAAY,MAAM,UAAU,SAAS;AAC3C,UAAM,MAAM,oBAAI,IAAyB;AACzC,eAAW,YAAY,wBAAwB,MAAM,UAAU,QAAQ,GAAG;AACxE,YAAM,qBAAqB,MAAM,sBAAsB,IAAI,QAAQ;AACnE,UAAI,CAAC,oBAAoB;AACvB,cAAM,IAAI,MAAM,8DAA8D,QAAQ,GAAG;AAAA,MAC3F;AACA,UAAI;AAAA,QACF;AAAA,QACA,KAAK,YAAY;AAAA,UACf;AAAA,UACA,wBAAwB,YAAY,QAAQ;AAAA,UAC5C,UAAU,MAAM;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,UACf,SAAS,MAAM;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,YAAY,OAQJ;AACd,UAAM,EAAE,YAAY,kBAAkB,IAAI,MAAM;AAChD,UAAM,UAAU,QAAQ,MAAM,wBAAwB,MAAM;AAC5D,UAAM,eAAe;AAAA,MACnB,GAAG,iBAAiB;AAAA,QAClB,MAAM,MAAM;AAAA,QACZ;AAAA,QACA;AAAA,QACA,kBAAkB,QAAQ,MAAM,OAAO;AAAA,QACvC,SAAS,MAAM;AAAA,QACf,mBAAmB,MAAM,SAAS;AAAA,QAClC,QAAQ,MAAM,SAAS;AAAA,MACzB,CAAC;AAAA,MACD,GAAI,qBAAqB,CAAC;AAAA,IAC5B;AACA,WAAO,IAAI,YAAY;AAAA,MACrB;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM,wBAAwB,YAAY,SAAS,UAAU,MAAM,WAAW;AAAA,MACrF,SAAS,MAAM;AAAA,MACf,SAAS,MAAM,wBAAwB;AAAA,MACvC,qBAAqB,MAAM,wBAAwB;AAAA,MACnD,QAAQ,MAAM,wBAAwB,UAAU;AAAA,MAChD,WAAW,MAAM,wBAAwB,cAAc;AAAA,MACvD,uBAAuB,MAAM,wBAAwB,cAAc;AAAA,MACnE;AAAA,MACA,iBAAiB,MAAM,wBAAwB,oBAAoB;AAAA,MACnE,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM,SAAS;AAAA,IACzB,CAAC;AAAA,EACH;AAAA,EAEQ,gCAAgC,OAMR;AAC9B,WAAO,OAAM,WAAU;AACrB,YAAM,EAAE,YAAY,kBAAkB,IAAI,MAAM,MAAM,SAAS,uBAAuB;AAAA,QACpF,MAAM,MAAM;AAAA,QACZ,YAAY,OAAO;AAAA,QACnB,cAAc,MAAM;AAAA,QACpB,QAAQ,OAAO;AAAA,QACf,SAAS,MAAM;AAAA,MACjB,CAAC;AAGD,YAAM,kBAAmC;AAAA,QACvC,GAAG;AAAA,QACH,UAAU,OAAO,iBAAiB,YAAY,WAAW;AAAA;AAAA;AAAA,QAGzD,aAAa;AAAA,QACb,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,OAAO,QAAQ,MAAM,CAAC;AAAA;AAAA,QAE1D,gBAAgB;AAAA,MAClB;AACA,YAAM,eAAe;AAAA,QACnB,GAAG,iBAAiB;AAAA,UAClB,MAAM,MAAM;AAAA,UACZ,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,kBAAkB,QAAQ,MAAM,OAAO;AAAA,UACvC,SAAS,MAAM;AAAA,UACf,mBAAmB,MAAM,SAAS;AAAA,UAClC,QAAQ,MAAM,SAAS;AAAA,QACzB,CAAC;AAAA,QACD,GAAI,qBAAqB,CAAC;AAAA,MAC5B;AACA,aAAO,IAAI,YAAY;AAAA,QACrB,YAAY;AAAA,QACZ,UAAU,OAAO;AAAA,QACjB,OAAO,OAAO,QAAQ;AAAA,QACtB,SAAS,MAAM;AAAA,QACf,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,SAAS,MAAM;AAAA,QACf,QAAQ,MAAM,SAAS;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/agent-session/SessionHandle.ts"],"sourcesContent":["/**\n * Bound session handle: starts turns via {@link SessionHandle.createTurn}.\n */\nimport { newEventId } from '../core/events/schema';\nimport type { AgentDefinition } from '../core/runtime/AgentDefinition';\nimport { AgentThread } from '../core/runtime/AgentThread';\nimport type {\n AgentThreadAppendContext,\n AgentThreadSendBatch,\n AgentThreadSnapshot,\n} from '../core/runtime/AgentThread.types';\nimport { AgentThreadOrchestrator } from '../core/runtime/AgentThreadOrchestrator';\nimport {\n isApprovalDecisionMessage,\n isClientSideToolResponseMessage,\n isInputUserMessage,\n} from '../core/runtime/contextUtils';\nimport type { CreateDynamicSubAgentThread } from '../core/runtime/CreateDynamicSubAgentThread';\nimport type { Sandbox } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { builtinsFromSpec } from './builtinsFromSpec';\nimport type { ITurnResourceResolver, ResolvedAgentDefinition } from './ITurnResourceResolver';\nimport type { SessionRecord } from './models/SessionRecord';\nimport { MAIN_THREAD_ID, type TurnRecord, type TurnSnapshot } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\nimport type { SessionEventItem } from './schemas/events';\nimport { EventType, type TurnDoneEvent } from './schemas/events';\nimport type { TokenPagination } from './schemas/pagination';\nimport type { SessionAgent } from './schemas/session';\nimport type { TurnInputItem } from './schemas/turn';\nimport { CancellationReason } from './schemas/turn';\nimport type { ISessionStore, NewThreadInit, TurnContextAppend, TurnRecordWithoutSnapshot } from './store/ISessionStore';\nimport { TurnHandle } from './TurnHandle';\n\n/** How many recent ancestors SessionHandle persists on each turn. Store-local. */\nconst MAX_TURN_ANCESTORS = 20;\n\nfunction resolvePreviousTurnId(requested: string | undefined, lastTurnId: string | null | undefined): string | null {\n if (requested === 'none') {\n return null;\n }\n if (requested === undefined || requested === 'auto') {\n return lastTurnId ?? null;\n }\n return requested;\n}\n\nfunction toSendBatch(input: TurnInputItem[] | undefined): AgentThreadSendBatch {\n if (!input || input.length === 0) {\n return [];\n }\n if (input.every(msg => isApprovalDecisionMessage(msg) || isClientSideToolResponseMessage(msg))) {\n return input;\n }\n if (input.every(isInputUserMessage)) {\n return input;\n }\n throw new Error('input must be homogeneous: all user messages, or all approval/tool-response messages');\n}\n\nfunction toNewThreadInit(snapshot: AgentThreadSnapshot): NewThreadInit {\n const { context, current_context_usage, completion, capability_state, ...rest } = snapshot;\n void context;\n void current_context_usage;\n void completion;\n void capability_state;\n return rest;\n}\n\nfunction collectContextAppends(\n events: AsyncGenerator<AgentThreadAppendContext, void, unknown>,\n): Promise<TurnContextAppend[]> {\n return (async () => {\n const appendMap = new Map<string, TurnContextAppend>();\n for await (const event of events) {\n const existing = appendMap.get(event.thread_id);\n if (existing) {\n existing.context.push(...event.context);\n if (event.current_context_usage !== undefined) {\n existing.current_context_usage = event.current_context_usage;\n }\n } else {\n appendMap.set(event.thread_id, {\n thread_id: event.thread_id,\n context: [...event.context],\n current_context_usage: event.current_context_usage ?? null,\n });\n }\n }\n return [...appendMap.values()];\n })();\n}\n\nfunction cancelledTurnDoneEvent(reason: CancellationReason): TurnDoneEvent {\n return {\n type: EventType.TURN_DONE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n state: {\n status: 'cancelled',\n reason,\n completed_at: new Date().toISOString(),\n },\n thread_id: null,\n };\n}\n\nfunction threadsRecordFromMap(threads: Map<string, AgentThread>): Record<string, AgentThreadSnapshot> {\n const out: Record<string, AgentThreadSnapshot> = {};\n for (const [id, thread] of threads) {\n out[id] = thread.toSnapshot();\n }\n return out;\n}\n\n// Current-turn thread ids. Main (`MAIN_THREAD_ID`) is always present — first turn\n// synthesizes it; later turns always carry it in the previous snapshot.\nfunction threadIdsForCurrentTurn(snapshot: TurnSnapshot | undefined): string[] {\n return snapshot ? Object.keys(snapshot.threads) : [MAIN_THREAD_ID];\n}\n\nexport class SessionHandle<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> {\n private readonly store: ISessionStore<TSessionCustom, TTurnCustom>;\n private session: SessionRecord<TSessionCustom>;\n\n constructor(options: { store: ISessionStore<TSessionCustom, TTurnCustom>; session: SessionRecord<TSessionCustom> }) {\n this.store = options.store;\n this.session = options.session;\n }\n\n get session_id(): string {\n return this.session.session_id;\n }\n\n get tenant_id(): string {\n return this.session.tenant_id;\n }\n\n get agent(): SessionAgent {\n return this.session.agent;\n }\n\n get custom(): TSessionCustom | null {\n return this.session.custom;\n }\n\n get metadata(): SessionRecord<TSessionCustom>['metadata'] {\n return this.session.metadata;\n }\n\n get record(): SessionRecord<TSessionCustom> {\n return this.session;\n }\n\n /**\n * Prepares and commits a new turn — NO execution happens here (execution =\n * TurnHandle.stream()). Builds threads from the previous turn's snapshot, then\n * sends the input through the orchestrator fully drained (validation +\n * context append; empty input still preflights threads awaiting user input),\n * then persists via one atomic store.createTurn LAST. A send/validation\n * failure therefore persists nothing. The returned turn is durable with\n * state { status: 'running' }.\n *\n * On any failure, createTurn() closes the resolver (best-effort) before rethrowing,\n * so resources acquired here (e.g. a sandbox VM) never outlive a failed run.\n * On success, ownership of resolver.close() passes to TurnHandle.stream().\n *\n * `previous_turn_id`: omitted/`'auto'` → session tip; `'none'` → new root\n * (no parent, even on a non-empty session); string → fork from that turn\n * (must exist). Concurrent `'auto'` forks both succeed.\n */\n async createTurn(input: {\n turn_id: string;\n active_executor_id: string;\n input?: TurnInputItem[] | undefined;\n /** 'auto'/omitted → session.last_turn_id; 'none' → new root; id → fork from that turn. */\n previous_turn_id?: string | undefined;\n signal: AbortSignal;\n resolver: ITurnResourceResolver<TTurnCustom>;\n /** Value = stored as-is. Fn = merge over previous turn's custom. Omitted = undefined. */\n custom?: TTurnCustom | ((previous?: TTurnCustom) => TTurnCustom) | undefined;\n /**\n * Forwarded to store.createTurn: sets session.title in the same atomic\n * unit IF the session has none; never overwrites. The caller derives the\n * value (e.g. from the first user message) — the library does not.\n */\n update_session_title_if_not_exist?: string | undefined;\n }): Promise<TurnHandle<TTurnCustom>> {\n const previousTurnId = resolvePreviousTurnId(input.previous_turn_id, this.session.last_turn_id);\n const previous = previousTurnId\n ? await this.freezeTurn({\n turn_id: previousTurnId,\n reason: CancellationReason.CancelledForNextTurn,\n })\n : undefined;\n\n const custom = typeof input.custom === 'function' ? input.custom(previous?.custom ?? undefined) : input.custom;\n\n // Dispose-on-early-failure: any resource acquired below (sandbox handle,\n // MCP connections) is owned by createTurn() until the TurnHandle is returned; from then\n // on TurnHandle.stream()'s finally owns resolver.close(). On any throw in this\n // acquisition phase we close the resolver (best-effort, error swallowed)\n // and rethrow — same pattern as the gateway's sessionTurnHandler, which\n // wraps getAgent/handler.init and calls gatewayStore.dispose() on failure.\n try {\n const tracing = input.resolver.createTracing();\n const agent = this.session.agent;\n const spec = agent.type === 'inline' ? agent.spec : await input.resolver.resolveAgentSpec({ agent_id: agent.id });\n const sandbox = await input.resolver.resolveSandbox({\n spec,\n existing: previous?.snapshot.sandbox_info ?? undefined,\n previousTurn: previous,\n signal: input.signal,\n tracing,\n });\n\n const definitionsByThreadId = await this.resolveAgentDefinitions({\n previous,\n resolver: input.resolver,\n spec,\n tracing,\n signal: input.signal,\n });\n\n // Wire Code Mode once from main toolSets before threads share the sandbox.\n const mainDefinition = definitionsByThreadId.get(MAIN_THREAD_ID);\n if (!mainDefinition) {\n throw new Error('Unreachable: missing resolved agent definition for main thread');\n }\n if (sandbox) {\n sandbox.configureCodeMode(mainDefinition.definition.toolSets ?? []);\n }\n\n const agentThreads = this.buildThreads({\n previous,\n resolver: input.resolver,\n spec,\n sandbox,\n tracing,\n definitionsByThreadId,\n });\n\n const createDynamicSubAgentThread = this.makeCreateDynamicSubAgentThread({\n resolver: input.resolver,\n previous,\n spec,\n sandbox,\n tracing,\n });\n\n const orchestrator = new AgentThreadOrchestrator({\n agentThreads,\n createDynamicSubAgentThread,\n tracing,\n logger: input.resolver.logger,\n });\n\n // SEND BEFORE COMMIT — validate + append; throw ⇒ nothing persisted.\n const sendBatch = toSendBatch(input.input);\n const new_context_appends = await collectContextAppends(orchestrator.send(sendBatch));\n\n const turnId = input.turn_id;\n const now = new Date();\n\n const new_threads: NewThreadInit[] = [];\n if (!previous) {\n const root = agentThreads.get(MAIN_THREAD_ID);\n if (root) {\n new_threads.push(toNewThreadInit(root.toSnapshot()));\n }\n } else {\n for (const [threadId, thread] of agentThreads) {\n if (previous.snapshot.threads[threadId] === undefined) {\n new_threads.push(toNewThreadInit(thread.toSnapshot()));\n }\n }\n }\n\n const turnInit: TurnRecordWithoutSnapshot<TTurnCustom> = {\n turn_id: turnId,\n session_id: this.session.session_id,\n first_turn_id: previous?.first_turn_id ?? turnId,\n ancestor_ids: previous ? [...previous.ancestor_ids, previous.turn_id].slice(-MAX_TURN_ANCESTORS) : [],\n previous_turn_id: previousTurnId,\n active_executor_id: input.active_executor_id,\n state: { status: 'running' },\n input: input.input ?? [],\n created_at: now,\n updated_at: now,\n custom: custom ?? null,\n };\n\n const turnRecord: TurnRecord<TTurnCustom> = {\n ...turnInit,\n snapshot: {\n threads: threadsRecordFromMap(agentThreads),\n mcp_servers: previous?.snapshot.mcp_servers ?? null,\n sandbox_info: previous?.snapshot.sandbox_info ?? null,\n },\n };\n\n await this.store.createTurn({\n turn: turnInit,\n new_threads,\n new_context_appends,\n capability_states: [...agentThreads].map(([thread_id, thread]) => ({\n thread_id,\n capability_state: thread.toSnapshot().capability_state,\n })),\n update_session_title_if_not_exist: input.update_session_title_if_not_exist ?? null,\n });\n\n const refreshed = await this.store.getSession({\n tenant_id: this.tenant_id,\n session_id: this.session.session_id,\n });\n if (refreshed) {\n this.session = refreshed;\n }\n\n return new TurnHandle({\n store: this.store,\n turn: turnRecord,\n orchestrator,\n resolver: input.resolver,\n signal: input.signal,\n });\n } catch (error) {\n await input.resolver.close().catch((closeError: unknown) => {\n input.resolver.logger.warn('TurnResourceResolver.close() failed after createTurn() error', {\n err: closeError,\n });\n });\n throw error;\n }\n }\n\n /**\n * Conditionally cancel a running turn in this session and return the\n * now-immutable record. Already-terminal turns are returned unchanged.\n * Missing turn → {@link TurnNotFoundError}.\n */\n async freezeTurn(input: { turn_id: string; reason: CancellationReason }): Promise<TurnRecord<TTurnCustom>> {\n return this.store.freezeAndGetTurn({\n session_id: this.session.session_id,\n turn_id: input.turn_id,\n reason: input.reason,\n turn_done_event: cancelledTurnDoneEvent(input.reason),\n });\n }\n\n /** Returns the turn handle (store-backed; not executable), or undefined if not found. */\n async getTurn(turn_id: string): Promise<TurnHandle<TTurnCustom> | undefined> {\n return TurnHandle.get({\n store: this.store,\n session_id: this.session.session_id,\n turn_id,\n });\n }\n\n /** Paginated list of this session's turn rows (no snapshot). */\n async listTurns(input: {\n limit: number;\n page_token?: string | undefined;\n }): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }> {\n return this.store.listTurns({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n });\n }\n\n /**\n * Paginated session-wide feed of persisted events across turns, including\n * turn.created / turn.done lifecycle events. Reads from the store only —\n * nothing is synthesized on read.\n */\n async listEvents(input: {\n limit: number;\n page_token?: string | undefined;\n last_turn_id?: string | undefined;\n }): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }> {\n return this.store.listSessionEvents({\n session_id: this.session.session_id,\n limit: input.limit,\n page_token: input.page_token,\n last_turn_id: input.last_turn_id,\n });\n }\n\n private async resolveAgentDefinitions(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n tracing: AgentTracing;\n signal: AbortSignal;\n }): Promise<Map<string, ResolvedAgentDefinition>> {\n const snapshots = input.previous?.snapshot.threads;\n const threadIds = threadIdsForCurrentTurn(input.previous?.snapshot);\n const definitionsByThreadId = new Map<string, ResolvedAgentDefinition>();\n await Promise.all(\n threadIds.map(async threadId => {\n const previousThreadSnapshot = snapshots?.[threadId];\n const resolved = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: previousThreadSnapshot?.agent_info ?? undefined,\n previousTurn: input.previous,\n signal: input.signal,\n tracing: input.tracing,\n });\n definitionsByThreadId.set(threadId, resolved);\n }),\n );\n return definitionsByThreadId;\n }\n\n private buildThreads(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n definitionsByThreadId: ReadonlyMap<string, ResolvedAgentDefinition>;\n }): Map<string, AgentThread> {\n const snapshots = input.previous?.snapshot.threads;\n const map = new Map<string, AgentThread>();\n for (const threadId of threadIdsForCurrentTurn(input.previous?.snapshot)) {\n const resolvedDefinition = input.definitionsByThreadId.get(threadId);\n if (!resolvedDefinition) {\n throw new Error(`Unreachable: missing resolved agent definition for thread '${threadId}'`);\n }\n map.set(\n threadId,\n this.buildThread({\n threadId,\n previousThreadSnapshot: snapshots?.[threadId],\n resolver: input.resolver,\n spec: input.spec,\n sandbox: input.sandbox,\n tracing: input.tracing,\n resolvedDefinition,\n }),\n );\n }\n return map;\n }\n\n private buildThread(input: {\n threadId: string;\n previousThreadSnapshot?: AgentThreadSnapshot | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n resolvedDefinition: ResolvedAgentDefinition;\n }): AgentThread {\n const { definition, extraCapabilities } = input.resolvedDefinition;\n const isChild = Boolean(input.previousThreadSnapshot?.parent);\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition,\n isChild,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition,\n threadId: input.threadId,\n title: input.previousThreadSnapshot?.agent_info?.name ?? (isChild ? input.threadId : 'main'),\n sandbox: input.sandbox,\n context: input.previousThreadSnapshot?.context,\n currentContextUsage: input.previousThreadSnapshot?.current_context_usage,\n parent: input.previousThreadSnapshot?.parent ?? undefined,\n agentInfo: input.previousThreadSnapshot?.agent_info ?? undefined,\n preComputedCompletion: input.previousThreadSnapshot?.completion ?? undefined,\n capabilities,\n capabilityState: input.previousThreadSnapshot?.capability_state ?? undefined,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n }\n\n private makeCreateDynamicSubAgentThread(input: {\n resolver: ITurnResourceResolver<TTurnCustom>;\n previous: TurnRecord<TTurnCustom> | undefined;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n }): CreateDynamicSubAgentThread {\n return async params => {\n const { definition, extraCapabilities } = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n agent_info: params.request,\n previousTurn: input.previous,\n signal: params.signal,\n tracing: input.tracing,\n });\n // Model override (request.model) is resolved inside resolveAgentDefinition\n // into modelClient — do not re-label a stale client here.\n const childDefinition: AgentDefinition = {\n ...definition,\n toolSets: params.parentDefinition.toolSets ?? definition.toolSets,\n // The delegated task goes in as the initial user message; the sub-agent\n // system prompt is SUB_AGENT_IDENTITY (added by AgentThread.buildInstruction).\n instruction: undefined,\n messages: [{ role: 'user', content: params.request.input }],\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: undefined,\n };\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition: childDefinition,\n isChild: true,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n webSearchProvider: input.resolver.webSearchProvider,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition: childDefinition,\n threadId: params.threadId,\n title: params.request.name,\n sandbox: input.sandbox,\n parent: params.parent,\n agentInfo: params.request,\n capabilities,\n tracing: input.tracing,\n logger: input.resolver.logger,\n });\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TurnRecord.d.ts","sourceRoot":"","sources":["../../../src/agent-session/models/TurnRecord.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhE,wCAAwC;AACxC,eAAO,MAAM,cAAc,SAAS,CAAC;AAErC;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC7C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACtD,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,UAAU,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,mFAAmF;IACnF,UAAU,EAAE,IAAI,CAAC;IACjB,wFAAwF;IACxF,UAAU,EAAE,IAAI,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACxB"}
|
|
1
|
+
{"version":3,"file":"TurnRecord.d.ts","sourceRoot":"","sources":["../../../src/agent-session/models/TurnRecord.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhE,wCAAwC;AACxC,eAAO,MAAM,cAAc,SAAS,CAAC;AAErC;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC7C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACtD,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,UAAU,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,mFAAmF;IACnF,UAAU,EAAE,IAAI,CAAC;IACjB,wFAAwF;IACxF,UAAU,EAAE,IAAI,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/agent-session/models/TurnRecord.ts"],"sourcesContent":["import type { MCPServerInitInfo } from '../../core/events/schema';\nimport type { AgentThreadSnapshot } from '../../core/runtime/AgentThread.types';\nimport type { SandboxInfo } from '../../core/sandbox/Sandbox';\nimport type { TurnInputItem, TurnState } from '../schemas/turn';\n\n/** Root thread id for every session. */\nexport const MAIN_THREAD_ID = 'main';\n\n/**\n * Public wire / store shape — JSON-friendly `Record`, not `Map`, so every\n * backend can persist it directly. In-process runtime may still use Map;\n * adapt at the store/Session boundary.\n */\nexport interface TurnSnapshot {\n threads: Record<string, AgentThreadSnapshot>;\n mcp_servers: Record<string, MCPServerInitInfo> | null;\n sandbox_info: SandboxInfo | null;\n}\n\nexport interface TurnRecord<TCustom extends object = Record<string, never>> {\n turn_id: string;\n session_id: string;\n first_turn_id: string;\n /**\n * Newest-last list of recent ancestor turn ids. Writers may truncate to a\n * recent window; this need not reach the session root. Store readers that\n * need the full chain spill through older turns' own `ancestor_ids`.\n */\n ancestor_ids: string[];\n previous_turn_id: string | null;\n state: TurnState;\n input: TurnInputItem[];\n snapshot: TurnSnapshot;\n /** Instant the turn was created (store domain). Wire/API serialize as ISO-8601. */\n created_at: Date;\n /** Instant the turn was last updated (store domain). Wire/API serialize as ISO-8601. */\n updated_at: Date;\n custom: TCustom | null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,IAAM,iBAAiB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/agent-session/models/TurnRecord.ts"],"sourcesContent":["import type { MCPServerInitInfo } from '../../core/events/schema';\nimport type { AgentThreadSnapshot } from '../../core/runtime/AgentThread.types';\nimport type { SandboxInfo } from '../../core/sandbox/Sandbox';\nimport type { TurnInputItem, TurnState } from '../schemas/turn';\n\n/** Root thread id for every session. */\nexport const MAIN_THREAD_ID = 'main';\n\n/**\n * Public wire / store shape — JSON-friendly `Record`, not `Map`, so every\n * backend can persist it directly. In-process runtime may still use Map;\n * adapt at the store/Session boundary.\n */\nexport interface TurnSnapshot {\n threads: Record<string, AgentThreadSnapshot>;\n mcp_servers: Record<string, MCPServerInitInfo> | null;\n sandbox_info: SandboxInfo | null;\n}\n\nexport interface TurnRecord<TCustom extends object = Record<string, never>> {\n turn_id: string;\n session_id: string;\n first_turn_id: string;\n /**\n * Newest-last list of recent ancestor turn ids. Writers may truncate to a\n * recent window; this need not reach the session root. Store readers that\n * need the full chain spill through older turns' own `ancestor_ids`.\n */\n ancestor_ids: string[];\n previous_turn_id: string | null;\n active_executor_id: string;\n state: TurnState;\n input: TurnInputItem[];\n snapshot: TurnSnapshot;\n /** Instant the turn was created (store domain). Wire/API serialize as ISO-8601. */\n created_at: Date;\n /** Instant the turn was last updated (store domain). Wire/API serialize as ISO-8601. */\n updated_at: Date;\n custom: TCustom | null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,IAAM,iBAAiB;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/agent-session/models/TurnRecord.ts"],"sourcesContent":["import type { MCPServerInitInfo } from '../../core/events/schema';\nimport type { AgentThreadSnapshot } from '../../core/runtime/AgentThread.types';\nimport type { SandboxInfo } from '../../core/sandbox/Sandbox';\nimport type { TurnInputItem, TurnState } from '../schemas/turn';\n\n/** Root thread id for every session. */\nexport const MAIN_THREAD_ID = 'main';\n\n/**\n * Public wire / store shape — JSON-friendly `Record`, not `Map`, so every\n * backend can persist it directly. In-process runtime may still use Map;\n * adapt at the store/Session boundary.\n */\nexport interface TurnSnapshot {\n threads: Record<string, AgentThreadSnapshot>;\n mcp_servers: Record<string, MCPServerInitInfo> | null;\n sandbox_info: SandboxInfo | null;\n}\n\nexport interface TurnRecord<TCustom extends object = Record<string, never>> {\n turn_id: string;\n session_id: string;\n first_turn_id: string;\n /**\n * Newest-last list of recent ancestor turn ids. Writers may truncate to a\n * recent window; this need not reach the session root. Store readers that\n * need the full chain spill through older turns' own `ancestor_ids`.\n */\n ancestor_ids: string[];\n previous_turn_id: string | null;\n state: TurnState;\n input: TurnInputItem[];\n snapshot: TurnSnapshot;\n /** Instant the turn was created (store domain). Wire/API serialize as ISO-8601. */\n created_at: Date;\n /** Instant the turn was last updated (store domain). Wire/API serialize as ISO-8601. */\n updated_at: Date;\n custom: TCustom | null;\n}\n"],"mappings":";AAMO,IAAM,iBAAiB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/agent-session/models/TurnRecord.ts"],"sourcesContent":["import type { MCPServerInitInfo } from '../../core/events/schema';\nimport type { AgentThreadSnapshot } from '../../core/runtime/AgentThread.types';\nimport type { SandboxInfo } from '../../core/sandbox/Sandbox';\nimport type { TurnInputItem, TurnState } from '../schemas/turn';\n\n/** Root thread id for every session. */\nexport const MAIN_THREAD_ID = 'main';\n\n/**\n * Public wire / store shape — JSON-friendly `Record`, not `Map`, so every\n * backend can persist it directly. In-process runtime may still use Map;\n * adapt at the store/Session boundary.\n */\nexport interface TurnSnapshot {\n threads: Record<string, AgentThreadSnapshot>;\n mcp_servers: Record<string, MCPServerInitInfo> | null;\n sandbox_info: SandboxInfo | null;\n}\n\nexport interface TurnRecord<TCustom extends object = Record<string, never>> {\n turn_id: string;\n session_id: string;\n first_turn_id: string;\n /**\n * Newest-last list of recent ancestor turn ids. Writers may truncate to a\n * recent window; this need not reach the session root. Store readers that\n * need the full chain spill through older turns' own `ancestor_ids`.\n */\n ancestor_ids: string[];\n previous_turn_id: string | null;\n active_executor_id: string;\n state: TurnState;\n input: TurnInputItem[];\n snapshot: TurnSnapshot;\n /** Instant the turn was created (store domain). Wire/API serialize as ISO-8601. */\n created_at: Date;\n /** Instant the turn was last updated (store domain). Wire/API serialize as ISO-8601. */\n updated_at: Date;\n custom: TCustom | null;\n}\n"],"mappings":";AAMO,IAAM,iBAAiB;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenUI.d.ts","sourceRoot":"","sources":["../../../../src/core/capabilities/builtins/OpenUI.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAc,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,iCAAiC,4BAA4B,CAAC;AAI3E,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAC3C,eAAO,MAAM,2BAA2B,4BAA4B,CAAC;AACrE,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,+BAA+B,gCAAgC,CAAC;AAC7E,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE,eAAO,MAAM,iCAAiC,kCAAkC,CAAC;AACjF,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AACnE,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AACzE,eAAO,MAAM,qCAAqC,sCAAsC,CAAC;AAEzF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"OpenUI.d.ts","sourceRoot":"","sources":["../../../../src/core/capabilities/builtins/OpenUI.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAc,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,iCAAiC,4BAA4B,CAAC;AAI3E,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAC3C,eAAO,MAAM,2BAA2B,4BAA4B,CAAC;AACrE,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,eAAO,MAAM,+BAA+B,gCAAgC,CAAC;AAC7E,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE,eAAO,MAAM,iCAAiC,kCAAkC,CAAC;AACjF,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AACnE,eAAO,MAAM,6BAA6B,8BAA8B,CAAC;AACzE,eAAO,MAAM,qCAAqC,sCAAsC,CAAC;AAEzF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CA6OxE;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,IAAI,MAAM,CAY3C;AAiBD,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,QAAQ,CAAC,IAAI,YAAoB;IACjC,QAAQ,CAAC,WAAW,YAAY;IAEhC,YAAY,OAAO,EAAE,YAAY,EAEhC;IAED,OAAO,CAAC,KAAK,CAUX;IAEF,SAAS,CAAC,QAAQ,IAAI,cAAc,EAAE,CAErC;CACF;AAED,wBAAgB,MAAM,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,eAAe,CAW/F"}
|
|
@@ -264,6 +264,7 @@ function buildOpenUIInstruction(builder) {
|
|
|
264
264
|
OPENUI_IMPORTANT_RULES_TAG,
|
|
265
265
|
import_dedent.default`
|
|
266
266
|
- When asked about data, generate realistic/plausible data
|
|
267
|
+
- Prefer OpenUI charts for plot/chart/visualize; images only if downloadable
|
|
267
268
|
- Choose components that best represent the content (tables for comparisons, charts for trends, forms for input, etc.)
|
|
268
269
|
- When you render data in an openui block (tables, charts, KPI cards), do NOT repeat the same numbers/facts in the markdown text outside the block.
|
|
269
270
|
- Text outside the openui block can optionally include:
|
|
@@ -291,7 +292,7 @@ function buildOpenUIInstruction(builder) {
|
|
|
291
292
|
openui.addSection(
|
|
292
293
|
OPENUI_USER_INTERACTION_CHECKLIST_TAG,
|
|
293
294
|
import_dedent.default`
|
|
294
|
-
1.
|
|
295
|
+
1. Plot/chart/visualize or UI-heavy beyond markdown? Use openui.
|
|
295
296
|
2. \`\`\`openui\`\`\` fencing must be closed.`
|
|
296
297
|
);
|
|
297
298
|
}
|
|
@@ -317,7 +318,8 @@ function buildOpenUIDeferredInstruction(builder) {
|
|
|
317
318
|
Before writing any \`\`\`openui fence, the Agent MUST call ${GET_OPENUI_INSTRUCTIONS_TOOL_NAME} with arguments {}.
|
|
318
319
|
Do not invent OpenUI syntax or component APIs without loading those instructions.
|
|
319
320
|
|
|
320
|
-
|
|
321
|
+
Prefer OpenUI for plot/chart/visualize over sandbox code; sandbox images only for downloads.
|
|
322
|
+
Otherwise use OpenUI only when UI-heavy beyond markdown.
|
|
321
323
|
`.trim()
|
|
322
324
|
);
|
|
323
325
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/capabilities/builtins/OpenUI.ts"],"sourcesContent":["import dedent from 'dedent';\nimport { z } from 'zod';\nimport { InstructionBuilder } from '../../InstructionBuilder';\nimport { toolResultResponse } from '../../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../../tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../../tracing/NoopAgentTracing';\nimport type { AgentCapability } from '../AgentCapability';\n\nexport const OPENUI_SERVER_ID = 'openui';\nexport const GET_OPENUI_INSTRUCTIONS_TOOL_NAME = 'get_openui_instructions';\n\nconst getOpenUIInstructionsInputSchema = z.object({}).strict();\n\nexport const OPENUI_SECTION_TAG = 'openui';\nexport const OPENUI_MARKDOWN_FENCING_TAG = 'openui-markdown-fencing';\nexport const OPENUI_SYNTAX_RULES_TAG = 'openui-syntax-rules';\nexport const OPENUI_COMPONENT_SIGNATURES_TAG = 'openui-component-signatures';\nexport const OPENUI_BUILTIN_FUNCTIONS_TAG = 'openui-builtin-functions';\nexport const OPENUI_HOISTING_AND_STREAMING_TAG = 'openui-hoisting-and-streaming';\nexport const OPENUI_EXAMPLES_TAG = 'openui-examples';\nexport const OPENUI_IMPORTANT_RULES_TAG = 'openui-important-rules';\nexport const OPENUI_FINAL_VERIFICATION_TAG = 'openui-final-verification';\nexport const OPENUI_USER_INTERACTION_CHECKLIST_TAG = 'openui-user-interaction-checklist';\n\nexport function buildOpenUIInstruction(builder: InstructionBuilder): void {\n const openui = builder.beginSection(OPENUI_SECTION_TAG);\n\n openui.addSection(\n OPENUI_MARKDOWN_FENCING_TAG,\n dedent`\n All openui, code must be fenced within openui block.\n \\`\\`\\`openui\n code\n \\`\\`\\``,\n );\n\n openui.addSection(\n OPENUI_SYNTAX_RULES_TAG,\n dedent`\n 1. Each statement is on its own line: \\`identifier = Expression\\`\n 2. \\`root\\` is the entry point — every program must define \\`root = Stack(...)\\`\n 3. Expressions are: strings (\"...\"), numbers, booleans (true/false), null, arrays ([...]), objects ({...}), or component calls TypeName(arg1, arg2, ...)\n 4. Use references for readability: define \\`name = ...\\` on one line, then use \\`name\\` later\n 5. EVERY variable (except root) MUST be referenced by at least one other variable. Unreferenced variables are silently dropped and will NOT render. Always include defined variables in their parent's children/items array.\n 6. Arguments are POSITIONAL (order matters, not names). Write \\`Stack([children], \"row\", \"l\")\\` NOT \\`Stack([children], direction: \"row\", gap: \"l\")\\` — colon syntax is NOT supported and silently breaks\n 7. Optional arguments can be omitted from the end\n - Strings use double quotes with backslash escaping`,\n );\n\n openui.addSection(\n OPENUI_COMPONENT_SIGNATURES_TAG,\n dedent`\n Arguments marked with ? are optional. Sub-components can be inline or referenced; prefer references for better streaming.\n Props typed \\`ActionExpression\\` accept an Action([@steps...]) expression. See the Action section for available steps (@ToAssistant, @OpenUrl).\n Props marked \\`$binding<type>\\` accept a \\`$variable\\` reference for two-way binding.\n\n Layout:\n Stack([children], direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Flex container. direction: \"row\"|\"column\" (default \"column\"). gap: \"none\"|\"xs\"|\"s\"|\"m\"|\"l\"|\"xl\"|\"2xl\" (default \"m\"). align: \"start\"|\"center\"|\"end\"|\"stretch\"|\"baseline\". justify: \"start\"|\"center\"|\"end\"|\"between\"|\"around\"|\"evenly\".\n Tabs(items: TabItem[]) — Tabbed container\n TabItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is tab label, content is array of components\n Accordion(items: AccordionItem[]) — Collapsible sections\n AccordionItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is section title\n Steps(items: StepsItem[]) — Step-by-step guide\n StepsItem(title: string, details: string) — title and details text for one step\n Carousel(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[][], variant?: \"card\" | \"sunk\") — Horizontal scrollable carousel\n Separator(orientation?: \"horizontal\" | \"vertical\", decorative?: boolean) — Visual divider between content sections\n Modal(title: string, open?: $binding<boolean>, children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[], size?: \"sm\" | \"md\" | \"lg\") — Modal dialog. open is a reactive $boolean binding — set to true to open, X/Escape/backdrop auto-closes. Put Form with buttons inside children.\n - For grid-like layouts, use Stack with direction \"row\" and wrap set to true.\n - Prefer justify \"start\" (or omit justify) with wrap=true for stable columns instead of uneven gutters.\n - Use nested Stacks when you need explicit rows/sections.\n - Show/hide sections: $editId != \"\" ? Card([editForm]) : null\n - Modal: Modal(\"Title\", $showModal, [content]) — $showModal is boolean, X/Escape auto-closes. Put Form with its own buttons inside children.\n - Use Tabs for alternative views (chart types, data sections) — no $variable needed\n - Shared filter across Tabs: same $days binding in Query args works across all TabItems\n\n Content:\n Card(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | Tabs | Carousel | Stack)[], variant?: \"card\" | \"sunk\" | \"clear\", direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Styled container. variant: \"card\" (default, elevated) | \"sunk\" (recessed) | \"clear\" (transparent). Always full width. Accepts all Stack flex params (default: direction \"column\"). Cards flex to share space in row/wrap layouts.\n CardHeader(title?: string, subtitle?: string) — Header with optional title and subtitle\n TextContent(text: string, size?: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\") — Text block. Supports markdown. Optional size: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\".\n MarkDownRenderer(textMarkdown: string, variant?: \"clear\" | \"card\" | \"sunk\") — Renders markdown text with optional container variant\n Callout(variant: \"info\" | \"warning\" | \"error\" | \"success\" | \"neutral\", title: string, description: string, visible?: $binding<boolean>) — Callout banner. Optional visible is a reactive $boolean — auto-dismisses after 3s by setting $visible to false.\n TextCallout(variant?: \"neutral\" | \"info\" | \"warning\" | \"success\" | \"danger\", title?: string, description?: string) — Text callout with variant, title, and description\n Image(alt: string, src?: string) — Image with alt text and optional URL\n ImageBlock(src: string, alt?: string) — Image block with loading state\n ImageGallery(images: {src: string, alt?: string, details?: string}[]) — Gallery grid of images with modal preview\n CodeBlock(language: string, codeString: string) — Syntax-highlighted code block\n - Use Cards to group related KPIs or sections. Stack with direction \"row\" for side-by-side layouts.\n - Success toast: Callout(\"success\", \"Saved\", \"Done.\", $showSuccess) — use @Set($showSuccess, true) in save action, auto-dismisses after 3s. For errors: result.status == \"error\" ? Callout(\"error\", \"Failed\", result.error) : null\n - KPI card: Card([TextContent(\"Label\", \"small\"), TextContent(\"\" + @Count(@Filter(data.rows, \"field\", \"==\", \"value\")), \"large-heavy\")])\n\n Tables:\n Table(columns: Col[]) — Data table — column-oriented. Each Col holds its own data array.\n Col(label: string, data, type?: \"string\" | \"number\" | \"action\") — Column definition — holds label + data array\n - Table is COLUMN-oriented: Table([Col(\"Label\", dataArray), Col(\"Count\", countArray, \"number\")]). Use array pluck for data: data.rows.fieldName\n - Col data can be component arrays for styled cells: Col(\"Status\", @Each(data.rows, \"item\", Tag(item.status, null, \"sm\", item.status == \"open\" ? \"success\" : \"danger\")))\n - Row actions: Col(\"Actions\", @Each(data.rows, \"t\", Button(\"Edit\", Action([@Set($showEdit, true), @Set($editId, t.id)]))))\n - Sortable: sorted = @Sort(data.rows, $sortField, \"desc\"). Bind $sortField to Select. Use sorted.fieldName for Col data\n - Searchable: filtered = @Filter(data.rows, \"title\", \"contains\", $search). Bind $search to Input\n - Chain sort + filter: filtered = @Filter(...) then sorted = @Sort(filtered, ...) — use sorted for both Table and Charts\n - Empty state: @Count(data.rows) > 0 ? Table([...]) : TextContent(\"No data yet\")\n\n Charts (2D):\n BarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Vertical bars; use for comparing values across categories with one or more series\n LineChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Lines over categories; use for trends and continuous data over time\n AreaChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Filled area under lines; use for cumulative totals or volume trends over time\n RadarChart(labels: string[], series: Series[]) — Spider/web chart; use for comparing multiple variables across one or more entities\n HorizontalBarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Horizontal bars; prefer when category labels are long or for ranked lists\n Series(category: string, values: number[]) — One data series\n - Charts accept column arrays: LineChart(labels, [Series(\"Name\", values)]). Use array pluck: LineChart(data.rows.day, [Series(\"Views\", data.rows.views)])\n - Use Cards to wrap charts with CardHeader for titled sections\n - Chart + Table from same source: use @Sort or @Filter result for both LineChart and Table Col data\n - Multiple chart views: use Tabs — Tabs([TabItem(\"line\", \"Line\", [LineChart(...)]), TabItem(\"bar\", \"Bar\", [BarChart(...)])])\n\n Charts (1D):\n PieChart(labels: string[], values: number[], variant?: \"pie\" | \"donut\") — Circular slices; use plucked arrays: PieChart(data.categories, data.values)\n RadialChart(labels: string[], values: number[]) — Radial bars; use plucked arrays: RadialChart(data.categories, data.values)\n SingleStackedBarChart(labels: string[], values: number[]) — Single horizontal stacked bar; use plucked arrays: SingleStackedBarChart(data.categories, data.values)\n Slice(category: string, value: number) — One slice with label and numeric value\n - PieChart and BarChart need NUMBERS, not objects. For list data, use @Count(@Filter(...)) to aggregate:\n - PieChart from list: \\`PieChart([\"Low\", \"Med\", \"High\"], [@Count(@Filter(data.rows, \"priority\", \"==\", \"low\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"medium\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"high\"))], \"donut\")\\`\n - KPI from count: \\`TextContent(\"\" + @Count(@Filter(data.rows, \"status\", \"==\", \"open\")), \"large-heavy\")\\`\n\n Charts (Scatter):\n ScatterChart(datasets: ScatterSeries[], xLabel?: string, yLabel?: string) — X/Y scatter plot; use for correlations, distributions, and clustering\n ScatterSeries(name: string, points: Point[]) — Named dataset\n Point(x: number, y: number, z?: number) — Data point with numeric coordinates\n\n Data Display:\n TagBlock(tags: string[]) — tags is an array of strings\n Tag(text: string, icon?: string, size?: \"sm\" | \"md\" | \"lg\", variant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\") — Styled tag/badge with optional icon and variant\n - Color-mapped Tag: Tag(value, null, \"sm\", value == \"high\" ? \"danger\" : value == \"medium\" ? \"warning\" : \"neutral\")`,\n );\n\n openui.addSection(\n OPENUI_BUILTIN_FUNCTIONS_TAG,\n dedent`\n Data functions prefixed with \\`@\\` to distinguish from components. These are the ONLY functions available — do NOT invent new ones.\n Use @-prefixed built-in functions (@Count, @Sum, @Avg, @Min, @Max, @Round) on Query results — do NOT hardcode computed values.\n\n @Count(array) → number — Returns array length\n @First(array) → element — Returns first element of array\n @Last(array) → element — Returns last element of array\n @Sum(numbers[]) → number — Sum of numeric array\n @Avg(numbers[]) → number — Average of numeric array\n @Min(numbers[]) → number — Minimum value in array\n @Max(numbers[]) → number — Maximum value in array\n @Sort(array, field, direction?) → sorted array — Sort array by field. Direction: \"asc\" (default) or \"desc\"\n @Filter(array, field, operator: \"==\" | \"!=\" | \">\" | \"<\" | \">=\" | \"<=\" | \"contains\", value) → filtered array — Filter array by field value\n @Round(number, decimals?) → number — Round to N decimal places (default 0)\n @Abs(number) → number — Absolute value\n @Floor(number) → number — Round down to nearest integer\n @Ceil(number) → number — Round up to nearest integer\n @Each(array, varName, template) — Evaluate template for each element. varName is the loop variable — use it ONLY inside the template expression (inline). Do NOT create a separate statement for the template.\n\n Builtins compose — output of one is input to the next:\n \\`@Count(@Filter(data.rows, \"field\", \"==\", \"val\"))\\` for KPIs/chart values, \\`@Round(@Avg(data.rows.score), 1)\\`, \\`@Each(data.rows, \"item\", Comp(item.field))\\` for per-item rendering.\n Array pluck: \\`data.rows.field\\` extracts a field from every row → use with @Sum, @Avg, charts, tables.\n\n IMPORTANT @Each rule: The loop variable (e.g. \"item\") is ONLY available inside the @Each template expression. Always inline the template — do NOT extract it to a separate statement.\n CORRECT: \\`Col(\"Actions\", @Each(rows, \"t\", Button(\"Edit\", Action([@Set($id, t.id)]))))\\`\n WRONG: \\`myBtn = Button(\"Edit\", Action([@Set($id, t.id)]))\\` then \\`Col(\"Actions\", @Each(rows, \"t\", myBtn))\\` — t is undefined in myBtn.`,\n );\n\n openui.addSection(\n OPENUI_HOISTING_AND_STREAMING_TAG,\n dedent`\n openui-lang supports hoisting: a reference can be used BEFORE it is defined. The parser resolves all references after the full input is parsed.\n\n During streaming, the output is re-parsed on every chunk. Undefined references are temporarily unresolved and appear once their definitions stream in. This creates a progressive top-down reveal — structure first, then data fills in.\n\n Recommended statement order for optimal streaming:\n 1. \\`root = Stack(...)\\` — UI shell appears immediately\n 2. $variable declarations — state ready for bindings\n 3. Query statements — defaults resolve immediately so components render with data\n 4. Component definitions — fill in with data already available\n 5. Data values — leaf content last\n\n Always write the root = Stack(...) statement first so the UI shell appears immediately, even before child data has streamed in.`,\n );\n\n openui.addSection(\n OPENUI_EXAMPLES_TAG,\n dedent`\n Example 1 — Table (column-oriented):\n\n root = Stack([title, tbl])\n title = TextContent(\"Top Languages\", \"large-heavy\")\n tbl = Table([Col(\"Language\", langs), Col(\"Users (M)\", users), Col(\"Year\", years)])\n langs = [\"Python\", \"JavaScript\", \"Java\", \"TypeScript\", \"Go\"]\n users = [15.7, 14.2, 12.1, 8.5, 5.2]\n years = [1991, 1995, 1995, 2012, 2009]\n\n Example 2 — Bar chart:\n\n root = Stack([title, chart])\n title = TextContent(\"Q4 Revenue\", \"large-heavy\")\n chart = BarChart(labels, [s1, s2], \"grouped\")\n labels = [\"Oct\", \"Nov\", \"Dec\"]\n s1 = Series(\"Product A\", [120, 150, 180])\n s2 = Series(\"Product B\", [90, 110, 140])\n\n Example 3 — Form with validation:\n\n root = Stack([title, form])\n title = TextContent(\"Contact Us\", \"large-heavy\")\n form = Form(\"contact\", btns, [nameField, emailField, countryField, msgField])\n nameField = FormControl(\"Name\", Input(\"name\", \"Your name\", \"text\", { required: true, minLength: 2 }))\n emailField = FormControl(\"Email\", Input(\"email\", \"you@example.com\", \"email\", { required: true, email: true }))\n countryField = FormControl(\"Country\", Select(\"country\", countryOpts, \"Select...\", { required: true }))\n msgField = FormControl(\"Message\", TextArea(\"message\", \"Tell us more...\", 4, { required: true, minLength: 10 }))\n countryOpts = [SelectItem(\"us\", \"United States\"), SelectItem(\"uk\", \"United Kingdom\"), SelectItem(\"de\", \"Germany\")]\n btns = Buttons([Button(\"Submit\", Action([@ToAssistant(\"Submit\")]), \"primary\"), Button(\"Cancel\", Action([@ToAssistant(\"Cancel\")]), \"secondary\")])\n\n Example 4 — Tabs with mixed content:\n\n root = Stack([title, tabs])\n title = TextContent(\"React vs Vue\", \"large-heavy\")\n tabs = Tabs([tabReact, tabVue])\n tabReact = TabItem(\"react\", \"React\", reactContent)\n tabVue = TabItem(\"vue\", \"Vue\", vueContent)\n reactContent = [TextContent(\"React is a library by Meta for building UIs.\"), Callout(\"info\", \"Note\", \"React uses JSX syntax.\")]\n vueContent = [TextContent(\"Vue is a progressive framework by Evan You.\"), Callout(\"success\", \"Tip\", \"Vue has a gentle learning curve.\")]`,\n );\n\n openui.addSection(\n OPENUI_IMPORTANT_RULES_TAG,\n dedent`\n - When asked about data, generate realistic/plausible data\n - Choose components that best represent the content (tables for comparisons, charts for trends, forms for input, etc.)\n - When you render data in an openui block (tables, charts, KPI cards), do NOT repeat the same numbers/facts in the markdown text outside the block.\n - Text outside the openui block can optionally include:\n 1. **Qualitative insights** — patterns, anomalies, or recommendations that aren't obvious from the visual (e.g. \"the high input-to-output ratio suggests document processing\")\n 2. **Actionable next steps** — what the user can do next\n 3. **Caveats/context** — things the data doesn't show\n - If all the information is already visible in the openui components, a brief one-line summary is sufficient — do not enumerate the same values again.`,\n );\n\n openui.addSection(\n OPENUI_FINAL_VERIFICATION_TAG,\n dedent`\n Before finishing, walk your output and verify:\n 1. root = Stack(...) is the FIRST line (for optimal streaming).\n 2. Every referenced name is defined. Every defined name (other than root) is reachable from root.\n\n - For grid-like layouts, use Stack with direction \"row\" and wrap=true. Avoid justify=\"between\" unless you specifically want large gutters.\n - For forms, define one FormControl reference per field so controls can stream progressively.\n - For forms, always provide the second Form argument with Buttons(...) actions: Form(name, buttons, fields).\n - Never nest Form inside Form.\n - Use @Reset($var1, $var2) after form submit to restore defaults — not @Set($var, \"\")\n - Multi-query refresh: Action([@Run(mutation), @Run(query1), @Run(query2), @Reset(...)])\n - $variables are reactive: changing via Select or @Set re-evaluates all Queries and expressions referencing them\n - Use existing components (Tabs, Accordion, Modal) before inventing ternary show/hide patterns`,\n );\n\n openui.addSection(\n OPENUI_USER_INTERACTION_CHECKLIST_TAG,\n dedent`\n 1. Will the response be UI heavy and will contain components which are not supported by markdown? Use openui if the answer is yes.\n 2. \\`\\`\\`openui\\`\\`\\` fencing must be closed.`,\n );\n}\n\n/** Renders the existing OpenUI prompt tree without duplicating section bodies. */\nexport function renderOpenUIPrompt(): string {\n const root = new InstructionBuilder('_openui_render');\n buildOpenUIInstruction(root);\n const wrapped = root.build();\n const openTag = `<${OPENUI_SECTION_TAG}>`;\n const closeTag = `</${OPENUI_SECTION_TAG}>`;\n const start = wrapped.indexOf(openTag);\n const end = wrapped.lastIndexOf(closeTag);\n if (start === -1 || end === -1) {\n throw new Error('Failed to render OpenUI prompt from buildOpenUIInstruction');\n }\n return wrapped.slice(start, end + closeTag.length);\n}\n\nfunction buildOpenUIDeferredInstruction(builder: InstructionBuilder): void {\n builder.addSection(\n OPENUI_SECTION_TAG,\n dedent`\n The Agent can render interactive UI that markdown cannot express by emitting a fenced \\`\\`\\`openui block.\n\n Before writing any \\`\\`\\`openui fence, the Agent MUST call ${GET_OPENUI_INSTRUCTIONS_TOOL_NAME} with arguments {}.\n Do not invent OpenUI syntax or component APIs without loading those instructions.\n\n Use OpenUI only when the response is UI-heavy and needs components markdown does not support.\n `.trim(),\n );\n}\n\nexport class OpenUIInstructions extends LocalToolMCP {\n readonly name = OPENUI_SERVER_ID;\n readonly displayName = 'OpenUI';\n\n constructor(tracing: AgentTracing) {\n super({ tracing });\n }\n\n private tools: ToolDefinition[] = [\n defineTool({\n name: GET_OPENUI_INSTRUCTIONS_TOOL_NAME,\n description: [\n 'Load the full OpenUI generative-UI authoring instructions (syntax, components, builtins, examples, rules).',\n 'Call this before emitting any ```openui fenced block. Pass an empty object as arguments: {}.',\n ].join(' '),\n schema: getOpenUIInstructionsInputSchema,\n handler: () => Promise.resolve(toolResultResponse({ text: renderOpenUIPrompt() })),\n }),\n ];\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n}\n\nexport function openUI(options?: { preload?: boolean; tracing?: AgentTracing }): AgentCapability {\n const preload = options?.preload ?? true;\n if (preload) {\n return {\n instructionBuilders: [buildOpenUIInstruction],\n };\n }\n return {\n systemToolSets: [new OpenUIInstructions(options?.tracing ?? NOOP_AGENT_TRACING)],\n instructionBuilders: [buildOpenUIDeferredInstruction],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AACnB,iBAAkB;AAClB,gCAAmC;AACnC,wBAAmC;AACnC,0BAA8D;AAE9D,8BAAmC;AAG5B,IAAM,mBAAmB;AACzB,IAAM,oCAAoC;AAEjD,IAAM,mCAAmC,aAAE,OAAO,CAAC,CAAC,EAAE,OAAO;AAEtD,IAAM,qBAAqB;AAC3B,IAAM,8BAA8B;AACpC,IAAM,0BAA0B;AAChC,IAAM,kCAAkC;AACxC,IAAM,+BAA+B;AACrC,IAAM,oCAAoC;AAC1C,IAAM,sBAAsB;AAC5B,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,wCAAwC;AAE9C,SAAS,uBAAuB,SAAmC;AACxE,QAAM,SAAS,QAAQ,aAAa,kBAAkB;AAEtD,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgFF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA,EAGF;AACF;AAGO,SAAS,qBAA6B;AAC3C,QAAM,OAAO,IAAI,6CAAmB,gBAAgB;AACpD,yBAAuB,IAAI;AAC3B,QAAM,UAAU,KAAK,MAAM;AAC3B,QAAM,UAAU,IAAI,kBAAkB;AACtC,QAAM,WAAW,KAAK,kBAAkB;AACxC,QAAM,QAAQ,QAAQ,QAAQ,OAAO;AACrC,QAAM,MAAM,QAAQ,YAAY,QAAQ;AACxC,MAAI,UAAU,MAAM,QAAQ,IAAI;AAC9B,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AACA,SAAO,QAAQ,MAAM,OAAO,MAAM,SAAS,MAAM;AACnD;AAEA,SAAS,+BAA+B,SAAmC;AACzE,UAAQ;AAAA,IACN;AAAA,IACA,cAAAA;AAAA;AAAA;AAAA,mEAG+D,iCAAiC;AAAA;AAAA;AAAA;AAAA,MAI9F,KAAK;AAAA,EACT;AACF;AAEO,IAAM,qBAAN,cAAiC,iCAAa;AAAA,EAC1C,OAAO;AAAA,EACP,cAAc;AAAA,EAEvB,YAAY,SAAuB;AACjC,UAAM,EAAE,QAAQ,CAAC;AAAA,EACnB;AAAA,EAEQ,QAA0B;AAAA,QAChC,gCAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,QACX;AAAA,QACA;AAAA,MACF,EAAE,KAAK,GAAG;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,MAAM,QAAQ,YAAQ,sCAAmB,EAAE,MAAM,mBAAmB,EAAE,CAAC,CAAC;AAAA,IACnF,CAAC;AAAA,EACH;AAAA,EAEU,WAA6B;AACrC,WAAO,KAAK;AAAA,EACd;AACF;AAEO,SAAS,OAAO,SAA0E;AAC/F,QAAM,UAAU,SAAS,WAAW;AACpC,MAAI,SAAS;AACX,WAAO;AAAA,MACL,qBAAqB,CAAC,sBAAsB;AAAA,IAC9C;AAAA,EACF;AACA,SAAO;AAAA,IACL,gBAAgB,CAAC,IAAI,mBAAmB,SAAS,WAAW,0CAAkB,CAAC;AAAA,IAC/E,qBAAqB,CAAC,8BAA8B;AAAA,EACtD;AACF;","names":["dedent"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/capabilities/builtins/OpenUI.ts"],"sourcesContent":["import dedent from 'dedent';\nimport { z } from 'zod';\nimport { InstructionBuilder } from '../../InstructionBuilder';\nimport { toolResultResponse } from '../../mcp/IMCPServer';\nimport { defineTool, LocalToolMCP, type ToolDefinition } from '../../mcp/LocalToolMCP';\nimport type { AgentTracing } from '../../tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../../tracing/NoopAgentTracing';\nimport type { AgentCapability } from '../AgentCapability';\n\nexport const OPENUI_SERVER_ID = 'openui';\nexport const GET_OPENUI_INSTRUCTIONS_TOOL_NAME = 'get_openui_instructions';\n\nconst getOpenUIInstructionsInputSchema = z.object({}).strict();\n\nexport const OPENUI_SECTION_TAG = 'openui';\nexport const OPENUI_MARKDOWN_FENCING_TAG = 'openui-markdown-fencing';\nexport const OPENUI_SYNTAX_RULES_TAG = 'openui-syntax-rules';\nexport const OPENUI_COMPONENT_SIGNATURES_TAG = 'openui-component-signatures';\nexport const OPENUI_BUILTIN_FUNCTIONS_TAG = 'openui-builtin-functions';\nexport const OPENUI_HOISTING_AND_STREAMING_TAG = 'openui-hoisting-and-streaming';\nexport const OPENUI_EXAMPLES_TAG = 'openui-examples';\nexport const OPENUI_IMPORTANT_RULES_TAG = 'openui-important-rules';\nexport const OPENUI_FINAL_VERIFICATION_TAG = 'openui-final-verification';\nexport const OPENUI_USER_INTERACTION_CHECKLIST_TAG = 'openui-user-interaction-checklist';\n\nexport function buildOpenUIInstruction(builder: InstructionBuilder): void {\n const openui = builder.beginSection(OPENUI_SECTION_TAG);\n\n openui.addSection(\n OPENUI_MARKDOWN_FENCING_TAG,\n dedent`\n All openui, code must be fenced within openui block.\n \\`\\`\\`openui\n code\n \\`\\`\\``,\n );\n\n openui.addSection(\n OPENUI_SYNTAX_RULES_TAG,\n dedent`\n 1. Each statement is on its own line: \\`identifier = Expression\\`\n 2. \\`root\\` is the entry point — every program must define \\`root = Stack(...)\\`\n 3. Expressions are: strings (\"...\"), numbers, booleans (true/false), null, arrays ([...]), objects ({...}), or component calls TypeName(arg1, arg2, ...)\n 4. Use references for readability: define \\`name = ...\\` on one line, then use \\`name\\` later\n 5. EVERY variable (except root) MUST be referenced by at least one other variable. Unreferenced variables are silently dropped and will NOT render. Always include defined variables in their parent's children/items array.\n 6. Arguments are POSITIONAL (order matters, not names). Write \\`Stack([children], \"row\", \"l\")\\` NOT \\`Stack([children], direction: \"row\", gap: \"l\")\\` — colon syntax is NOT supported and silently breaks\n 7. Optional arguments can be omitted from the end\n - Strings use double quotes with backslash escaping`,\n );\n\n openui.addSection(\n OPENUI_COMPONENT_SIGNATURES_TAG,\n dedent`\n Arguments marked with ? are optional. Sub-components can be inline or referenced; prefer references for better streaming.\n Props typed \\`ActionExpression\\` accept an Action([@steps...]) expression. See the Action section for available steps (@ToAssistant, @OpenUrl).\n Props marked \\`$binding<type>\\` accept a \\`$variable\\` reference for two-way binding.\n\n Layout:\n Stack([children], direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Flex container. direction: \"row\"|\"column\" (default \"column\"). gap: \"none\"|\"xs\"|\"s\"|\"m\"|\"l\"|\"xl\"|\"2xl\" (default \"m\"). align: \"start\"|\"center\"|\"end\"|\"stretch\"|\"baseline\". justify: \"start\"|\"center\"|\"end\"|\"between\"|\"around\"|\"evenly\".\n Tabs(items: TabItem[]) — Tabbed container\n TabItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is tab label, content is array of components\n Accordion(items: AccordionItem[]) — Collapsible sections\n AccordionItem(value: string, trigger: string, content: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[]) — value is unique id, trigger is section title\n Steps(items: StepsItem[]) — Step-by-step guide\n StepsItem(title: string, details: string) — title and details text for one step\n Carousel(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[][], variant?: \"card\" | \"sunk\") — Horizontal scrollable carousel\n Separator(orientation?: \"horizontal\" | \"vertical\", decorative?: boolean) — Visual divider between content sections\n Modal(title: string, open?: $binding<boolean>, children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps)[], size?: \"sm\" | \"md\" | \"lg\") — Modal dialog. open is a reactive $boolean binding — set to true to open, X/Escape/backdrop auto-closes. Put Form with buttons inside children.\n - For grid-like layouts, use Stack with direction \"row\" and wrap set to true.\n - Prefer justify \"start\" (or omit justify) with wrap=true for stable columns instead of uneven gutters.\n - Use nested Stacks when you need explicit rows/sections.\n - Show/hide sections: $editId != \"\" ? Card([editForm]) : null\n - Modal: Modal(\"Title\", $showModal, [content]) — $showModal is boolean, X/Escape auto-closes. Put Form with its own buttons inside children.\n - Use Tabs for alternative views (chart types, data sections) — no $variable needed\n - Shared filter across Tabs: same $days binding in Query args works across all TabItems\n\n Content:\n Card(children: (TextContent | MarkDownRenderer | CardHeader | Callout | TextCallout | CodeBlock | Image | ImageBlock | ImageGallery | Separator | HorizontalBarChart | RadarChart | PieChart | RadialChart | SingleStackedBarChart | ScatterChart | AreaChart | BarChart | LineChart | Table | TagBlock | Form | Buttons | Steps | Tabs | Carousel | Stack)[], variant?: \"card\" | \"sunk\" | \"clear\", direction?: \"row\" | \"column\", gap?: \"none\" | \"xs\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\", align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\", justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\", wrap?: boolean) — Styled container. variant: \"card\" (default, elevated) | \"sunk\" (recessed) | \"clear\" (transparent). Always full width. Accepts all Stack flex params (default: direction \"column\"). Cards flex to share space in row/wrap layouts.\n CardHeader(title?: string, subtitle?: string) — Header with optional title and subtitle\n TextContent(text: string, size?: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\") — Text block. Supports markdown. Optional size: \"small\" | \"default\" | \"large\" | \"small-heavy\" | \"large-heavy\".\n MarkDownRenderer(textMarkdown: string, variant?: \"clear\" | \"card\" | \"sunk\") — Renders markdown text with optional container variant\n Callout(variant: \"info\" | \"warning\" | \"error\" | \"success\" | \"neutral\", title: string, description: string, visible?: $binding<boolean>) — Callout banner. Optional visible is a reactive $boolean — auto-dismisses after 3s by setting $visible to false.\n TextCallout(variant?: \"neutral\" | \"info\" | \"warning\" | \"success\" | \"danger\", title?: string, description?: string) — Text callout with variant, title, and description\n Image(alt: string, src?: string) — Image with alt text and optional URL\n ImageBlock(src: string, alt?: string) — Image block with loading state\n ImageGallery(images: {src: string, alt?: string, details?: string}[]) — Gallery grid of images with modal preview\n CodeBlock(language: string, codeString: string) — Syntax-highlighted code block\n - Use Cards to group related KPIs or sections. Stack with direction \"row\" for side-by-side layouts.\n - Success toast: Callout(\"success\", \"Saved\", \"Done.\", $showSuccess) — use @Set($showSuccess, true) in save action, auto-dismisses after 3s. For errors: result.status == \"error\" ? Callout(\"error\", \"Failed\", result.error) : null\n - KPI card: Card([TextContent(\"Label\", \"small\"), TextContent(\"\" + @Count(@Filter(data.rows, \"field\", \"==\", \"value\")), \"large-heavy\")])\n\n Tables:\n Table(columns: Col[]) — Data table — column-oriented. Each Col holds its own data array.\n Col(label: string, data, type?: \"string\" | \"number\" | \"action\") — Column definition — holds label + data array\n - Table is COLUMN-oriented: Table([Col(\"Label\", dataArray), Col(\"Count\", countArray, \"number\")]). Use array pluck for data: data.rows.fieldName\n - Col data can be component arrays for styled cells: Col(\"Status\", @Each(data.rows, \"item\", Tag(item.status, null, \"sm\", item.status == \"open\" ? \"success\" : \"danger\")))\n - Row actions: Col(\"Actions\", @Each(data.rows, \"t\", Button(\"Edit\", Action([@Set($showEdit, true), @Set($editId, t.id)]))))\n - Sortable: sorted = @Sort(data.rows, $sortField, \"desc\"). Bind $sortField to Select. Use sorted.fieldName for Col data\n - Searchable: filtered = @Filter(data.rows, \"title\", \"contains\", $search). Bind $search to Input\n - Chain sort + filter: filtered = @Filter(...) then sorted = @Sort(filtered, ...) — use sorted for both Table and Charts\n - Empty state: @Count(data.rows) > 0 ? Table([...]) : TextContent(\"No data yet\")\n\n Charts (2D):\n BarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Vertical bars; use for comparing values across categories with one or more series\n LineChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Lines over categories; use for trends and continuous data over time\n AreaChart(labels: string[], series: Series[], variant?: \"linear\" | \"natural\" | \"step\", xLabel?: string, yLabel?: string) — Filled area under lines; use for cumulative totals or volume trends over time\n RadarChart(labels: string[], series: Series[]) — Spider/web chart; use for comparing multiple variables across one or more entities\n HorizontalBarChart(labels: string[], series: Series[], variant?: \"grouped\" | \"stacked\", xLabel?: string, yLabel?: string) — Horizontal bars; prefer when category labels are long or for ranked lists\n Series(category: string, values: number[]) — One data series\n - Charts accept column arrays: LineChart(labels, [Series(\"Name\", values)]). Use array pluck: LineChart(data.rows.day, [Series(\"Views\", data.rows.views)])\n - Use Cards to wrap charts with CardHeader for titled sections\n - Chart + Table from same source: use @Sort or @Filter result for both LineChart and Table Col data\n - Multiple chart views: use Tabs — Tabs([TabItem(\"line\", \"Line\", [LineChart(...)]), TabItem(\"bar\", \"Bar\", [BarChart(...)])])\n\n Charts (1D):\n PieChart(labels: string[], values: number[], variant?: \"pie\" | \"donut\") — Circular slices; use plucked arrays: PieChart(data.categories, data.values)\n RadialChart(labels: string[], values: number[]) — Radial bars; use plucked arrays: RadialChart(data.categories, data.values)\n SingleStackedBarChart(labels: string[], values: number[]) — Single horizontal stacked bar; use plucked arrays: SingleStackedBarChart(data.categories, data.values)\n Slice(category: string, value: number) — One slice with label and numeric value\n - PieChart and BarChart need NUMBERS, not objects. For list data, use @Count(@Filter(...)) to aggregate:\n - PieChart from list: \\`PieChart([\"Low\", \"Med\", \"High\"], [@Count(@Filter(data.rows, \"priority\", \"==\", \"low\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"medium\")), @Count(@Filter(data.rows, \"priority\", \"==\", \"high\"))], \"donut\")\\`\n - KPI from count: \\`TextContent(\"\" + @Count(@Filter(data.rows, \"status\", \"==\", \"open\")), \"large-heavy\")\\`\n\n Charts (Scatter):\n ScatterChart(datasets: ScatterSeries[], xLabel?: string, yLabel?: string) — X/Y scatter plot; use for correlations, distributions, and clustering\n ScatterSeries(name: string, points: Point[]) — Named dataset\n Point(x: number, y: number, z?: number) — Data point with numeric coordinates\n\n Data Display:\n TagBlock(tags: string[]) — tags is an array of strings\n Tag(text: string, icon?: string, size?: \"sm\" | \"md\" | \"lg\", variant?: \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\") — Styled tag/badge with optional icon and variant\n - Color-mapped Tag: Tag(value, null, \"sm\", value == \"high\" ? \"danger\" : value == \"medium\" ? \"warning\" : \"neutral\")`,\n );\n\n openui.addSection(\n OPENUI_BUILTIN_FUNCTIONS_TAG,\n dedent`\n Data functions prefixed with \\`@\\` to distinguish from components. These are the ONLY functions available — do NOT invent new ones.\n Use @-prefixed built-in functions (@Count, @Sum, @Avg, @Min, @Max, @Round) on Query results — do NOT hardcode computed values.\n\n @Count(array) → number — Returns array length\n @First(array) → element — Returns first element of array\n @Last(array) → element — Returns last element of array\n @Sum(numbers[]) → number — Sum of numeric array\n @Avg(numbers[]) → number — Average of numeric array\n @Min(numbers[]) → number — Minimum value in array\n @Max(numbers[]) → number — Maximum value in array\n @Sort(array, field, direction?) → sorted array — Sort array by field. Direction: \"asc\" (default) or \"desc\"\n @Filter(array, field, operator: \"==\" | \"!=\" | \">\" | \"<\" | \">=\" | \"<=\" | \"contains\", value) → filtered array — Filter array by field value\n @Round(number, decimals?) → number — Round to N decimal places (default 0)\n @Abs(number) → number — Absolute value\n @Floor(number) → number — Round down to nearest integer\n @Ceil(number) → number — Round up to nearest integer\n @Each(array, varName, template) — Evaluate template for each element. varName is the loop variable — use it ONLY inside the template expression (inline). Do NOT create a separate statement for the template.\n\n Builtins compose — output of one is input to the next:\n \\`@Count(@Filter(data.rows, \"field\", \"==\", \"val\"))\\` for KPIs/chart values, \\`@Round(@Avg(data.rows.score), 1)\\`, \\`@Each(data.rows, \"item\", Comp(item.field))\\` for per-item rendering.\n Array pluck: \\`data.rows.field\\` extracts a field from every row → use with @Sum, @Avg, charts, tables.\n\n IMPORTANT @Each rule: The loop variable (e.g. \"item\") is ONLY available inside the @Each template expression. Always inline the template — do NOT extract it to a separate statement.\n CORRECT: \\`Col(\"Actions\", @Each(rows, \"t\", Button(\"Edit\", Action([@Set($id, t.id)]))))\\`\n WRONG: \\`myBtn = Button(\"Edit\", Action([@Set($id, t.id)]))\\` then \\`Col(\"Actions\", @Each(rows, \"t\", myBtn))\\` — t is undefined in myBtn.`,\n );\n\n openui.addSection(\n OPENUI_HOISTING_AND_STREAMING_TAG,\n dedent`\n openui-lang supports hoisting: a reference can be used BEFORE it is defined. The parser resolves all references after the full input is parsed.\n\n During streaming, the output is re-parsed on every chunk. Undefined references are temporarily unresolved and appear once their definitions stream in. This creates a progressive top-down reveal — structure first, then data fills in.\n\n Recommended statement order for optimal streaming:\n 1. \\`root = Stack(...)\\` — UI shell appears immediately\n 2. $variable declarations — state ready for bindings\n 3. Query statements — defaults resolve immediately so components render with data\n 4. Component definitions — fill in with data already available\n 5. Data values — leaf content last\n\n Always write the root = Stack(...) statement first so the UI shell appears immediately, even before child data has streamed in.`,\n );\n\n openui.addSection(\n OPENUI_EXAMPLES_TAG,\n dedent`\n Example 1 — Table (column-oriented):\n\n root = Stack([title, tbl])\n title = TextContent(\"Top Languages\", \"large-heavy\")\n tbl = Table([Col(\"Language\", langs), Col(\"Users (M)\", users), Col(\"Year\", years)])\n langs = [\"Python\", \"JavaScript\", \"Java\", \"TypeScript\", \"Go\"]\n users = [15.7, 14.2, 12.1, 8.5, 5.2]\n years = [1991, 1995, 1995, 2012, 2009]\n\n Example 2 — Bar chart:\n\n root = Stack([title, chart])\n title = TextContent(\"Q4 Revenue\", \"large-heavy\")\n chart = BarChart(labels, [s1, s2], \"grouped\")\n labels = [\"Oct\", \"Nov\", \"Dec\"]\n s1 = Series(\"Product A\", [120, 150, 180])\n s2 = Series(\"Product B\", [90, 110, 140])\n\n Example 3 — Form with validation:\n\n root = Stack([title, form])\n title = TextContent(\"Contact Us\", \"large-heavy\")\n form = Form(\"contact\", btns, [nameField, emailField, countryField, msgField])\n nameField = FormControl(\"Name\", Input(\"name\", \"Your name\", \"text\", { required: true, minLength: 2 }))\n emailField = FormControl(\"Email\", Input(\"email\", \"you@example.com\", \"email\", { required: true, email: true }))\n countryField = FormControl(\"Country\", Select(\"country\", countryOpts, \"Select...\", { required: true }))\n msgField = FormControl(\"Message\", TextArea(\"message\", \"Tell us more...\", 4, { required: true, minLength: 10 }))\n countryOpts = [SelectItem(\"us\", \"United States\"), SelectItem(\"uk\", \"United Kingdom\"), SelectItem(\"de\", \"Germany\")]\n btns = Buttons([Button(\"Submit\", Action([@ToAssistant(\"Submit\")]), \"primary\"), Button(\"Cancel\", Action([@ToAssistant(\"Cancel\")]), \"secondary\")])\n\n Example 4 — Tabs with mixed content:\n\n root = Stack([title, tabs])\n title = TextContent(\"React vs Vue\", \"large-heavy\")\n tabs = Tabs([tabReact, tabVue])\n tabReact = TabItem(\"react\", \"React\", reactContent)\n tabVue = TabItem(\"vue\", \"Vue\", vueContent)\n reactContent = [TextContent(\"React is a library by Meta for building UIs.\"), Callout(\"info\", \"Note\", \"React uses JSX syntax.\")]\n vueContent = [TextContent(\"Vue is a progressive framework by Evan You.\"), Callout(\"success\", \"Tip\", \"Vue has a gentle learning curve.\")]`,\n );\n\n openui.addSection(\n OPENUI_IMPORTANT_RULES_TAG,\n dedent`\n - When asked about data, generate realistic/plausible data\n - Prefer OpenUI charts for plot/chart/visualize; images only if downloadable\n - Choose components that best represent the content (tables for comparisons, charts for trends, forms for input, etc.)\n - When you render data in an openui block (tables, charts, KPI cards), do NOT repeat the same numbers/facts in the markdown text outside the block.\n - Text outside the openui block can optionally include:\n 1. **Qualitative insights** — patterns, anomalies, or recommendations that aren't obvious from the visual (e.g. \"the high input-to-output ratio suggests document processing\")\n 2. **Actionable next steps** — what the user can do next\n 3. **Caveats/context** — things the data doesn't show\n - If all the information is already visible in the openui components, a brief one-line summary is sufficient — do not enumerate the same values again.`,\n );\n\n openui.addSection(\n OPENUI_FINAL_VERIFICATION_TAG,\n dedent`\n Before finishing, walk your output and verify:\n 1. root = Stack(...) is the FIRST line (for optimal streaming).\n 2. Every referenced name is defined. Every defined name (other than root) is reachable from root.\n\n - For grid-like layouts, use Stack with direction \"row\" and wrap=true. Avoid justify=\"between\" unless you specifically want large gutters.\n - For forms, define one FormControl reference per field so controls can stream progressively.\n - For forms, always provide the second Form argument with Buttons(...) actions: Form(name, buttons, fields).\n - Never nest Form inside Form.\n - Use @Reset($var1, $var2) after form submit to restore defaults — not @Set($var, \"\")\n - Multi-query refresh: Action([@Run(mutation), @Run(query1), @Run(query2), @Reset(...)])\n - $variables are reactive: changing via Select or @Set re-evaluates all Queries and expressions referencing them\n - Use existing components (Tabs, Accordion, Modal) before inventing ternary show/hide patterns`,\n );\n\n openui.addSection(\n OPENUI_USER_INTERACTION_CHECKLIST_TAG,\n dedent`\n 1. Plot/chart/visualize or UI-heavy beyond markdown? Use openui.\n 2. \\`\\`\\`openui\\`\\`\\` fencing must be closed.`,\n );\n}\n\n/** Renders the existing OpenUI prompt tree without duplicating section bodies. */\nexport function renderOpenUIPrompt(): string {\n const root = new InstructionBuilder('_openui_render');\n buildOpenUIInstruction(root);\n const wrapped = root.build();\n const openTag = `<${OPENUI_SECTION_TAG}>`;\n const closeTag = `</${OPENUI_SECTION_TAG}>`;\n const start = wrapped.indexOf(openTag);\n const end = wrapped.lastIndexOf(closeTag);\n if (start === -1 || end === -1) {\n throw new Error('Failed to render OpenUI prompt from buildOpenUIInstruction');\n }\n return wrapped.slice(start, end + closeTag.length);\n}\n\nfunction buildOpenUIDeferredInstruction(builder: InstructionBuilder): void {\n builder.addSection(\n OPENUI_SECTION_TAG,\n dedent`\n The Agent can render interactive UI that markdown cannot express by emitting a fenced \\`\\`\\`openui block.\n\n Before writing any \\`\\`\\`openui fence, the Agent MUST call ${GET_OPENUI_INSTRUCTIONS_TOOL_NAME} with arguments {}.\n Do not invent OpenUI syntax or component APIs without loading those instructions.\n\n Prefer OpenUI for plot/chart/visualize over sandbox code; sandbox images only for downloads.\n Otherwise use OpenUI only when UI-heavy beyond markdown.\n `.trim(),\n );\n}\n\nexport class OpenUIInstructions extends LocalToolMCP {\n readonly name = OPENUI_SERVER_ID;\n readonly displayName = 'OpenUI';\n\n constructor(tracing: AgentTracing) {\n super({ tracing });\n }\n\n private tools: ToolDefinition[] = [\n defineTool({\n name: GET_OPENUI_INSTRUCTIONS_TOOL_NAME,\n description: [\n 'Load the full OpenUI generative-UI authoring instructions (syntax, components, builtins, examples, rules).',\n 'Call this before emitting any ```openui fenced block. Pass an empty object as arguments: {}.',\n ].join(' '),\n schema: getOpenUIInstructionsInputSchema,\n handler: () => Promise.resolve(toolResultResponse({ text: renderOpenUIPrompt() })),\n }),\n ];\n\n protected getTools(): ToolDefinition[] {\n return this.tools;\n }\n}\n\nexport function openUI(options?: { preload?: boolean; tracing?: AgentTracing }): AgentCapability {\n const preload = options?.preload ?? true;\n if (preload) {\n return {\n instructionBuilders: [buildOpenUIInstruction],\n };\n }\n return {\n systemToolSets: [new OpenUIInstructions(options?.tracing ?? NOOP_AGENT_TRACING)],\n instructionBuilders: [buildOpenUIDeferredInstruction],\n };\n}\n"],"mappings":"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","names":["dedent"]}
|
|
@@ -215,6 +215,7 @@ function buildOpenUIInstruction(builder) {
|
|
|
215
215
|
OPENUI_IMPORTANT_RULES_TAG,
|
|
216
216
|
dedent`
|
|
217
217
|
- When asked about data, generate realistic/plausible data
|
|
218
|
+
- Prefer OpenUI charts for plot/chart/visualize; images only if downloadable
|
|
218
219
|
- Choose components that best represent the content (tables for comparisons, charts for trends, forms for input, etc.)
|
|
219
220
|
- When you render data in an openui block (tables, charts, KPI cards), do NOT repeat the same numbers/facts in the markdown text outside the block.
|
|
220
221
|
- Text outside the openui block can optionally include:
|
|
@@ -242,7 +243,7 @@ function buildOpenUIInstruction(builder) {
|
|
|
242
243
|
openui.addSection(
|
|
243
244
|
OPENUI_USER_INTERACTION_CHECKLIST_TAG,
|
|
244
245
|
dedent`
|
|
245
|
-
1.
|
|
246
|
+
1. Plot/chart/visualize or UI-heavy beyond markdown? Use openui.
|
|
246
247
|
2. \`\`\`openui\`\`\` fencing must be closed.`
|
|
247
248
|
);
|
|
248
249
|
}
|
|
@@ -268,7 +269,8 @@ function buildOpenUIDeferredInstruction(builder) {
|
|
|
268
269
|
Before writing any \`\`\`openui fence, the Agent MUST call ${GET_OPENUI_INSTRUCTIONS_TOOL_NAME} with arguments {}.
|
|
269
270
|
Do not invent OpenUI syntax or component APIs without loading those instructions.
|
|
270
271
|
|
|
271
|
-
|
|
272
|
+
Prefer OpenUI for plot/chart/visualize over sandbox code; sandbox images only for downloads.
|
|
273
|
+
Otherwise use OpenUI only when UI-heavy beyond markdown.
|
|
272
274
|
`.trim()
|
|
273
275
|
);
|
|
274
276
|
}
|