@truefoundry/trueforge-core 0.1.1 → 0.1.2
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/ITurnResourceResolver.d.ts +8 -7
- package/dist/agent-session/ITurnResourceResolver.d.ts.map +1 -1
- package/dist/agent-session/ITurnResourceResolver.js.map +1 -1
- package/dist/agent-session/SessionHandle.d.ts +12 -0
- package/dist/agent-session/SessionHandle.d.ts.map +1 -1
- package/dist/agent-session/SessionHandle.js +74 -33
- package/dist/agent-session/SessionHandle.js.map +1 -1
- package/dist/agent-session/SessionHandle.mjs +74 -33
- package/dist/agent-session/SessionHandle.mjs.map +1 -1
- package/dist/agent-session/TurnResourceResolver.d.ts +3 -8
- package/dist/agent-session/TurnResourceResolver.d.ts.map +1 -1
- package/dist/agent-session/TurnResourceResolver.js.map +1 -1
- package/dist/agent-session/TurnResourceResolver.mjs.map +1 -1
- package/dist/agent-session/store/ISessionStore.d.ts +7 -6
- package/dist/agent-session/store/ISessionStore.d.ts.map +1 -1
- package/dist/agent-session/store/ISessionStore.js.map +1 -1
- package/dist/agent-session/store/InMemorySessionStore.js +1 -2
- package/dist/agent-session/store/InMemorySessionStore.js.map +1 -1
- package/dist/agent-session/store/InMemorySessionStore.mjs +1 -2
- package/dist/agent-session/store/InMemorySessionStore.mjs.map +1 -1
- package/dist/core/runtime/AgentThread.d.ts.map +1 -1
- package/dist/core/runtime/AgentThread.js +0 -3
- package/dist/core/runtime/AgentThread.js.map +1 -1
- package/dist/core/runtime/AgentThread.mjs +0 -3
- package/dist/core/runtime/AgentThread.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -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 } from './ITurnResourceResolver';\nimport type { SessionRecord } from './models/SessionRecord';\nimport { MAIN_THREAD_ID, type TurnRecord } 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;\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(): TurnDoneEvent {\n return {\n type: EventType.TURN_DONE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n state: {\n status: 'cancelled',\n reason: CancellationReason.CancelledForNextTurn,\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\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 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.store.freezeAndGetTurn({\n session_id: this.session.session_id,\n turn_id: previousTurnId,\n turn_done_event: cancelledTurnDoneEvent(),\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 agentThreads = await this.buildThreads({\n previous,\n resolver: input.resolver,\n spec,\n sandbox,\n tracing,\n signal: input.signal,\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 /** 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 buildThreads(input: {\n previous: TurnRecord<TTurnCustom> | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n signal: AbortSignal;\n }): Promise<Map<string, AgentThread>> {\n const snapshots = input.previous?.snapshot.threads;\n const threadIds = snapshots ? Object.keys(snapshots) : [MAIN_THREAD_ID];\n const map = new Map<string, AgentThread>();\n for (const threadId of threadIds) {\n const data = snapshots?.[threadId];\n map.set(\n threadId,\n await this.buildThread({\n threadId,\n data,\n resolver: input.resolver,\n previous: input.previous,\n spec: input.spec,\n sandbox: input.sandbox,\n tracing: input.tracing,\n signal: input.signal,\n }),\n );\n }\n return map;\n }\n\n private async buildThread(input: {\n threadId: string;\n data?: AgentThreadSnapshot | undefined;\n resolver: ITurnResourceResolver<TTurnCustom>;\n previous: TurnRecord<TTurnCustom> | undefined;\n spec: AgentSpec;\n sandbox: Sandbox | undefined;\n tracing: AgentTracing;\n signal: AbortSignal;\n }): Promise<AgentThread> {\n const { definition, extraCapabilities } = await input.resolver.resolveAgentDefinition({\n spec: input.spec,\n thread_id: input.threadId,\n agent_info: input.data?.agent_info ?? undefined,\n previousTurn: input.previous,\n signal: input.signal,\n tracing: input.tracing,\n });\n const isChild = Boolean(input.data?.parent);\n const capabilities = [\n ...builtinsFromSpec({\n spec: input.spec,\n definition,\n isChild,\n sandboxAvailable: Boolean(input.sandbox),\n tracing: input.tracing,\n logger: input.resolver.logger,\n }),\n ...(extraCapabilities ?? []),\n ];\n return new AgentThread({\n definition,\n threadId: input.threadId,\n title: input.data?.agent_info?.name ?? (isChild ? input.threadId : 'main'),\n sandbox: input.sandbox,\n context: input.data?.context,\n currentContextUsage: input.data?.current_context_usage,\n parent: input.data?.parent ?? undefined,\n agentInfo: input.data?.agent_info ?? undefined,\n preComputedCompletion: input.data?.completion ?? undefined,\n capabilities,\n capabilityState: input.data?.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 thread_id: params.threadId,\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 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 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 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 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,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,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,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,13 +1,12 @@
|
|
|
1
1
|
import type { Logger } from 'winston';
|
|
2
|
-
import type { AgentCapability } from '../core/capabilities/AgentCapability';
|
|
3
2
|
import type { ILLM } from '../core/llm/ILLM';
|
|
4
3
|
import type { ToolSource } from '../core/mcp/IMCPServer';
|
|
5
4
|
import { type RemoteMcpHeaders } from '../core/mcp/RemoteMCP';
|
|
6
|
-
import type {
|
|
5
|
+
import type { ModelParams } from '../core/runtime/AgentDefinition';
|
|
7
6
|
import type { AgentInfo } from '../core/runtime/AgentThread.types';
|
|
8
7
|
import type { Sandbox, SandboxInfo } from '../core/sandbox/Sandbox';
|
|
9
8
|
import type { AgentTracing } from '../core/tracing/AgentTracing';
|
|
10
|
-
import type { ITurnResourceResolver } from './ITurnResourceResolver';
|
|
9
|
+
import type { ITurnResourceResolver, ResolvedAgentDefinition } from './ITurnResourceResolver';
|
|
11
10
|
import type { TurnRecord } from './models/TurnRecord';
|
|
12
11
|
import type { AgentSpec } from './schemas/agentSpec';
|
|
13
12
|
/**
|
|
@@ -129,15 +128,11 @@ export declare class TurnResourceResolver<TTurnCustom extends object = Record<st
|
|
|
129
128
|
*/
|
|
130
129
|
resolveAgentDefinition(input: {
|
|
131
130
|
spec: AgentSpec;
|
|
132
|
-
thread_id: string;
|
|
133
131
|
agent_info?: AgentInfo | undefined;
|
|
134
132
|
previousTurn?: TurnRecord<TTurnCustom> | undefined;
|
|
135
133
|
signal: AbortSignal;
|
|
136
134
|
tracing: AgentTracing;
|
|
137
|
-
}): Promise<
|
|
138
|
-
definition: AgentDefinition;
|
|
139
|
-
extraCapabilities?: AgentCapability[] | undefined;
|
|
140
|
-
}>;
|
|
135
|
+
}): Promise<ResolvedAgentDefinition>;
|
|
141
136
|
/**
|
|
142
137
|
* Returns the tool source for `id`, creating it on first call — use from
|
|
143
138
|
* resolveAgentDefinition overrides so agents sharing a server share one
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TurnResourceResolver.d.ts","sourceRoot":"","sources":["../../src/agent-session/TurnResourceResolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"TurnResourceResolver.d.ts","sourceRoot":"","sources":["../../src/agent-session/TurnResourceResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/agent-session/TurnResourceResolver.ts"],"sourcesContent":["import type { Logger } from 'winston';\nimport type { AgentCapability } from '../core/capabilities/AgentCapability';\nimport type { ILLM } from '../core/llm/ILLM';\nimport type { ToolSource } from '../core/mcp/IMCPServer';\nimport { RemoteMCP, type RemoteMcpHeaders } from '../core/mcp/RemoteMCP';\nimport type { ToolSelectorConfig } from '../core/mcp/ToolSelectorPolicy';\nimport { ToolSet } from '../core/mcp/ToolSet';\nimport type { AgentDefinition, ModelParams } from '../core/runtime/AgentDefinition';\nimport type { AgentInfo } from '../core/runtime/AgentThread.types';\nimport type { Sandbox, SandboxInfo } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../core/tracing/NoopAgentTracing';\nimport type { ITurnResourceResolver } from './ITurnResourceResolver';\nimport type { TurnRecord } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\n\n/**\n * Factory that creates a Sandbox handle for a run (reattach via\n * existingSandboxId). `spec` carries the sandbox-relevant agent settings\n * (e.g. config.sandbox.file_downloads) so implementations can shape the\n * Sandbox per run without the factory type growing a field per option.\n */\nexport type TurnSandboxFactory = (input: {\n spec: AgentSpec;\n existingSandboxId?: string | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n}) => Promise<Sandbox>;\n\nfunction specWantsSandbox(spec: AgentSpec): boolean {\n return spec.config.sandbox.enabled;\n}\n\nfunction toSelectors(entry: {\n enable_tools: string[];\n disable_tools: string[];\n preload_tools: string[];\n require_approval_for_tools: string[];\n}): ToolSelectorConfig {\n return {\n enableTools: entry.enable_tools,\n disableTools: entry.disable_tools,\n preloadTools: entry.preload_tools,\n requireApprovalForTools: entry.require_approval_for_tools,\n };\n}\n\n/**\n * Batteries-included base implementation. Construct-and-go for the default\n * behavior; subclass and override to customize (tool sources, sandbox,\n * tracing).\n */\nexport class TurnResourceResolver<\n TTurnCustom extends object = Record<string, never>,\n> implements ITurnResourceResolver<TTurnCustom> {\n readonly #sources = new Map<string, Promise<ToolSource>>();\n #sandbox?: Sandbox | undefined;\n\n constructor(\n protected readonly deps: {\n /** Model name → client and defaults. Called once per resolved definition; may load provider config. */\n llm: (model: string) => Promise<{\n modelClient: ILLM;\n defaultModelParams: ModelParams;\n }>;\n /**\n * MCP server name → connection details. Required to use spec.mcp_servers:\n * the AgentSpec carries names only (no url/headers on the wire) — the\n * runtime supplies the catalog. Called once per distinct server name per\n * turn. Throw for unknown names. `headers` supports the async resolver form.\n */\n mcp: (name: string) => Promise<{ url: string; headers?: RemoteMcpHeaders }>;\n mcpRequestTimeoutMs: number;\n mcpConnectTimeoutMs: number;\n /** One sandbox type per runtime. Omit = no sandbox support. */\n sandboxProvider?: TurnSandboxFactory | undefined;\n /**\n * Named-agent lookup (registry id → live AgentSpec). Required when a\n * session is bound by reference; omit only if all sessions use inline agents.\n */\n agent?: ((agentId: string) => Promise<AgentSpec>) | undefined;\n /** Forwarded to RemoteMCP / AgentThread (required by their constructors). */\n logger: Logger;\n },\n ) {}\n\n get logger(): Logger {\n return this.deps.logger;\n }\n\n /** Default: no-op tracing. Override to plug in a real tracer. */\n createTracing(): AgentTracing {\n return NOOP_AGENT_TRACING;\n }\n\n /** Named (ref) session agent → live registry lookup via deps.agent. */\n async resolveAgentSpec(input: { agent_id: string }): Promise<AgentSpec> {\n if (this.deps.agent === undefined) {\n // Host forgot to wire deps.agent — not \"agent id missing from the registry\"\n // (that failure belongs in the lookup callback, e.g. HTTP 422 on the server).\n throw new Error(\n `Named agent '${input.agent_id}' cannot be resolved: no agent lookup configured on the turn resolver`,\n );\n }\n return await this.deps.agent(input.agent_id);\n }\n\n /**\n * Default: creates a sandbox iff a provider is configured AND the spec wants\n * one; reattaches to the previous turn's VM via `existing.sandbox_id` when\n * present. Overrides that resolve their own sandbox must assign it so\n * close() can release it (or override close() too).\n */\n async resolveSandbox(input: {\n spec: AgentSpec;\n existing?: SandboxInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<Sandbox | undefined> {\n if (!this.deps.sandboxProvider || !specWantsSandbox(input.spec)) {\n return undefined;\n }\n this.#sandbox = await this.deps.sandboxProvider({\n spec: input.spec,\n existingSandboxId: input.existing?.sandbox_id,\n signal: input.signal,\n tracing: input.tracing,\n });\n return this.#sandbox;\n }\n\n /**\n * Closes the sandbox HANDLE if one was resolved. This releases only this\n * process's connection (local bridge); the sandbox VM keeps running and the\n * next turn reattaches via `existing.sandbox_id`.\n *\n * Tool sources (MCP connections) are intentionally NOT closed: the run's\n * AbortSignal already aborts their in-flight calls, and connections are\n * per-run objects that are simply dropped. If deterministic MCP socket\n * release is ever needed, add it here — no contract change required.\n *\n * Subclasses that acquire additional resources MUST override, release\n * their own resources best-effort, and call `await super.close()`.\n * Idempotent; never throws.\n */\n async close(): Promise<void> {\n const sandbox = this.#sandbox;\n this.#sandbox = undefined;\n await sandbox?.close().catch(() => {\n /* no-op */\n });\n }\n\n /**\n * Default: maps the spec directly to a definition — spec.mcp_servers carry\n * names only; deps.mcp resolves each name to url/headers, and the result\n * becomes a RemoteMCP source (deduped per turn via getOrCreateToolSource)\n * wrapped in a per-agent ToolSet view. Passes the previous turn's persisted\n * MCP session_id into RemoteMCP for cross-turn stateful resume.\n */\n async resolveAgentDefinition(input: {\n spec: AgentSpec;\n thread_id: string;\n agent_info?: AgentInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<{\n definition: AgentDefinition;\n extraCapabilities?: AgentCapability[] | undefined;\n }> {\n const { spec, agent_info: agentInfo, previousTurn, signal, tracing } = input;\n const toolSets = await Promise.all(\n (spec.mcp_servers ?? []).map(async entry => {\n const source = await this.getOrCreateToolSource({\n id: entry.name,\n create: async () => {\n const { url, headers } = await this.deps.mcp(entry.name);\n return new RemoteMCP({\n id: entry.name,\n name: entry.name,\n url,\n headers: headers ?? {},\n sessionId: previousTurn?.snapshot.mcp_servers?.[entry.name]?.session_id,\n requestTimeoutMs: this.deps.mcpRequestTimeoutMs,\n connectTimeoutMs: this.deps.mcpConnectTimeoutMs,\n logger: this.deps.logger,\n tracing,\n signal,\n });\n },\n });\n return new ToolSet({\n source,\n selectors: toSelectors(entry),\n preload: entry.preload,\n });\n }),\n );\n // Sub-agents may request a different catalog model via agent_info.model;\n // resolve that name so modelClient matches the override (not just a label).\n const modelName = agentInfo?.model ?? spec.model.name;\n const resolvedModel = await this.deps.llm(modelName);\n return {\n definition: {\n modelClient: resolvedModel.modelClient,\n // Sub-agents receive the delegated task as a user message; their system\n // prompt is SUB_AGENT_IDENTITY (added by AgentThread), not user instructions.\n instruction: agentInfo ? undefined : spec.instructions,\n messages: agentInfo\n ? [{ role: 'user' as const, content: agentInfo.input }]\n : spec.messages?.map(m => ({\n role: 'user' as const,\n content: m.content,\n })),\n modelParams: {\n ...resolvedModel.defaultModelParams,\n ...spec.model.params,\n },\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: agentInfo ? undefined : spec.response_format,\n iterationLimit: spec.config.iteration_limit,\n toolSets,\n },\n };\n }\n\n /**\n * Returns the tool source for `id`, creating it on first call — use from\n * resolveAgentDefinition overrides so agents sharing a server share one\n * connection. Single-flight by id: the promise is stored synchronously (no\n * await between get and set), so overlapping resolveAgentDefinition calls\n * can never double-create. Rejections stay cached: one attempt per turn.\n * Do not override.\n */\n protected getOrCreateToolSource(input: { id: string; create: () => Promise<ToolSource> }): Promise<ToolSource> {\n const cached = this.#sources.get(input.id);\n if (cached) {\n return cached;\n }\n const made = input.create();\n this.#sources.set(input.id, made);\n return made;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/agent-session/TurnResourceResolver.ts"],"sourcesContent":["import type { Logger } from 'winston';\nimport type { ILLM } from '../core/llm/ILLM';\nimport type { ToolSource } from '../core/mcp/IMCPServer';\nimport { RemoteMCP, type RemoteMcpHeaders } from '../core/mcp/RemoteMCP';\nimport type { ToolSelectorConfig } from '../core/mcp/ToolSelectorPolicy';\nimport { ToolSet } from '../core/mcp/ToolSet';\nimport type { ModelParams } from '../core/runtime/AgentDefinition';\nimport type { AgentInfo } from '../core/runtime/AgentThread.types';\nimport type { Sandbox, SandboxInfo } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../core/tracing/NoopAgentTracing';\nimport type { ITurnResourceResolver, ResolvedAgentDefinition } from './ITurnResourceResolver';\nimport type { TurnRecord } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\n\n/**\n * Factory that creates a Sandbox handle for a run (reattach via\n * existingSandboxId). `spec` carries the sandbox-relevant agent settings\n * (e.g. config.sandbox.file_downloads) so implementations can shape the\n * Sandbox per run without the factory type growing a field per option.\n */\nexport type TurnSandboxFactory = (input: {\n spec: AgentSpec;\n existingSandboxId?: string | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n}) => Promise<Sandbox>;\n\nfunction specWantsSandbox(spec: AgentSpec): boolean {\n return spec.config.sandbox.enabled;\n}\n\nfunction toSelectors(entry: {\n enable_tools: string[];\n disable_tools: string[];\n preload_tools: string[];\n require_approval_for_tools: string[];\n}): ToolSelectorConfig {\n return {\n enableTools: entry.enable_tools,\n disableTools: entry.disable_tools,\n preloadTools: entry.preload_tools,\n requireApprovalForTools: entry.require_approval_for_tools,\n };\n}\n\n/**\n * Batteries-included base implementation. Construct-and-go for the default\n * behavior; subclass and override to customize (tool sources, sandbox,\n * tracing).\n */\nexport class TurnResourceResolver<\n TTurnCustom extends object = Record<string, never>,\n> implements ITurnResourceResolver<TTurnCustom> {\n readonly #sources = new Map<string, Promise<ToolSource>>();\n #sandbox?: Sandbox | undefined;\n\n constructor(\n protected readonly deps: {\n /** Model name → client and defaults. Called once per resolved definition; may load provider config. */\n llm: (model: string) => Promise<{\n modelClient: ILLM;\n defaultModelParams: ModelParams;\n }>;\n /**\n * MCP server name → connection details. Required to use spec.mcp_servers:\n * the AgentSpec carries names only (no url/headers on the wire) — the\n * runtime supplies the catalog. Called once per distinct server name per\n * turn. Throw for unknown names. `headers` supports the async resolver form.\n */\n mcp: (name: string) => Promise<{ url: string; headers?: RemoteMcpHeaders }>;\n mcpRequestTimeoutMs: number;\n mcpConnectTimeoutMs: number;\n /** One sandbox type per runtime. Omit = no sandbox support. */\n sandboxProvider?: TurnSandboxFactory | undefined;\n /**\n * Named-agent lookup (registry id → live AgentSpec). Required when a\n * session is bound by reference; omit only if all sessions use inline agents.\n */\n agent?: ((agentId: string) => Promise<AgentSpec>) | undefined;\n /** Forwarded to RemoteMCP / AgentThread (required by their constructors). */\n logger: Logger;\n },\n ) {}\n\n get logger(): Logger {\n return this.deps.logger;\n }\n\n /** Default: no-op tracing. Override to plug in a real tracer. */\n createTracing(): AgentTracing {\n return NOOP_AGENT_TRACING;\n }\n\n /** Named (ref) session agent → live registry lookup via deps.agent. */\n async resolveAgentSpec(input: { agent_id: string }): Promise<AgentSpec> {\n if (this.deps.agent === undefined) {\n // Host forgot to wire deps.agent — not \"agent id missing from the registry\"\n // (that failure belongs in the lookup callback, e.g. HTTP 422 on the server).\n throw new Error(\n `Named agent '${input.agent_id}' cannot be resolved: no agent lookup configured on the turn resolver`,\n );\n }\n return await this.deps.agent(input.agent_id);\n }\n\n /**\n * Default: creates a sandbox iff a provider is configured AND the spec wants\n * one; reattaches to the previous turn's VM via `existing.sandbox_id` when\n * present. Overrides that resolve their own sandbox must assign it so\n * close() can release it (or override close() too).\n */\n async resolveSandbox(input: {\n spec: AgentSpec;\n existing?: SandboxInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<Sandbox | undefined> {\n if (!this.deps.sandboxProvider || !specWantsSandbox(input.spec)) {\n return undefined;\n }\n this.#sandbox = await this.deps.sandboxProvider({\n spec: input.spec,\n existingSandboxId: input.existing?.sandbox_id,\n signal: input.signal,\n tracing: input.tracing,\n });\n return this.#sandbox;\n }\n\n /**\n * Closes the sandbox HANDLE if one was resolved. This releases only this\n * process's connection (local bridge); the sandbox VM keeps running and the\n * next turn reattaches via `existing.sandbox_id`.\n *\n * Tool sources (MCP connections) are intentionally NOT closed: the run's\n * AbortSignal already aborts their in-flight calls, and connections are\n * per-run objects that are simply dropped. If deterministic MCP socket\n * release is ever needed, add it here — no contract change required.\n *\n * Subclasses that acquire additional resources MUST override, release\n * their own resources best-effort, and call `await super.close()`.\n * Idempotent; never throws.\n */\n async close(): Promise<void> {\n const sandbox = this.#sandbox;\n this.#sandbox = undefined;\n await sandbox?.close().catch(() => {\n /* no-op */\n });\n }\n\n /**\n * Default: maps the spec directly to a definition — spec.mcp_servers carry\n * names only; deps.mcp resolves each name to url/headers, and the result\n * becomes a RemoteMCP source (deduped per turn via getOrCreateToolSource)\n * wrapped in a per-agent ToolSet view. Passes the previous turn's persisted\n * MCP session_id into RemoteMCP for cross-turn stateful resume.\n */\n async resolveAgentDefinition(input: {\n spec: AgentSpec;\n agent_info?: AgentInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<ResolvedAgentDefinition> {\n const { spec, agent_info: agentInfo, previousTurn, signal, tracing } = input;\n const toolSets = await Promise.all(\n (spec.mcp_servers ?? []).map(async entry => {\n const source = await this.getOrCreateToolSource({\n id: entry.name,\n create: async () => {\n const { url, headers } = await this.deps.mcp(entry.name);\n return new RemoteMCP({\n id: entry.name,\n name: entry.name,\n url,\n headers: headers ?? {},\n sessionId: previousTurn?.snapshot.mcp_servers?.[entry.name]?.session_id,\n requestTimeoutMs: this.deps.mcpRequestTimeoutMs,\n connectTimeoutMs: this.deps.mcpConnectTimeoutMs,\n logger: this.deps.logger,\n tracing,\n signal,\n });\n },\n });\n return new ToolSet({\n source,\n selectors: toSelectors(entry),\n preload: entry.preload,\n });\n }),\n );\n // Sub-agents may request a different catalog model via agent_info.model;\n // resolve that name so modelClient matches the override (not just a label).\n const modelName = agentInfo?.model ?? spec.model.name;\n const resolvedModel = await this.deps.llm(modelName);\n return {\n definition: {\n modelClient: resolvedModel.modelClient,\n // Sub-agents receive the delegated task as a user message; their system\n // prompt is SUB_AGENT_IDENTITY (added by AgentThread), not user instructions.\n instruction: agentInfo ? undefined : spec.instructions,\n messages: agentInfo\n ? [{ role: 'user' as const, content: agentInfo.input }]\n : spec.messages?.map(m => ({\n role: 'user' as const,\n content: m.content,\n })),\n modelParams: {\n ...resolvedModel.defaultModelParams,\n ...spec.model.params,\n },\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: agentInfo ? undefined : spec.response_format,\n iterationLimit: spec.config.iteration_limit,\n toolSets,\n },\n };\n }\n\n /**\n * Returns the tool source for `id`, creating it on first call — use from\n * resolveAgentDefinition overrides so agents sharing a server share one\n * connection. Single-flight by id: the promise is stored synchronously (no\n * await between get and set), so overlapping resolveAgentDefinition calls\n * can never double-create. Rejections stay cached: one attempt per turn.\n * Do not override.\n */\n protected getOrCreateToolSource(input: { id: string; create: () => Promise<ToolSource> }): Promise<ToolSource> {\n const cached = this.#sources.get(input.id);\n if (cached) {\n return cached;\n }\n const made = input.create();\n this.#sources.set(input.id, made);\n return made;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/agent-session/TurnResourceResolver.ts"],"sourcesContent":["import type { Logger } from 'winston';\nimport type { AgentCapability } from '../core/capabilities/AgentCapability';\nimport type { ILLM } from '../core/llm/ILLM';\nimport type { ToolSource } from '../core/mcp/IMCPServer';\nimport { RemoteMCP, type RemoteMcpHeaders } from '../core/mcp/RemoteMCP';\nimport type { ToolSelectorConfig } from '../core/mcp/ToolSelectorPolicy';\nimport { ToolSet } from '../core/mcp/ToolSet';\nimport type { AgentDefinition, ModelParams } from '../core/runtime/AgentDefinition';\nimport type { AgentInfo } from '../core/runtime/AgentThread.types';\nimport type { Sandbox, SandboxInfo } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../core/tracing/NoopAgentTracing';\nimport type { ITurnResourceResolver } from './ITurnResourceResolver';\nimport type { TurnRecord } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\n\n/**\n * Factory that creates a Sandbox handle for a run (reattach via\n * existingSandboxId). `spec` carries the sandbox-relevant agent settings\n * (e.g. config.sandbox.file_downloads) so implementations can shape the\n * Sandbox per run without the factory type growing a field per option.\n */\nexport type TurnSandboxFactory = (input: {\n spec: AgentSpec;\n existingSandboxId?: string | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n}) => Promise<Sandbox>;\n\nfunction specWantsSandbox(spec: AgentSpec): boolean {\n return spec.config.sandbox.enabled;\n}\n\nfunction toSelectors(entry: {\n enable_tools: string[];\n disable_tools: string[];\n preload_tools: string[];\n require_approval_for_tools: string[];\n}): ToolSelectorConfig {\n return {\n enableTools: entry.enable_tools,\n disableTools: entry.disable_tools,\n preloadTools: entry.preload_tools,\n requireApprovalForTools: entry.require_approval_for_tools,\n };\n}\n\n/**\n * Batteries-included base implementation. Construct-and-go for the default\n * behavior; subclass and override to customize (tool sources, sandbox,\n * tracing).\n */\nexport class TurnResourceResolver<\n TTurnCustom extends object = Record<string, never>,\n> implements ITurnResourceResolver<TTurnCustom> {\n readonly #sources = new Map<string, Promise<ToolSource>>();\n #sandbox?: Sandbox | undefined;\n\n constructor(\n protected readonly deps: {\n /** Model name → client and defaults. Called once per resolved definition; may load provider config. */\n llm: (model: string) => Promise<{\n modelClient: ILLM;\n defaultModelParams: ModelParams;\n }>;\n /**\n * MCP server name → connection details. Required to use spec.mcp_servers:\n * the AgentSpec carries names only (no url/headers on the wire) — the\n * runtime supplies the catalog. Called once per distinct server name per\n * turn. Throw for unknown names. `headers` supports the async resolver form.\n */\n mcp: (name: string) => Promise<{ url: string; headers?: RemoteMcpHeaders }>;\n mcpRequestTimeoutMs: number;\n mcpConnectTimeoutMs: number;\n /** One sandbox type per runtime. Omit = no sandbox support. */\n sandboxProvider?: TurnSandboxFactory | undefined;\n /**\n * Named-agent lookup (registry id → live AgentSpec). Required when a\n * session is bound by reference; omit only if all sessions use inline agents.\n */\n agent?: ((agentId: string) => Promise<AgentSpec>) | undefined;\n /** Forwarded to RemoteMCP / AgentThread (required by their constructors). */\n logger: Logger;\n },\n ) {}\n\n get logger(): Logger {\n return this.deps.logger;\n }\n\n /** Default: no-op tracing. Override to plug in a real tracer. */\n createTracing(): AgentTracing {\n return NOOP_AGENT_TRACING;\n }\n\n /** Named (ref) session agent → live registry lookup via deps.agent. */\n async resolveAgentSpec(input: { agent_id: string }): Promise<AgentSpec> {\n if (this.deps.agent === undefined) {\n // Host forgot to wire deps.agent — not \"agent id missing from the registry\"\n // (that failure belongs in the lookup callback, e.g. HTTP 422 on the server).\n throw new Error(\n `Named agent '${input.agent_id}' cannot be resolved: no agent lookup configured on the turn resolver`,\n );\n }\n return await this.deps.agent(input.agent_id);\n }\n\n /**\n * Default: creates a sandbox iff a provider is configured AND the spec wants\n * one; reattaches to the previous turn's VM via `existing.sandbox_id` when\n * present. Overrides that resolve their own sandbox must assign it so\n * close() can release it (or override close() too).\n */\n async resolveSandbox(input: {\n spec: AgentSpec;\n existing?: SandboxInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<Sandbox | undefined> {\n if (!this.deps.sandboxProvider || !specWantsSandbox(input.spec)) {\n return undefined;\n }\n this.#sandbox = await this.deps.sandboxProvider({\n spec: input.spec,\n existingSandboxId: input.existing?.sandbox_id,\n signal: input.signal,\n tracing: input.tracing,\n });\n return this.#sandbox;\n }\n\n /**\n * Closes the sandbox HANDLE if one was resolved. This releases only this\n * process's connection (local bridge); the sandbox VM keeps running and the\n * next turn reattaches via `existing.sandbox_id`.\n *\n * Tool sources (MCP connections) are intentionally NOT closed: the run's\n * AbortSignal already aborts their in-flight calls, and connections are\n * per-run objects that are simply dropped. If deterministic MCP socket\n * release is ever needed, add it here — no contract change required.\n *\n * Subclasses that acquire additional resources MUST override, release\n * their own resources best-effort, and call `await super.close()`.\n * Idempotent; never throws.\n */\n async close(): Promise<void> {\n const sandbox = this.#sandbox;\n this.#sandbox = undefined;\n await sandbox?.close().catch(() => {\n /* no-op */\n });\n }\n\n /**\n * Default: maps the spec directly to a definition — spec.mcp_servers carry\n * names only; deps.mcp resolves each name to url/headers, and the result\n * becomes a RemoteMCP source (deduped per turn via getOrCreateToolSource)\n * wrapped in a per-agent ToolSet view. Passes the previous turn's persisted\n * MCP session_id into RemoteMCP for cross-turn stateful resume.\n */\n async resolveAgentDefinition(input: {\n spec: AgentSpec;\n thread_id: string;\n agent_info?: AgentInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<{\n definition: AgentDefinition;\n extraCapabilities?: AgentCapability[] | undefined;\n }> {\n const { spec, agent_info: agentInfo, previousTurn, signal, tracing } = input;\n const toolSets = await Promise.all(\n (spec.mcp_servers ?? []).map(async entry => {\n const source = await this.getOrCreateToolSource({\n id: entry.name,\n create: async () => {\n const { url, headers } = await this.deps.mcp(entry.name);\n return new RemoteMCP({\n id: entry.name,\n name: entry.name,\n url,\n headers: headers ?? {},\n sessionId: previousTurn?.snapshot.mcp_servers?.[entry.name]?.session_id,\n requestTimeoutMs: this.deps.mcpRequestTimeoutMs,\n connectTimeoutMs: this.deps.mcpConnectTimeoutMs,\n logger: this.deps.logger,\n tracing,\n signal,\n });\n },\n });\n return new ToolSet({\n source,\n selectors: toSelectors(entry),\n preload: entry.preload,\n });\n }),\n );\n // Sub-agents may request a different catalog model via agent_info.model;\n // resolve that name so modelClient matches the override (not just a label).\n const modelName = agentInfo?.model ?? spec.model.name;\n const resolvedModel = await this.deps.llm(modelName);\n return {\n definition: {\n modelClient: resolvedModel.modelClient,\n // Sub-agents receive the delegated task as a user message; their system\n // prompt is SUB_AGENT_IDENTITY (added by AgentThread), not user instructions.\n instruction: agentInfo ? undefined : spec.instructions,\n messages: agentInfo\n ? [{ role: 'user' as const, content: agentInfo.input }]\n : spec.messages?.map(m => ({\n role: 'user' as const,\n content: m.content,\n })),\n modelParams: {\n ...resolvedModel.defaultModelParams,\n ...spec.model.params,\n },\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: agentInfo ? undefined : spec.response_format,\n iterationLimit: spec.config.iteration_limit,\n toolSets,\n },\n };\n }\n\n /**\n * Returns the tool source for `id`, creating it on first call — use from\n * resolveAgentDefinition overrides so agents sharing a server share one\n * connection. Single-flight by id: the promise is stored synchronously (no\n * await between get and set), so overlapping resolveAgentDefinition calls\n * can never double-create. Rejections stay cached: one attempt per turn.\n * Do not override.\n */\n protected getOrCreateToolSource(input: { id: string; create: () => Promise<ToolSource> }): Promise<ToolSource> {\n const cached = this.#sources.get(input.id);\n if (cached) {\n return cached;\n }\n const made = input.create();\n this.#sources.set(input.id, made);\n return made;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/agent-session/TurnResourceResolver.ts"],"sourcesContent":["import type { Logger } from 'winston';\nimport type { ILLM } from '../core/llm/ILLM';\nimport type { ToolSource } from '../core/mcp/IMCPServer';\nimport { RemoteMCP, type RemoteMcpHeaders } from '../core/mcp/RemoteMCP';\nimport type { ToolSelectorConfig } from '../core/mcp/ToolSelectorPolicy';\nimport { ToolSet } from '../core/mcp/ToolSet';\nimport type { ModelParams } from '../core/runtime/AgentDefinition';\nimport type { AgentInfo } from '../core/runtime/AgentThread.types';\nimport type { Sandbox, SandboxInfo } from '../core/sandbox/Sandbox';\nimport type { AgentTracing } from '../core/tracing/AgentTracing';\nimport { NOOP_AGENT_TRACING } from '../core/tracing/NoopAgentTracing';\nimport type { ITurnResourceResolver, ResolvedAgentDefinition } from './ITurnResourceResolver';\nimport type { TurnRecord } from './models/TurnRecord';\nimport type { AgentSpec } from './schemas/agentSpec';\n\n/**\n * Factory that creates a Sandbox handle for a run (reattach via\n * existingSandboxId). `spec` carries the sandbox-relevant agent settings\n * (e.g. config.sandbox.file_downloads) so implementations can shape the\n * Sandbox per run without the factory type growing a field per option.\n */\nexport type TurnSandboxFactory = (input: {\n spec: AgentSpec;\n existingSandboxId?: string | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n}) => Promise<Sandbox>;\n\nfunction specWantsSandbox(spec: AgentSpec): boolean {\n return spec.config.sandbox.enabled;\n}\n\nfunction toSelectors(entry: {\n enable_tools: string[];\n disable_tools: string[];\n preload_tools: string[];\n require_approval_for_tools: string[];\n}): ToolSelectorConfig {\n return {\n enableTools: entry.enable_tools,\n disableTools: entry.disable_tools,\n preloadTools: entry.preload_tools,\n requireApprovalForTools: entry.require_approval_for_tools,\n };\n}\n\n/**\n * Batteries-included base implementation. Construct-and-go for the default\n * behavior; subclass and override to customize (tool sources, sandbox,\n * tracing).\n */\nexport class TurnResourceResolver<\n TTurnCustom extends object = Record<string, never>,\n> implements ITurnResourceResolver<TTurnCustom> {\n readonly #sources = new Map<string, Promise<ToolSource>>();\n #sandbox?: Sandbox | undefined;\n\n constructor(\n protected readonly deps: {\n /** Model name → client and defaults. Called once per resolved definition; may load provider config. */\n llm: (model: string) => Promise<{\n modelClient: ILLM;\n defaultModelParams: ModelParams;\n }>;\n /**\n * MCP server name → connection details. Required to use spec.mcp_servers:\n * the AgentSpec carries names only (no url/headers on the wire) — the\n * runtime supplies the catalog. Called once per distinct server name per\n * turn. Throw for unknown names. `headers` supports the async resolver form.\n */\n mcp: (name: string) => Promise<{ url: string; headers?: RemoteMcpHeaders }>;\n mcpRequestTimeoutMs: number;\n mcpConnectTimeoutMs: number;\n /** One sandbox type per runtime. Omit = no sandbox support. */\n sandboxProvider?: TurnSandboxFactory | undefined;\n /**\n * Named-agent lookup (registry id → live AgentSpec). Required when a\n * session is bound by reference; omit only if all sessions use inline agents.\n */\n agent?: ((agentId: string) => Promise<AgentSpec>) | undefined;\n /** Forwarded to RemoteMCP / AgentThread (required by their constructors). */\n logger: Logger;\n },\n ) {}\n\n get logger(): Logger {\n return this.deps.logger;\n }\n\n /** Default: no-op tracing. Override to plug in a real tracer. */\n createTracing(): AgentTracing {\n return NOOP_AGENT_TRACING;\n }\n\n /** Named (ref) session agent → live registry lookup via deps.agent. */\n async resolveAgentSpec(input: { agent_id: string }): Promise<AgentSpec> {\n if (this.deps.agent === undefined) {\n // Host forgot to wire deps.agent — not \"agent id missing from the registry\"\n // (that failure belongs in the lookup callback, e.g. HTTP 422 on the server).\n throw new Error(\n `Named agent '${input.agent_id}' cannot be resolved: no agent lookup configured on the turn resolver`,\n );\n }\n return await this.deps.agent(input.agent_id);\n }\n\n /**\n * Default: creates a sandbox iff a provider is configured AND the spec wants\n * one; reattaches to the previous turn's VM via `existing.sandbox_id` when\n * present. Overrides that resolve their own sandbox must assign it so\n * close() can release it (or override close() too).\n */\n async resolveSandbox(input: {\n spec: AgentSpec;\n existing?: SandboxInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<Sandbox | undefined> {\n if (!this.deps.sandboxProvider || !specWantsSandbox(input.spec)) {\n return undefined;\n }\n this.#sandbox = await this.deps.sandboxProvider({\n spec: input.spec,\n existingSandboxId: input.existing?.sandbox_id,\n signal: input.signal,\n tracing: input.tracing,\n });\n return this.#sandbox;\n }\n\n /**\n * Closes the sandbox HANDLE if one was resolved. This releases only this\n * process's connection (local bridge); the sandbox VM keeps running and the\n * next turn reattaches via `existing.sandbox_id`.\n *\n * Tool sources (MCP connections) are intentionally NOT closed: the run's\n * AbortSignal already aborts their in-flight calls, and connections are\n * per-run objects that are simply dropped. If deterministic MCP socket\n * release is ever needed, add it here — no contract change required.\n *\n * Subclasses that acquire additional resources MUST override, release\n * their own resources best-effort, and call `await super.close()`.\n * Idempotent; never throws.\n */\n async close(): Promise<void> {\n const sandbox = this.#sandbox;\n this.#sandbox = undefined;\n await sandbox?.close().catch(() => {\n /* no-op */\n });\n }\n\n /**\n * Default: maps the spec directly to a definition — spec.mcp_servers carry\n * names only; deps.mcp resolves each name to url/headers, and the result\n * becomes a RemoteMCP source (deduped per turn via getOrCreateToolSource)\n * wrapped in a per-agent ToolSet view. Passes the previous turn's persisted\n * MCP session_id into RemoteMCP for cross-turn stateful resume.\n */\n async resolveAgentDefinition(input: {\n spec: AgentSpec;\n agent_info?: AgentInfo | undefined;\n previousTurn?: TurnRecord<TTurnCustom> | undefined;\n signal: AbortSignal;\n tracing: AgentTracing;\n }): Promise<ResolvedAgentDefinition> {\n const { spec, agent_info: agentInfo, previousTurn, signal, tracing } = input;\n const toolSets = await Promise.all(\n (spec.mcp_servers ?? []).map(async entry => {\n const source = await this.getOrCreateToolSource({\n id: entry.name,\n create: async () => {\n const { url, headers } = await this.deps.mcp(entry.name);\n return new RemoteMCP({\n id: entry.name,\n name: entry.name,\n url,\n headers: headers ?? {},\n sessionId: previousTurn?.snapshot.mcp_servers?.[entry.name]?.session_id,\n requestTimeoutMs: this.deps.mcpRequestTimeoutMs,\n connectTimeoutMs: this.deps.mcpConnectTimeoutMs,\n logger: this.deps.logger,\n tracing,\n signal,\n });\n },\n });\n return new ToolSet({\n source,\n selectors: toSelectors(entry),\n preload: entry.preload,\n });\n }),\n );\n // Sub-agents may request a different catalog model via agent_info.model;\n // resolve that name so modelClient matches the override (not just a label).\n const modelName = agentInfo?.model ?? spec.model.name;\n const resolvedModel = await this.deps.llm(modelName);\n return {\n definition: {\n modelClient: resolvedModel.modelClient,\n // Sub-agents receive the delegated task as a user message; their system\n // prompt is SUB_AGENT_IDENTITY (added by AgentThread), not user instructions.\n instruction: agentInfo ? undefined : spec.instructions,\n messages: agentInfo\n ? [{ role: 'user' as const, content: agentInfo.input }]\n : spec.messages?.map(m => ({\n role: 'user' as const,\n content: m.content,\n })),\n modelParams: {\n ...resolvedModel.defaultModelParams,\n ...spec.model.params,\n },\n // Sub-agents should return free-form summaries to the parent, not the user-facing structured response.\n responseFormat: agentInfo ? undefined : spec.response_format,\n iterationLimit: spec.config.iteration_limit,\n toolSets,\n },\n };\n }\n\n /**\n * Returns the tool source for `id`, creating it on first call — use from\n * resolveAgentDefinition overrides so agents sharing a server share one\n * connection. Single-flight by id: the promise is stored synchronously (no\n * await between get and set), so overlapping resolveAgentDefinition calls\n * can never double-create. Rejections stay cached: one attempt per turn.\n * Do not override.\n */\n protected getOrCreateToolSource(input: { id: string; create: () => Promise<ToolSource> }): Promise<ToolSource> {\n const cached = this.#sources.get(input.id);\n if (cached) {\n return cached;\n }\n const made = input.create();\n this.#sources.set(input.id, made);\n return made;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,7 +7,7 @@ import type { SessionRecord } from '../models/SessionRecord';
|
|
|
7
7
|
import type { TurnRecord } from '../models/TurnRecord';
|
|
8
8
|
import type { PersistedTurnEvent, SessionEventItem } from '../schemas/events';
|
|
9
9
|
import type { TokenPagination } from '../schemas/pagination';
|
|
10
|
-
import type { TerminalTurnState } from '../schemas/turn';
|
|
10
|
+
import type { CancellationReason, TerminalTurnState } from '../schemas/turn';
|
|
11
11
|
/**
|
|
12
12
|
* Caller-supplied fields for creating a session; the store owns timestamps and tip state.
|
|
13
13
|
* `agent` is a discriminated reference | inline binding.
|
|
@@ -82,6 +82,8 @@ export interface CreateTurnInput<TTurnCustom extends object = Record<string, nev
|
|
|
82
82
|
export interface FreezeAndGetTurnInput {
|
|
83
83
|
session_id: string;
|
|
84
84
|
turn_id: string;
|
|
85
|
+
/** Written onto the turn row when the freeze actually cancels a running turn. */
|
|
86
|
+
reason: CancellationReason;
|
|
85
87
|
/** Caller-built cancelled turn.done event; store persists atomically with state flip when it cancels. */
|
|
86
88
|
turn_done_event: PersistedTurnEvent;
|
|
87
89
|
}
|
|
@@ -232,11 +234,10 @@ export interface ISessionStore<TSessionCustom extends object = Record<string, ne
|
|
|
232
234
|
*/
|
|
233
235
|
createTurn(input: CreateTurnInput<TTurnCustom>): Promise<void>;
|
|
234
236
|
/**
|
|
235
|
-
* One tx: (a) conditionally cancel a running turn with
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
* {@link TurnNotFoundError}.
|
|
237
|
+
* One tx: (a) conditionally cancel a running turn with `reason`; (b) if it
|
|
238
|
+
* did cancel, insert the caller-built `turn_done_event` — already-terminal
|
|
239
|
+
* turns skip the event insert; (c) return the now-immutable turn record.
|
|
240
|
+
* Missing turn → {@link TurnNotFoundError}.
|
|
240
241
|
*/
|
|
241
242
|
freezeAndGetTurn(input: FreezeAndGetTurnInput): Promise<TurnRecord<TTurnCustom>>;
|
|
242
243
|
/** Returns the turn record, or undefined if not found in this session. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ISessionStore.d.ts","sourceRoot":"","sources":["../../../src/agent-session/store/ISessionStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,wBAAwB,EACzB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ISessionStore.d.ts","sourceRoot":"","sources":["../../../src/agent-session/store/ISessionStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,wBAAwB,EACzB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE7E;;;GAGG;AACH,MAAM,MAAM,kBAAkB,CAAC,cAAc,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAC1F,aAAa,CAAC,cAAc,CAAC,EAC7B,WAAW,GAAG,YAAY,GAAG,OAAO,GAAG,YAAY,CACpD,GAAG;IACF,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,kBAAkB,CAAC,cAAc,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAC1F,aAAa,CAAC,cAAc,CAAC,EAC7B,WAAW,GAAG,YAAY,CAC3B,GAAG;IACF,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,SAAS,CAAC;IACvF,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;CAC3D,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,uDAAuD;IACvD,eAAe,EAAE,IAAI,GAAG,SAAS,CAAC;IAClC,uDAAuD;IACvD,aAAa,EAAE,IAAI,GAAG,SAAS,CAAC;IAChC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,wDAAwD;IACxD,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,6EAA6E;AAC7E,MAAM,MAAM,yBAAyB,CAAC,WAAW,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAC9F,UAAU,CAAC,WAAW,CAAC,EACvB,UAAU,CACX,CAAC;AAEF,8FAA8F;AAC9F,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,mBAAmB,EACnB,SAAS,GAAG,uBAAuB,GAAG,YAAY,GAAG,kBAAkB,CACxE,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,mBAAmB,EAAE,WAAW,GAAG,kBAAkB,CAAC,CAAC;AAEpG,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,qBAAqB,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,eAAe,CAAC,WAAW,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IACjF,IAAI,EAAE,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAC7C,iFAAiF;IACjF,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B;;;;;;OAMG;IACH,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;IACzC;;;OAGG;IACH,iBAAiB,EAAE,yBAAyB,EAAE,CAAC;IAC/C,4DAA4D;IAC5D,iCAAiC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,MAAM,EAAE,kBAAkB,CAAC;IAC3B,yGAAyG;IACzG,eAAe,EAAE,kBAAkB,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,iBAAiB,CAAC;IACzB,qFAAqF;IACrF,eAAe,EAAE,kBAAkB,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,qBAAqB,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClD,UAAU,EAAE,wBAAwB,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,2BAA2B,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa,CAC5B,cAAc,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACrD,WAAW,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAElD;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE,wFAAwF;IACxF,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC,CAAC;IAEvF;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE;;;;;;;OAOG;IACH,YAAY,CACV,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC;QAAE,IAAI,EAAE,aAAa,CAAC,cAAc,CAAC,EAAE,CAAC;QAAC,UAAU,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,UAAU,CAAC,KAAK,EAAE,eAAe,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/D;;;;;OAKG;IACH,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IAEjF,0EAA0E;IAC1E,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,CAAC;IAE3E,qFAAqF;IACrF,SAAS,CACP,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC;QAAE,IAAI,EAAE,yBAAyB,CAAC,WAAW,CAAC,EAAE,CAAC;QAAC,UAAU,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAE5F;;;;;;;;;;OAUG;IACH,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D;;;;;;;;OAQG;IACH,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D,4DAA4D;IAC5D,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD,2CAA2C;IAC3C,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD,4FAA4F;IAC5F,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE,uEAAuE;IACvE,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E,uEAAuE;IACvE,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D,6EAA6E;IAC7E,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9D,qEAAqE;IACrE,0BAA0B,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElF,8EAA8E;IAC9E,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC;QAClD,IAAI,EAAE,kBAAkB,EAAE,CAAC;QAC3B,UAAU,EAAE,eAAe,CAAC;KAC7B,CAAC,CAAC;IAEH;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC;QACxD,IAAI,EAAE,gBAAgB,EAAE,CAAC;QACzB,UAAU,EAAE,eAAe,CAAC;KAC7B,CAAC,CAAC;CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/agent-session/store/ISessionStore.ts"],"sourcesContent":["import type { JsonValue } from '../../core/capabilities/AgentCapability';\nimport type { MCPServerInitInfo, ThreadOverwriteContextEvent } from '../../core/events/schema';\nimport type {\n AgentThreadSnapshot,\n ContextMessage,\n SubAgentCompletionMarker,\n} from '../../core/runtime/AgentThread.types';\nimport type { CurrentContextUsage } from '../../core/runtime/contextUsage';\nimport type { SandboxInfo } from '../../core/sandbox/Sandbox';\nimport type { SessionRecord } from '../models/SessionRecord';\nimport type { TurnRecord } from '../models/TurnRecord';\nimport type { PersistedTurnEvent, SessionEventItem } from '../schemas/events';\nimport type { TokenPagination } from '../schemas/pagination';\nimport type { TerminalTurnState } from '../schemas/turn';\n\n/**\n * Caller-supplied fields for creating a session; the store owns timestamps and tip state.\n * `agent` is a discriminated reference | inline binding.\n */\nexport type CreateSessionInput<TSessionCustom extends object = Record<string, never>> = Pick<\n SessionRecord<TSessionCustom>,\n 'tenant_id' | 'session_id' | 'agent' | 'created_by'\n> & {\n custom: TSessionCustom | null;\n};\n\n/**\n * PATCH fields for an existing session; `undefined` fields are left unchanged.\n * `agent` may be set only on inline sessions, and only as an inline arm (`{ type: 'inline', spec }`).\n */\nexport type UpdateSessionInput<TSessionCustom extends object = Record<string, never>> = Pick<\n SessionRecord<TSessionCustom>,\n 'tenant_id' | 'session_id'\n> & {\n agent: Extract<SessionRecord<TSessionCustom>['agent'], { type: 'inline' }> | undefined;\n title: SessionRecord<TSessionCustom>['title'] | undefined;\n};\n\nexport interface GetSessionInput {\n tenant_id: string;\n session_id: string;\n}\n\nexport interface DeleteSessionInput {\n tenant_id: string;\n session_id: string;\n}\n\nexport interface ListSessionsInput {\n tenant_id: string;\n limit: number;\n page_token: string | undefined;\n order: 'asc' | 'desc' | undefined;\n /** Inclusive lower bound on `created_at` (instant). */\n start_timestamp: Date | undefined;\n /** Inclusive upper bound on `created_at` (instant). */\n end_timestamp: Date | undefined;\n /** When set, only sessions bound to this named agent id. */\n agent_id: string | undefined;\n /** When set, only sessions created by this identity. */\n created_by: string | undefined;\n}\n\n/** Turn row fields without assembled snapshot (create input / listTurns). */\nexport type TurnRecordWithoutSnapshot<TTurnCustom extends object = Record<string, never>> = Omit<\n TurnRecord<TTurnCustom>,\n 'snapshot'\n>;\n\n/** Thread registration; mutable per-turn data arrives through dedicated createTurn fields. */\nexport type NewThreadInit = Omit<\n AgentThreadSnapshot,\n 'context' | 'current_context_usage' | 'completion' | 'capability_state'\n>;\n\n/** Full post-send capability map for one thread. */\nexport type ThreadCapabilityStateInit = Pick<AgentThreadSnapshot, 'thread_id' | 'capability_state'>;\n\n/** One drained send() append batch for one thread; writer = the new turn. */\nexport interface TurnContextAppend {\n thread_id: string;\n context: ContextMessage[];\n current_context_usage: CurrentContextUsage | null;\n}\n\nexport interface CreateTurnInput<TTurnCustom extends object = Record<string, never>> {\n turn: TurnRecordWithoutSnapshot<TTurnCustom>;\n /** Threads absent on the previous turn (turn 1: the root thread; else empty). */\n new_threads: NewThreadInit[];\n /**\n * All new messages, for new and carried-forward threads alike — collected by\n * draining orchestrator.send() BEFORE this call. Draining without persisting is\n * safe: send() mutates only in-memory threads, and if createTurn fails the whole\n * in-memory state (orchestrator, threads, resolver) is discarded — so either this\n * turn commits atomically with its appends, or nothing was persisted at all.\n */\n new_context_appends: TurnContextAppend[];\n /**\n * Complete post-send capability maps: exactly one entry per turn thread.\n * Authoritative for this turn; the store does not carry capability rows forward.\n */\n capability_states: ThreadCapabilityStateInit[];\n /** Set only if session.title is NULL (first write wins). */\n update_session_title_if_not_exist: string | null;\n}\n\nexport interface FreezeAndGetTurnInput {\n session_id: string;\n turn_id: string;\n /** Caller-built cancelled turn.done event; store persists atomically with state flip when it cancels. */\n turn_done_event: PersistedTurnEvent;\n}\n\nexport interface GetTurnInput {\n session_id: string;\n turn_id: string;\n}\n\nexport interface ListTurnsInput {\n session_id: string;\n limit: number;\n page_token: string | undefined;\n}\n\nexport interface UpdateTurnStateInput {\n session_id: string;\n turn_id: string;\n state: TerminalTurnState;\n /** Caller-built turn.done; written atomically with the state flip in the same tx. */\n turn_done_event: PersistedTurnEvent;\n}\n\nexport interface AppendToEventsInput {\n session_id: string;\n turn_id: string;\n events: PersistedTurnEvent[];\n}\n\nexport interface AddThreadsInput {\n session_id: string;\n turn_id: string;\n threads: AgentThreadSnapshot[];\n}\n\nexport interface RemoveThreadsInput {\n session_id: string;\n turn_id: string;\n thread_ids: string[];\n}\n\nexport interface AppendToThreadContextInput {\n session_id: string;\n turn_id: string;\n thread_id: string;\n context: ContextMessage[];\n current_context_usage: CurrentContextUsage | null;\n completion: SubAgentCompletionMarker | null;\n}\n\nexport interface OverwriteThreadContextInput {\n session_id: string;\n turn_id: string;\n event: ThreadOverwriteContextEvent;\n}\n\nexport interface PatchMCPServersInput {\n session_id: string;\n turn_id: string;\n mcp_servers: MCPServerInitInfo[];\n}\n\nexport interface PatchSandboxInfoInput {\n session_id: string;\n turn_id: string;\n sandbox_info: SandboxInfo;\n}\n\nexport interface PatchThreadCapabilityStateInput {\n session_id: string;\n turn_id: string;\n thread_id: string;\n key: string;\n state: JsonValue;\n}\n\nexport interface ListTurnEventsInput {\n session_id: string;\n turn_id: string;\n limit: number;\n page_token: string | undefined;\n order: 'asc' | 'desc' | undefined;\n}\n\nexport interface ListSessionEventsInput {\n session_id: string;\n limit: number;\n page_token: string | undefined;\n last_turn_id: string | undefined;\n}\n\n/**\n * Session/turn persistence contract. Pure durability: no streaming, SSE, or\n * subscription members. Callers authorize the parent session before using\n * turn-scoped operations, which rely on globally unique session_id values.\n * Capability maps are initialized atomically by createTurn and subsequently\n * updated through patchThreadCapabilityState. Agent binding is session-scoped\n * as a discriminated `agent` (ref | value); named agents are not hydrated on read.\n */\nexport interface ISessionStore<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> {\n /**\n * Persists a discriminated `agent` (ref | value). SQL backends may flatten to columns.\n * `session_id` is globally unique across tenants.\n * Persists caller-supplied `created_by` (immutable after create).\n * Sets `last_activity_timestamp_ms` (= now) on create.\n */\n createSession(input: CreateSessionInput<TSessionCustom>): Promise<void>;\n\n /** Permanently removes a session and all related data; missing sessions are a no-op. */\n deleteSession(input: DeleteSessionInput): Promise<void>;\n\n /**\n * Returns the session as stored (ref agents are not hydrated to a value).\n * Does **not** bump `last_activity_timestamp_ms` (read path).\n */\n getSession(input: GetSessionInput): Promise<SessionRecord<TSessionCustom> | undefined>;\n\n /**\n * PATCH semantics — update only the provided fields:\n * - agent: replace inline binding (inline sessions only; reference → invariant error).\n * - title: set/replace the session title.\n * Bumps `last_activity_timestamp_ms` (= now) in the same update.\n */\n updateSession(input: UpdateSessionInput<TSessionCustom>): Promise<void>;\n\n /**\n * Paginated list of the tenant's sessions ordered by `updated_at`\n * (`order` defaults to `desc`, `session_id` tie-break). `page_token` is a\n * keyset cursor on `(updated_at, session_id)`. `start_timestamp` /\n * `end_timestamp` are inclusive instant bounds on `created_at`. Optional\n * `agent_id` filters ref-bound sessions; optional `created_by` filters by\n * creator identity. Does **not** bump `last_activity_timestamp_ms` (read path).\n */\n listSessions(\n input: ListSessionsInput,\n ): Promise<{ data: SessionRecord<TSessionCustom>[]; pagination: TokenPagination }>;\n\n /**\n * Creates the turn AND advances `session.last_turn_id`. Context merging is the\n * store's responsibility: `new_context_appends` and `new_threads` are applied\n * on top of the previous turn's snapshot when `turn.previous_turn_id` is set.\n * `capability_states` is the complete authoritative map for every resulting\n * thread and is persisted directly without store-side carry-forward.\n *\n * Atomicity (store contract): insert turn + set `last_turn_id` (+ session\n * turn-list append if the backend has one) MUST be one atomic unit per\n * session. Concurrent createTurn on the same session must not drop a turn\n * row or leave `last_turn_id` pointing at a turn that was never created.\n * The implementation supplies the mechanism (session lock, row lock/tx, …).\n *\n * Also bumps `session.last_activity_timestamp_ms` in that same atomic unit.\n *\n * Fork semantics for `turn.previous_turn_id`:\n * - `null` — new root turn (no parent); always allowed.\n * - string — fork/chain from that turn when it exists. Tip-equality is NOT\n * required; concurrent forks from the same tip both succeed. Unknown id is\n * allowed (relaxed) and treated as no inheritance. If that turn exists and\n * is still `running`, reject with {@link PreviousTurnRunningError} —\n * callers must {@link freezeAndGetTurn} first.\n * `last_turn_id` always advances to the new turn in the same atomic unit.\n *\n * `update_session_title_if_not_exist`: when set AND `session.title` is\n * unset/null, set it in the same atomic unit; an existing title is NEVER\n * overwritten (first write wins). The caller derives the value; the store\n * only conditionally sets it.\n */\n createTurn(input: CreateTurnInput<TTurnCustom>): Promise<void>;\n\n /**\n * One tx: (a) conditionally cancel a running turn with\n * {@link CancellationReason.CancelledForNextTurn}; (b) if it did cancel,\n * insert the caller-built `turn_done_event` — already-terminal turns skip the\n * event insert; (c) return the now-immutable turn record. Missing turn →\n * {@link TurnNotFoundError}.\n */\n freezeAndGetTurn(input: FreezeAndGetTurnInput): Promise<TurnRecord<TTurnCustom>>;\n\n /** Returns the turn record, or undefined if not found in this session. */\n getTurn(input: GetTurnInput): Promise<TurnRecord<TTurnCustom> | undefined>;\n\n /** Paginated list of turn rows (no snapshot); use getTurn for assembled snapshot. */\n listTurns(\n input: ListTurnsInput,\n ): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }>;\n\n /**\n * Writes the terminal state and `turn_done_event` atomically. Store contract —\n * **first terminal write wins**:\n * - Allowed: `running` → `done` | `cancelled` | `error`.\n * - Rejected with **409** (or equivalent conflict): any write when status is already\n * terminal — including done→cancelled, cancelled→done, error→*, terminal→running.\n * - Missing turn → 404 / not-found.\n *\n * Check under the same concurrency control as other turn mutations (lock/CAS) —\n * not a racy read-then-write outside the critical section.\n */\n updateTurnState(input: UpdateTurnStateInput): Promise<void>;\n\n /**\n * Durable event log for the turn. MUST include lifecycle rows: a\n * `TurnCreatedEvent` at the start of the stream and a terminal `TurnDoneEvent`\n * (or its cancelled/error shape) at the end. Every turn written through this\n * API persists lifecycle in the stream — implementations never synthesize\n * missing created/done rows on read. Every event MUST carry `id` and\n * `created_at`; `id` is a monotonic ULID and is the primary within-turn sort\n * key. `created_at` records event creation time but is not the order key.\n */\n appendToEvents(input: AppendToEventsInput): Promise<void>;\n\n /** Adds thread snapshots to the turn (sub-agent spawns). */\n addThreads(input: AddThreadsInput): Promise<void>;\n\n /** Removes threads from the turn by id. */\n removeThreads(input: RemoveThreadsInput): Promise<void>;\n\n /** Appends messages to a thread's context; optionally updates usage / completion marker. */\n appendToThreadContext(input: AppendToThreadContextInput): Promise<void>;\n\n /** Replaces a thread's context wholesale (context-overwrite event). */\n overwriteThreadContext(input: OverwriteThreadContextInput): Promise<void>;\n\n /** Patches the turn snapshot's MCP server init info (by source id). */\n patchMCPServers(input: PatchMCPServersInput): Promise<void>;\n\n /** Patches the turn snapshot's sandbox info (id for cross-turn reattach). */\n patchSandboxInfo(input: PatchSandboxInfoInput): Promise<void>;\n\n /** Generic capability KV — store has zero Plan/feature knowledge. */\n patchThreadCapabilityState(input: PatchThreadCapabilityStateInput): Promise<void>;\n\n /** Paginated read ordered lexically by monotonic `event.id` (asc default). */\n listTurnEvents(input: ListTurnEventsInput): Promise<{\n data: PersistedTurnEvent[];\n pagination: TokenPagination;\n }>;\n\n /**\n * Paginated session-wide feed of persisted events across turns, including\n * turn.created / turn.done lifecycle rows. Reads only — never synthesizes.\n *\n * Includes events from **running** turns (the HTTP layer may 409 separately;\n * that is not store semantics). Ordering: newest turn first, then monotonic\n * `event.id` descending within each turn. `last_turn_id` anchors the window\n * to that turn plus its ancestors; when omitted, the session's current\n * `last_turn_id` selects the active branch. Continuation page tokens encode\n * that anchor and take precedence over `last_turn_id`, so later session\n * activity cannot move an in-progress pagination walk to another branch.\n * `ancestor_ids` may include only the previous N ancestors and need not reach\n * the root — implementations must spill through older turns' own\n * `ancestor_ids` when needed. Sibling branches from forks are excluded.\n */\n listSessionEvents(input: ListSessionEventsInput): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/agent-session/store/ISessionStore.ts"],"sourcesContent":["import type { JsonValue } from '../../core/capabilities/AgentCapability';\nimport type { MCPServerInitInfo, ThreadOverwriteContextEvent } from '../../core/events/schema';\nimport type {\n AgentThreadSnapshot,\n ContextMessage,\n SubAgentCompletionMarker,\n} from '../../core/runtime/AgentThread.types';\nimport type { CurrentContextUsage } from '../../core/runtime/contextUsage';\nimport type { SandboxInfo } from '../../core/sandbox/Sandbox';\nimport type { SessionRecord } from '../models/SessionRecord';\nimport type { TurnRecord } from '../models/TurnRecord';\nimport type { PersistedTurnEvent, SessionEventItem } from '../schemas/events';\nimport type { TokenPagination } from '../schemas/pagination';\nimport type { CancellationReason, TerminalTurnState } from '../schemas/turn';\n\n/**\n * Caller-supplied fields for creating a session; the store owns timestamps and tip state.\n * `agent` is a discriminated reference | inline binding.\n */\nexport type CreateSessionInput<TSessionCustom extends object = Record<string, never>> = Pick<\n SessionRecord<TSessionCustom>,\n 'tenant_id' | 'session_id' | 'agent' | 'created_by'\n> & {\n custom: TSessionCustom | null;\n};\n\n/**\n * PATCH fields for an existing session; `undefined` fields are left unchanged.\n * `agent` may be set only on inline sessions, and only as an inline arm (`{ type: 'inline', spec }`).\n */\nexport type UpdateSessionInput<TSessionCustom extends object = Record<string, never>> = Pick<\n SessionRecord<TSessionCustom>,\n 'tenant_id' | 'session_id'\n> & {\n agent: Extract<SessionRecord<TSessionCustom>['agent'], { type: 'inline' }> | undefined;\n title: SessionRecord<TSessionCustom>['title'] | undefined;\n};\n\nexport interface GetSessionInput {\n tenant_id: string;\n session_id: string;\n}\n\nexport interface DeleteSessionInput {\n tenant_id: string;\n session_id: string;\n}\n\nexport interface ListSessionsInput {\n tenant_id: string;\n limit: number;\n page_token: string | undefined;\n order: 'asc' | 'desc' | undefined;\n /** Inclusive lower bound on `created_at` (instant). */\n start_timestamp: Date | undefined;\n /** Inclusive upper bound on `created_at` (instant). */\n end_timestamp: Date | undefined;\n /** When set, only sessions bound to this named agent id. */\n agent_id: string | undefined;\n /** When set, only sessions created by this identity. */\n created_by: string | undefined;\n}\n\n/** Turn row fields without assembled snapshot (create input / listTurns). */\nexport type TurnRecordWithoutSnapshot<TTurnCustom extends object = Record<string, never>> = Omit<\n TurnRecord<TTurnCustom>,\n 'snapshot'\n>;\n\n/** Thread registration; mutable per-turn data arrives through dedicated createTurn fields. */\nexport type NewThreadInit = Omit<\n AgentThreadSnapshot,\n 'context' | 'current_context_usage' | 'completion' | 'capability_state'\n>;\n\n/** Full post-send capability map for one thread. */\nexport type ThreadCapabilityStateInit = Pick<AgentThreadSnapshot, 'thread_id' | 'capability_state'>;\n\n/** One drained send() append batch for one thread; writer = the new turn. */\nexport interface TurnContextAppend {\n thread_id: string;\n context: ContextMessage[];\n current_context_usage: CurrentContextUsage | null;\n}\n\nexport interface CreateTurnInput<TTurnCustom extends object = Record<string, never>> {\n turn: TurnRecordWithoutSnapshot<TTurnCustom>;\n /** Threads absent on the previous turn (turn 1: the root thread; else empty). */\n new_threads: NewThreadInit[];\n /**\n * All new messages, for new and carried-forward threads alike — collected by\n * draining orchestrator.send() BEFORE this call. Draining without persisting is\n * safe: send() mutates only in-memory threads, and if createTurn fails the whole\n * in-memory state (orchestrator, threads, resolver) is discarded — so either this\n * turn commits atomically with its appends, or nothing was persisted at all.\n */\n new_context_appends: TurnContextAppend[];\n /**\n * Complete post-send capability maps: exactly one entry per turn thread.\n * Authoritative for this turn; the store does not carry capability rows forward.\n */\n capability_states: ThreadCapabilityStateInit[];\n /** Set only if session.title is NULL (first write wins). */\n update_session_title_if_not_exist: string | null;\n}\n\nexport interface FreezeAndGetTurnInput {\n session_id: string;\n turn_id: string;\n /** Written onto the turn row when the freeze actually cancels a running turn. */\n reason: CancellationReason;\n /** Caller-built cancelled turn.done event; store persists atomically with state flip when it cancels. */\n turn_done_event: PersistedTurnEvent;\n}\n\nexport interface GetTurnInput {\n session_id: string;\n turn_id: string;\n}\n\nexport interface ListTurnsInput {\n session_id: string;\n limit: number;\n page_token: string | undefined;\n}\n\nexport interface UpdateTurnStateInput {\n session_id: string;\n turn_id: string;\n state: TerminalTurnState;\n /** Caller-built turn.done; written atomically with the state flip in the same tx. */\n turn_done_event: PersistedTurnEvent;\n}\n\nexport interface AppendToEventsInput {\n session_id: string;\n turn_id: string;\n events: PersistedTurnEvent[];\n}\n\nexport interface AddThreadsInput {\n session_id: string;\n turn_id: string;\n threads: AgentThreadSnapshot[];\n}\n\nexport interface RemoveThreadsInput {\n session_id: string;\n turn_id: string;\n thread_ids: string[];\n}\n\nexport interface AppendToThreadContextInput {\n session_id: string;\n turn_id: string;\n thread_id: string;\n context: ContextMessage[];\n current_context_usage: CurrentContextUsage | null;\n completion: SubAgentCompletionMarker | null;\n}\n\nexport interface OverwriteThreadContextInput {\n session_id: string;\n turn_id: string;\n event: ThreadOverwriteContextEvent;\n}\n\nexport interface PatchMCPServersInput {\n session_id: string;\n turn_id: string;\n mcp_servers: MCPServerInitInfo[];\n}\n\nexport interface PatchSandboxInfoInput {\n session_id: string;\n turn_id: string;\n sandbox_info: SandboxInfo;\n}\n\nexport interface PatchThreadCapabilityStateInput {\n session_id: string;\n turn_id: string;\n thread_id: string;\n key: string;\n state: JsonValue;\n}\n\nexport interface ListTurnEventsInput {\n session_id: string;\n turn_id: string;\n limit: number;\n page_token: string | undefined;\n order: 'asc' | 'desc' | undefined;\n}\n\nexport interface ListSessionEventsInput {\n session_id: string;\n limit: number;\n page_token: string | undefined;\n last_turn_id: string | undefined;\n}\n\n/**\n * Session/turn persistence contract. Pure durability: no streaming, SSE, or\n * subscription members. Callers authorize the parent session before using\n * turn-scoped operations, which rely on globally unique session_id values.\n * Capability maps are initialized atomically by createTurn and subsequently\n * updated through patchThreadCapabilityState. Agent binding is session-scoped\n * as a discriminated `agent` (ref | value); named agents are not hydrated on read.\n */\nexport interface ISessionStore<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> {\n /**\n * Persists a discriminated `agent` (ref | value). SQL backends may flatten to columns.\n * `session_id` is globally unique across tenants.\n * Persists caller-supplied `created_by` (immutable after create).\n * Sets `last_activity_timestamp_ms` (= now) on create.\n */\n createSession(input: CreateSessionInput<TSessionCustom>): Promise<void>;\n\n /** Permanently removes a session and all related data; missing sessions are a no-op. */\n deleteSession(input: DeleteSessionInput): Promise<void>;\n\n /**\n * Returns the session as stored (ref agents are not hydrated to a value).\n * Does **not** bump `last_activity_timestamp_ms` (read path).\n */\n getSession(input: GetSessionInput): Promise<SessionRecord<TSessionCustom> | undefined>;\n\n /**\n * PATCH semantics — update only the provided fields:\n * - agent: replace inline binding (inline sessions only; reference → invariant error).\n * - title: set/replace the session title.\n * Bumps `last_activity_timestamp_ms` (= now) in the same update.\n */\n updateSession(input: UpdateSessionInput<TSessionCustom>): Promise<void>;\n\n /**\n * Paginated list of the tenant's sessions ordered by `updated_at`\n * (`order` defaults to `desc`, `session_id` tie-break). `page_token` is a\n * keyset cursor on `(updated_at, session_id)`. `start_timestamp` /\n * `end_timestamp` are inclusive instant bounds on `created_at`. Optional\n * `agent_id` filters ref-bound sessions; optional `created_by` filters by\n * creator identity. Does **not** bump `last_activity_timestamp_ms` (read path).\n */\n listSessions(\n input: ListSessionsInput,\n ): Promise<{ data: SessionRecord<TSessionCustom>[]; pagination: TokenPagination }>;\n\n /**\n * Creates the turn AND advances `session.last_turn_id`. Context merging is the\n * store's responsibility: `new_context_appends` and `new_threads` are applied\n * on top of the previous turn's snapshot when `turn.previous_turn_id` is set.\n * `capability_states` is the complete authoritative map for every resulting\n * thread and is persisted directly without store-side carry-forward.\n *\n * Atomicity (store contract): insert turn + set `last_turn_id` (+ session\n * turn-list append if the backend has one) MUST be one atomic unit per\n * session. Concurrent createTurn on the same session must not drop a turn\n * row or leave `last_turn_id` pointing at a turn that was never created.\n * The implementation supplies the mechanism (session lock, row lock/tx, …).\n *\n * Also bumps `session.last_activity_timestamp_ms` in that same atomic unit.\n *\n * Fork semantics for `turn.previous_turn_id`:\n * - `null` — new root turn (no parent); always allowed.\n * - string — fork/chain from that turn when it exists. Tip-equality is NOT\n * required; concurrent forks from the same tip both succeed. Unknown id is\n * allowed (relaxed) and treated as no inheritance. If that turn exists and\n * is still `running`, reject with {@link PreviousTurnRunningError} —\n * callers must {@link freezeAndGetTurn} first.\n * `last_turn_id` always advances to the new turn in the same atomic unit.\n *\n * `update_session_title_if_not_exist`: when set AND `session.title` is\n * unset/null, set it in the same atomic unit; an existing title is NEVER\n * overwritten (first write wins). The caller derives the value; the store\n * only conditionally sets it.\n */\n createTurn(input: CreateTurnInput<TTurnCustom>): Promise<void>;\n\n /**\n * One tx: (a) conditionally cancel a running turn with `reason`; (b) if it\n * did cancel, insert the caller-built `turn_done_event` — already-terminal\n * turns skip the event insert; (c) return the now-immutable turn record.\n * Missing turn → {@link TurnNotFoundError}.\n */\n freezeAndGetTurn(input: FreezeAndGetTurnInput): Promise<TurnRecord<TTurnCustom>>;\n\n /** Returns the turn record, or undefined if not found in this session. */\n getTurn(input: GetTurnInput): Promise<TurnRecord<TTurnCustom> | undefined>;\n\n /** Paginated list of turn rows (no snapshot); use getTurn for assembled snapshot. */\n listTurns(\n input: ListTurnsInput,\n ): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }>;\n\n /**\n * Writes the terminal state and `turn_done_event` atomically. Store contract —\n * **first terminal write wins**:\n * - Allowed: `running` → `done` | `cancelled` | `error`.\n * - Rejected with **409** (or equivalent conflict): any write when status is already\n * terminal — including done→cancelled, cancelled→done, error→*, terminal→running.\n * - Missing turn → 404 / not-found.\n *\n * Check under the same concurrency control as other turn mutations (lock/CAS) —\n * not a racy read-then-write outside the critical section.\n */\n updateTurnState(input: UpdateTurnStateInput): Promise<void>;\n\n /**\n * Durable event log for the turn. MUST include lifecycle rows: a\n * `TurnCreatedEvent` at the start of the stream and a terminal `TurnDoneEvent`\n * (or its cancelled/error shape) at the end. Every turn written through this\n * API persists lifecycle in the stream — implementations never synthesize\n * missing created/done rows on read. Every event MUST carry `id` and\n * `created_at`; `id` is a monotonic ULID and is the primary within-turn sort\n * key. `created_at` records event creation time but is not the order key.\n */\n appendToEvents(input: AppendToEventsInput): Promise<void>;\n\n /** Adds thread snapshots to the turn (sub-agent spawns). */\n addThreads(input: AddThreadsInput): Promise<void>;\n\n /** Removes threads from the turn by id. */\n removeThreads(input: RemoveThreadsInput): Promise<void>;\n\n /** Appends messages to a thread's context; optionally updates usage / completion marker. */\n appendToThreadContext(input: AppendToThreadContextInput): Promise<void>;\n\n /** Replaces a thread's context wholesale (context-overwrite event). */\n overwriteThreadContext(input: OverwriteThreadContextInput): Promise<void>;\n\n /** Patches the turn snapshot's MCP server init info (by source id). */\n patchMCPServers(input: PatchMCPServersInput): Promise<void>;\n\n /** Patches the turn snapshot's sandbox info (id for cross-turn reattach). */\n patchSandboxInfo(input: PatchSandboxInfoInput): Promise<void>;\n\n /** Generic capability KV — store has zero Plan/feature knowledge. */\n patchThreadCapabilityState(input: PatchThreadCapabilityStateInput): Promise<void>;\n\n /** Paginated read ordered lexically by monotonic `event.id` (asc default). */\n listTurnEvents(input: ListTurnEventsInput): Promise<{\n data: PersistedTurnEvent[];\n pagination: TokenPagination;\n }>;\n\n /**\n * Paginated session-wide feed of persisted events across turns, including\n * turn.created / turn.done lifecycle rows. Reads only — never synthesizes.\n *\n * Includes events from **running** turns (the HTTP layer may 409 separately;\n * that is not store semantics). Ordering: newest turn first, then monotonic\n * `event.id` descending within each turn. `last_turn_id` anchors the window\n * to that turn plus its ancestors; when omitted, the session's current\n * `last_turn_id` selects the active branch. Continuation page tokens encode\n * that anchor and take precedence over `last_turn_id`, so later session\n * activity cannot move an in-progress pagination walk to another branch.\n * `ancestor_ids` may include only the previous N ancestors and need not reach\n * the root — implementations must spill through older turns' own\n * `ancestor_ids` when needed. Sibling branches from forks are excluded.\n */\n listSessionEvents(input: ListSessionEventsInput): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
|
@@ -24,7 +24,6 @@ __export(InMemorySessionStore_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(InMemorySessionStore_exports);
|
|
26
26
|
var import_contextUsage = require("../../core/runtime/contextUsage.js");
|
|
27
|
-
var import_turn = require("../schemas/turn.js");
|
|
28
27
|
var import_assertCreateTurnThreadDelta = require("./assertCreateTurnThreadDelta.js");
|
|
29
28
|
var import_OffsetPageToken = require("./OffsetPageToken.js");
|
|
30
29
|
var import_SessionEventPageToken = require("./SessionEventPageToken.js");
|
|
@@ -263,7 +262,7 @@ var InMemorySessionStore = class {
|
|
|
263
262
|
if (turn.state.status === "running") {
|
|
264
263
|
const cancelledState = {
|
|
265
264
|
status: "cancelled",
|
|
266
|
-
reason:
|
|
265
|
+
reason: input.reason,
|
|
267
266
|
completed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
268
267
|
};
|
|
269
268
|
turn.state = cancelledState;
|