@truefoundry/trueforge-core 0.1.4 → 0.2.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/agent-session/SessionHandle.d.ts +1 -0
  2. package/dist/agent-session/SessionHandle.d.ts.map +1 -1
  3. package/dist/agent-session/SessionHandle.js +3 -0
  4. package/dist/agent-session/SessionHandle.js.map +1 -1
  5. package/dist/agent-session/SessionHandle.mjs +3 -0
  6. package/dist/agent-session/SessionHandle.mjs.map +1 -1
  7. package/dist/agent-session/Sessions.d.ts +17 -6
  8. package/dist/agent-session/Sessions.d.ts.map +1 -1
  9. package/dist/agent-session/Sessions.js +45 -1
  10. package/dist/agent-session/Sessions.js.map +1 -1
  11. package/dist/agent-session/Sessions.mjs +45 -1
  12. package/dist/agent-session/Sessions.mjs.map +1 -1
  13. package/dist/agent-session/TurnResourceResolver.d.ts +3 -1
  14. package/dist/agent-session/TurnResourceResolver.d.ts.map +1 -1
  15. package/dist/agent-session/TurnResourceResolver.js +1 -0
  16. package/dist/agent-session/TurnResourceResolver.js.map +1 -1
  17. package/dist/agent-session/TurnResourceResolver.mjs +1 -0
  18. package/dist/agent-session/TurnResourceResolver.mjs.map +1 -1
  19. package/dist/agent-session/builtinsFromSpec.js +1 -1
  20. package/dist/agent-session/builtinsFromSpec.js.map +1 -1
  21. package/dist/agent-session/builtinsFromSpec.mjs +1 -1
  22. package/dist/agent-session/builtinsFromSpec.mjs.map +1 -1
  23. package/dist/agent-session/index.d.ts +6 -4
  24. package/dist/agent-session/index.d.ts.map +1 -1
  25. package/dist/agent-session/index.js +9 -0
  26. package/dist/agent-session/index.js.map +1 -1
  27. package/dist/agent-session/index.mjs +7 -1
  28. package/dist/agent-session/index.mjs.map +1 -1
  29. package/dist/agent-session/models/SessionRecord.d.ts +10 -2
  30. package/dist/agent-session/models/SessionRecord.d.ts.map +1 -1
  31. package/dist/agent-session/models/SessionRecord.js.map +1 -1
  32. package/dist/agent-session/schemas/agentSpec.d.ts +10 -4
  33. package/dist/agent-session/schemas/agentSpec.d.ts.map +1 -1
  34. package/dist/agent-session/schemas/agentSpec.js +6 -2
  35. package/dist/agent-session/schemas/agentSpec.js.map +1 -1
  36. package/dist/agent-session/schemas/agentSpec.mjs +6 -2
  37. package/dist/agent-session/schemas/agentSpec.mjs.map +1 -1
  38. package/dist/agent-session/schemas/session.d.ts +34 -7
  39. package/dist/agent-session/schemas/session.d.ts.map +1 -1
  40. package/dist/agent-session/schemas/session.js +23 -3
  41. package/dist/agent-session/schemas/session.js.map +1 -1
  42. package/dist/agent-session/schemas/session.mjs +21 -3
  43. package/dist/agent-session/schemas/session.mjs.map +1 -1
  44. package/dist/agent-session/schemas/subject.d.ts +9 -0
  45. package/dist/agent-session/schemas/subject.d.ts.map +1 -0
  46. package/dist/agent-session/schemas/subject.js +36 -0
  47. package/dist/agent-session/schemas/subject.js.map +1 -0
  48. package/dist/agent-session/schemas/subject.mjs +11 -0
  49. package/dist/agent-session/schemas/subject.mjs.map +1 -0
  50. package/dist/agent-session/store/ISessionStore.d.ts +29 -20
  51. package/dist/agent-session/store/ISessionStore.d.ts.map +1 -1
  52. package/dist/agent-session/store/ISessionStore.js.map +1 -1
  53. package/dist/agent-session/store/InMemorySessionStore.d.ts +4 -1
  54. package/dist/agent-session/store/InMemorySessionStore.d.ts.map +1 -1
  55. package/dist/agent-session/store/InMemorySessionStore.js +47 -3
  56. package/dist/agent-session/store/InMemorySessionStore.js.map +1 -1
  57. package/dist/agent-session/store/InMemorySessionStore.mjs +48 -3
  58. package/dist/agent-session/store/InMemorySessionStore.mjs.map +1 -1
  59. package/dist/agent-session/store/SessionStoreErrors.d.ts +4 -0
  60. package/dist/agent-session/store/SessionStoreErrors.d.ts.map +1 -1
  61. package/dist/agent-session/store/SessionStoreErrors.js +10 -0
  62. package/dist/agent-session/store/SessionStoreErrors.js.map +1 -1
  63. package/dist/agent-session/store/SessionStoreErrors.mjs +9 -0
  64. package/dist/agent-session/store/SessionStoreErrors.mjs.map +1 -1
  65. package/dist/core/capabilities/builtins/ContextCompaction.d.ts +6 -0
  66. package/dist/core/capabilities/builtins/ContextCompaction.d.ts.map +1 -1
  67. package/dist/core/capabilities/builtins/ContextCompaction.js +29 -3
  68. package/dist/core/capabilities/builtins/ContextCompaction.js.map +1 -1
  69. package/dist/core/capabilities/builtins/ContextCompaction.mjs +26 -2
  70. package/dist/core/capabilities/builtins/ContextCompaction.mjs.map +1 -1
  71. package/dist/core/llm/VercelAILLM.d.ts +1 -1
  72. package/dist/core/llm/VercelAILLM.d.ts.map +1 -1
  73. package/dist/core/llm/VercelAILLM.js +4 -2
  74. package/dist/core/llm/VercelAILLM.js.map +1 -1
  75. package/dist/core/llm/VercelAILLM.mjs +4 -2
  76. package/dist/core/llm/VercelAILLM.mjs.map +1 -1
  77. package/dist/core/mcp/remoteMcpClient.js +1 -1
  78. package/dist/core/mcp/remoteMcpClient.js.map +1 -1
  79. package/dist/core/mcp/remoteMcpClient.mjs +1 -1
  80. package/dist/core/mcp/remoteMcpClient.mjs.map +1 -1
  81. package/dist/core/runtime/AgentDefinition.d.ts +4 -0
  82. package/dist/core/runtime/AgentDefinition.d.ts.map +1 -1
  83. package/dist/core/runtime/AgentDefinition.js.map +1 -1
  84. package/dist/core/sandbox/sandboxScripts.gen.d.ts +1 -1
  85. package/dist/core/sandbox/sandboxScripts.gen.d.ts.map +1 -1
  86. package/dist/core/sandbox/sandboxScripts.gen.js +8 -1
  87. package/dist/core/sandbox/sandboxScripts.gen.js.map +1 -1
  88. package/dist/core/sandbox/sandboxScripts.gen.mjs +8 -1
  89. package/dist/core/sandbox/sandboxScripts.gen.mjs.map +1 -1
  90. package/package.json +23 -23
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/agent-session/store/InMemorySessionStore.ts"],"sourcesContent":["import type { AgentThreadSnapshot } from '../../core/runtime/AgentThread.types';\nimport { getEmptyCurrentContextUsage } from '../../core/runtime/contextUsage';\nimport type { SessionRecord } from '../models/SessionRecord';\nimport type { TurnRecord, TurnSnapshot } from '../models/TurnRecord';\nimport type { PersistedTurnEvent, SessionEventItem } from '../schemas/events';\nimport type { TokenPagination } from '../schemas/pagination';\nimport type { TerminalTurnState } from '../schemas/turn';\nimport { assertCreateTurnThreadDelta } from './assertCreateTurnThreadDelta';\nimport type {\n AddThreadsInput,\n AppendToEventsInput,\n AppendToThreadContextInput,\n CreateSessionInput,\n CreateTurnInput,\n DeleteSessionInput,\n FreezeAndGetTurnInput,\n GetSessionInput,\n GetTurnInput,\n ISessionStore,\n ListSessionEventsInput,\n ListSessionsInput,\n ListTurnEventsInput,\n ListTurnsInput,\n NewThreadInit,\n OverwriteThreadContextInput,\n PatchMCPServersInput,\n PatchSandboxInfoInput,\n PatchThreadCapabilityStateInput,\n RemoveThreadsInput,\n TurnContextAppend,\n TurnRecordWithoutSnapshot,\n UpdateSessionInput,\n UpdateTurnStateInput,\n} from './ISessionStore';\nimport { decodeOffsetPageToken, encodeOffsetPageToken } from './OffsetPageToken';\nimport {\n decodeSessionEventPageToken,\n paginateSessionEventRows,\n type SessionEventPageCursor,\n} from './SessionEventPageToken';\nimport { decodeSessionListPageToken, paginateSessionListRows } from './SessionListPageToken';\nimport {\n PreviousTurnRunningError,\n SessionAlreadyExistsError,\n SessionNotFoundError,\n SessionStoreInvariantError,\n TurnAlreadyExistsError,\n TurnNotFoundError,\n TurnNotRunningError,\n} from './SessionStoreErrors';\n\n/* eslint-disable @typescript-eslint/require-await -- in-memory store is synchronous; methods stay async so thrown SessionStore*Error reject as Promises for ISessionStore callers */\n\ntype StoredEvent = PersistedTurnEvent;\n\ninterface StoredSession<TSessionCustom extends object> {\n record: SessionRecord<TSessionCustom>;\n turnIds: string[];\n}\n\nfunction deepCopy<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction sessionKey(sessionId: string): string {\n return sessionId;\n}\n\nfunction turnKey({ session_id, turn_id }: { session_id: string; turn_id: string }): string {\n return `${session_id}:${turn_id}`;\n}\n\n/** Lexicographic session_id order — shared by listSessions sort and keyset filter. */\nfunction compareSessionId(a: string, b: string): number {\n if (a < b) {\n return -1;\n }\n if (a > b) {\n return 1;\n }\n return 0;\n}\n\nfunction newThreadSnapshot(thread: NewThreadInit): AgentThreadSnapshot {\n return {\n thread_id: thread.thread_id,\n parent: thread.parent ?? null,\n agent_info: thread.agent_info ?? null,\n capability_state: null,\n context: [],\n current_context_usage: getEmptyCurrentContextUsage(),\n completion: null,\n };\n}\n\nfunction applyContextAppends(threads: Record<string, AgentThreadSnapshot>, appends: TurnContextAppend[]): void {\n for (const append of appends) {\n const thread = threads[append.thread_id];\n if (!thread) {\n throw new SessionStoreInvariantError(`new_context_appends references unknown thread ${append.thread_id}`);\n }\n thread.context.push(...deepCopy(append.context));\n if (append.current_context_usage !== null) {\n thread.current_context_usage = deepCopy(append.current_context_usage);\n }\n }\n}\n\nfunction buildSnapshotFromDelta(input: {\n previousSnapshot: TurnSnapshot | undefined;\n new_threads: NewThreadInit[];\n new_context_appends: TurnContextAppend[];\n capability_states: CreateTurnInput['capability_states'];\n}): TurnSnapshot {\n const threads: Record<string, AgentThreadSnapshot> = input.previousSnapshot\n ? deepCopy(input.previousSnapshot.threads)\n : {};\n\n assertCreateTurnThreadDelta({\n previousThreadIds: new Set(Object.keys(threads)),\n new_threads: input.new_threads,\n new_context_appends: input.new_context_appends,\n capability_states: input.capability_states,\n });\n\n for (const nt of input.new_threads) {\n threads[nt.thread_id] = newThreadSnapshot(nt);\n }\n\n applyContextAppends(threads, input.new_context_appends);\n for (const capability of input.capability_states) {\n const thread = threads[capability.thread_id];\n if (thread === undefined) {\n throw new SessionStoreInvariantError(`capability_states references unknown thread ${capability.thread_id}`);\n }\n thread.capability_state = deepCopy(capability.capability_state);\n }\n\n return {\n threads,\n mcp_servers: input.previousSnapshot ? deepCopy(input.previousSnapshot.mcp_servers) : null,\n sandbox_info: input.previousSnapshot ? deepCopy(input.previousSnapshot.sandbox_info) : null,\n };\n}\n\nfunction paginate<T>(items: T[], limit: number, pageToken?: string): { data: T[]; pagination: TokenPagination } {\n const offset = decodeOffsetPageToken(pageToken);\n const slice = items.slice(offset, offset + limit);\n return {\n data: slice,\n pagination: {\n limit,\n ...(offset + limit < items.length ? { next_page_token: encodeOffsetPageToken(offset + limit) } : {}),\n ...(offset > 0 ? { previous_page_token: encodeOffsetPageToken(Math.max(0, offset - limit)) } : {}),\n },\n };\n}\n\n/**\n * Reference ISessionStore implementation. Proves the contract without SSE/subscription\n * hooks. Deep-copies on read/write boundaries so callers cannot mutate stored state.\n */\nexport class InMemorySessionStore<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> implements ISessionStore<TSessionCustom, TTurnCustom> {\n private readonly sessions = new Map<string, StoredSession<TSessionCustom>>();\n private readonly turns = new Map<string, TurnRecord<TTurnCustom>>();\n private readonly events = new Map<string, StoredEvent[]>();\n\n async createSession(input: CreateSessionInput<TSessionCustom>): Promise<void> {\n const key = sessionKey(input.session_id);\n if (this.sessions.has(key)) {\n throw new SessionAlreadyExistsError(input.session_id);\n }\n const now = new Date();\n const record: SessionRecord<TSessionCustom> = {\n tenant_id: input.tenant_id,\n session_id: input.session_id,\n created_by: input.created_by,\n agent: deepCopy(input.agent),\n title: null,\n last_turn_id: null,\n created_at: now,\n updated_at: now,\n last_activity_timestamp_ms: Date.now(),\n custom: input.custom !== null ? deepCopy(input.custom) : null,\n };\n this.sessions.set(key, { record, turnIds: [] });\n return;\n }\n\n async deleteSession(input: DeleteSessionInput): Promise<void> {\n const sKey = sessionKey(input.session_id);\n const stored = this.sessions.get(sKey);\n if (stored?.record.tenant_id !== input.tenant_id) {\n return;\n }\n for (const turnId of stored.turnIds) {\n const tKey = turnKey({ session_id: input.session_id, turn_id: turnId });\n this.turns.delete(tKey);\n this.events.delete(tKey);\n }\n this.sessions.delete(sKey);\n }\n\n async getSession(input: GetSessionInput): Promise<SessionRecord<TSessionCustom> | undefined> {\n const stored = this.sessions.get(sessionKey(input.session_id));\n return stored?.record.tenant_id === input.tenant_id ? deepCopy(stored.record) : undefined;\n }\n\n async updateSession(input: UpdateSessionInput<TSessionCustom>): Promise<void> {\n const key = sessionKey(input.session_id);\n const stored = this.sessions.get(key);\n if (stored?.record.tenant_id !== input.tenant_id) {\n throw new SessionNotFoundError(input.session_id);\n }\n if (input.agent !== undefined) {\n if (stored.record.agent.type === 'reference') {\n throw new SessionStoreInvariantError(`Session ${input.session_id} is named; agent cannot be updated`);\n }\n stored.record.agent = deepCopy(input.agent);\n }\n if (input.title !== undefined) {\n stored.record.title = input.title;\n }\n const now = Date.now();\n stored.record.updated_at = new Date(now);\n stored.record.last_activity_timestamp_ms = now;\n return;\n }\n\n async listSessions(\n input: ListSessionsInput,\n ): Promise<{ data: SessionRecord<TSessionCustom>[]; pagination: TokenPagination }> {\n const records: SessionRecord<TSessionCustom>[] = [];\n for (const stored of this.sessions.values()) {\n if (stored.record.tenant_id !== input.tenant_id) {\n continue;\n }\n if (\n input.agent_id !== undefined &&\n (stored.record.agent.type !== 'reference' || stored.record.agent.id !== input.agent_id)\n ) {\n continue;\n }\n if (input.created_by !== undefined && stored.record.created_by !== input.created_by) {\n continue;\n }\n const createdAt = stored.record.created_at.getTime();\n if (input.start_timestamp !== undefined && createdAt < input.start_timestamp.getTime()) {\n continue;\n }\n if (input.end_timestamp !== undefined && createdAt > input.end_timestamp.getTime()) {\n continue;\n }\n records.push(stored.record);\n }\n records.sort((a, b) => {\n const aTime = a.updated_at.getTime();\n const bTime = b.updated_at.getTime();\n if (aTime !== bTime) {\n return input.order === 'asc' ? aTime - bTime : bTime - aTime;\n }\n // Same lexicographic order as the keyset predicate below (and Postgres/SQLite).\n return input.order === 'asc'\n ? compareSessionId(a.session_id, b.session_id)\n : compareSessionId(b.session_id, a.session_id);\n });\n\n let filtered = records;\n const cursor = decodeSessionListPageToken(input.page_token);\n if (cursor) {\n const cursorTime = new Date(cursor.updated_at).getTime();\n filtered = records.filter(record => {\n const t = record.updated_at.getTime();\n const idCmp = compareSessionId(record.session_id, cursor.session_id);\n if (input.order === 'asc') {\n return t > cursorTime || (t === cursorTime && idCmp > 0);\n }\n return t < cursorTime || (t === cursorTime && idCmp < 0);\n });\n }\n\n const page = paginateSessionListRows(filtered, input.limit, row => row.updated_at.toISOString());\n return { data: deepCopy(page.data), pagination: page.pagination };\n }\n\n async createTurn(input: CreateTurnInput<TTurnCustom>): Promise<void> {\n // Atomicity is free here: this body is fully synchronous, so Node's\n // run-to-completion guarantees it. Real backends must still use their own\n // locking/transactions to satisfy the ISessionStore createTurn contract.\n const sKey = sessionKey(input.turn.session_id);\n const stored = this.sessions.get(sKey);\n if (!stored) {\n throw new SessionNotFoundError(input.turn.session_id);\n }\n\n const previousTurnId = input.turn.previous_turn_id;\n let previousSnapshot: TurnSnapshot | undefined;\n if (previousTurnId !== null) {\n const prevKey = turnKey({ session_id: input.turn.session_id, turn_id: previousTurnId });\n const prev = this.turns.get(prevKey);\n // Unknown previous_turn_id is allowed (relaxed): treat as no inheritance.\n // A still-running previous must be frozen first.\n if (prev !== undefined) {\n if (prev.state.status === 'running') {\n throw new PreviousTurnRunningError(previousTurnId);\n }\n previousSnapshot = prev.snapshot;\n }\n }\n\n const tKey = turnKey(input.turn);\n if (this.turns.has(tKey)) {\n throw new TurnAlreadyExistsError(input.turn.turn_id);\n }\n\n const snapshot = buildSnapshotFromDelta({\n previousSnapshot,\n new_threads: input.new_threads,\n new_context_appends: input.new_context_appends,\n capability_states: input.capability_states,\n });\n\n const turnRecord: TurnRecord<TTurnCustom> = {\n ...deepCopy(input.turn),\n snapshot,\n };\n\n this.turns.set(tKey, turnRecord);\n this.events.set(tKey, []);\n stored.turnIds.push(input.turn.turn_id);\n stored.record.last_turn_id = input.turn.turn_id;\n stored.record.last_activity_timestamp_ms = Date.now();\n stored.record.updated_at = new Date();\n if (input.update_session_title_if_not_exist !== null && stored.record.title === null) {\n stored.record.title = input.update_session_title_if_not_exist;\n }\n }\n\n async freezeAndGetTurn(input: FreezeAndGetTurnInput): Promise<TurnRecord<TTurnCustom>> {\n const tKey = turnKey(input);\n const turn = this.requireTurn(input.session_id, input.turn_id);\n\n if (turn.state.status === 'running') {\n const cancelledState: TerminalTurnState = {\n status: 'cancelled',\n reason: input.reason,\n completed_at: new Date().toISOString(),\n };\n turn.state = cancelledState;\n turn.updated_at = new Date();\n const list = this.events.get(tKey);\n if (list) {\n list.push(deepCopy(input.turn_done_event));\n }\n }\n\n return deepCopy(turn);\n }\n\n async getTurn(input: GetTurnInput): Promise<TurnRecord<TTurnCustom> | undefined> {\n const turn = this.turns.get(turnKey(input));\n return turn ? deepCopy(turn) : undefined;\n }\n\n async listTurns(\n input: ListTurnsInput,\n ): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }> {\n const stored = this.sessions.get(sessionKey(input.session_id));\n if (!stored) {\n throw new SessionNotFoundError(input.session_id);\n }\n const records = stored.turnIds.map(id => {\n const turn = this.turns.get(turnKey({ session_id: input.session_id, turn_id: id }));\n if (!turn) {\n throw new TurnNotFoundError(id);\n }\n const { snapshot, ...row } = deepCopy(turn);\n void snapshot;\n return row;\n });\n return paginate(records, input.limit, input.page_token);\n }\n\n async updateTurnState(input: UpdateTurnStateInput): Promise<void> {\n // Same as createTurn: synchronous body ⇒ atomic under run-to-completion.\n const tKey = turnKey(input);\n const turn = this.requireTurn(input.session_id, input.turn_id);\n if (turn.state.status !== 'running') {\n throw new TurnNotRunningError(input.turn_id, turn.state);\n }\n turn.state = deepCopy(input.state);\n turn.updated_at = new Date();\n const list = this.events.get(tKey);\n if (list) {\n list.push(deepCopy(input.turn_done_event));\n }\n }\n\n async appendToEvents(input: AppendToEventsInput): Promise<void> {\n this.requireRunningTurn(input.session_id, input.turn_id);\n const tKey = turnKey(input);\n const list = this.events.get(tKey);\n if (!list) {\n throw new TurnNotFoundError(input.turn_id);\n }\n list.push(...deepCopy(input.events));\n return;\n }\n\n private requireTurn(sessionId: string, turnId: string): TurnRecord<TTurnCustom> {\n const turn = this.turns.get(turnKey({ session_id: sessionId, turn_id: turnId }));\n if (!turn) {\n throw new TurnNotFoundError(turnId);\n }\n return turn;\n }\n\n private requireRunningTurn(sessionId: string, turnId: string): TurnRecord<TTurnCustom> {\n const turn = this.requireTurn(sessionId, turnId);\n if (turn.state.status !== 'running') {\n throw new TurnNotRunningError(turnId, turn.state);\n }\n return turn;\n }\n\n async addThreads(input: AddThreadsInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n for (const thread of input.threads) {\n turn.snapshot.threads[thread.thread_id] = deepCopy(thread);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async removeThreads(input: RemoveThreadsInput): Promise<void> {\n if (input.thread_ids.length === 0) {\n return;\n }\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n for (const id of input.thread_ids) {\n Reflect.deleteProperty(turn.snapshot.threads, id);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async appendToThreadContext(input: AppendToThreadContextInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n const thread = turn.snapshot.threads[input.thread_id];\n if (!thread) {\n throw new SessionStoreInvariantError(`Thread not found: ${input.thread_id}`);\n }\n thread.context.push(...deepCopy(input.context));\n if (input.current_context_usage !== null) {\n thread.current_context_usage = deepCopy(input.current_context_usage);\n }\n if (input.completion !== null) {\n thread.completion = deepCopy(input.completion);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async overwriteThreadContext(input: OverwriteThreadContextInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n const threadId = input.event.thread_id;\n const thread = turn.snapshot.threads[threadId];\n if (!thread) {\n throw new SessionStoreInvariantError(`Thread not found: ${threadId}`);\n }\n thread.context = deepCopy(input.event.context);\n thread.current_context_usage = deepCopy(input.event.current_context_usage);\n turn.updated_at = new Date();\n return;\n }\n\n async patchMCPServers(input: PatchMCPServersInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n turn.snapshot.mcp_servers ??= {};\n for (const server of input.mcp_servers) {\n turn.snapshot.mcp_servers[server.id] = deepCopy(server);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async patchSandboxInfo(input: PatchSandboxInfoInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n turn.snapshot.sandbox_info = deepCopy(input.sandbox_info);\n turn.updated_at = new Date();\n return;\n }\n\n async patchThreadCapabilityState(input: PatchThreadCapabilityStateInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n const thread = turn.snapshot.threads[input.thread_id];\n if (!thread) {\n throw new SessionStoreInvariantError(`Thread not found: ${input.thread_id}`);\n }\n thread.capability_state ??= {};\n if (input.state === null) {\n Reflect.deleteProperty(thread.capability_state, input.key);\n if (Object.keys(thread.capability_state).length === 0) {\n thread.capability_state = null;\n }\n } else {\n thread.capability_state[input.key] = deepCopy(input.state);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async listTurnEvents(input: ListTurnEventsInput): Promise<{\n data: PersistedTurnEvent[];\n pagination: TokenPagination;\n }> {\n this.requireTurn(input.session_id, input.turn_id);\n const list = this.events.get(turnKey(input));\n if (!list) {\n throw new TurnNotFoundError(input.turn_id);\n }\n const ordered = [...list].sort((a, b) =>\n input.order === 'desc' ? b.id.localeCompare(a.id) : a.id.localeCompare(b.id),\n );\n const page = paginate(ordered, input.limit, input.page_token);\n return { data: deepCopy(page.data), pagination: page.pagination };\n }\n\n async listSessionEvents(input: ListSessionEventsInput): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }> {\n const stored = this.sessions.get(sessionKey(input.session_id));\n if (!stored) {\n throw new SessionNotFoundError(input.session_id);\n }\n\n const decodedCursor = input.page_token === undefined ? undefined : decodeSessionEventPageToken(input.page_token);\n const lastTurnId = decodedCursor?.last_turn_id ?? input.last_turn_id ?? stored.record.last_turn_id;\n if (lastTurnId === null) {\n return { data: [], pagination: { limit: input.limit } };\n }\n const cursor: SessionEventPageCursor = {\n last_turn_id: lastTurnId,\n offset: decodedCursor?.offset ?? 0,\n };\n\n const anchor = this.turns.get(turnKey({ session_id: input.session_id, turn_id: cursor.last_turn_id }));\n if (!anchor) {\n throw new TurnNotFoundError(cursor.last_turn_id);\n }\n const turnIds = this.resolveAncestorChain(input.session_id, anchor);\n const flattened: SessionEventItem[] = [];\n for (const turnId of [...turnIds].reverse()) {\n const evts = this.events.get(turnKey({ session_id: input.session_id, turn_id: turnId })) ?? [];\n for (const event of [...evts].sort((a, b) => b.id.localeCompare(a.id))) {\n flattened.push({ turn_id: turnId, event });\n }\n }\n const page = paginateSessionEventRows(\n flattened.slice(cursor.offset, cursor.offset + input.limit + 1),\n input.limit,\n cursor,\n );\n return { data: deepCopy(page.data), pagination: page.pagination };\n }\n\n /**\n * Full chain (oldest first, anchor last). `ancestor_ids` may be only the\n * previous N ancestors, so spill through the oldest ancestor's own window\n * until a root or gap. A missing turn or repeated id ends the walk.\n */\n private resolveAncestorChain(sessionId: string, anchor: TurnRecord<TTurnCustom>): string[] {\n const chain = [...anchor.ancestor_ids, anchor.turn_id];\n const seen = new Set(chain);\n let oldestId = chain[0];\n while (oldestId && oldestId !== anchor.turn_id) {\n const oldest = this.turns.get(turnKey({ session_id: sessionId, turn_id: oldestId }));\n if (!oldest) {\n break;\n }\n const older = oldest.ancestor_ids.filter(id => !seen.has(id));\n if (older.length === 0) {\n break;\n }\n chain.unshift(...older);\n for (const id of older) {\n seen.add(id);\n }\n oldestId = older[0];\n }\n return chain;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/agent-session/store/InMemorySessionStore.ts"],"sourcesContent":["import type { AgentThreadSnapshot } from '../../core/runtime/AgentThread.types';\nimport { getEmptyCurrentContextUsage } from '../../core/runtime/contextUsage';\nimport type { SessionRecord } from '../models/SessionRecord';\nimport type { TurnRecord, TurnSnapshot } from '../models/TurnRecord';\nimport type { PersistedTurnEvent, SessionEventItem } from '../schemas/events';\nimport type { TokenPagination } from '../schemas/pagination';\nimport type { TerminalTurnState } from '../schemas/turn';\nimport { assertCreateTurnThreadDelta } from './assertCreateTurnThreadDelta';\nimport type {\n AddThreadsInput,\n AppendToEventsInput,\n AppendToThreadContextInput,\n CreateSessionInput,\n CreateTurnInput,\n DeleteSessionInput,\n FreezeAndGetTurnInput,\n GetSessionByExternalIdInput,\n GetSessionInput,\n GetTurnInput,\n ISessionStore,\n ListSessionEventsInput,\n ListSessionsInput,\n ListTurnEventsInput,\n ListTurnsInput,\n NewThreadInit,\n OverwriteThreadContextInput,\n PatchMCPServersInput,\n PatchSandboxInfoInput,\n PatchThreadCapabilityStateInput,\n RemoveThreadsInput,\n TurnContextAppend,\n TurnRecordWithoutSnapshot,\n UpdateSessionInput,\n UpdateTurnStateInput,\n} from './ISessionStore';\nimport { decodeOffsetPageToken, encodeOffsetPageToken } from './OffsetPageToken';\nimport {\n decodeSessionEventPageToken,\n paginateSessionEventRows,\n type SessionEventPageCursor,\n} from './SessionEventPageToken';\nimport { decodeSessionListPageToken, paginateSessionListRows } from './SessionListPageToken';\nimport {\n PreviousTurnRunningError,\n SessionAlreadyExistsError,\n SessionExternalIdConflictError,\n SessionNotFoundError,\n SessionStoreInvariantError,\n TurnAlreadyExistsError,\n TurnNotFoundError,\n TurnNotRunningError,\n} from './SessionStoreErrors';\n\n/* eslint-disable @typescript-eslint/require-await -- in-memory store is synchronous; methods stay async so thrown SessionStore*Error reject as Promises for ISessionStore callers */\n\ntype StoredEvent = PersistedTurnEvent;\n\ninterface StoredSession<TSessionCustom extends object> {\n record: SessionRecord<TSessionCustom>;\n turnIds: string[];\n}\n\nfunction deepCopy<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction sessionKey(sessionId: string): string {\n return sessionId;\n}\n\nfunction turnKey({ session_id, turn_id }: { session_id: string; turn_id: string }): string {\n return `${session_id}:${turn_id}`;\n}\n\n/** Lexicographic session_id order — shared by listSessions sort and keyset filter. */\nfunction compareSessionId(a: string, b: string): number {\n if (a < b) {\n return -1;\n }\n if (a > b) {\n return 1;\n }\n return 0;\n}\n\nfunction newThreadSnapshot(thread: NewThreadInit): AgentThreadSnapshot {\n return {\n thread_id: thread.thread_id,\n parent: thread.parent ?? null,\n agent_info: thread.agent_info ?? null,\n capability_state: null,\n context: [],\n current_context_usage: getEmptyCurrentContextUsage(),\n completion: null,\n };\n}\n\nfunction applyContextAppends(threads: Record<string, AgentThreadSnapshot>, appends: TurnContextAppend[]): void {\n for (const append of appends) {\n const thread = threads[append.thread_id];\n if (!thread) {\n throw new SessionStoreInvariantError(`new_context_appends references unknown thread ${append.thread_id}`);\n }\n thread.context.push(...deepCopy(append.context));\n if (append.current_context_usage !== null) {\n thread.current_context_usage = deepCopy(append.current_context_usage);\n }\n }\n}\n\nfunction buildSnapshotFromDelta(input: {\n previousSnapshot: TurnSnapshot | undefined;\n new_threads: NewThreadInit[];\n new_context_appends: TurnContextAppend[];\n capability_states: CreateTurnInput['capability_states'];\n}): TurnSnapshot {\n const threads: Record<string, AgentThreadSnapshot> = input.previousSnapshot\n ? deepCopy(input.previousSnapshot.threads)\n : {};\n\n assertCreateTurnThreadDelta({\n previousThreadIds: new Set(Object.keys(threads)),\n new_threads: input.new_threads,\n new_context_appends: input.new_context_appends,\n capability_states: input.capability_states,\n });\n\n for (const nt of input.new_threads) {\n threads[nt.thread_id] = newThreadSnapshot(nt);\n }\n\n applyContextAppends(threads, input.new_context_appends);\n for (const capability of input.capability_states) {\n const thread = threads[capability.thread_id];\n if (thread === undefined) {\n throw new SessionStoreInvariantError(`capability_states references unknown thread ${capability.thread_id}`);\n }\n thread.capability_state = deepCopy(capability.capability_state);\n }\n\n return {\n threads,\n mcp_servers: input.previousSnapshot ? deepCopy(input.previousSnapshot.mcp_servers) : null,\n sandbox_info: input.previousSnapshot ? deepCopy(input.previousSnapshot.sandbox_info) : null,\n };\n}\n\nfunction paginate<T>(items: T[], limit: number, pageToken?: string): { data: T[]; pagination: TokenPagination } {\n const offset = decodeOffsetPageToken(pageToken);\n const slice = items.slice(offset, offset + limit);\n return {\n data: slice,\n pagination: {\n limit,\n ...(offset + limit < items.length ? { next_page_token: encodeOffsetPageToken(offset + limit) } : {}),\n ...(offset > 0 ? { previous_page_token: encodeOffsetPageToken(Math.max(0, offset - limit)) } : {}),\n },\n };\n}\n\n/**\n * Reference ISessionStore implementation. Proves the contract without SSE/subscription\n * hooks. Deep-copies on read/write boundaries so callers cannot mutate stored state.\n */\nexport class InMemorySessionStore<\n TSessionCustom extends object = Record<string, never>,\n TTurnCustom extends object = Record<string, never>,\n> implements ISessionStore<TSessionCustom, TTurnCustom> {\n private readonly sessions = new Map<string, StoredSession<TSessionCustom>>();\n private readonly turns = new Map<string, TurnRecord<TTurnCustom>>();\n private readonly events = new Map<string, StoredEvent[]>();\n\n async createSession(input: CreateSessionInput<TSessionCustom>): Promise<void> {\n const key = sessionKey(input.session_id);\n if (this.sessions.has(key)) {\n throw new SessionAlreadyExistsError(input.session_id);\n }\n const externalId = input.external_id;\n if (externalId !== null) {\n for (const stored of this.sessions.values()) {\n if (stored.record.tenant_id === input.tenant_id && stored.record.external_id === externalId) {\n throw new SessionExternalIdConflictError(externalId);\n }\n }\n }\n const now = new Date();\n const record: SessionRecord<TSessionCustom> = {\n tenant_id: input.tenant_id,\n session_id: input.session_id,\n created_by_subject: input.created_by_subject,\n agent: deepCopy(input.agent),\n title: null,\n last_turn_id: null,\n external_id: externalId,\n created_at: now,\n updated_at: now,\n last_activity_timestamp_ms: Date.now(),\n metrics: {\n total_cost_in_usd: 0,\n total_duration_ms: 0,\n total_turns: 0,\n },\n metadata: deepCopy(input.metadata),\n custom: input.custom !== null ? deepCopy(input.custom) : null,\n };\n this.sessions.set(key, { record, turnIds: [] });\n return;\n }\n\n async deleteSession(input: DeleteSessionInput): Promise<void> {\n const sKey = sessionKey(input.session_id);\n const stored = this.sessions.get(sKey);\n if (stored?.record.tenant_id !== input.tenant_id) {\n return;\n }\n for (const turnId of stored.turnIds) {\n const tKey = turnKey({ session_id: input.session_id, turn_id: turnId });\n this.turns.delete(tKey);\n this.events.delete(tKey);\n }\n this.sessions.delete(sKey);\n }\n\n async getSession(input: GetSessionInput): Promise<SessionRecord<TSessionCustom> | undefined> {\n const stored = this.sessions.get(sessionKey(input.session_id));\n return stored?.record.tenant_id === input.tenant_id ? deepCopy(stored.record) : undefined;\n }\n\n async getSessionByExternalId(input: GetSessionByExternalIdInput): Promise<SessionRecord<TSessionCustom> | undefined> {\n for (const stored of this.sessions.values()) {\n if (stored.record.tenant_id === input.tenant_id && stored.record.external_id === input.external_id) {\n return deepCopy(stored.record);\n }\n }\n return undefined;\n }\n\n async updateSession(input: UpdateSessionInput<TSessionCustom>): Promise<void> {\n const key = sessionKey(input.session_id);\n const stored = this.sessions.get(key);\n if (stored?.record.tenant_id !== input.tenant_id) {\n throw new SessionNotFoundError(input.session_id);\n }\n if (input.agent !== undefined) {\n if (stored.record.agent.type === 'reference') {\n throw new SessionStoreInvariantError(`Session ${input.session_id} is named; agent cannot be updated`);\n }\n stored.record.agent = deepCopy(input.agent);\n }\n if (input.title !== undefined) {\n stored.record.title = input.title;\n }\n if (input.metadata !== undefined) {\n stored.record.metadata = deepCopy(input.metadata);\n }\n const now = Date.now();\n stored.record.updated_at = new Date(now);\n stored.record.last_activity_timestamp_ms = now;\n return;\n }\n\n async listSessions(\n input: ListSessionsInput,\n ): Promise<{ data: SessionRecord<TSessionCustom>[]; pagination: TokenPagination }> {\n const records: SessionRecord<TSessionCustom>[] = [];\n const createdByOrAgentIds = input.created_by_or_agent_ids;\n for (const stored of this.sessions.values()) {\n if (stored.record.tenant_id !== input.tenant_id) {\n continue;\n }\n if (\n input.agent_id !== undefined &&\n (stored.record.agent.type !== 'reference' || stored.record.agent.id !== input.agent_id)\n ) {\n continue;\n }\n if (createdByOrAgentIds !== undefined) {\n const creatorMatches =\n stored.record.created_by_subject.subject_id === createdByOrAgentIds.created_by_subject_id;\n const agentMatches =\n stored.record.agent.type === 'reference' && createdByOrAgentIds.agent_ids.includes(stored.record.agent.id);\n if (!creatorMatches && !agentMatches) {\n continue;\n }\n }\n const createdAt = stored.record.created_at.getTime();\n if (input.start_timestamp !== undefined && createdAt < input.start_timestamp.getTime()) {\n continue;\n }\n if (input.end_timestamp !== undefined && createdAt > input.end_timestamp.getTime()) {\n continue;\n }\n records.push(stored.record);\n }\n records.sort((a, b) => {\n const aTime = a.updated_at.getTime();\n const bTime = b.updated_at.getTime();\n if (aTime !== bTime) {\n return input.order === 'asc' ? aTime - bTime : bTime - aTime;\n }\n // Same lexicographic order as the keyset predicate below (and Postgres/SQLite).\n return input.order === 'asc'\n ? compareSessionId(a.session_id, b.session_id)\n : compareSessionId(b.session_id, a.session_id);\n });\n\n let filtered = records;\n const cursor = decodeSessionListPageToken(input.page_token);\n if (cursor) {\n const cursorTime = new Date(cursor.updated_at).getTime();\n filtered = records.filter(record => {\n const t = record.updated_at.getTime();\n const idCmp = compareSessionId(record.session_id, cursor.session_id);\n if (input.order === 'asc') {\n return t > cursorTime || (t === cursorTime && idCmp > 0);\n }\n return t < cursorTime || (t === cursorTime && idCmp < 0);\n });\n }\n\n const page = paginateSessionListRows(filtered, input.limit, row => row.updated_at.toISOString());\n return { data: deepCopy(page.data), pagination: page.pagination };\n }\n\n async createTurn(input: CreateTurnInput<TTurnCustom>): Promise<void> {\n // Atomicity is free here: this body is fully synchronous, so Node's\n // run-to-completion guarantees it. Real backends must still use their own\n // locking/transactions to satisfy the ISessionStore createTurn contract.\n const sKey = sessionKey(input.turn.session_id);\n const stored = this.sessions.get(sKey);\n if (!stored) {\n throw new SessionNotFoundError(input.turn.session_id);\n }\n\n const previousTurnId = input.turn.previous_turn_id;\n let previousSnapshot: TurnSnapshot | undefined;\n if (previousTurnId !== null) {\n const prevKey = turnKey({ session_id: input.turn.session_id, turn_id: previousTurnId });\n const prev = this.turns.get(prevKey);\n // Unknown previous_turn_id is allowed (relaxed): treat as no inheritance.\n // A still-running previous must be frozen first.\n if (prev !== undefined) {\n if (prev.state.status === 'running') {\n throw new PreviousTurnRunningError(previousTurnId);\n }\n previousSnapshot = prev.snapshot;\n }\n }\n\n const tKey = turnKey(input.turn);\n if (this.turns.has(tKey)) {\n throw new TurnAlreadyExistsError(input.turn.turn_id);\n }\n\n const snapshot = buildSnapshotFromDelta({\n previousSnapshot,\n new_threads: input.new_threads,\n new_context_appends: input.new_context_appends,\n capability_states: input.capability_states,\n });\n\n const turnRecord: TurnRecord<TTurnCustom> = {\n ...deepCopy(input.turn),\n snapshot,\n };\n\n this.turns.set(tKey, turnRecord);\n this.events.set(tKey, []);\n stored.turnIds.push(input.turn.turn_id);\n stored.record.last_turn_id = input.turn.turn_id;\n stored.record.metrics.total_turns += 1;\n stored.record.last_activity_timestamp_ms = Date.now();\n stored.record.updated_at = new Date();\n if (input.update_session_title_if_not_exist !== null && stored.record.title === null) {\n stored.record.title = input.update_session_title_if_not_exist;\n }\n }\n\n async freezeAndGetTurn(input: FreezeAndGetTurnInput): Promise<TurnRecord<TTurnCustom>> {\n const tKey = turnKey(input);\n const turn = this.requireTurn(input.session_id, input.turn_id);\n\n if (turn.state.status === 'running') {\n const cancelledState: TerminalTurnState = {\n status: 'cancelled',\n reason: input.reason,\n completed_at: new Date().toISOString(),\n };\n turn.state = cancelledState;\n turn.updated_at = new Date();\n const list = this.events.get(tKey);\n if (list) {\n list.push(deepCopy(input.turn_done_event));\n }\n this.addTerminalSessionMetrics(input.session_id, turn.created_at, cancelledState);\n }\n\n return deepCopy(turn);\n }\n\n async getTurn(input: GetTurnInput): Promise<TurnRecord<TTurnCustom> | undefined> {\n const turn = this.turns.get(turnKey(input));\n return turn ? deepCopy(turn) : undefined;\n }\n\n async listTurns(\n input: ListTurnsInput,\n ): Promise<{ data: TurnRecordWithoutSnapshot<TTurnCustom>[]; pagination: TokenPagination }> {\n const stored = this.sessions.get(sessionKey(input.session_id));\n if (!stored) {\n throw new SessionNotFoundError(input.session_id);\n }\n const records = stored.turnIds.map(id => {\n const turn = this.turns.get(turnKey({ session_id: input.session_id, turn_id: id }));\n if (!turn) {\n throw new TurnNotFoundError(id);\n }\n const { snapshot, ...row } = deepCopy(turn);\n void snapshot;\n return row;\n });\n return paginate(records, input.limit, input.page_token);\n }\n\n async updateTurnState(input: UpdateTurnStateInput): Promise<void> {\n // Same as createTurn: synchronous body ⇒ atomic under run-to-completion.\n const tKey = turnKey(input);\n const turn = this.requireTurn(input.session_id, input.turn_id);\n if (turn.state.status !== 'running') {\n throw new TurnNotRunningError(input.turn_id, turn.state);\n }\n turn.state = deepCopy(input.state);\n turn.updated_at = new Date();\n const list = this.events.get(tKey);\n if (list) {\n list.push(deepCopy(input.turn_done_event));\n }\n this.addTerminalSessionMetrics(input.session_id, turn.created_at, input.state);\n }\n\n async appendToEvents(input: AppendToEventsInput): Promise<void> {\n this.requireRunningTurn(input.session_id, input.turn_id);\n const tKey = turnKey(input);\n const list = this.events.get(tKey);\n if (!list) {\n throw new TurnNotFoundError(input.turn_id);\n }\n list.push(...deepCopy(input.events));\n return;\n }\n\n /** Cost from turn metrics; duration is completed_at − created_at, floored at 0. */\n private addTerminalSessionMetrics(sessionId: string, created_at: Date, state: TerminalTurnState): void {\n const stored = this.sessions.get(sessionKey(sessionId));\n if (!stored) {\n throw new SessionNotFoundError(sessionId);\n }\n const elapsed_ms = Date.parse(state.completed_at) - created_at.getTime();\n stored.record.metrics.total_cost_in_usd += state.metrics?.total_cost_in_usd ?? 0;\n stored.record.metrics.total_duration_ms += elapsed_ms > 0 ? Math.trunc(elapsed_ms) : 0;\n }\n\n private requireTurn(sessionId: string, turnId: string): TurnRecord<TTurnCustom> {\n const turn = this.turns.get(turnKey({ session_id: sessionId, turn_id: turnId }));\n if (!turn) {\n throw new TurnNotFoundError(turnId);\n }\n return turn;\n }\n\n private requireRunningTurn(sessionId: string, turnId: string): TurnRecord<TTurnCustom> {\n const turn = this.requireTurn(sessionId, turnId);\n if (turn.state.status !== 'running') {\n throw new TurnNotRunningError(turnId, turn.state);\n }\n return turn;\n }\n\n async addThreads(input: AddThreadsInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n for (const thread of input.threads) {\n turn.snapshot.threads[thread.thread_id] = deepCopy(thread);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async removeThreads(input: RemoveThreadsInput): Promise<void> {\n if (input.thread_ids.length === 0) {\n return;\n }\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n for (const id of input.thread_ids) {\n Reflect.deleteProperty(turn.snapshot.threads, id);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async appendToThreadContext(input: AppendToThreadContextInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n const thread = turn.snapshot.threads[input.thread_id];\n if (!thread) {\n throw new SessionStoreInvariantError(`Thread not found: ${input.thread_id}`);\n }\n thread.context.push(...deepCopy(input.context));\n if (input.current_context_usage !== null) {\n thread.current_context_usage = deepCopy(input.current_context_usage);\n }\n if (input.completion !== null) {\n thread.completion = deepCopy(input.completion);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async overwriteThreadContext(input: OverwriteThreadContextInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n const threadId = input.event.thread_id;\n const thread = turn.snapshot.threads[threadId];\n if (!thread) {\n throw new SessionStoreInvariantError(`Thread not found: ${threadId}`);\n }\n thread.context = deepCopy(input.event.context);\n thread.current_context_usage = deepCopy(input.event.current_context_usage);\n turn.updated_at = new Date();\n return;\n }\n\n async patchMCPServers(input: PatchMCPServersInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n turn.snapshot.mcp_servers ??= {};\n for (const server of input.mcp_servers) {\n turn.snapshot.mcp_servers[server.id] = deepCopy(server);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async patchSandboxInfo(input: PatchSandboxInfoInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n turn.snapshot.sandbox_info = deepCopy(input.sandbox_info);\n turn.updated_at = new Date();\n return;\n }\n\n async patchThreadCapabilityState(input: PatchThreadCapabilityStateInput): Promise<void> {\n const turn = this.requireRunningTurn(input.session_id, input.turn_id);\n const thread = turn.snapshot.threads[input.thread_id];\n if (!thread) {\n throw new SessionStoreInvariantError(`Thread not found: ${input.thread_id}`);\n }\n thread.capability_state ??= {};\n if (input.state === null) {\n Reflect.deleteProperty(thread.capability_state, input.key);\n if (Object.keys(thread.capability_state).length === 0) {\n thread.capability_state = null;\n }\n } else {\n thread.capability_state[input.key] = deepCopy(input.state);\n }\n turn.updated_at = new Date();\n return;\n }\n\n async listTurnEvents(input: ListTurnEventsInput): Promise<{\n data: PersistedTurnEvent[];\n pagination: TokenPagination;\n }> {\n this.requireTurn(input.session_id, input.turn_id);\n const list = this.events.get(turnKey(input));\n if (!list) {\n throw new TurnNotFoundError(input.turn_id);\n }\n const ordered = [...list].sort((a, b) =>\n input.order === 'desc' ? b.id.localeCompare(a.id) : a.id.localeCompare(b.id),\n );\n const page = paginate(ordered, input.limit, input.page_token);\n return { data: deepCopy(page.data), pagination: page.pagination };\n }\n\n async listSessionEvents(input: ListSessionEventsInput): Promise<{\n data: SessionEventItem[];\n pagination: TokenPagination;\n }> {\n const stored = this.sessions.get(sessionKey(input.session_id));\n if (!stored) {\n throw new SessionNotFoundError(input.session_id);\n }\n\n const decodedCursor = input.page_token === undefined ? undefined : decodeSessionEventPageToken(input.page_token);\n const lastTurnId = decodedCursor?.last_turn_id ?? input.last_turn_id ?? stored.record.last_turn_id;\n if (lastTurnId === null) {\n return { data: [], pagination: { limit: input.limit } };\n }\n const cursor: SessionEventPageCursor = {\n last_turn_id: lastTurnId,\n offset: decodedCursor?.offset ?? 0,\n };\n\n const anchor = this.turns.get(turnKey({ session_id: input.session_id, turn_id: cursor.last_turn_id }));\n if (!anchor) {\n throw new TurnNotFoundError(cursor.last_turn_id);\n }\n const turnIds = this.resolveAncestorChain(input.session_id, anchor);\n const flattened: SessionEventItem[] = [];\n for (const turnId of [...turnIds].reverse()) {\n const evts = this.events.get(turnKey({ session_id: input.session_id, turn_id: turnId })) ?? [];\n for (const event of [...evts].sort((a, b) => b.id.localeCompare(a.id))) {\n flattened.push({ turn_id: turnId, event });\n }\n }\n const page = paginateSessionEventRows(\n flattened.slice(cursor.offset, cursor.offset + input.limit + 1),\n input.limit,\n cursor,\n );\n return { data: deepCopy(page.data), pagination: page.pagination };\n }\n\n /**\n * Full chain (oldest first, anchor last). `ancestor_ids` may be only the\n * previous N ancestors, so spill through the oldest ancestor's own window\n * until a root or gap. A missing turn or repeated id ends the walk.\n */\n private resolveAncestorChain(sessionId: string, anchor: TurnRecord<TTurnCustom>): string[] {\n const chain = [...anchor.ancestor_ids, anchor.turn_id];\n const seen = new Set(chain);\n let oldestId = chain[0];\n while (oldestId && oldestId !== anchor.turn_id) {\n const oldest = this.turns.get(turnKey({ session_id: sessionId, turn_id: oldestId }));\n if (!oldest) {\n break;\n }\n const older = oldest.ancestor_ids.filter(id => !seen.has(id));\n if (older.length === 0) {\n break;\n }\n chain.unshift(...older);\n for (const id of older) {\n seen.add(id);\n }\n oldestId = older[0];\n }\n return chain;\n }\n}\n"],"mappings":"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","names":[]}
@@ -23,6 +23,10 @@ export declare class SessionAlreadyExistsError extends SessionStoreConflictError
23
23
  readonly session_id: string;
24
24
  constructor(session_id: string, options?: ErrorOptions);
25
25
  }
26
+ export declare class SessionExternalIdConflictError extends SessionStoreConflictError {
27
+ readonly external_id: string;
28
+ constructor(external_id: string, options?: ErrorOptions);
29
+ }
26
30
  export declare class TurnAlreadyExistsError extends SessionStoreConflictError {
27
31
  readonly turn_id: string;
28
32
  constructor(turn_id: string, options?: ErrorOptions);
@@ -1 +1 @@
1
- {"version":3,"file":"SessionStoreErrors.d.ts","sourceRoot":"","sources":["../../../src/agent-session/store/SessionStoreErrors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,kFAAkF;AAClF,8BAAsB,yBAA0B,SAAQ,KAAK;IAC3D,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,iDAAiD;AACjD,8BAAsB,yBAA0B,SAAQ,KAAK;IAC3D,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,+EAA+E;AAC/E,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,qBAAa,oBAAqB,SAAQ,yBAAyB;IACjE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,YAAY,UAAU,EAAE,MAAM,EAI7B;CACF;AAED,qBAAa,iBAAkB,SAAQ,yBAAyB;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,YAAY,OAAO,EAAE,MAAM,EAI1B;CACF;AAED,qBAAa,yBAA0B,SAAQ,yBAAyB;IACtE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,YAAY,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAIrD;CACF;AAED,qBAAa,sBAAuB,SAAQ,yBAAyB;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAIlD;CACF;AAED,qBAAa,wBAAyB,SAAQ,yBAAyB;IACrE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC,YAAY,gBAAgB,EAAE,MAAM,EAMnC;CACF;AAED,qBAAa,mBAAoB,SAAQ,yBAAyB;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAElC,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAKpD;CACF;AAED,qBAAa,qBAAsB,SAAQ,yBAAyB;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,YAAY,KAAK,EAAE,MAAM,EAIxB;CACF"}
1
+ {"version":3,"file":"SessionStoreErrors.d.ts","sourceRoot":"","sources":["../../../src/agent-session/store/SessionStoreErrors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,kFAAkF;AAClF,8BAAsB,yBAA0B,SAAQ,KAAK;IAC3D,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,iDAAiD;AACjD,8BAAsB,yBAA0B,SAAQ,KAAK;IAC3D,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,+EAA+E;AAC/E,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,qBAAa,oBAAqB,SAAQ,yBAAyB;IACjE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,YAAY,UAAU,EAAE,MAAM,EAI7B;CACF;AAED,qBAAa,iBAAkB,SAAQ,yBAAyB;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,YAAY,OAAO,EAAE,MAAM,EAI1B;CACF;AAED,qBAAa,yBAA0B,SAAQ,yBAAyB;IACtE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,YAAY,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAIrD;CACF;AAED,qBAAa,8BAA+B,SAAQ,yBAAyB;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,YAAY,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAItD;CACF;AAED,qBAAa,sBAAuB,SAAQ,yBAAyB;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAIlD;CACF;AAED,qBAAa,wBAAyB,SAAQ,yBAAyB;IACrE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC,YAAY,gBAAgB,EAAE,MAAM,EAMnC;CACF;AAED,qBAAa,mBAAoB,SAAQ,yBAAyB;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAElC,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAKpD;CACF;AAED,qBAAa,qBAAsB,SAAQ,yBAAyB;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,YAAY,KAAK,EAAE,MAAM,EAIxB;CACF"}
@@ -23,6 +23,7 @@ __export(SessionStoreErrors_exports, {
23
23
  InvalidPageTokenError: () => InvalidPageTokenError,
24
24
  PreviousTurnRunningError: () => PreviousTurnRunningError,
25
25
  SessionAlreadyExistsError: () => SessionAlreadyExistsError,
26
+ SessionExternalIdConflictError: () => SessionExternalIdConflictError,
26
27
  SessionNotFoundError: () => SessionNotFoundError,
27
28
  SessionStoreConflictError: () => SessionStoreConflictError,
28
29
  SessionStoreInvariantError: () => SessionStoreInvariantError,
@@ -74,6 +75,14 @@ var SessionAlreadyExistsError = class extends SessionStoreConflictError {
74
75
  this.session_id = session_id;
75
76
  }
76
77
  };
78
+ var SessionExternalIdConflictError = class extends SessionStoreConflictError {
79
+ external_id;
80
+ constructor(external_id, options) {
81
+ super(`Session already exists for external id: ${external_id}`, options);
82
+ this.name = "SessionExternalIdConflictError";
83
+ this.external_id = external_id;
84
+ }
85
+ };
77
86
  var TurnAlreadyExistsError = class extends SessionStoreConflictError {
78
87
  turn_id;
79
88
  constructor(turn_id, options) {
@@ -115,6 +124,7 @@ var InvalidPageTokenError = class extends SessionStoreConflictError {
115
124
  InvalidPageTokenError,
116
125
  PreviousTurnRunningError,
117
126
  SessionAlreadyExistsError,
127
+ SessionExternalIdConflictError,
118
128
  SessionNotFoundError,
119
129
  SessionStoreConflictError,
120
130
  SessionStoreInvariantError,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/agent-session/store/SessionStoreErrors.ts"],"sourcesContent":["import type { TerminalTurnState } from '../schemas/turn';\n\n/** Store conflict (e.g. first-terminal-wins violation, concurrent createTurn). */\nexport abstract class SessionStoreConflictError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreConflictError';\n }\n}\n\n/** Store not-found (session or turn missing). */\nexport abstract class SessionStoreNotFoundError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreNotFoundError';\n }\n}\n\n/** Implementation bug or thread misuse — not mapped to 4xx by API handlers. */\nexport class SessionStoreInvariantError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreInvariantError';\n }\n}\n\nexport class SessionNotFoundError extends SessionStoreNotFoundError {\n readonly session_id: string;\n\n constructor(session_id: string) {\n super(`Session not found: ${session_id}`);\n this.name = 'SessionNotFoundError';\n this.session_id = session_id;\n }\n}\n\nexport class TurnNotFoundError extends SessionStoreNotFoundError {\n readonly turn_id: string;\n\n constructor(turn_id: string) {\n super(`Turn not found: ${turn_id}`);\n this.name = 'TurnNotFoundError';\n this.turn_id = turn_id;\n }\n}\n\nexport class SessionAlreadyExistsError extends SessionStoreConflictError {\n readonly session_id: string;\n\n constructor(session_id: string, options?: ErrorOptions) {\n super(`Session already exists: ${session_id}`, options);\n this.name = 'SessionAlreadyExistsError';\n this.session_id = session_id;\n }\n}\n\nexport class TurnAlreadyExistsError extends SessionStoreConflictError {\n readonly turn_id: string;\n\n constructor(turn_id: string, options?: ErrorOptions) {\n super(`Turn already exists: ${turn_id}`, options);\n this.name = 'TurnAlreadyExistsError';\n this.turn_id = turn_id;\n }\n}\n\nexport class PreviousTurnRunningError extends SessionStoreConflictError {\n readonly previous_turn_id: string;\n\n constructor(previous_turn_id: string) {\n super(\n `Previous turn ${previous_turn_id} is still running; freezeAndGetTurn must be called before creating a successor`,\n );\n this.name = 'PreviousTurnRunningError';\n this.previous_turn_id = previous_turn_id;\n }\n}\n\nexport class TurnNotRunningError extends SessionStoreConflictError {\n readonly turn_id: string;\n readonly state: TerminalTurnState;\n\n constructor(turn_id: string, state: TerminalTurnState) {\n super(`Turn ${turn_id} is not running (${state.status})`);\n this.name = 'TurnNotRunningError';\n this.turn_id = turn_id;\n this.state = state;\n }\n}\n\nexport class InvalidPageTokenError extends SessionStoreConflictError {\n readonly token: string;\n\n constructor(token: string) {\n super(`Invalid page token: ${token}`);\n this.name = 'InvalidPageTokenError';\n this.token = token;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EACpD,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,0BAA0B;AAAA,EACzD;AAAA,EAET,YAAY,YAAoB;AAC9B,UAAM,sBAAsB,UAAU,EAAE;AACxC,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,oBAAN,cAAgC,0BAA0B;AAAA,EACtD;AAAA,EAET,YAAY,SAAiB;AAC3B,UAAM,mBAAmB,OAAO,EAAE;AAClC,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,4BAAN,cAAwC,0BAA0B;AAAA,EAC9D;AAAA,EAET,YAAY,YAAoB,SAAwB;AACtD,UAAM,2BAA2B,UAAU,IAAI,OAAO;AACtD,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,yBAAN,cAAqC,0BAA0B;AAAA,EAC3D;AAAA,EAET,YAAY,SAAiB,SAAwB;AACnD,UAAM,wBAAwB,OAAO,IAAI,OAAO;AAChD,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,2BAAN,cAAuC,0BAA0B;AAAA,EAC7D;AAAA,EAET,YAAY,kBAA0B;AACpC;AAAA,MACE,iBAAiB,gBAAgB;AAAA,IACnC;AACA,SAAK,OAAO;AACZ,SAAK,mBAAmB;AAAA,EAC1B;AACF;AAEO,IAAM,sBAAN,cAAkC,0BAA0B;AAAA,EACxD;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,OAA0B;AACrD,UAAM,QAAQ,OAAO,oBAAoB,MAAM,MAAM,GAAG;AACxD,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AACF;AAEO,IAAM,wBAAN,cAAoC,0BAA0B;AAAA,EAC1D;AAAA,EAET,YAAY,OAAe;AACzB,UAAM,uBAAuB,KAAK,EAAE;AACpC,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/agent-session/store/SessionStoreErrors.ts"],"sourcesContent":["import type { TerminalTurnState } from '../schemas/turn';\n\n/** Store conflict (e.g. first-terminal-wins violation, concurrent createTurn). */\nexport abstract class SessionStoreConflictError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreConflictError';\n }\n}\n\n/** Store not-found (session or turn missing). */\nexport abstract class SessionStoreNotFoundError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreNotFoundError';\n }\n}\n\n/** Implementation bug or thread misuse — not mapped to 4xx by API handlers. */\nexport class SessionStoreInvariantError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreInvariantError';\n }\n}\n\nexport class SessionNotFoundError extends SessionStoreNotFoundError {\n readonly session_id: string;\n\n constructor(session_id: string) {\n super(`Session not found: ${session_id}`);\n this.name = 'SessionNotFoundError';\n this.session_id = session_id;\n }\n}\n\nexport class TurnNotFoundError extends SessionStoreNotFoundError {\n readonly turn_id: string;\n\n constructor(turn_id: string) {\n super(`Turn not found: ${turn_id}`);\n this.name = 'TurnNotFoundError';\n this.turn_id = turn_id;\n }\n}\n\nexport class SessionAlreadyExistsError extends SessionStoreConflictError {\n readonly session_id: string;\n\n constructor(session_id: string, options?: ErrorOptions) {\n super(`Session already exists: ${session_id}`, options);\n this.name = 'SessionAlreadyExistsError';\n this.session_id = session_id;\n }\n}\n\nexport class SessionExternalIdConflictError extends SessionStoreConflictError {\n readonly external_id: string;\n\n constructor(external_id: string, options?: ErrorOptions) {\n super(`Session already exists for external id: ${external_id}`, options);\n this.name = 'SessionExternalIdConflictError';\n this.external_id = external_id;\n }\n}\n\nexport class TurnAlreadyExistsError extends SessionStoreConflictError {\n readonly turn_id: string;\n\n constructor(turn_id: string, options?: ErrorOptions) {\n super(`Turn already exists: ${turn_id}`, options);\n this.name = 'TurnAlreadyExistsError';\n this.turn_id = turn_id;\n }\n}\n\nexport class PreviousTurnRunningError extends SessionStoreConflictError {\n readonly previous_turn_id: string;\n\n constructor(previous_turn_id: string) {\n super(\n `Previous turn ${previous_turn_id} is still running; freezeAndGetTurn must be called before creating a successor`,\n );\n this.name = 'PreviousTurnRunningError';\n this.previous_turn_id = previous_turn_id;\n }\n}\n\nexport class TurnNotRunningError extends SessionStoreConflictError {\n readonly turn_id: string;\n readonly state: TerminalTurnState;\n\n constructor(turn_id: string, state: TerminalTurnState) {\n super(`Turn ${turn_id} is not running (${state.status})`);\n this.name = 'TurnNotRunningError';\n this.turn_id = turn_id;\n this.state = state;\n }\n}\n\nexport class InvalidPageTokenError extends SessionStoreConflictError {\n readonly token: string;\n\n constructor(token: string) {\n super(`Invalid page token: ${token}`);\n this.name = 'InvalidPageTokenError';\n this.token = token;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EACpD,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,0BAA0B;AAAA,EACzD;AAAA,EAET,YAAY,YAAoB;AAC9B,UAAM,sBAAsB,UAAU,EAAE;AACxC,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,oBAAN,cAAgC,0BAA0B;AAAA,EACtD;AAAA,EAET,YAAY,SAAiB;AAC3B,UAAM,mBAAmB,OAAO,EAAE;AAClC,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,4BAAN,cAAwC,0BAA0B;AAAA,EAC9D;AAAA,EAET,YAAY,YAAoB,SAAwB;AACtD,UAAM,2BAA2B,UAAU,IAAI,OAAO;AACtD,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,iCAAN,cAA6C,0BAA0B;AAAA,EACnE;AAAA,EAET,YAAY,aAAqB,SAAwB;AACvD,UAAM,2CAA2C,WAAW,IAAI,OAAO;AACvE,SAAK,OAAO;AACZ,SAAK,cAAc;AAAA,EACrB;AACF;AAEO,IAAM,yBAAN,cAAqC,0BAA0B;AAAA,EAC3D;AAAA,EAET,YAAY,SAAiB,SAAwB;AACnD,UAAM,wBAAwB,OAAO,IAAI,OAAO;AAChD,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,2BAAN,cAAuC,0BAA0B;AAAA,EAC7D;AAAA,EAET,YAAY,kBAA0B;AACpC;AAAA,MACE,iBAAiB,gBAAgB;AAAA,IACnC;AACA,SAAK,OAAO;AACZ,SAAK,mBAAmB;AAAA,EAC1B;AACF;AAEO,IAAM,sBAAN,cAAkC,0BAA0B;AAAA,EACxD;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,OAA0B;AACrD,UAAM,QAAQ,OAAO,oBAAoB,MAAM,MAAM,GAAG;AACxD,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AACF;AAEO,IAAM,wBAAN,cAAoC,0BAA0B;AAAA,EAC1D;AAAA,EAET,YAAY,OAAe;AACzB,UAAM,uBAAuB,KAAK,EAAE;AACpC,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;","names":[]}
@@ -41,6 +41,14 @@ var SessionAlreadyExistsError = class extends SessionStoreConflictError {
41
41
  this.session_id = session_id;
42
42
  }
43
43
  };
44
+ var SessionExternalIdConflictError = class extends SessionStoreConflictError {
45
+ external_id;
46
+ constructor(external_id, options) {
47
+ super(`Session already exists for external id: ${external_id}`, options);
48
+ this.name = "SessionExternalIdConflictError";
49
+ this.external_id = external_id;
50
+ }
51
+ };
44
52
  var TurnAlreadyExistsError = class extends SessionStoreConflictError {
45
53
  turn_id;
46
54
  constructor(turn_id, options) {
@@ -81,6 +89,7 @@ export {
81
89
  InvalidPageTokenError,
82
90
  PreviousTurnRunningError,
83
91
  SessionAlreadyExistsError,
92
+ SessionExternalIdConflictError,
84
93
  SessionNotFoundError,
85
94
  SessionStoreConflictError,
86
95
  SessionStoreInvariantError,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/agent-session/store/SessionStoreErrors.ts"],"sourcesContent":["import type { TerminalTurnState } from '../schemas/turn';\n\n/** Store conflict (e.g. first-terminal-wins violation, concurrent createTurn). */\nexport abstract class SessionStoreConflictError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreConflictError';\n }\n}\n\n/** Store not-found (session or turn missing). */\nexport abstract class SessionStoreNotFoundError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreNotFoundError';\n }\n}\n\n/** Implementation bug or thread misuse — not mapped to 4xx by API handlers. */\nexport class SessionStoreInvariantError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreInvariantError';\n }\n}\n\nexport class SessionNotFoundError extends SessionStoreNotFoundError {\n readonly session_id: string;\n\n constructor(session_id: string) {\n super(`Session not found: ${session_id}`);\n this.name = 'SessionNotFoundError';\n this.session_id = session_id;\n }\n}\n\nexport class TurnNotFoundError extends SessionStoreNotFoundError {\n readonly turn_id: string;\n\n constructor(turn_id: string) {\n super(`Turn not found: ${turn_id}`);\n this.name = 'TurnNotFoundError';\n this.turn_id = turn_id;\n }\n}\n\nexport class SessionAlreadyExistsError extends SessionStoreConflictError {\n readonly session_id: string;\n\n constructor(session_id: string, options?: ErrorOptions) {\n super(`Session already exists: ${session_id}`, options);\n this.name = 'SessionAlreadyExistsError';\n this.session_id = session_id;\n }\n}\n\nexport class TurnAlreadyExistsError extends SessionStoreConflictError {\n readonly turn_id: string;\n\n constructor(turn_id: string, options?: ErrorOptions) {\n super(`Turn already exists: ${turn_id}`, options);\n this.name = 'TurnAlreadyExistsError';\n this.turn_id = turn_id;\n }\n}\n\nexport class PreviousTurnRunningError extends SessionStoreConflictError {\n readonly previous_turn_id: string;\n\n constructor(previous_turn_id: string) {\n super(\n `Previous turn ${previous_turn_id} is still running; freezeAndGetTurn must be called before creating a successor`,\n );\n this.name = 'PreviousTurnRunningError';\n this.previous_turn_id = previous_turn_id;\n }\n}\n\nexport class TurnNotRunningError extends SessionStoreConflictError {\n readonly turn_id: string;\n readonly state: TerminalTurnState;\n\n constructor(turn_id: string, state: TerminalTurnState) {\n super(`Turn ${turn_id} is not running (${state.status})`);\n this.name = 'TurnNotRunningError';\n this.turn_id = turn_id;\n this.state = state;\n }\n}\n\nexport class InvalidPageTokenError extends SessionStoreConflictError {\n readonly token: string;\n\n constructor(token: string) {\n super(`Invalid page token: ${token}`);\n this.name = 'InvalidPageTokenError';\n this.token = token;\n }\n}\n"],"mappings":";AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EACpD,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,0BAA0B;AAAA,EACzD;AAAA,EAET,YAAY,YAAoB;AAC9B,UAAM,sBAAsB,UAAU,EAAE;AACxC,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,oBAAN,cAAgC,0BAA0B;AAAA,EACtD;AAAA,EAET,YAAY,SAAiB;AAC3B,UAAM,mBAAmB,OAAO,EAAE;AAClC,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,4BAAN,cAAwC,0BAA0B;AAAA,EAC9D;AAAA,EAET,YAAY,YAAoB,SAAwB;AACtD,UAAM,2BAA2B,UAAU,IAAI,OAAO;AACtD,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,yBAAN,cAAqC,0BAA0B;AAAA,EAC3D;AAAA,EAET,YAAY,SAAiB,SAAwB;AACnD,UAAM,wBAAwB,OAAO,IAAI,OAAO;AAChD,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,2BAAN,cAAuC,0BAA0B;AAAA,EAC7D;AAAA,EAET,YAAY,kBAA0B;AACpC;AAAA,MACE,iBAAiB,gBAAgB;AAAA,IACnC;AACA,SAAK,OAAO;AACZ,SAAK,mBAAmB;AAAA,EAC1B;AACF;AAEO,IAAM,sBAAN,cAAkC,0BAA0B;AAAA,EACxD;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,OAA0B;AACrD,UAAM,QAAQ,OAAO,oBAAoB,MAAM,MAAM,GAAG;AACxD,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AACF;AAEO,IAAM,wBAAN,cAAoC,0BAA0B;AAAA,EAC1D;AAAA,EAET,YAAY,OAAe;AACzB,UAAM,uBAAuB,KAAK,EAAE;AACpC,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/agent-session/store/SessionStoreErrors.ts"],"sourcesContent":["import type { TerminalTurnState } from '../schemas/turn';\n\n/** Store conflict (e.g. first-terminal-wins violation, concurrent createTurn). */\nexport abstract class SessionStoreConflictError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreConflictError';\n }\n}\n\n/** Store not-found (session or turn missing). */\nexport abstract class SessionStoreNotFoundError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreNotFoundError';\n }\n}\n\n/** Implementation bug or thread misuse — not mapped to 4xx by API handlers. */\nexport class SessionStoreInvariantError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'SessionStoreInvariantError';\n }\n}\n\nexport class SessionNotFoundError extends SessionStoreNotFoundError {\n readonly session_id: string;\n\n constructor(session_id: string) {\n super(`Session not found: ${session_id}`);\n this.name = 'SessionNotFoundError';\n this.session_id = session_id;\n }\n}\n\nexport class TurnNotFoundError extends SessionStoreNotFoundError {\n readonly turn_id: string;\n\n constructor(turn_id: string) {\n super(`Turn not found: ${turn_id}`);\n this.name = 'TurnNotFoundError';\n this.turn_id = turn_id;\n }\n}\n\nexport class SessionAlreadyExistsError extends SessionStoreConflictError {\n readonly session_id: string;\n\n constructor(session_id: string, options?: ErrorOptions) {\n super(`Session already exists: ${session_id}`, options);\n this.name = 'SessionAlreadyExistsError';\n this.session_id = session_id;\n }\n}\n\nexport class SessionExternalIdConflictError extends SessionStoreConflictError {\n readonly external_id: string;\n\n constructor(external_id: string, options?: ErrorOptions) {\n super(`Session already exists for external id: ${external_id}`, options);\n this.name = 'SessionExternalIdConflictError';\n this.external_id = external_id;\n }\n}\n\nexport class TurnAlreadyExistsError extends SessionStoreConflictError {\n readonly turn_id: string;\n\n constructor(turn_id: string, options?: ErrorOptions) {\n super(`Turn already exists: ${turn_id}`, options);\n this.name = 'TurnAlreadyExistsError';\n this.turn_id = turn_id;\n }\n}\n\nexport class PreviousTurnRunningError extends SessionStoreConflictError {\n readonly previous_turn_id: string;\n\n constructor(previous_turn_id: string) {\n super(\n `Previous turn ${previous_turn_id} is still running; freezeAndGetTurn must be called before creating a successor`,\n );\n this.name = 'PreviousTurnRunningError';\n this.previous_turn_id = previous_turn_id;\n }\n}\n\nexport class TurnNotRunningError extends SessionStoreConflictError {\n readonly turn_id: string;\n readonly state: TerminalTurnState;\n\n constructor(turn_id: string, state: TerminalTurnState) {\n super(`Turn ${turn_id} is not running (${state.status})`);\n this.name = 'TurnNotRunningError';\n this.turn_id = turn_id;\n this.state = state;\n }\n}\n\nexport class InvalidPageTokenError extends SessionStoreConflictError {\n readonly token: string;\n\n constructor(token: string) {\n super(`Invalid page token: ${token}`);\n this.name = 'InvalidPageTokenError';\n this.token = token;\n }\n}\n"],"mappings":";AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAe,4BAAf,cAAiD,MAAM;AAAA,EAC5D,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EACpD,YAAY,SAAiB,SAAwB;AACnD,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,0BAA0B;AAAA,EACzD;AAAA,EAET,YAAY,YAAoB;AAC9B,UAAM,sBAAsB,UAAU,EAAE;AACxC,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,oBAAN,cAAgC,0BAA0B;AAAA,EACtD;AAAA,EAET,YAAY,SAAiB;AAC3B,UAAM,mBAAmB,OAAO,EAAE;AAClC,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,4BAAN,cAAwC,0BAA0B;AAAA,EAC9D;AAAA,EAET,YAAY,YAAoB,SAAwB;AACtD,UAAM,2BAA2B,UAAU,IAAI,OAAO;AACtD,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,iCAAN,cAA6C,0BAA0B;AAAA,EACnE;AAAA,EAET,YAAY,aAAqB,SAAwB;AACvD,UAAM,2CAA2C,WAAW,IAAI,OAAO;AACvE,SAAK,OAAO;AACZ,SAAK,cAAc;AAAA,EACrB;AACF;AAEO,IAAM,yBAAN,cAAqC,0BAA0B;AAAA,EAC3D;AAAA,EAET,YAAY,SAAiB,SAAwB;AACnD,UAAM,wBAAwB,OAAO,IAAI,OAAO;AAChD,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,IAAM,2BAAN,cAAuC,0BAA0B;AAAA,EAC7D;AAAA,EAET,YAAY,kBAA0B;AACpC;AAAA,MACE,iBAAiB,gBAAgB;AAAA,IACnC;AACA,SAAK,OAAO;AACZ,SAAK,mBAAmB;AAAA,EAC1B;AACF;AAEO,IAAM,sBAAN,cAAkC,0BAA0B;AAAA,EACxD;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,OAA0B;AACrD,UAAM,QAAQ,OAAO,oBAAoB,MAAM,MAAM,GAAG;AACxD,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AACF;AAEO,IAAM,wBAAN,cAAoC,0BAA0B;AAAA,EAC1D;AAAA,EAET,YAAY,OAAe;AACzB,UAAM,uBAAuB,KAAK,EAAE;AACpC,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AACF;","names":[]}
@@ -3,6 +3,12 @@ import type { AgentDefinition } from '../../runtime/AgentDefinition';
3
3
  import type { AgentCapability } from '../AgentCapability';
4
4
  import type { AgentContextProcessorOutput, AgentThreadExecutionContext, PreLLMAgentContextProcessor } from '../AgentContextProcessor';
5
5
  export declare const DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS: number;
6
+ export declare const DEFAULT_CONTEXT_COMPACTION_RATIO = 0.8;
7
+ export declare function resolveCompactionThresholdTokens(input: {
8
+ configuredThresholdTokens: number | undefined;
9
+ modelContextLength: number | undefined;
10
+ modelParams: AgentDefinition['modelParams'];
11
+ }): number;
6
12
  export declare class ContextCompaction implements PreLLMAgentContextProcessor {
7
13
  private modelClient;
8
14
  private compactionThresholdTokens;
@@ -1 +1 @@
1
- {"version":3,"file":"ContextCompaction.d.ts","sourceRoot":"","sources":["../../../../src/core/capabilities/builtins/ContextCompaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAmB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EACV,2BAA2B,EAC3B,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAElC,eAAO,MAAM,2CAA2C,QAAY,CAAC;AA8JrE,qBAAa,iBAAkB,YAAW,2BAA2B;IACnE,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,yBAAyB,CAAS;IAE1C,YAAY,KAAK,EAAE;QAAE,WAAW,EAAE,IAAI,CAAC;QAAC,yBAAyB,EAAE,MAAM,CAAA;KAAE,EAG1E;IAEM,aAAa,CAClB,SAAS,EAAE,QAAQ,CAAC,2BAA2B,CAAC,GAC/C,cAAc,CAAC,2BAA2B,EAAE,IAAI,EAAE,OAAO,CAAC,CAkC5D;CACF;AAED,MAAM,WAAW,yBAAyB;IACxC,yBAAyB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;IACjD,yBAAyB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChD,GAAG,eAAe,CAalB"}
1
+ {"version":3,"file":"ContextCompaction.d.ts","sourceRoot":"","sources":["../../../../src/core/capabilities/builtins/ContextCompaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAmB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EACV,2BAA2B,EAC3B,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAElC,eAAO,MAAM,2CAA2C,QAAY,CAAC;AACrE,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAEpD,wBAAgB,gCAAgC,CAAC,KAAK,EAAE;IACtD,yBAAyB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,WAAW,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;CAC7C,GAAG,MAAM,CAqBT;AA8JD,qBAAa,iBAAkB,YAAW,2BAA2B;IACnE,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,yBAAyB,CAAS;IAE1C,YAAY,KAAK,EAAE;QAAE,WAAW,EAAE,IAAI,CAAC;QAAC,yBAAyB,EAAE,MAAM,CAAA;KAAE,EAG1E;IAEM,aAAa,CAClB,SAAS,EAAE,QAAQ,CAAC,2BAA2B,CAAC,GAC/C,cAAc,CAAC,2BAA2B,EAAE,IAAI,EAAE,OAAO,CAAC,CAkC5D;CACF;AAED,MAAM,WAAW,yBAAyB;IACxC,yBAAyB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;IACjD,yBAAyB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChD,GAAG,eAAe,CAclB"}
@@ -21,13 +21,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var ContextCompaction_exports = {};
22
22
  __export(ContextCompaction_exports, {
23
23
  ContextCompaction: () => ContextCompaction,
24
+ DEFAULT_CONTEXT_COMPACTION_RATIO: () => DEFAULT_CONTEXT_COMPACTION_RATIO,
24
25
  DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS: () => DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS,
25
- contextCompaction: () => contextCompaction
26
+ contextCompaction: () => contextCompaction,
27
+ resolveCompactionThresholdTokens: () => resolveCompactionThresholdTokens
26
28
  });
27
29
  module.exports = __toCommonJS(ContextCompaction_exports);
28
30
  var import_schema = require("../../events/schema.js");
29
31
  var import_contextUtils = require("../../runtime/contextUtils.js");
30
32
  var DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS = 50 * 1e3;
33
+ var DEFAULT_CONTEXT_COMPACTION_RATIO = 0.8;
34
+ function resolveCompactionThresholdTokens(input) {
35
+ if (input.configuredThresholdTokens !== void 0) {
36
+ return input.configuredThresholdTokens;
37
+ }
38
+ if (input.modelContextLength !== void 0) {
39
+ const ratioThreshold = Math.floor(input.modelContextLength * DEFAULT_CONTEXT_COMPACTION_RATIO);
40
+ const configuredMaxOutputTokens = input.modelParams?.["max_completion_tokens"] ?? input.modelParams?.["max_tokens"];
41
+ if (typeof configuredMaxOutputTokens === "number" && Number.isFinite(configuredMaxOutputTokens) && configuredMaxOutputTokens >= 0) {
42
+ const inputBudget = Math.floor(input.modelContextLength - configuredMaxOutputTokens);
43
+ if (inputBudget > 0) {
44
+ return Math.min(ratioThreshold, inputBudget);
45
+ }
46
+ }
47
+ return ratioThreshold;
48
+ }
49
+ return DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;
50
+ }
31
51
  var PROMPT_TOKENS = 931;
32
52
  var PROMPT = `
33
53
  Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
@@ -216,7 +236,11 @@ var ContextCompaction = class {
216
236
  }
217
237
  };
218
238
  function contextCompaction(options) {
219
- const threshold = options.compactionThresholdTokens ?? options.settings?.compactionThresholdTokens ?? DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;
239
+ const threshold = resolveCompactionThresholdTokens({
240
+ configuredThresholdTokens: options.compactionThresholdTokens ?? options.settings?.compactionThresholdTokens,
241
+ modelContextLength: options.definition.modelProperties?.contextLength,
242
+ modelParams: options.definition.modelParams
243
+ });
220
244
  return {
221
245
  preLLMProcessors: [
222
246
  new ContextCompaction({
@@ -229,7 +253,9 @@ function contextCompaction(options) {
229
253
  // Annotate the CommonJS export names for ESM import in node:
230
254
  0 && (module.exports = {
231
255
  ContextCompaction,
256
+ DEFAULT_CONTEXT_COMPACTION_RATIO,
232
257
  DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS,
233
- contextCompaction
258
+ contextCompaction,
259
+ resolveCompactionThresholdTokens
234
260
  });
235
261
  //# sourceMappingURL=ContextCompaction.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/capabilities/builtins/ContextCompaction.ts"],"sourcesContent":["import { EventType, newEventId } from '../../events/schema';\nimport type { ILLM, LLMCreateParams } from '../../llm/ILLM';\nimport type { AgentDefinition } from '../../runtime/AgentDefinition';\nimport type { ContextMessage } from '../../runtime/AgentThread.types';\nimport { internalSystemMessage, isInternalSystemMessage, isLLMContextMessage } from '../../runtime/contextUtils';\nimport type { AgentCapability } from '../AgentCapability';\nimport type {\n AgentContextProcessorOutput,\n AgentThreadExecutionContext,\n PreLLMAgentContextProcessor,\n} from '../AgentContextProcessor';\n\nexport const DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS = 50 * 1000;\n\n// https://platform.openai.com/tokenizer\nconst PROMPT_TOKENS = 931;\nconst PROMPT = `\nYour task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.\nThis summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.\n\nBefore providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:\n\n1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:\n - The user's explicit requests and intents\n - Your approach to addressing the user's requests\n - Key decisions, technical concepts and code patterns\n - Specific details like:\n - file names\n - full code snippets\n - function signatures\n - file edits\n - Errors that you ran into and how you fixed them\n - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.\n\nYour summary should include the following sections:\n\n1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail\n2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.\n3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.\n4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.\n6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.\n6. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.\n7. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.\n8. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.\n If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.\n\nHere's an example of how your output should be structured:\n\n<example>\n<analysis>\n[Your thought process, ensuring all points are covered thoroughly and accurately]\n</analysis>\n\n<summary>\n1. Primary Request and Intent:\n [Detailed description]\n\n2. Key Technical Concepts:\n - [Concept 1]\n - [Concept 2]\n - [...]\n\n\n3. Errors and fixes:\n - [Detailed description of error 1]:\n - [How you fixed the error]\n - [User feedback on the error if any]\n - [...]\n\n4. Problem Solving:\n [Description of solved problems and ongoing troubleshooting]\n\n5. All user messages: \n - [Detailed non tool use user message]\n - [...]\n\n6. Pending Tasks:\n - [Task 1]\n - [Task 2]\n - [...]\n\n7. Current Work:\n [Precise description of current work]\n\n8. Optional Next Step:\n [Optional Next step to take]\n\n</summary>\n</example>\n\nPlease provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response. \n\nThere may be additional summarization instructions provided in the included context. If so, remember to follow these instructions when creating the above summary. Examples of instructions include:\n<example>\n## Compact Instructions\nWhen summarizing the conversation focus on typescript code changes and also remember the mistakes you made and how you fixed them.\n</example>\n\n<example>\n# Summary instructions\nWhen you are using compact - please focus on test output and code changes. Include file reads verbatim.\n</example>\n`;\n\nconst CONTINUATION_MESSAGE = internalSystemMessage(\n 'The above is the summarised context of the work so far. The Agent must not repeat or re-run any work that was already completed. If results were already obtained, the Agent should present them directly.',\n);\nObject.freeze(CONTINUATION_MESSAGE);\n// https://platform.openai.com/tokenizer\nconst CONTINUATION_MESSAGE_TOKENS = 42;\n\nfunction formatAssistantContent(\n content: string | ({ type: 'text'; text: string } | { type: 'refusal'; refusal: string })[] | null | undefined,\n): string {\n if (typeof content === 'string') {\n return content;\n }\n if (!content) {\n return '';\n }\n return content.map(part => (part.type === 'text' ? part.text : part.refusal)).join('\\n');\n}\n\nfunction createSummarizationCandidate(context: ContextMessage[]) {\n let candidate = '';\n let index = -1;\n for (const m of context) {\n index += 1;\n if (isInternalSystemMessage(m)) {\n continue;\n }\n if (!isLLMContextMessage(m)) {\n continue;\n }\n switch (m.role) {\n case 'user':\n if (typeof m.content === 'string') {\n candidate += `<${String(index)}><user>:` + m.content;\n } else {\n const parts: string[] = [];\n for (const p of m.content) {\n if (p.type === 'text') {\n parts.push(p.text);\n } else {\n parts.push(`[user attached a ${p.type} here, no longer available after summarization]`);\n }\n }\n candidate += `<${String(index)}><user>:` + parts.join('\\n');\n }\n break;\n case 'tool':\n candidate += `<${String(index)}><tool-response id=${m.tool_call_id}>:` + m.content;\n break;\n case 'assistant':\n for (const block of m.thinking_blocks ?? []) {\n if (block.type === 'thinking') {\n candidate += `<${String(index)}><assistant-thinking>:` + block.thinking;\n }\n }\n candidate += `<${String(index)}><assistant>:` + formatAssistantContent(m.content);\n for (const t of m.tool_calls ?? []) {\n candidate += `<tool-call id=${t.id} name=${t.function.name}>:` + t.function.arguments;\n }\n }\n }\n return candidate;\n}\n\nexport class ContextCompaction implements PreLLMAgentContextProcessor {\n private modelClient: ILLM;\n private compactionThresholdTokens: number;\n\n constructor(input: { modelClient: ILLM; compactionThresholdTokens: number }) {\n this.modelClient = input.modelClient;\n this.compactionThresholdTokens = input.compactionThresholdTokens;\n }\n\n async *processPreLLM(\n execution: Readonly<AgentThreadExecutionContext>,\n ): AsyncGenerator<AgentContextProcessorOutput, void, unknown> {\n const contextTokens = execution.currentContextUsage.prompt_tokens + execution.currentContextUsage.completion_tokens;\n if (contextTokens + PROMPT_TOKENS < this.compactionThresholdTokens) {\n return;\n }\n\n // Model identity is owned by modelClient — omit OpenAI's required `model` field.\n const body: LLMCreateParams = {\n messages: [\n { role: 'user', content: createSummarizationCandidate(execution.context) },\n { role: 'user', content: PROMPT },\n ],\n stream: false,\n };\n\n const response = await this.modelClient.createNonStream(body);\n const context: ContextMessage[] = [{ role: 'assistant', content: response.output.content }, CONTINUATION_MESSAGE];\n\n yield {\n type: EventType.AGENT_CONTEXT_OVERWRITE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n reason: 'compaction',\n context: context,\n current_context_usage: {\n // NOTE(agent): This is not really correct.\n // This is not taking into account that the original request had\n // tool definition in them.\n // This will get refreshed in the next LLM call.\n prompt_tokens: response.usage.input_tokens + CONTINUATION_MESSAGE_TOKENS,\n completion_tokens: 0,\n },\n usage: response.usage,\n };\n }\n}\n\nexport interface ContextCompactionSettings {\n compactionThresholdTokens?: number | undefined;\n}\n\nexport function contextCompaction(options: {\n definition: AgentDefinition;\n settings?: ContextCompactionSettings | undefined;\n compactionThresholdTokens?: number | undefined;\n}): AgentCapability {\n const threshold =\n options.compactionThresholdTokens ??\n options.settings?.compactionThresholdTokens ??\n DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;\n return {\n preLLMProcessors: [\n new ContextCompaction({\n modelClient: options.definition.modelClient,\n compactionThresholdTokens: threshold,\n }),\n ],\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/capabilities/builtins/ContextCompaction.ts"],"sourcesContent":["import { EventType, newEventId } from '../../events/schema';\nimport type { ILLM, LLMCreateParams } from '../../llm/ILLM';\nimport type { AgentDefinition } from '../../runtime/AgentDefinition';\nimport type { ContextMessage } from '../../runtime/AgentThread.types';\nimport { internalSystemMessage, isInternalSystemMessage, isLLMContextMessage } from '../../runtime/contextUtils';\nimport type { AgentCapability } from '../AgentCapability';\nimport type {\n AgentContextProcessorOutput,\n AgentThreadExecutionContext,\n PreLLMAgentContextProcessor,\n} from '../AgentContextProcessor';\n\nexport const DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS = 50 * 1000;\nexport const DEFAULT_CONTEXT_COMPACTION_RATIO = 0.8;\n\nexport function resolveCompactionThresholdTokens(input: {\n configuredThresholdTokens: number | undefined;\n modelContextLength: number | undefined;\n modelParams: AgentDefinition['modelParams'];\n}): number {\n if (input.configuredThresholdTokens !== undefined) {\n return input.configuredThresholdTokens;\n }\n if (input.modelContextLength !== undefined) {\n const ratioThreshold = Math.floor(input.modelContextLength * DEFAULT_CONTEXT_COMPACTION_RATIO);\n const configuredMaxOutputTokens = input.modelParams?.['max_completion_tokens'] ?? input.modelParams?.['max_tokens'];\n if (\n typeof configuredMaxOutputTokens === 'number' &&\n Number.isFinite(configuredMaxOutputTokens) &&\n configuredMaxOutputTokens >= 0\n ) {\n const inputBudget = Math.floor(input.modelContextLength - configuredMaxOutputTokens);\n if (inputBudget > 0) {\n return Math.min(ratioThreshold, inputBudget);\n }\n }\n // An unusable output reservation must not turn compaction into an always-on loop.\n return ratioThreshold;\n }\n return DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;\n}\n\n// https://platform.openai.com/tokenizer\nconst PROMPT_TOKENS = 931;\nconst PROMPT = `\nYour task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.\nThis summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.\n\nBefore providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:\n\n1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:\n - The user's explicit requests and intents\n - Your approach to addressing the user's requests\n - Key decisions, technical concepts and code patterns\n - Specific details like:\n - file names\n - full code snippets\n - function signatures\n - file edits\n - Errors that you ran into and how you fixed them\n - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.\n\nYour summary should include the following sections:\n\n1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail\n2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.\n3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.\n4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.\n6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.\n6. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.\n7. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.\n8. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.\n If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.\n\nHere's an example of how your output should be structured:\n\n<example>\n<analysis>\n[Your thought process, ensuring all points are covered thoroughly and accurately]\n</analysis>\n\n<summary>\n1. Primary Request and Intent:\n [Detailed description]\n\n2. Key Technical Concepts:\n - [Concept 1]\n - [Concept 2]\n - [...]\n\n\n3. Errors and fixes:\n - [Detailed description of error 1]:\n - [How you fixed the error]\n - [User feedback on the error if any]\n - [...]\n\n4. Problem Solving:\n [Description of solved problems and ongoing troubleshooting]\n\n5. All user messages: \n - [Detailed non tool use user message]\n - [...]\n\n6. Pending Tasks:\n - [Task 1]\n - [Task 2]\n - [...]\n\n7. Current Work:\n [Precise description of current work]\n\n8. Optional Next Step:\n [Optional Next step to take]\n\n</summary>\n</example>\n\nPlease provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response. \n\nThere may be additional summarization instructions provided in the included context. If so, remember to follow these instructions when creating the above summary. Examples of instructions include:\n<example>\n## Compact Instructions\nWhen summarizing the conversation focus on typescript code changes and also remember the mistakes you made and how you fixed them.\n</example>\n\n<example>\n# Summary instructions\nWhen you are using compact - please focus on test output and code changes. Include file reads verbatim.\n</example>\n`;\n\nconst CONTINUATION_MESSAGE = internalSystemMessage(\n 'The above is the summarised context of the work so far. The Agent must not repeat or re-run any work that was already completed. If results were already obtained, the Agent should present them directly.',\n);\nObject.freeze(CONTINUATION_MESSAGE);\n// https://platform.openai.com/tokenizer\nconst CONTINUATION_MESSAGE_TOKENS = 42;\n\nfunction formatAssistantContent(\n content: string | ({ type: 'text'; text: string } | { type: 'refusal'; refusal: string })[] | null | undefined,\n): string {\n if (typeof content === 'string') {\n return content;\n }\n if (!content) {\n return '';\n }\n return content.map(part => (part.type === 'text' ? part.text : part.refusal)).join('\\n');\n}\n\nfunction createSummarizationCandidate(context: ContextMessage[]) {\n let candidate = '';\n let index = -1;\n for (const m of context) {\n index += 1;\n if (isInternalSystemMessage(m)) {\n continue;\n }\n if (!isLLMContextMessage(m)) {\n continue;\n }\n switch (m.role) {\n case 'user':\n if (typeof m.content === 'string') {\n candidate += `<${String(index)}><user>:` + m.content;\n } else {\n const parts: string[] = [];\n for (const p of m.content) {\n if (p.type === 'text') {\n parts.push(p.text);\n } else {\n parts.push(`[user attached a ${p.type} here, no longer available after summarization]`);\n }\n }\n candidate += `<${String(index)}><user>:` + parts.join('\\n');\n }\n break;\n case 'tool':\n candidate += `<${String(index)}><tool-response id=${m.tool_call_id}>:` + m.content;\n break;\n case 'assistant':\n for (const block of m.thinking_blocks ?? []) {\n if (block.type === 'thinking') {\n candidate += `<${String(index)}><assistant-thinking>:` + block.thinking;\n }\n }\n candidate += `<${String(index)}><assistant>:` + formatAssistantContent(m.content);\n for (const t of m.tool_calls ?? []) {\n candidate += `<tool-call id=${t.id} name=${t.function.name}>:` + t.function.arguments;\n }\n }\n }\n return candidate;\n}\n\nexport class ContextCompaction implements PreLLMAgentContextProcessor {\n private modelClient: ILLM;\n private compactionThresholdTokens: number;\n\n constructor(input: { modelClient: ILLM; compactionThresholdTokens: number }) {\n this.modelClient = input.modelClient;\n this.compactionThresholdTokens = input.compactionThresholdTokens;\n }\n\n async *processPreLLM(\n execution: Readonly<AgentThreadExecutionContext>,\n ): AsyncGenerator<AgentContextProcessorOutput, void, unknown> {\n const contextTokens = execution.currentContextUsage.prompt_tokens + execution.currentContextUsage.completion_tokens;\n if (contextTokens + PROMPT_TOKENS < this.compactionThresholdTokens) {\n return;\n }\n\n // Model identity is owned by modelClient — omit OpenAI's required `model` field.\n const body: LLMCreateParams = {\n messages: [\n { role: 'user', content: createSummarizationCandidate(execution.context) },\n { role: 'user', content: PROMPT },\n ],\n stream: false,\n };\n\n const response = await this.modelClient.createNonStream(body);\n const context: ContextMessage[] = [{ role: 'assistant', content: response.output.content }, CONTINUATION_MESSAGE];\n\n yield {\n type: EventType.AGENT_CONTEXT_OVERWRITE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n reason: 'compaction',\n context: context,\n current_context_usage: {\n // NOTE(agent): This is not really correct.\n // This is not taking into account that the original request had\n // tool definition in them.\n // This will get refreshed in the next LLM call.\n prompt_tokens: response.usage.input_tokens + CONTINUATION_MESSAGE_TOKENS,\n completion_tokens: 0,\n },\n usage: response.usage,\n };\n }\n}\n\nexport interface ContextCompactionSettings {\n compactionThresholdTokens?: number | undefined;\n}\n\nexport function contextCompaction(options: {\n definition: AgentDefinition;\n settings?: ContextCompactionSettings | undefined;\n compactionThresholdTokens?: number | undefined;\n}): AgentCapability {\n const threshold = resolveCompactionThresholdTokens({\n configuredThresholdTokens: options.compactionThresholdTokens ?? options.settings?.compactionThresholdTokens,\n modelContextLength: options.definition.modelProperties?.contextLength,\n modelParams: options.definition.modelParams,\n });\n return {\n preLLMProcessors: [\n new ContextCompaction({\n modelClient: options.definition.modelClient,\n compactionThresholdTokens: threshold,\n }),\n ],\n };\n}\n"],"mappings":"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","names":[]}
@@ -2,6 +2,24 @@
2
2
  import { EventType, newEventId } from "../../events/schema.mjs";
3
3
  import { internalSystemMessage, isInternalSystemMessage, isLLMContextMessage } from "../../runtime/contextUtils.mjs";
4
4
  var DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS = 50 * 1e3;
5
+ var DEFAULT_CONTEXT_COMPACTION_RATIO = 0.8;
6
+ function resolveCompactionThresholdTokens(input) {
7
+ if (input.configuredThresholdTokens !== void 0) {
8
+ return input.configuredThresholdTokens;
9
+ }
10
+ if (input.modelContextLength !== void 0) {
11
+ const ratioThreshold = Math.floor(input.modelContextLength * DEFAULT_CONTEXT_COMPACTION_RATIO);
12
+ const configuredMaxOutputTokens = input.modelParams?.["max_completion_tokens"] ?? input.modelParams?.["max_tokens"];
13
+ if (typeof configuredMaxOutputTokens === "number" && Number.isFinite(configuredMaxOutputTokens) && configuredMaxOutputTokens >= 0) {
14
+ const inputBudget = Math.floor(input.modelContextLength - configuredMaxOutputTokens);
15
+ if (inputBudget > 0) {
16
+ return Math.min(ratioThreshold, inputBudget);
17
+ }
18
+ }
19
+ return ratioThreshold;
20
+ }
21
+ return DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;
22
+ }
5
23
  var PROMPT_TOKENS = 931;
6
24
  var PROMPT = `
7
25
  Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
@@ -190,7 +208,11 @@ var ContextCompaction = class {
190
208
  }
191
209
  };
192
210
  function contextCompaction(options) {
193
- const threshold = options.compactionThresholdTokens ?? options.settings?.compactionThresholdTokens ?? DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;
211
+ const threshold = resolveCompactionThresholdTokens({
212
+ configuredThresholdTokens: options.compactionThresholdTokens ?? options.settings?.compactionThresholdTokens,
213
+ modelContextLength: options.definition.modelProperties?.contextLength,
214
+ modelParams: options.definition.modelParams
215
+ });
194
216
  return {
195
217
  preLLMProcessors: [
196
218
  new ContextCompaction({
@@ -202,7 +224,9 @@ function contextCompaction(options) {
202
224
  }
203
225
  export {
204
226
  ContextCompaction,
227
+ DEFAULT_CONTEXT_COMPACTION_RATIO,
205
228
  DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS,
206
- contextCompaction
229
+ contextCompaction,
230
+ resolveCompactionThresholdTokens
207
231
  };
208
232
  //# sourceMappingURL=ContextCompaction.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/capabilities/builtins/ContextCompaction.ts"],"sourcesContent":["import { EventType, newEventId } from '../../events/schema';\nimport type { ILLM, LLMCreateParams } from '../../llm/ILLM';\nimport type { AgentDefinition } from '../../runtime/AgentDefinition';\nimport type { ContextMessage } from '../../runtime/AgentThread.types';\nimport { internalSystemMessage, isInternalSystemMessage, isLLMContextMessage } from '../../runtime/contextUtils';\nimport type { AgentCapability } from '../AgentCapability';\nimport type {\n AgentContextProcessorOutput,\n AgentThreadExecutionContext,\n PreLLMAgentContextProcessor,\n} from '../AgentContextProcessor';\n\nexport const DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS = 50 * 1000;\n\n// https://platform.openai.com/tokenizer\nconst PROMPT_TOKENS = 931;\nconst PROMPT = `\nYour task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.\nThis summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.\n\nBefore providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:\n\n1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:\n - The user's explicit requests and intents\n - Your approach to addressing the user's requests\n - Key decisions, technical concepts and code patterns\n - Specific details like:\n - file names\n - full code snippets\n - function signatures\n - file edits\n - Errors that you ran into and how you fixed them\n - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.\n\nYour summary should include the following sections:\n\n1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail\n2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.\n3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.\n4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.\n6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.\n6. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.\n7. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.\n8. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.\n If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.\n\nHere's an example of how your output should be structured:\n\n<example>\n<analysis>\n[Your thought process, ensuring all points are covered thoroughly and accurately]\n</analysis>\n\n<summary>\n1. Primary Request and Intent:\n [Detailed description]\n\n2. Key Technical Concepts:\n - [Concept 1]\n - [Concept 2]\n - [...]\n\n\n3. Errors and fixes:\n - [Detailed description of error 1]:\n - [How you fixed the error]\n - [User feedback on the error if any]\n - [...]\n\n4. Problem Solving:\n [Description of solved problems and ongoing troubleshooting]\n\n5. All user messages: \n - [Detailed non tool use user message]\n - [...]\n\n6. Pending Tasks:\n - [Task 1]\n - [Task 2]\n - [...]\n\n7. Current Work:\n [Precise description of current work]\n\n8. Optional Next Step:\n [Optional Next step to take]\n\n</summary>\n</example>\n\nPlease provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response. \n\nThere may be additional summarization instructions provided in the included context. If so, remember to follow these instructions when creating the above summary. Examples of instructions include:\n<example>\n## Compact Instructions\nWhen summarizing the conversation focus on typescript code changes and also remember the mistakes you made and how you fixed them.\n</example>\n\n<example>\n# Summary instructions\nWhen you are using compact - please focus on test output and code changes. Include file reads verbatim.\n</example>\n`;\n\nconst CONTINUATION_MESSAGE = internalSystemMessage(\n 'The above is the summarised context of the work so far. The Agent must not repeat or re-run any work that was already completed. If results were already obtained, the Agent should present them directly.',\n);\nObject.freeze(CONTINUATION_MESSAGE);\n// https://platform.openai.com/tokenizer\nconst CONTINUATION_MESSAGE_TOKENS = 42;\n\nfunction formatAssistantContent(\n content: string | ({ type: 'text'; text: string } | { type: 'refusal'; refusal: string })[] | null | undefined,\n): string {\n if (typeof content === 'string') {\n return content;\n }\n if (!content) {\n return '';\n }\n return content.map(part => (part.type === 'text' ? part.text : part.refusal)).join('\\n');\n}\n\nfunction createSummarizationCandidate(context: ContextMessage[]) {\n let candidate = '';\n let index = -1;\n for (const m of context) {\n index += 1;\n if (isInternalSystemMessage(m)) {\n continue;\n }\n if (!isLLMContextMessage(m)) {\n continue;\n }\n switch (m.role) {\n case 'user':\n if (typeof m.content === 'string') {\n candidate += `<${String(index)}><user>:` + m.content;\n } else {\n const parts: string[] = [];\n for (const p of m.content) {\n if (p.type === 'text') {\n parts.push(p.text);\n } else {\n parts.push(`[user attached a ${p.type} here, no longer available after summarization]`);\n }\n }\n candidate += `<${String(index)}><user>:` + parts.join('\\n');\n }\n break;\n case 'tool':\n candidate += `<${String(index)}><tool-response id=${m.tool_call_id}>:` + m.content;\n break;\n case 'assistant':\n for (const block of m.thinking_blocks ?? []) {\n if (block.type === 'thinking') {\n candidate += `<${String(index)}><assistant-thinking>:` + block.thinking;\n }\n }\n candidate += `<${String(index)}><assistant>:` + formatAssistantContent(m.content);\n for (const t of m.tool_calls ?? []) {\n candidate += `<tool-call id=${t.id} name=${t.function.name}>:` + t.function.arguments;\n }\n }\n }\n return candidate;\n}\n\nexport class ContextCompaction implements PreLLMAgentContextProcessor {\n private modelClient: ILLM;\n private compactionThresholdTokens: number;\n\n constructor(input: { modelClient: ILLM; compactionThresholdTokens: number }) {\n this.modelClient = input.modelClient;\n this.compactionThresholdTokens = input.compactionThresholdTokens;\n }\n\n async *processPreLLM(\n execution: Readonly<AgentThreadExecutionContext>,\n ): AsyncGenerator<AgentContextProcessorOutput, void, unknown> {\n const contextTokens = execution.currentContextUsage.prompt_tokens + execution.currentContextUsage.completion_tokens;\n if (contextTokens + PROMPT_TOKENS < this.compactionThresholdTokens) {\n return;\n }\n\n // Model identity is owned by modelClient — omit OpenAI's required `model` field.\n const body: LLMCreateParams = {\n messages: [\n { role: 'user', content: createSummarizationCandidate(execution.context) },\n { role: 'user', content: PROMPT },\n ],\n stream: false,\n };\n\n const response = await this.modelClient.createNonStream(body);\n const context: ContextMessage[] = [{ role: 'assistant', content: response.output.content }, CONTINUATION_MESSAGE];\n\n yield {\n type: EventType.AGENT_CONTEXT_OVERWRITE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n reason: 'compaction',\n context: context,\n current_context_usage: {\n // NOTE(agent): This is not really correct.\n // This is not taking into account that the original request had\n // tool definition in them.\n // This will get refreshed in the next LLM call.\n prompt_tokens: response.usage.input_tokens + CONTINUATION_MESSAGE_TOKENS,\n completion_tokens: 0,\n },\n usage: response.usage,\n };\n }\n}\n\nexport interface ContextCompactionSettings {\n compactionThresholdTokens?: number | undefined;\n}\n\nexport function contextCompaction(options: {\n definition: AgentDefinition;\n settings?: ContextCompactionSettings | undefined;\n compactionThresholdTokens?: number | undefined;\n}): AgentCapability {\n const threshold =\n options.compactionThresholdTokens ??\n options.settings?.compactionThresholdTokens ??\n DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;\n return {\n preLLMProcessors: [\n new ContextCompaction({\n modelClient: options.definition.modelClient,\n compactionThresholdTokens: threshold,\n }),\n ],\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/capabilities/builtins/ContextCompaction.ts"],"sourcesContent":["import { EventType, newEventId } from '../../events/schema';\nimport type { ILLM, LLMCreateParams } from '../../llm/ILLM';\nimport type { AgentDefinition } from '../../runtime/AgentDefinition';\nimport type { ContextMessage } from '../../runtime/AgentThread.types';\nimport { internalSystemMessage, isInternalSystemMessage, isLLMContextMessage } from '../../runtime/contextUtils';\nimport type { AgentCapability } from '../AgentCapability';\nimport type {\n AgentContextProcessorOutput,\n AgentThreadExecutionContext,\n PreLLMAgentContextProcessor,\n} from '../AgentContextProcessor';\n\nexport const DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS = 50 * 1000;\nexport const DEFAULT_CONTEXT_COMPACTION_RATIO = 0.8;\n\nexport function resolveCompactionThresholdTokens(input: {\n configuredThresholdTokens: number | undefined;\n modelContextLength: number | undefined;\n modelParams: AgentDefinition['modelParams'];\n}): number {\n if (input.configuredThresholdTokens !== undefined) {\n return input.configuredThresholdTokens;\n }\n if (input.modelContextLength !== undefined) {\n const ratioThreshold = Math.floor(input.modelContextLength * DEFAULT_CONTEXT_COMPACTION_RATIO);\n const configuredMaxOutputTokens = input.modelParams?.['max_completion_tokens'] ?? input.modelParams?.['max_tokens'];\n if (\n typeof configuredMaxOutputTokens === 'number' &&\n Number.isFinite(configuredMaxOutputTokens) &&\n configuredMaxOutputTokens >= 0\n ) {\n const inputBudget = Math.floor(input.modelContextLength - configuredMaxOutputTokens);\n if (inputBudget > 0) {\n return Math.min(ratioThreshold, inputBudget);\n }\n }\n // An unusable output reservation must not turn compaction into an always-on loop.\n return ratioThreshold;\n }\n return DEFAULT_CONTEXT_COMPACTION_THRESHOLD_TOKENS;\n}\n\n// https://platform.openai.com/tokenizer\nconst PROMPT_TOKENS = 931;\nconst PROMPT = `\nYour task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.\nThis summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.\n\nBefore providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:\n\n1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:\n - The user's explicit requests and intents\n - Your approach to addressing the user's requests\n - Key decisions, technical concepts and code patterns\n - Specific details like:\n - file names\n - full code snippets\n - function signatures\n - file edits\n - Errors that you ran into and how you fixed them\n - Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.\n\nYour summary should include the following sections:\n\n1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail\n2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.\n3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.\n4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.\n5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.\n6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.\n6. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.\n7. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.\n8. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.\n If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.\n\nHere's an example of how your output should be structured:\n\n<example>\n<analysis>\n[Your thought process, ensuring all points are covered thoroughly and accurately]\n</analysis>\n\n<summary>\n1. Primary Request and Intent:\n [Detailed description]\n\n2. Key Technical Concepts:\n - [Concept 1]\n - [Concept 2]\n - [...]\n\n\n3. Errors and fixes:\n - [Detailed description of error 1]:\n - [How you fixed the error]\n - [User feedback on the error if any]\n - [...]\n\n4. Problem Solving:\n [Description of solved problems and ongoing troubleshooting]\n\n5. All user messages: \n - [Detailed non tool use user message]\n - [...]\n\n6. Pending Tasks:\n - [Task 1]\n - [Task 2]\n - [...]\n\n7. Current Work:\n [Precise description of current work]\n\n8. Optional Next Step:\n [Optional Next step to take]\n\n</summary>\n</example>\n\nPlease provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response. \n\nThere may be additional summarization instructions provided in the included context. If so, remember to follow these instructions when creating the above summary. Examples of instructions include:\n<example>\n## Compact Instructions\nWhen summarizing the conversation focus on typescript code changes and also remember the mistakes you made and how you fixed them.\n</example>\n\n<example>\n# Summary instructions\nWhen you are using compact - please focus on test output and code changes. Include file reads verbatim.\n</example>\n`;\n\nconst CONTINUATION_MESSAGE = internalSystemMessage(\n 'The above is the summarised context of the work so far. The Agent must not repeat or re-run any work that was already completed. If results were already obtained, the Agent should present them directly.',\n);\nObject.freeze(CONTINUATION_MESSAGE);\n// https://platform.openai.com/tokenizer\nconst CONTINUATION_MESSAGE_TOKENS = 42;\n\nfunction formatAssistantContent(\n content: string | ({ type: 'text'; text: string } | { type: 'refusal'; refusal: string })[] | null | undefined,\n): string {\n if (typeof content === 'string') {\n return content;\n }\n if (!content) {\n return '';\n }\n return content.map(part => (part.type === 'text' ? part.text : part.refusal)).join('\\n');\n}\n\nfunction createSummarizationCandidate(context: ContextMessage[]) {\n let candidate = '';\n let index = -1;\n for (const m of context) {\n index += 1;\n if (isInternalSystemMessage(m)) {\n continue;\n }\n if (!isLLMContextMessage(m)) {\n continue;\n }\n switch (m.role) {\n case 'user':\n if (typeof m.content === 'string') {\n candidate += `<${String(index)}><user>:` + m.content;\n } else {\n const parts: string[] = [];\n for (const p of m.content) {\n if (p.type === 'text') {\n parts.push(p.text);\n } else {\n parts.push(`[user attached a ${p.type} here, no longer available after summarization]`);\n }\n }\n candidate += `<${String(index)}><user>:` + parts.join('\\n');\n }\n break;\n case 'tool':\n candidate += `<${String(index)}><tool-response id=${m.tool_call_id}>:` + m.content;\n break;\n case 'assistant':\n for (const block of m.thinking_blocks ?? []) {\n if (block.type === 'thinking') {\n candidate += `<${String(index)}><assistant-thinking>:` + block.thinking;\n }\n }\n candidate += `<${String(index)}><assistant>:` + formatAssistantContent(m.content);\n for (const t of m.tool_calls ?? []) {\n candidate += `<tool-call id=${t.id} name=${t.function.name}>:` + t.function.arguments;\n }\n }\n }\n return candidate;\n}\n\nexport class ContextCompaction implements PreLLMAgentContextProcessor {\n private modelClient: ILLM;\n private compactionThresholdTokens: number;\n\n constructor(input: { modelClient: ILLM; compactionThresholdTokens: number }) {\n this.modelClient = input.modelClient;\n this.compactionThresholdTokens = input.compactionThresholdTokens;\n }\n\n async *processPreLLM(\n execution: Readonly<AgentThreadExecutionContext>,\n ): AsyncGenerator<AgentContextProcessorOutput, void, unknown> {\n const contextTokens = execution.currentContextUsage.prompt_tokens + execution.currentContextUsage.completion_tokens;\n if (contextTokens + PROMPT_TOKENS < this.compactionThresholdTokens) {\n return;\n }\n\n // Model identity is owned by modelClient — omit OpenAI's required `model` field.\n const body: LLMCreateParams = {\n messages: [\n { role: 'user', content: createSummarizationCandidate(execution.context) },\n { role: 'user', content: PROMPT },\n ],\n stream: false,\n };\n\n const response = await this.modelClient.createNonStream(body);\n const context: ContextMessage[] = [{ role: 'assistant', content: response.output.content }, CONTINUATION_MESSAGE];\n\n yield {\n type: EventType.AGENT_CONTEXT_OVERWRITE,\n id: newEventId(),\n created_at: new Date().toISOString(),\n reason: 'compaction',\n context: context,\n current_context_usage: {\n // NOTE(agent): This is not really correct.\n // This is not taking into account that the original request had\n // tool definition in them.\n // This will get refreshed in the next LLM call.\n prompt_tokens: response.usage.input_tokens + CONTINUATION_MESSAGE_TOKENS,\n completion_tokens: 0,\n },\n usage: response.usage,\n };\n }\n}\n\nexport interface ContextCompactionSettings {\n compactionThresholdTokens?: number | undefined;\n}\n\nexport function contextCompaction(options: {\n definition: AgentDefinition;\n settings?: ContextCompactionSettings | undefined;\n compactionThresholdTokens?: number | undefined;\n}): AgentCapability {\n const threshold = resolveCompactionThresholdTokens({\n configuredThresholdTokens: options.compactionThresholdTokens ?? options.settings?.compactionThresholdTokens,\n modelContextLength: options.definition.modelProperties?.contextLength,\n modelParams: options.definition.modelParams,\n });\n return {\n preLLMProcessors: [\n new ContextCompaction({\n modelClient: options.definition.modelClient,\n compactionThresholdTokens: threshold,\n }),\n ],\n };\n}\n"],"mappings":"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","names":[]}
@@ -9,7 +9,7 @@ import { type CompletionUsage, type ExtendedChatCompletionChunk, type RawAssista
9
9
  * Providers with a case in {@link buildLanguageModel}. Canonical: the server derives the provider
10
10
  * types it will configure from this, so anything it accepts has an adapter behind it.
11
11
  */
12
- export declare const VERCEL_AI_PROVIDER_NAMES: readonly ['openai', 'anthropic', 'google-gemini', 'fireworks', 'zai', 'moonshot', 'alibaba', 'together', 'custom'];
12
+ export declare const VERCEL_AI_PROVIDER_NAMES: readonly ['openai', 'anthropic', 'google-gemini', 'fireworks', 'zai', 'moonshot', 'alibaba', 'together', 'custom', 'truefoundry'];
13
13
  export type VercelAIProviderName = (typeof VERCEL_AI_PROVIDER_NAMES)[number];
14
14
  /**
15
15
  * Adapter-facing config, camelCase throughout. Callers translate from the snake_case wire and