@alvin0/ai-agent-sdk-core 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/define/session/model-config.js +1 -1
- package/dist/agent/define/session/model-config.js.map +1 -1
- package/dist/agent/define/session/types.d.ts +21 -0
- package/dist/agent/define/session/types.d.ts.map +1 -1
- package/dist/agent/define/session.d.ts +2 -0
- package/dist/agent/define/session.d.ts.map +1 -1
- package/dist/agent/define/session.js +1 -1
- package/dist/agent/define/session.js.map +1 -1
- package/dist/agent/history/validation.js +1 -1
- package/dist/agent/history/validation.js.map +1 -1
- package/dist/agent/loop/events.d.ts +5 -0
- package/dist/agent/loop/events.d.ts.map +1 -1
- package/dist/agent/loop/schedule.js +1 -1
- package/dist/agent/loop/schedule.js.map +1 -1
- package/dist/agent/loop/turn/model-round.js +1 -1
- package/dist/agent/loop/turn/model-round.js.map +1 -1
- package/dist/agent/loop/turn/types.d.ts +2 -0
- package/dist/agent/loop/turn/types.d.ts.map +1 -1
- package/dist/agent/loop/turn/validation.js +1 -1
- package/dist/agent/loop/turn/validation.js.map +1 -1
- package/dist/agent/memory/compaction.d.ts +10 -1
- package/dist/agent/memory/compaction.d.ts.map +1 -1
- package/dist/agent/memory/compaction.js +2 -2
- package/dist/agent/memory/compaction.js.map +1 -1
- package/dist/agent/memory/token-estimator.js +1 -1
- package/dist/agent/memory/token-estimator.js.map +1 -1
- package/dist/agent/mode/run-agent.js +1 -1
- package/dist/agent/mode/run-agent.js.map +1 -1
- package/dist/composition/agent/options.js +1 -1
- package/dist/composition/agent/options.js.map +1 -1
- package/dist/composition/agent/session.js +1 -1
- package/dist/composition/agent/session.js.map +1 -1
- package/dist/composition/agent/types.d.ts +43 -1
- package/dist/composition/agent/types.d.ts.map +1 -1
- package/dist/composition/common/errors.d.ts.map +1 -1
- package/dist/composition/common/errors.js +1 -1
- package/dist/composition/common/errors.js.map +1 -1
- package/dist/composition/embedding/activation.js +2 -0
- package/dist/composition/embedding/activation.js.map +1 -0
- package/dist/composition/embedding/cache.js +2 -0
- package/dist/composition/embedding/cache.js.map +1 -0
- package/dist/composition/embedding/definition.d.ts +7 -0
- package/dist/composition/embedding/definition.d.ts.map +1 -0
- package/dist/composition/embedding/definition.js +2 -0
- package/dist/composition/embedding/definition.js.map +1 -0
- package/dist/composition/embedding/handle.js +2 -0
- package/dist/composition/embedding/handle.js.map +1 -0
- package/dist/composition/embedding/limiter.js +2 -0
- package/dist/composition/embedding/limiter.js.map +1 -0
- package/dist/composition/embedding/manager.js +2 -0
- package/dist/composition/embedding/manager.js.map +1 -0
- package/dist/composition/embedding/observation.js +2 -0
- package/dist/composition/embedding/observation.js.map +1 -0
- package/dist/composition/embedding/planner.js +2 -0
- package/dist/composition/embedding/planner.js.map +1 -0
- package/dist/composition/embedding/plugin-types.d.ts +48 -0
- package/dist/composition/embedding/plugin-types.d.ts.map +1 -0
- package/dist/composition/embedding/plugin-types.js +2 -0
- package/dist/composition/embedding/plugin-types.js.map +1 -0
- package/dist/composition/embedding/preflight.js +2 -0
- package/dist/composition/embedding/preflight.js.map +1 -0
- package/dist/composition/embedding/registry.js +2 -0
- package/dist/composition/embedding/registry.js.map +1 -0
- package/dist/composition/embedding/retry.js +2 -0
- package/dist/composition/embedding/retry.js.map +1 -0
- package/dist/composition/embedding/usage.js +2 -0
- package/dist/composition/embedding/usage.js.map +1 -0
- package/dist/composition/lifecycle/types.d.ts +5 -1
- package/dist/composition/lifecycle/types.d.ts.map +1 -1
- package/dist/composition/lifecycle/types.js +1 -1
- package/dist/composition/lifecycle/types.js.map +1 -1
- package/dist/composition/preflight.js +1 -1
- package/dist/composition/preflight.js.map +1 -1
- package/dist/composition/provider/activation.js +1 -1
- package/dist/composition/provider/activation.js.map +1 -1
- package/dist/composition/provider/model-selection.js +1 -1
- package/dist/composition/provider/model-selection.js.map +1 -1
- package/dist/composition/provider/preflight.js +1 -1
- package/dist/composition/provider/preflight.js.map +1 -1
- package/dist/composition/runtime/owner.js +1 -1
- package/dist/composition/runtime/owner.js.map +1 -1
- package/dist/composition/runtime/public.js +1 -1
- package/dist/composition/runtime/public.js.map +1 -1
- package/dist/composition/runtime/types.d.ts +25 -2
- package/dist/composition/runtime/types.d.ts.map +1 -1
- package/dist/composition/startup.js +1 -1
- package/dist/composition/startup.js.map +1 -1
- package/dist/composition/team/options.js +1 -1
- package/dist/composition/team/options.js.map +1 -1
- package/dist/composition/team/runtime.js +1 -1
- package/dist/composition/team/runtime.js.map +1 -1
- package/dist/composition/team/types.d.ts +3 -0
- package/dist/composition/team/types.d.ts.map +1 -1
- package/dist/contract/generate-options.d.ts +2 -0
- package/dist/contract/generate-options.d.ts.map +1 -1
- package/dist/contract/model-info.d.ts +12 -2
- package/dist/contract/model-info.d.ts.map +1 -1
- package/dist/embedding/adapter.d.ts +104 -0
- package/dist/embedding/adapter.d.ts.map +1 -0
- package/dist/embedding/adapter.js +2 -0
- package/dist/embedding/adapter.js.map +1 -0
- package/dist/embedding/catalog.d.ts +82 -0
- package/dist/embedding/catalog.d.ts.map +1 -0
- package/dist/embedding/catalog.js +2 -0
- package/dist/embedding/catalog.js.map +1 -0
- package/dist/embedding/errors.d.ts +98 -0
- package/dist/embedding/errors.d.ts.map +1 -0
- package/dist/embedding/errors.js +2 -0
- package/dist/embedding/errors.js.map +1 -0
- package/dist/embedding/handle.d.ts +76 -0
- package/dist/embedding/handle.d.ts.map +1 -0
- package/dist/embedding/limits.d.ts +47 -0
- package/dist/embedding/limits.d.ts.map +1 -0
- package/dist/embedding/limits.js +2 -0
- package/dist/embedding/limits.js.map +1 -0
- package/dist/embedding/profile.d.ts +89 -0
- package/dist/embedding/profile.d.ts.map +1 -0
- package/dist/embedding/profile.js +2 -0
- package/dist/embedding/profile.js.map +1 -0
- package/dist/embedding/purpose.d.ts +37 -0
- package/dist/embedding/purpose.d.ts.map +1 -0
- package/dist/embedding/request.d.ts +54 -0
- package/dist/embedding/request.d.ts.map +1 -0
- package/dist/embedding/request.js +2 -0
- package/dist/embedding/request.js.map +1 -0
- package/dist/embedding/result.d.ts +50 -0
- package/dist/embedding/result.d.ts.map +1 -0
- package/dist/embedding/usage.d.ts +64 -0
- package/dist/embedding/usage.d.ts.map +1 -0
- package/dist/embedding/usage.js +2 -0
- package/dist/embedding/usage.js.map +1 -0
- package/dist/embedding/validation.d.ts +68 -0
- package/dist/embedding/validation.d.ts.map +1 -0
- package/dist/embedding/validation.js +2 -0
- package/dist/embedding/validation.js.map +1 -0
- package/dist/embedding.d.ts +12 -0
- package/dist/embedding.js +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1 -1
- package/dist/message/content.d.ts +71 -1
- package/dist/message/content.d.ts.map +1 -1
- package/dist/message/projection.d.ts +28 -2
- package/dist/message/projection.d.ts.map +1 -1
- package/dist/message/projection.js +1 -1
- package/dist/message/projection.js.map +1 -1
- package/dist/observability/bus.js +1 -1
- package/dist/observation/event.d.ts +1 -1
- package/dist/observation/event.d.ts.map +1 -1
- package/dist/observation/event.js.map +1 -1
- package/dist/observation/port.d.ts +1 -1
- package/dist/observation/port.d.ts.map +1 -1
- package/dist/observation/port.js.map +1 -1
- package/dist/observation/privacy.js +1 -1
- package/dist/observation/privacy.js.map +1 -1
- package/dist/observation/report.d.ts +2 -0
- package/dist/observation/report.d.ts.map +1 -1
- package/dist/observation/report.js.map +1 -1
- package/dist/primitives/version.d.ts +1 -1
- package/dist/primitives/version.js +1 -1
- package/dist/primitives/version.js.map +1 -1
- package/dist/provider.d.ts +3 -1
- package/dist/provider.js +1 -1
- package/dist/runtime/model-call-handle.js +1 -1
- package/dist/runtime/model-call-handle.js.map +1 -1
- package/dist/runtime/model-metadata.js +1 -1
- package/dist/runtime/model-metadata.js.map +1 -1
- package/dist/runtime/model-stream.js +1 -1
- package/dist/runtime/model-stream.js.map +1 -1
- package/dist/runtime/registry.js +1 -1
- package/dist/runtime/with-retry.d.ts.map +1 -1
- package/dist/runtime/with-retry.js +1 -1
- package/dist/runtime/with-retry.js.map +1 -1
- package/dist/stream/assembler.d.ts.map +1 -1
- package/dist/stream/assembler.js +1 -1
- package/dist/stream/assembler.js.map +1 -1
- package/dist/stream/chunk.d.ts +6 -0
- package/dist/stream/chunk.d.ts.map +1 -1
- package/package.json +6 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-round.js","names":[],"sources":["../../../../src/agent/loop/turn/model-round.ts"],"sourcesContent":["import type { GenerateOptions } from '../../../contract/index.ts'\nimport { MODEL_ERROR_CODES, type ModelFailure } from '../../../errors/index.ts'\nimport type { ContentBlock, Message, ToolCallBlock } from '../../../message/index.ts'\nimport { BlockAssembler } from '../../../stream/index.ts'\nimport type { FinishReason } from '../../../stream/index.ts'\nimport type { ModelCallReport } from '../../../observation/index.ts'\nimport { normalizeToolPairing } from '../../history/normalize.ts'\nimport { createSpanId, type TraceRef } from '../../trace/trace.ts'\nimport type { AgentEvent, AgentMaintenanceEvent } from '../types.ts'\nimport { type ModelRoundPhase, type RunTurnOptions, type RoundResult } from './types.ts'\nimport { positiveFinite, positiveSafeInteger } from './config.ts'\nimport { serializedBytes, modelFailureFinish, modelAbortedFinish, messageOf, now } from './common.ts'\nimport { validateStreamChunk } from './validation.ts'\nimport { StreamAbortError, nextWithAbort, closeIterator } from './cancellation.ts'\nimport { runOptionalHook } from './hooks.ts'\nimport { accountingUsageStop } from './usage-stop.ts'\nimport {\n classifyTextPhases, dropDuplicateToolCalls, invalidHostToolCall, contentTiming,\n recentToolResultIds, systemText,\n createAssistant, textOf,\n} from './content.ts'\n\n/** How much of one message the trace keeps. */\nconst PREVIEW_CHARS = 600\n\n/** How many trailing messages the trace keeps. */\nconst PREVIEW_MESSAGES = 8\n\nfunction clip(text: string): string {\n const flattened = text.replace(/\\s+/gu, ' ').trim()\n return flattened.length > PREVIEW_CHARS ? `${flattened.slice(0, PREVIEW_CHARS)}…` : flattened\n}\n\n/** One message as a line: who spoke, and what the model could read of it. */\nfunction previewMessage(message: Message): Record<string, unknown> {\n const parts: string[] = []\n const calls: string[] = []\n for (const block of message.content) {\n if (block.type === 'text' || block.type === 'reasoning') parts.push(block.text)\n else if (block.type === 'tool-call') calls.push(`${block.name}(${clip(block.arguments)})`)\n else if (block.type === 'tool-result') parts.push(textOf(block.content))\n else parts.push(`[${block.type}]`)\n }\n return {\n role: message.role,\n producer: message.source.kind,\n ...parts.length === 0 ? {} : { text: clip(parts.join(' ')) },\n ...calls.length === 0 ? {} : { toolCalls: calls },\n }\n}\n\n/**\n * What this round sent the model, in a form a person can read.\n *\n * A summary, not a copy: the request can be the whole conversation plus every\n * tool schema, and a trace that stored it verbatim would be larger than the\n * work it describes. What survives is the part that explains the round — which\n * tools were on offer, how long the context was, and the tail of the\n * conversation the model was actually answering, each message clipped.\n * @param request - The request about to be dispatched.\n * @returns The summary for the span.\n */\nfunction requestSummary(request: GenerateOptions): Record<string, unknown> {\n const messages = request.messages ?? []\n const dropped = Math.max(0, messages.length - PREVIEW_MESSAGES)\n return {\n messageCount: messages.length,\n // The identity of the request, for a host that records the provider call\n // separately and has to say WHICH round each recording belongs to. Message\n // ids are stable across every representation boundary, so the last one plus\n // the count names one round of one agent without ambiguity.\n ...messages.at(-1) === undefined ? {} : { lastMessageId: messages.at(-1)?.id },\n ...request.system === undefined ? {} : { system: clip(request.system) },\n ...request.tools === undefined || request.tools.length === 0\n ? {}\n : { tools: request.tools.map(tool => tool.name) },\n ...request.toolChoice === undefined ? {} : { toolChoice: request.toolChoice },\n ...dropped === 0 ? {} : { earlierMessagesOmitted: dropped },\n messages: messages.slice(-PREVIEW_MESSAGES).map(previewMessage),\n }\n}\n\nexport async function modelRound(\n options: RunTurnOptions,\n signal: AbortSignal,\n emit: (event: AgentEvent) => Promise<void>,\n emitMaintenance: (event: AgentMaintenanceEvent) => Promise<void>,\n root: TraceRef,\n turn: number,\n step: number,\n phase: ModelRoundPhase,\n): Promise<RoundResult> {\n const forcedFinal = phase === 'forced-final'\n const finalOutput = phase === 'final' || forcedFinal\n const trace: TraceRef = { traceId: root.traceId, spanId: createSpanId(), parentSpanId: root.spanId }\n let messages = normalizeToolPairing(options.history.messages())\n const afterToolCallIds = recentToolResultIds(options.history)\n const generation = options.history.generation()\n const entries = options.history.entries().length\n const stopped = (): RoundResult | undefined => {\n const stop = accountingUsageStop(options.accounting)\n if (stop === undefined && !signal.aborted) return undefined\n return {\n trace, finish: signal.aborted\n ? { kind: 'aborted', failure: { code: 'ABORTED', message: messageOf(signal.reason) } }\n : { kind: 'stop' },\n calls: [], afterToolCallIds, timing: contentTiming(false, afterToolCallIds.length > 0),\n ...(stop?.kind === 'error' ? { usageRequired: true } : {}),\n ...(stop?.kind === 'usage-unavailable' ? { usageUnavailable: true } : {}),\n }\n }\n const beforeMaintenance = stopped()\n if (beforeMaintenance !== undefined) return beforeMaintenance\n const decision = await runOptionalHook(options.hooks?.beforeStep, [{\n turn, step, messages, snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n emit: emitMaintenance,\n }], options, signal, 'beforeStep')\n const afterMaintenance = stopped()\n if (afterMaintenance !== undefined) return afterMaintenance\n if (decision?.kind === 'reject') {\n const failure: ModelFailure = { message: decision.reason, code: 'STEP_REJECTED' }\n return {\n trace, finish: { kind: 'error', failure }, calls: [], afterToolCallIds,\n timing: contentTiming(false, afterToolCallIds.length > 0),\n }\n }\n // Hooks may append live steering as well as replacing compacted history.\n // Refresh for either mutation so new user input stays at the chronological\n // tail instead of needing to be prepended ahead of older history.\n if (options.history.generation() !== generation\n || options.history.entries().length !== entries) {\n messages = normalizeToolPairing(options.history.messages())\n }\n if (decision?.prepend !== undefined) messages = Object.freeze([...decision.prepend, ...messages])\n const system = systemText(options, forcedFinal)\n const availableTools = [\n ...options.tools?.schemas() ?? [],\n ...options.nativeTools ?? [],\n ]\n const tools = availableTools\n const outputFormat = !finalOutput && options.outputFormat?.type === 'json_schema'\n ? { type: 'text' as const }\n : options.outputFormat\n const requestBase: GenerateOptions = {\n ...options.config,\n messages,\n ...system.length === 0 ? {} : { system },\n ...tools.length === 0 ? {} : { tools },\n ...finalOutput && tools.length > 0\n ? { toolChoice: 'none' as const }\n : options.toolChoice === undefined ? {} : { toolChoice: options.toolChoice },\n ...options.imagePolicy === undefined ? {} : { imagePolicy: options.imagePolicy },\n ...outputFormat === undefined ? {} : { outputFormat },\n }\n const checkpointRequest: GenerateOptions = { ...requestBase, signal }\n try {\n await runOptionalHook(options.hooks?.checkpoint, [{\n kind: 'before-model-request', request: checkpointRequest,\n snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n }], options, signal, 'checkpoint')\n } catch (error: unknown) {\n const failure: ModelFailure = { message: `history checkpoint failed: ${messageOf(error)}`, code: 'CHECKPOINT_FAILED' }\n return {\n trace, finish: { kind: 'error', failure }, calls: [], afterToolCallIds,\n timing: contentTiming(false, afterToolCallIds.length > 0),\n }\n }\n const beforeDispatch = stopped()\n if (beforeDispatch !== undefined) return beforeDispatch\n await emit({ type: 'span-start', trace, at: now(), name: `chat ${options.config.model}`, kind: 'chat', attributes: {\n 'gen_ai.operation.name': 'chat', 'gen_ai.request.model': options.config.model,\n // The effort is part of WHICH call this was: the same model at minimal and\n // at high is two different requests, priced and paced differently, and a\n // trace that omits it cannot explain either. Absent when the route has no\n // effort ladder, rather than reported as a default nobody chose.\n ...options.config.reasoningEffort === undefined\n ? {}\n : { 'gen_ai.request.reasoning_effort': options.config.reasoningEffort },\n turn, step, forcedFinal, phase,\n }, input: requestSummary(requestBase) })\n await emit({ type: 'step-start', turn, step, trace, ...forcedFinal ? { forcedFinal: true as const } : {} })\n const assembler = new BlockAssembler()\n const closedBlockIndexes = new Set<number>()\n const modelTimeoutMs = positiveFinite(options.modelTimeoutMs ?? 10 * 60_000, 'modelTimeoutMs')\n const maxRequestBytes = positiveSafeInteger(options.maxModelRequestBytes ?? 32 * 1024 * 1024, 'maxModelRequestBytes')\n const maxResponseBytes = positiveSafeInteger(options.maxModelResponseBytes ?? 32 * 1024 * 1024, 'maxModelResponseBytes')\n const maxStreamEvents = positiveSafeInteger(options.maxModelStreamEvents ?? 100_000, 'maxModelStreamEvents')\n const teardownTimeoutMs = positiveFinite(options.teardownTimeoutMs ?? 30_000, 'teardownTimeoutMs')\n let modelCallReport: ModelCallReport | undefined\n let usageRequired = false\n let usageUnavailable = false\n let requestBytes: number\n try {\n requestBytes = serializedBytes(requestBase)\n } catch (error: unknown) {\n requestBytes = -1\n assembler.push(modelFailureFinish(`model request is not serializable: ${messageOf(error)}`, 'INVALID_MODEL_REQUEST'))\n }\n if (requestBytes > maxRequestBytes) {\n assembler.push(modelFailureFinish(\n `model request exceeds the ${maxRequestBytes}-byte limit`,\n 'MODEL_REQUEST_TOO_LARGE',\n ))\n } else if (requestBytes >= 0) {\n const owned = new AbortController()\n const roundSignal = AbortSignal.any([signal, owned.signal])\n let timedOut = false\n const timeout = setTimeout(() => {\n timedOut = true\n owned.abort(new Error(`model stream exceeded ${modelTimeoutMs}ms`))\n }, modelTimeoutMs)\n const handle = options.registry.stream(\n { ...requestBase, signal: roundSignal },\n options.accounting?.modelInvocation,\n )\n const iterator = handle[Symbol.asyncIterator]()\n let exhausted = false\n let events = 0\n let responseBytes = 0\n let sawFinish = false\n try {\n while (true) {\n const next = await nextWithAbort(iterator.next(), roundSignal)\n if (next.done === true) {\n exhausted = true\n break\n }\n const chunk = next.value\n try {\n validateStreamChunk(chunk, maxStreamEvents)\n } catch (error: unknown) {\n assembler.push(modelFailureFinish(\n `model adapter emitted an invalid stream chunk: ${messageOf(error)}`,\n 'INVALID_MODEL_STREAM',\n ))\n owned.abort(new Error('invalid model stream chunk'))\n break\n }\n events++\n try {\n responseBytes += serializedBytes(chunk)\n } catch (error: unknown) {\n assembler.push(modelFailureFinish(\n `model adapter emitted a non-serializable stream chunk: ${messageOf(error)}`,\n 'INVALID_MODEL_STREAM',\n ))\n owned.abort(new Error('non-serializable model stream chunk'))\n break\n }\n if (events > maxStreamEvents || responseBytes > maxResponseBytes) {\n const dimension = events > maxStreamEvents\n ? `${maxStreamEvents}-event`\n : `${maxResponseBytes}-byte`\n assembler.push(modelFailureFinish(\n `model response exceeds the ${dimension} limit`,\n 'MODEL_RESPONSE_TOO_LARGE',\n ))\n owned.abort(new Error('model response resource limit exceeded'))\n break\n }\n if (sawFinish) {\n assembler.push(modelFailureFinish(\n 'model adapter emitted data after its terminal finish chunk',\n 'INVALID_MODEL_STREAM',\n ))\n owned.abort(new Error('invalid model stream'))\n break\n }\n assembler.push(chunk)\n // The assembler ignores deltas after the first close. The visible\n // stream must do the same or UI text can disagree with stored history.\n if ((chunk.type === 'text-delta' || chunk.type === 'reasoning-delta' || chunk.type === 'tool-call-delta')\n && closedBlockIndexes.has(chunk.index)) continue\n if (chunk.type === 'block-end') closedBlockIndexes.add(chunk.index)\n if (chunk.type === 'finish') sawFinish = true\n if (chunk.type === 'text-delta') await emit({\n type: 'text-delta', index: chunk.index, text: chunk.text,\n phase: phase === 'process' ? 'commentary' : chunk.phase ?? 'unknown', trace,\n })\n else if (chunk.type === 'reasoning-delta') await emit({\n type: 'reasoning-delta', index: chunk.index, text: chunk.text, trace,\n })\n else if (chunk.type === 'image-delta') await emit({\n type: 'image-delta', itemId: chunk.itemId, data: chunk.data,\n mediaType: chunk.mediaType, ...chunk.partialIndex === undefined ? {} : { partialIndex: chunk.partialIndex }, trace,\n })\n else if (chunk.type === 'usage') await emit({ type: 'usage', usage: chunk.usage, trace })\n }\n } catch (error: unknown) {\n if (!(error instanceof StreamAbortError)) throw error\n assembler.push(signal.aborted\n ? modelAbortedFinish(messageOf(signal.reason ?? error))\n : timedOut\n ? modelFailureFinish(`model stream exceeded ${modelTimeoutMs}ms`, 'MODEL_TIMEOUT')\n : modelFailureFinish(messageOf(error.cause ?? error), 'MODEL_STREAM_ABORTED'))\n } finally {\n clearTimeout(timeout)\n if (!exhausted) {\n owned.abort(new Error('model stream closed before exhaustion'))\n const settled = await closeIterator(iterator, teardownTimeoutMs)\n if (!settled) {\n assembler.push(modelFailureFinish(\n `model stream ignored cancellation for more than ${teardownTimeoutMs}ms; the adapter operation may still be running`,\n 'MODEL_TEARDOWN_TIMEOUT',\n ))\n }\n }\n }\n const report = await handle.report\n const decision = options.accounting === undefined\n ? undefined\n : await options.accounting.recordModelCall(report, { ...requestBase, signal })\n modelCallReport = decision?.report ?? report\n usageRequired = decision?.usageRequired ?? false\n usageUnavailable = decision?.usageUnavailable ?? false\n }\n let providerFinish = assembler.finish\n let retainedPrefix = providerFinish.kind === 'aborted'\n let rawBlocks: ContentBlock[]\n try {\n rawBlocks = providerFinish.kind === 'aborted' ? assembler.interruptedBlocks() : assembler.blocks()\n } catch (error: unknown) {\n providerFinish = {\n kind: 'error',\n failure: {\n message: `model adapter emitted an invalid block sequence: ${messageOf(error)}`,\n code: 'INVALID_MODEL_STREAM',\n },\n }\n // A broken extension must not discard text already delivered to the user.\n // This prefix deliberately excludes tools and unassembled extension data.\n retainedPrefix = true\n rawBlocks = assembler.interruptedBlocks()\n }\n // Interrupted/truncated assembly drops unfinished calls, but the text that\n // introduced those calls is still process narration, not a final answer.\n const canonicalTexts = assembler.textBlocks()\n .filter(({ block }) => !retainedPrefix || block.text.trim() !== '')\n let textPosition = 0\n const classifiedRaw = classifyTextPhases(rawBlocks.map(block => {\n if (block.type !== 'text') return block\n const canonical = canonicalTexts[textPosition++]\n // Safe-prefix recovery removes native calls too. Retain their position so\n // search narration cannot become an answer merely because a call was removed.\n return block.phase === undefined && canonical?.beforeNativeCall\n ? { ...block, phase: 'commentary' as const } : block\n }), phase === 'process', assembler.hasToolCalls)\n // A repeated id costs the model that one call, not its whole turn.\n const deduped = dropDuplicateToolCalls(classifiedRaw, options.history)\n const classified = deduped.blocks\n const structuredOutputFailure = finalOutput\n && options.outputFormat?.type === 'json_schema'\n && providerFinish.kind === 'stop'\n && !isJsonText(textOf(classified), options.validateOutput)\n ? {\n message: 'model returned invalid JSON or failed the structured output validator',\n code: MODEL_ERROR_CODES.MALFORMED_RESPONSE,\n }\n : undefined\n const disabledCall = finalOutput && classified.some(block => block.type === 'tool-call')\n ? { message: 'model emitted a host tool call during the final output phase', code: 'INVALID_TOOL_CALL' }\n : undefined\n const invalidCall = disabledCall\n ?? structuredOutputFailure\n ?? invalidHostToolCall(classified, options.history)\n const blocks = invalidCall === undefined\n ? classified\n : classified.filter(block => block.type !== 'tool-call')\n const finish: FinishReason = invalidCall === undefined\n ? providerFinish\n : { kind: 'error', failure: invalidCall }\n const message = blocks.length === 0 && (finish.kind === 'error' || finish.kind === 'aborted')\n ? undefined\n : createAssistant(options, blocks, retainedPrefix ? undefined : assembler.replayState)\n const calls = message?.content\n .filter((block): block is ToolCallBlock => block.type === 'tool-call')\n .map(block => ({ callId: block.id, toolName: block.name, rawArguments: block.arguments })) ?? []\n const timing = contentTiming(calls.length > 0, afterToolCallIds.length > 0)\n // Deltas may have no phase, or block-end may correct it. Publish the\n // canonical snapshot before consumers close this step, including providers\n // that only emit block-end. Keep provider indexes (which may be sparse).\n if (blocks.some(block => block.type === 'text')) {\n const indexes = canonicalTexts.map(({ index }) => index)\n const incomplete = finish.kind === 'error' || finish.kind === 'aborted' || finish.kind === 'max-tokens'\n let position = 0\n for (const block of blocks) {\n if (block.type !== 'text') continue\n const index = indexes[position++]\n if (index !== undefined) await emit({\n type: 'text-end', index, text: block.text,\n phase: block.phase ?? 'final-answer', trace,\n ...incomplete ? { incomplete: true as const } : {},\n })\n }\n }\n await emit({\n type: 'span-end', trace, at: now(),\n status: finish.kind === 'error' ? 'error' : finish.kind === 'aborted' ? 'aborted' : 'success',\n output: message === undefined ? undefined : {\n text: textOf(message.content),\n commentary: message.content.flatMap(block => block.type === 'text' && block.phase === 'commentary' ? [block.text] : []),\n reasoning: message.content.flatMap(block => block.type === 'reasoning' ? [block.text] : []),\n toolCalls: calls.length,\n },\n ...assembler.usage === undefined ? {} : { usage: assembler.usage },\n ...finish.kind === 'error' || finish.kind === 'aborted'\n ? { error: { type: 'ModelError', message: finish.failure.message, code: finish.failure.code } }\n : {},\n })\n if (calls.length === 0 || finalOutput) await emit({ type: 'step-end', turn, step, trace })\n return {\n trace, ...message === undefined ? {} : { message }, finish,\n ...assembler.usage === undefined ? {} : { usage: assembler.usage },\n ...modelCallReport === undefined ? {} : { report: modelCallReport },\n ...usageRequired ? { usageRequired: true as const } : {},\n ...usageUnavailable ? { usageUnavailable: true as const } : {},\n calls, afterToolCallIds, timing,\n ...deduped.dropped.length === 0 ? {} : { droppedDuplicateCalls: deduped.dropped },\n }\n}\n\nfunction isJsonText(value: string, validate?: (value: unknown) => void): boolean {\n try {\n const parsed: unknown = JSON.parse(value)\n validate?.(parsed)\n return true\n } catch {\n return false\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"model-round.js","names":[],"sources":["../../../../src/agent/loop/turn/model-round.ts"],"sourcesContent":["import type { GenerateOptions } from '../../../contract/index.ts'\nimport { MODEL_ERROR_CODES, type ModelFailure } from '../../../errors/index.ts'\nimport type { ContentBlock, Message, ToolCallBlock } from '../../../message/index.ts'\nimport { BlockAssembler } from '../../../stream/index.ts'\nimport type { FinishReason } from '../../../stream/index.ts'\nimport type { ModelCallReport } from '../../../observation/index.ts'\nimport { normalizeToolPairing } from '../../history/normalize.ts'\nimport { createSpanId, type TraceRef } from '../../trace/trace.ts'\nimport type { AgentEvent, AgentMaintenanceEvent } from '../types.ts'\nimport { type ModelRoundPhase, type RunTurnOptions, type RoundResult } from './types.ts'\nimport { positiveFinite, positiveSafeInteger } from './config.ts'\nimport { serializedBytes, modelFailureFinish, modelAbortedFinish, messageOf, now } from './common.ts'\nimport { validateStreamChunk } from './validation.ts'\nimport { StreamAbortError, nextWithAbort, closeIterator } from './cancellation.ts'\nimport { runOptionalHook } from './hooks.ts'\nimport { accountingUsageStop } from './usage-stop.ts'\nimport {\n classifyTextPhases, dropDuplicateToolCalls, invalidHostToolCall, contentTiming,\n recentToolResultIds, systemText,\n createAssistant, textOf,\n} from './content.ts'\n\n/** How much of one message the trace keeps. */\nconst PREVIEW_CHARS = 600\n\n/** How many trailing messages the trace keeps. */\nconst PREVIEW_MESSAGES = 8\n\nfunction clip(text: string): string {\n const flattened = text.replace(/\\s+/gu, ' ').trim()\n return flattened.length > PREVIEW_CHARS ? `${flattened.slice(0, PREVIEW_CHARS)}…` : flattened\n}\n\n/** One message as a line: who spoke, and what the model could read of it. */\nfunction previewMessage(message: Message): Record<string, unknown> {\n const parts: string[] = []\n const calls: string[] = []\n for (const block of message.content) {\n if (block.type === 'text' || block.type === 'reasoning') parts.push(block.text)\n else if (block.type === 'tool-call') calls.push(`${block.name}(${clip(block.arguments)})`)\n else if (block.type === 'tool-result') parts.push(textOf(block.content))\n else parts.push(`[${block.type}]`)\n }\n return {\n role: message.role,\n producer: message.source.kind,\n ...parts.length === 0 ? {} : { text: clip(parts.join(' ')) },\n ...calls.length === 0 ? {} : { toolCalls: calls },\n }\n}\n\n/**\n * What this round sent the model, in a form a person can read.\n *\n * A summary, not a copy: the request can be the whole conversation plus every\n * tool schema, and a trace that stored it verbatim would be larger than the\n * work it describes. What survives is the part that explains the round — which\n * tools were on offer, how long the context was, and the tail of the\n * conversation the model was actually answering, each message clipped.\n * @param request - The request about to be dispatched.\n * @returns The summary for the span.\n */\nfunction requestSummary(request: GenerateOptions): Record<string, unknown> {\n const messages = request.messages ?? []\n const dropped = Math.max(0, messages.length - PREVIEW_MESSAGES)\n return {\n messageCount: messages.length,\n // The identity of the request, for a host that records the provider call\n // separately and has to say WHICH round each recording belongs to. Message\n // ids are stable across every representation boundary, so the last one plus\n // the count names one round of one agent without ambiguity.\n ...messages.at(-1) === undefined ? {} : { lastMessageId: messages.at(-1)?.id },\n ...request.system === undefined ? {} : { system: clip(request.system) },\n ...request.tools === undefined || request.tools.length === 0\n ? {}\n : { tools: request.tools.map(tool => tool.name) },\n ...request.toolChoice === undefined ? {} : { toolChoice: request.toolChoice },\n ...dropped === 0 ? {} : { earlierMessagesOmitted: dropped },\n messages: messages.slice(-PREVIEW_MESSAGES).map(previewMessage),\n }\n}\n\nexport async function modelRound(\n options: RunTurnOptions,\n signal: AbortSignal,\n emit: (event: AgentEvent) => Promise<void>,\n emitMaintenance: (event: AgentMaintenanceEvent) => Promise<void>,\n root: TraceRef,\n turn: number,\n step: number,\n phase: ModelRoundPhase,\n): Promise<RoundResult> {\n const forcedFinal = phase === 'forced-final'\n const finalOutput = phase === 'final' || forcedFinal\n const trace: TraceRef = { traceId: root.traceId, spanId: createSpanId(), parentSpanId: root.spanId }\n let messages = normalizeToolPairing(options.history.messages())\n const afterToolCallIds = recentToolResultIds(options.history)\n const generation = options.history.generation()\n const entries = options.history.entries().length\n const stopped = (): RoundResult | undefined => {\n const stop = accountingUsageStop(options.accounting)\n if (stop === undefined && !signal.aborted) return undefined\n return {\n trace, finish: signal.aborted\n ? { kind: 'aborted', failure: { code: 'ABORTED', message: messageOf(signal.reason) } }\n : { kind: 'stop' },\n calls: [], afterToolCallIds, timing: contentTiming(false, afterToolCallIds.length > 0),\n ...(stop?.kind === 'error' ? { usageRequired: true } : {}),\n ...(stop?.kind === 'usage-unavailable' ? { usageUnavailable: true } : {}),\n }\n }\n const beforeMaintenance = stopped()\n if (beforeMaintenance !== undefined) return beforeMaintenance\n const decision = await runOptionalHook(options.hooks?.beforeStep, [{\n turn, step, messages, snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n emit: emitMaintenance,\n }], options, signal, 'beforeStep')\n const afterMaintenance = stopped()\n if (afterMaintenance !== undefined) return afterMaintenance\n if (decision?.kind === 'reject') {\n const failure: ModelFailure = { message: decision.reason, code: 'STEP_REJECTED' }\n return {\n trace, finish: { kind: 'error', failure }, calls: [], afterToolCallIds,\n timing: contentTiming(false, afterToolCallIds.length > 0),\n }\n }\n // Hooks may append live steering as well as replacing compacted history.\n // Refresh for either mutation so new user input stays at the chronological\n // tail instead of needing to be prepended ahead of older history.\n if (options.history.generation() !== generation\n || options.history.entries().length !== entries) {\n messages = normalizeToolPairing(options.history.messages())\n }\n if (decision?.prepend !== undefined) messages = Object.freeze([...decision.prepend, ...messages])\n const system = systemText(options, forcedFinal)\n const availableTools = [\n ...options.tools?.schemas() ?? [],\n ...options.nativeTools ?? [],\n ]\n const tools = availableTools\n const outputFormat = !finalOutput && options.outputFormat?.type === 'json_schema'\n ? { type: 'text' as const }\n : options.outputFormat\n const requestBase: GenerateOptions = {\n ...options.config,\n messages,\n ...system.length === 0 ? {} : { system },\n ...tools.length === 0 ? {} : { tools },\n ...finalOutput && tools.length > 0\n ? { toolChoice: 'none' as const }\n : options.toolChoice === undefined ? {} : { toolChoice: options.toolChoice },\n ...options.imagePolicy === undefined ? {} : { imagePolicy: options.imagePolicy },\n ...options.documentPolicy === undefined ? {} : { documentPolicy: options.documentPolicy },\n ...outputFormat === undefined ? {} : { outputFormat },\n }\n const checkpointRequest: GenerateOptions = { ...requestBase, signal }\n try {\n await runOptionalHook(options.hooks?.checkpoint, [{\n kind: 'before-model-request', request: checkpointRequest,\n snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n }], options, signal, 'checkpoint')\n } catch (error: unknown) {\n const failure: ModelFailure = { message: `history checkpoint failed: ${messageOf(error)}`, code: 'CHECKPOINT_FAILED' }\n return {\n trace, finish: { kind: 'error', failure }, calls: [], afterToolCallIds,\n timing: contentTiming(false, afterToolCallIds.length > 0),\n }\n }\n const beforeDispatch = stopped()\n if (beforeDispatch !== undefined) return beforeDispatch\n await emit({ type: 'span-start', trace, at: now(), name: `chat ${options.config.model}`, kind: 'chat', attributes: {\n 'gen_ai.operation.name': 'chat', 'gen_ai.request.model': options.config.model,\n // The effort is part of WHICH call this was: the same model at minimal and\n // at high is two different requests, priced and paced differently, and a\n // trace that omits it cannot explain either. Absent when the route has no\n // effort ladder, rather than reported as a default nobody chose.\n ...options.config.reasoningEffort === undefined\n ? {}\n : { 'gen_ai.request.reasoning_effort': options.config.reasoningEffort },\n turn, step, forcedFinal, phase,\n }, input: requestSummary(requestBase) })\n await emit({ type: 'step-start', turn, step, trace, ...forcedFinal ? { forcedFinal: true as const } : {} })\n const assembler = new BlockAssembler()\n const closedBlockIndexes = new Set<number>()\n const modelTimeoutMs = positiveFinite(options.modelTimeoutMs ?? 10 * 60_000, 'modelTimeoutMs')\n const maxRequestBytes = positiveSafeInteger(options.maxModelRequestBytes ?? 32 * 1024 * 1024, 'maxModelRequestBytes')\n const maxResponseBytes = positiveSafeInteger(options.maxModelResponseBytes ?? 32 * 1024 * 1024, 'maxModelResponseBytes')\n const maxStreamEvents = positiveSafeInteger(options.maxModelStreamEvents ?? 100_000, 'maxModelStreamEvents')\n const teardownTimeoutMs = positiveFinite(options.teardownTimeoutMs ?? 30_000, 'teardownTimeoutMs')\n let modelCallReport: ModelCallReport | undefined\n let usageRequired = false\n let usageUnavailable = false\n let requestBytes: number\n try {\n requestBytes = serializedBytes(requestBase)\n } catch (error: unknown) {\n requestBytes = -1\n assembler.push(modelFailureFinish(`model request is not serializable: ${messageOf(error)}`, 'INVALID_MODEL_REQUEST'))\n }\n if (requestBytes > maxRequestBytes) {\n assembler.push(modelFailureFinish(\n `model request exceeds the ${maxRequestBytes}-byte limit`,\n 'MODEL_REQUEST_TOO_LARGE',\n ))\n } else if (requestBytes >= 0) {\n const owned = new AbortController()\n const roundSignal = AbortSignal.any([signal, owned.signal])\n let timedOut = false\n const timeout = setTimeout(() => {\n timedOut = true\n owned.abort(new Error(`model stream exceeded ${modelTimeoutMs}ms`))\n }, modelTimeoutMs)\n const handle = options.registry.stream(\n { ...requestBase, signal: roundSignal },\n options.accounting?.modelInvocation,\n )\n const iterator = handle[Symbol.asyncIterator]()\n let exhausted = false\n let events = 0\n let responseBytes = 0\n let sawFinish = false\n try {\n while (true) {\n const next = await nextWithAbort(iterator.next(), roundSignal)\n if (next.done === true) {\n exhausted = true\n break\n }\n const chunk = next.value\n try {\n validateStreamChunk(chunk, maxStreamEvents)\n } catch (error: unknown) {\n assembler.push(modelFailureFinish(\n `model adapter emitted an invalid stream chunk: ${messageOf(error)}`,\n 'INVALID_MODEL_STREAM',\n ))\n owned.abort(new Error('invalid model stream chunk'))\n break\n }\n events++\n try {\n responseBytes += serializedBytes(chunk)\n } catch (error: unknown) {\n assembler.push(modelFailureFinish(\n `model adapter emitted a non-serializable stream chunk: ${messageOf(error)}`,\n 'INVALID_MODEL_STREAM',\n ))\n owned.abort(new Error('non-serializable model stream chunk'))\n break\n }\n if (events > maxStreamEvents || responseBytes > maxResponseBytes) {\n const dimension = events > maxStreamEvents\n ? `${maxStreamEvents}-event`\n : `${maxResponseBytes}-byte`\n assembler.push(modelFailureFinish(\n `model response exceeds the ${dimension} limit`,\n 'MODEL_RESPONSE_TOO_LARGE',\n ))\n owned.abort(new Error('model response resource limit exceeded'))\n break\n }\n if (sawFinish) {\n assembler.push(modelFailureFinish(\n 'model adapter emitted data after its terminal finish chunk',\n 'INVALID_MODEL_STREAM',\n ))\n owned.abort(new Error('invalid model stream'))\n break\n }\n assembler.push(chunk)\n // The assembler ignores deltas after the first close. The visible\n // stream must do the same or UI text can disagree with stored history.\n if ((chunk.type === 'text-delta' || chunk.type === 'reasoning-delta' || chunk.type === 'tool-call-delta')\n && closedBlockIndexes.has(chunk.index)) continue\n if (chunk.type === 'block-end') closedBlockIndexes.add(chunk.index)\n if (chunk.type === 'finish') sawFinish = true\n if (chunk.type === 'text-delta') await emit({\n type: 'text-delta', index: chunk.index, text: chunk.text,\n phase: phase === 'process' ? 'commentary' : chunk.phase ?? 'unknown', trace,\n })\n else if (chunk.type === 'reasoning-delta') await emit({\n type: 'reasoning-delta', index: chunk.index, text: chunk.text, trace,\n })\n else if (chunk.type === 'image-delta') await emit({\n type: 'image-delta', itemId: chunk.itemId, data: chunk.data,\n mediaType: chunk.mediaType, ...chunk.partialIndex === undefined ? {} : { partialIndex: chunk.partialIndex }, trace,\n })\n else if (chunk.type === 'usage') await emit({ type: 'usage', usage: chunk.usage, trace })\n else if (chunk.type === 'usage-progress') await emit({ ...chunk, trace })\n }\n } catch (error: unknown) {\n if (!(error instanceof StreamAbortError)) throw error\n assembler.push(signal.aborted\n ? modelAbortedFinish(messageOf(signal.reason ?? error))\n : timedOut\n ? modelFailureFinish(`model stream exceeded ${modelTimeoutMs}ms`, 'MODEL_TIMEOUT')\n : modelFailureFinish(messageOf(error.cause ?? error), 'MODEL_STREAM_ABORTED'))\n } finally {\n clearTimeout(timeout)\n if (!exhausted) {\n owned.abort(new Error('model stream closed before exhaustion'))\n const settled = await closeIterator(iterator, teardownTimeoutMs)\n if (!settled) {\n assembler.push(modelFailureFinish(\n `model stream ignored cancellation for more than ${teardownTimeoutMs}ms; the adapter operation may still be running`,\n 'MODEL_TEARDOWN_TIMEOUT',\n ))\n }\n }\n }\n const report = await handle.report\n const decision = options.accounting === undefined\n ? undefined\n : await options.accounting.recordModelCall(report, { ...requestBase, signal })\n modelCallReport = decision?.report ?? report\n usageRequired = decision?.usageRequired ?? false\n usageUnavailable = decision?.usageUnavailable ?? false\n }\n let providerFinish = assembler.finish\n let retainedPrefix = providerFinish.kind === 'aborted'\n let rawBlocks: ContentBlock[]\n try {\n rawBlocks = providerFinish.kind === 'aborted' ? assembler.interruptedBlocks() : assembler.blocks()\n } catch (error: unknown) {\n providerFinish = {\n kind: 'error',\n failure: {\n message: `model adapter emitted an invalid block sequence: ${messageOf(error)}`,\n code: 'INVALID_MODEL_STREAM',\n },\n }\n // A broken extension must not discard text already delivered to the user.\n // This prefix deliberately excludes tools and unassembled extension data.\n retainedPrefix = true\n rawBlocks = assembler.interruptedBlocks()\n }\n // Interrupted/truncated assembly drops unfinished calls, but the text that\n // introduced those calls is still process narration, not a final answer.\n const canonicalTexts = assembler.textBlocks()\n .filter(({ block }) => !retainedPrefix || block.text.trim() !== '')\n let textPosition = 0\n const classifiedRaw = classifyTextPhases(rawBlocks.map(block => {\n if (block.type !== 'text') return block\n const canonical = canonicalTexts[textPosition++]\n // Safe-prefix recovery removes native calls too. Retain their position so\n // search narration cannot become an answer merely because a call was removed.\n return block.phase === undefined && canonical?.beforeNativeCall\n ? { ...block, phase: 'commentary' as const } : block\n }), phase === 'process', assembler.hasToolCalls)\n // A repeated id costs the model that one call, not its whole turn.\n const deduped = dropDuplicateToolCalls(classifiedRaw, options.history)\n const classified = deduped.blocks\n const structuredOutputFailure = finalOutput\n && options.outputFormat?.type === 'json_schema'\n && providerFinish.kind === 'stop'\n && !isJsonText(textOf(classified), options.validateOutput)\n ? {\n message: 'model returned invalid JSON or failed the structured output validator',\n code: MODEL_ERROR_CODES.MALFORMED_RESPONSE,\n }\n : undefined\n const disabledCall = finalOutput && classified.some(block => block.type === 'tool-call')\n ? { message: 'model emitted a host tool call during the final output phase', code: 'INVALID_TOOL_CALL' }\n : undefined\n const invalidCall = disabledCall\n ?? structuredOutputFailure\n ?? invalidHostToolCall(classified, options.history)\n const blocks = invalidCall === undefined\n ? classified\n : classified.filter(block => block.type !== 'tool-call')\n const finish: FinishReason = invalidCall === undefined\n ? providerFinish\n : { kind: 'error', failure: invalidCall }\n const message = blocks.length === 0 && (finish.kind === 'error' || finish.kind === 'aborted')\n ? undefined\n : createAssistant(options, blocks, retainedPrefix ? undefined : assembler.replayState)\n const calls = message?.content\n .filter((block): block is ToolCallBlock => block.type === 'tool-call')\n .map(block => ({ callId: block.id, toolName: block.name, rawArguments: block.arguments })) ?? []\n const timing = contentTiming(calls.length > 0, afterToolCallIds.length > 0)\n // Deltas may have no phase, or block-end may correct it. Publish the\n // canonical snapshot before consumers close this step, including providers\n // that only emit block-end. Keep provider indexes (which may be sparse).\n if (blocks.some(block => block.type === 'text')) {\n const indexes = canonicalTexts.map(({ index }) => index)\n const incomplete = finish.kind === 'error' || finish.kind === 'aborted' || finish.kind === 'max-tokens'\n let position = 0\n for (const block of blocks) {\n if (block.type !== 'text') continue\n const index = indexes[position++]\n if (index !== undefined) await emit({\n type: 'text-end', index, text: block.text,\n phase: block.phase ?? 'final-answer', trace,\n ...incomplete ? { incomplete: true as const } : {},\n })\n }\n }\n await emit({\n type: 'span-end', trace, at: now(),\n status: finish.kind === 'error' ? 'error' : finish.kind === 'aborted' ? 'aborted' : 'success',\n output: message === undefined ? undefined : {\n text: textOf(message.content),\n commentary: message.content.flatMap(block => block.type === 'text' && block.phase === 'commentary' ? [block.text] : []),\n reasoning: message.content.flatMap(block => block.type === 'reasoning' ? [block.text] : []),\n toolCalls: calls.length,\n },\n ...assembler.usage === undefined ? {} : { usage: assembler.usage },\n ...finish.kind === 'error' || finish.kind === 'aborted'\n ? { error: { type: 'ModelError', message: finish.failure.message, code: finish.failure.code } }\n : {},\n })\n if (calls.length === 0 || finalOutput) await emit({ type: 'step-end', turn, step, trace })\n return {\n trace, ...message === undefined ? {} : { message }, finish,\n ...assembler.usage === undefined ? {} : { usage: assembler.usage },\n ...modelCallReport === undefined ? {} : { report: modelCallReport },\n ...usageRequired ? { usageRequired: true as const } : {},\n ...usageUnavailable ? { usageUnavailable: true as const } : {},\n calls, afterToolCallIds, timing,\n ...deduped.dropped.length === 0 ? {} : { droppedDuplicateCalls: deduped.dropped },\n }\n}\n\nfunction isJsonText(value: string, validate?: (value: unknown) => void): boolean {\n try {\n const parsed: unknown = JSON.parse(value)\n validate?.(parsed)\n return true\n } catch {\n return false\n }\n}\n"],"mappings":"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"}
|
|
@@ -18,6 +18,8 @@ interface RunTurnOptions {
|
|
|
18
18
|
readonly validateOutput?: (value: unknown) => void;
|
|
19
19
|
/** strict rejects known text-only models when request history contains images; project permits lossy conversion. */
|
|
20
20
|
readonly imagePolicy?: 'strict' | 'project';
|
|
21
|
+
/** strict rejects models that decline document input when history contains documents; project permits lossy conversion. */
|
|
22
|
+
readonly documentPolicy?: 'strict' | 'project';
|
|
21
23
|
readonly registry: ModelRegistry;
|
|
22
24
|
readonly config: CallConfig;
|
|
23
25
|
readonly history: History;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../../src/agent/loop/turn/types.ts"],"mappings":";;;;;;;;;;;;;;;;UAkBiB;WACN,kBAAkB;;WAElB;WACA,UAAU;WACV,QAAQ;WACR,SAAS;WACT,QAAQ;;WAER,uBAAuB;;WAEvB,aAAa;;WAEb,eAAe;WACf;WACA,wBAAwB;WACxB,YAAY;WACZ,SAAS,QAAQ;WACjB,QAAQ;WACR,SAAS;;WAET,SAAS;;WAET;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;aACE,UAAU;aACV,eAAe;aACf;aACA;aACA;;;WAGF,aAAa;;;;;;;;WAQb,aAAa;;;;;;;WAOb,2BAA2B"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../../src/agent/loop/turn/types.ts"],"mappings":";;;;;;;;;;;;;;;;UAkBiB;WACN,kBAAkB;;WAElB;;WAEA;WACA,UAAU;WACV,QAAQ;WACR,SAAS;WACT,QAAQ;;WAER,uBAAuB;;WAEvB,aAAa;;WAEb,eAAe;WACf;WACA,wBAAwB;WACxB,YAAY;WACZ,SAAS,QAAQ;WACjB,QAAQ;WACR,SAAS;;WAET,SAAS;;WAET;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;aACE,UAAU;aACV,eAAe;aACf;aACA;aACA;;;WAGF,aAAa;;;;;;;;WAQb,aAAa;;;;;;;WAOb,2BAA2B"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(e,n){if(typeof e!=`object`||!e||typeof e.type!=`string`)throw TypeError(`chunk must be an object with a type`);if(`index`in e&&(!Number.isSafeInteger(e.index)||e.index<0))throw TypeError(`chunk index must be a non-negative safe integer`);switch(e.type){case`block-start`:if(typeof e.blockType!=`string`||e.blockType.length===0)throw TypeError(`blockType must be non-empty`);return;case`text-delta`:if(typeof e.text!=`string`)throw TypeError(`text delta must be a string`);if(e.phase!==void 0&&e.phase!==`commentary`&&e.phase!==`final-answer`)throw TypeError(`text phase is invalid`);return;case`reasoning-delta`:if(typeof e.text!=`string`)throw TypeError(`reasoning delta must be a string`);return;case`image-delta`:if(typeof e.itemId!=`string`||typeof e.data!=`string`||typeof e.mediaType!=`string`)throw TypeError(`image delta fields must be strings`);if(e.partialIndex!==void 0&&(!Number.isSafeInteger(e.partialIndex)||e.partialIndex<0))throw TypeError(`image partialIndex must be a non-negative safe integer`);return;case`tool-call-delta`:if(typeof e.id!=`string`||e.id.length===0||e.name!==void 0&&typeof e.name!=`string`||typeof e.argumentsDelta!=`string`)throw TypeError(`tool-call delta fields are invalid`);return;case`block-end`:if(typeof e.block!=`object`||e.block===null||typeof e.block.type!=`string`)throw TypeError(`block-end must contain a content block`);t(e.block,n);return;case`usage`:r(e.usage.inputTokens,`inputTokens`),r(e.usage.outputTokens,`outputTokens`);for(let t of[`totalTokens`,`cacheReadTokens`,`cacheWriteTokens`,`reasoningTokens`])e.usage[t]!==void 0&&r(e.usage[t],t);return;case`finish`:if(typeof e.reason!=`object`||e.reason===null||typeof e.reason.kind!=`string`)throw TypeError(`finish reason is invalid`);if((e.reason.kind===`error`||e.reason.kind===`aborted`)&&(typeof e.reason.failure!=`object`||e.reason.failure===null||typeof e.reason.failure.message!=`string`||typeof e.reason.failure.code!=`string`))throw TypeError(`finish failure is invalid`);return;default:throw TypeError(`unknown chunk type '${String(e.type)}'`)}}function t(e,t){let r=[e],i=0;for(;r.length>0;){let e=r.pop();if(!n(e)||typeof e.type!=`string`||e.type.length===0)throw TypeError(`content block must be an object with a non-empty type`);if(i++,i>t)throw TypeError(`content block tree exceeds ${t} nodes`);switch(e.type){case`text`:if(typeof e.text!=`string`)throw TypeError(`text block text must be a string`);if(e.phase!==void 0&&e.phase!==`commentary`&&e.phase!==`final-answer`)throw TypeError(`text block phase is invalid`);break;case`reasoning`:if(typeof e.text!=`string`)throw TypeError(`reasoning block text must be a string`);break;case`image`:if(!n(e.source)||typeof e.source.kind!=`string`)throw TypeError(`image block source is invalid`);if(e.source.kind===`base64`){if(typeof e.source.data!=`string`||typeof e.source.mediaType!=`string`)throw TypeError(`base64 image source is invalid`)}else if(e.source.kind===`url`){if(typeof e.source.url!=`string`)throw TypeError(`URL image source is invalid`)}else if(e.source.kind===`file`){if(typeof e.source.fileId!=`string`)throw TypeError(`file image source is invalid`)}else throw TypeError(`image source kind is invalid`);break;case`tool-call`:if(typeof e.id!=`string`||e.id.length===0||typeof e.name!=`string`||e.name.length===0||typeof e.arguments!=`string`)throw TypeError(`tool-call block fields are invalid`);break;case`tool-result`:if(typeof e.toolCallId!=`string`||e.toolCallId.length===0||!Array.isArray(e.content)||e.isError!==void 0&&typeof e.isError!=`boolean`)throw TypeError(`tool-result block fields are invalid`);for(let t=e.content.length-1;t>=0;t--)r.push(e.content[t]);break;case`native-tool-call`:if(typeof e.id!=`string`||e.id.length===0||typeof e.name!=`string`||e.name.length===0||e.status!==void 0&&typeof e.status!=`string`||!Array.isArray(e.content))throw TypeError(`native-tool-call block fields are invalid`);for(let t=e.content.length-1;t>=0;t--)r.push(e.content[t])}}}function n(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function r(e,t){if(!Number.isSafeInteger(e)||e<0)throw TypeError(`usage ${t} must be a non-negative safe integer`)}export{n as record,t as validateContentBlock,e as validateStreamChunk,r as validateUsageCount};
|
|
1
|
+
function e(e,n){if(typeof e!=`object`||!e||typeof e.type!=`string`)throw TypeError(`chunk must be an object with a type`);if(`index`in e&&(!Number.isSafeInteger(e.index)||e.index<0))throw TypeError(`chunk index must be a non-negative safe integer`);switch(e.type){case`block-start`:if(typeof e.blockType!=`string`||e.blockType.length===0)throw TypeError(`blockType must be non-empty`);return;case`text-delta`:if(typeof e.text!=`string`)throw TypeError(`text delta must be a string`);if(e.phase!==void 0&&e.phase!==`commentary`&&e.phase!==`final-answer`)throw TypeError(`text phase is invalid`);return;case`reasoning-delta`:if(typeof e.text!=`string`)throw TypeError(`reasoning delta must be a string`);return;case`image-delta`:if(typeof e.itemId!=`string`||typeof e.data!=`string`||typeof e.mediaType!=`string`)throw TypeError(`image delta fields must be strings`);if(e.partialIndex!==void 0&&(!Number.isSafeInteger(e.partialIndex)||e.partialIndex<0))throw TypeError(`image partialIndex must be a non-negative safe integer`);return;case`tool-call-delta`:if(typeof e.id!=`string`||e.id.length===0||e.name!==void 0&&typeof e.name!=`string`||typeof e.argumentsDelta!=`string`)throw TypeError(`tool-call delta fields are invalid`);return;case`block-end`:if(typeof e.block!=`object`||e.block===null||typeof e.block.type!=`string`)throw TypeError(`block-end must contain a content block`);t(e.block,n);return;case`usage-progress`:for(let t of[`inputTokens`,`outputTokens`,`totalTokens`,`cacheReadTokens`,`cacheWriteTokens`,`reasoningTokens`])e.usage[t]!==void 0&&r(e.usage[t],t);return;case`usage`:r(e.usage.inputTokens,`inputTokens`),r(e.usage.outputTokens,`outputTokens`);for(let t of[`totalTokens`,`cacheReadTokens`,`cacheWriteTokens`,`reasoningTokens`])e.usage[t]!==void 0&&r(e.usage[t],t);return;case`finish`:if(typeof e.reason!=`object`||e.reason===null||typeof e.reason.kind!=`string`)throw TypeError(`finish reason is invalid`);if((e.reason.kind===`error`||e.reason.kind===`aborted`)&&(typeof e.reason.failure!=`object`||e.reason.failure===null||typeof e.reason.failure.message!=`string`||typeof e.reason.failure.code!=`string`))throw TypeError(`finish failure is invalid`);return;default:throw TypeError(`unknown chunk type '${String(e.type)}'`)}}function t(e,t){let r=[e],i=0;for(;r.length>0;){let e=r.pop();if(!n(e)||typeof e.type!=`string`||e.type.length===0)throw TypeError(`content block must be an object with a non-empty type`);if(i++,i>t)throw TypeError(`content block tree exceeds ${t} nodes`);switch(e.type){case`text`:if(typeof e.text!=`string`)throw TypeError(`text block text must be a string`);if(e.phase!==void 0&&e.phase!==`commentary`&&e.phase!==`final-answer`)throw TypeError(`text block phase is invalid`);break;case`reasoning`:if(typeof e.text!=`string`)throw TypeError(`reasoning block text must be a string`);break;case`image`:if(!n(e.source)||typeof e.source.kind!=`string`)throw TypeError(`image block source is invalid`);if(e.source.kind===`base64`){if(typeof e.source.data!=`string`||typeof e.source.mediaType!=`string`)throw TypeError(`base64 image source is invalid`)}else if(e.source.kind===`url`){if(typeof e.source.url!=`string`)throw TypeError(`URL image source is invalid`)}else if(e.source.kind===`file`){if(typeof e.source.fileId!=`string`)throw TypeError(`file image source is invalid`)}else throw TypeError(`image source kind is invalid`);break;case`document`:if(!n(e.source)||typeof e.source.kind!=`string`)throw TypeError(`document block source is invalid`);if(e.source.kind===`base64`){if(typeof e.source.data!=`string`||typeof e.source.mediaType!=`string`)throw TypeError(`base64 document source is invalid`)}else if(e.source.kind===`url`){if(typeof e.source.url!=`string`)throw TypeError(`URL document source is invalid`)}else if(e.source.kind===`file`){if(typeof e.source.fileId!=`string`)throw TypeError(`file document source is invalid`)}else throw TypeError(`document source kind is invalid`);break;case`tool-call`:if(typeof e.id!=`string`||e.id.length===0||typeof e.name!=`string`||e.name.length===0||typeof e.arguments!=`string`)throw TypeError(`tool-call block fields are invalid`);break;case`tool-result`:if(typeof e.toolCallId!=`string`||e.toolCallId.length===0||!Array.isArray(e.content)||e.isError!==void 0&&typeof e.isError!=`boolean`)throw TypeError(`tool-result block fields are invalid`);for(let t=e.content.length-1;t>=0;t--)r.push(e.content[t]);break;case`native-tool-call`:if(typeof e.id!=`string`||e.id.length===0||typeof e.name!=`string`||e.name.length===0||e.status!==void 0&&typeof e.status!=`string`||!Array.isArray(e.content))throw TypeError(`native-tool-call block fields are invalid`);for(let t=e.content.length-1;t>=0;t--)r.push(e.content[t])}}}function n(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function r(e,t){if(!Number.isSafeInteger(e)||e<0)throw TypeError(`usage ${t} must be a non-negative safe integer`)}export{n as record,t as validateContentBlock,e as validateStreamChunk,r as validateUsageCount};
|
|
2
2
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","names":[],"sources":["../../../../src/agent/loop/turn/validation.ts"],"sourcesContent":["import type { ContentBlock } from '../../../message/index.ts'\nimport type { StreamChunk } from '../../../stream/index.ts'\n\nexport function validateStreamChunk(chunk: StreamChunk, maxBlockNodes: number): void {\n if (typeof chunk !== 'object' || chunk === null || typeof chunk.type !== 'string') {\n throw new TypeError('chunk must be an object with a type')\n }\n if ('index' in chunk && (!Number.isSafeInteger(chunk.index) || chunk.index < 0)) {\n throw new TypeError('chunk index must be a non-negative safe integer')\n }\n switch (chunk.type) {\n case 'block-start':\n if (typeof chunk.blockType !== 'string' || chunk.blockType.length === 0) throw new TypeError('blockType must be non-empty')\n return\n case 'text-delta':\n if (typeof chunk.text !== 'string') throw new TypeError('text delta must be a string')\n if (chunk.phase !== undefined && chunk.phase !== 'commentary' && chunk.phase !== 'final-answer') {\n throw new TypeError('text phase is invalid')\n }\n return\n case 'reasoning-delta':\n if (typeof chunk.text !== 'string') throw new TypeError('reasoning delta must be a string')\n return\n case 'image-delta':\n if (typeof chunk.itemId !== 'string' || typeof chunk.data !== 'string' || typeof chunk.mediaType !== 'string') {\n throw new TypeError('image delta fields must be strings')\n }\n if (chunk.partialIndex !== undefined\n && (!Number.isSafeInteger(chunk.partialIndex) || chunk.partialIndex < 0)) {\n throw new TypeError('image partialIndex must be a non-negative safe integer')\n }\n return\n case 'tool-call-delta':\n if (typeof chunk.id !== 'string' || chunk.id.length === 0\n || (chunk.name !== undefined && typeof chunk.name !== 'string')\n || typeof chunk.argumentsDelta !== 'string') {\n throw new TypeError('tool-call delta fields are invalid')\n }\n return\n case 'block-end':\n if (typeof chunk.block !== 'object' || chunk.block === null || typeof chunk.block.type !== 'string') {\n throw new TypeError('block-end must contain a content block')\n }\n validateContentBlock(chunk.block, maxBlockNodes)\n return\n case 'usage':\n validateUsageCount(chunk.usage.inputTokens, 'inputTokens')\n validateUsageCount(chunk.usage.outputTokens, 'outputTokens')\n for (const key of ['totalTokens', 'cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens'] as const) {\n if (chunk.usage[key] !== undefined) validateUsageCount(chunk.usage[key], key)\n }\n return\n case 'finish':\n if (typeof chunk.reason !== 'object' || chunk.reason === null || typeof chunk.reason.kind !== 'string') {\n throw new TypeError('finish reason is invalid')\n }\n if ((chunk.reason.kind === 'error' || chunk.reason.kind === 'aborted')\n && (typeof chunk.reason.failure !== 'object' || chunk.reason.failure === null\n || typeof chunk.reason.failure.message !== 'string'\n || typeof chunk.reason.failure.code !== 'string')) {\n throw new TypeError('finish failure is invalid')\n }\n return\n default:\n throw new TypeError(`unknown chunk type '${String((chunk as { type?: unknown }).type)}'`)\n }\n}\n\nexport function validateContentBlock(root: ContentBlock, maxNodes: number): void {\n const pending: unknown[] = [root]\n let nodes = 0\n while (pending.length > 0) {\n const value = pending.pop()\n if (!record(value) || typeof value.type !== 'string' || value.type.length === 0) {\n throw new TypeError('content block must be an object with a non-empty type')\n }\n nodes++\n if (nodes > maxNodes) throw new TypeError(`content block tree exceeds ${maxNodes} nodes`)\n switch (value.type) {\n case 'text':\n if (typeof value.text !== 'string') throw new TypeError('text block text must be a string')\n if (value.phase !== undefined && value.phase !== 'commentary' && value.phase !== 'final-answer') {\n throw new TypeError('text block phase is invalid')\n }\n break\n case 'reasoning':\n if (typeof value.text !== 'string') throw new TypeError('reasoning block text must be a string')\n break\n case 'image':\n if (!record(value.source) || typeof value.source.kind !== 'string') {\n throw new TypeError('image block source is invalid')\n }\n if (value.source.kind === 'base64') {\n if (typeof value.source.data !== 'string' || typeof value.source.mediaType !== 'string') {\n throw new TypeError('base64 image source is invalid')\n }\n } else if (value.source.kind === 'url') {\n if (typeof value.source.url !== 'string') throw new TypeError('URL image source is invalid')\n } else if (value.source.kind === 'file') {\n if (typeof value.source.fileId !== 'string') throw new TypeError('file image source is invalid')\n } else {\n throw new TypeError('image source kind is invalid')\n }\n break\n case 'tool-call':\n if (typeof value.id !== 'string' || value.id.length === 0\n || typeof value.name !== 'string' || value.name.length === 0\n || typeof value.arguments !== 'string') {\n throw new TypeError('tool-call block fields are invalid')\n }\n break\n case 'tool-result':\n if (typeof value.toolCallId !== 'string' || value.toolCallId.length === 0\n || !Array.isArray(value.content)\n || (value.isError !== undefined && typeof value.isError !== 'boolean')) {\n throw new TypeError('tool-result block fields are invalid')\n }\n for (let index = value.content.length - 1; index >= 0; index--) pending.push(value.content[index])\n break\n case 'native-tool-call':\n if (typeof value.id !== 'string' || value.id.length === 0\n || typeof value.name !== 'string' || value.name.length === 0\n || (value.status !== undefined && typeof value.status !== 'string')\n || !Array.isArray(value.content)) {\n throw new TypeError('native-tool-call block fields are invalid')\n }\n for (let index = value.content.length - 1; index >= 0; index--) pending.push(value.content[index])\n break\n default:\n // ContentBlockMap is declaration-merge extensible. The core can only\n // validate the tags it owns; extension blocks remain adapter-defined.\n break\n }\n }\n}\n\nexport function record(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\nexport function validateUsageCount(value: number, field: string): void {\n if (!Number.isSafeInteger(value) || value < 0) throw new TypeError(`usage ${field} must be a non-negative safe integer`)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validation.js","names":[],"sources":["../../../../src/agent/loop/turn/validation.ts"],"sourcesContent":["import type { ContentBlock } from '../../../message/index.ts'\nimport type { StreamChunk } from '../../../stream/index.ts'\n\nexport function validateStreamChunk(chunk: StreamChunk, maxBlockNodes: number): void {\n if (typeof chunk !== 'object' || chunk === null || typeof chunk.type !== 'string') {\n throw new TypeError('chunk must be an object with a type')\n }\n if ('index' in chunk && (!Number.isSafeInteger(chunk.index) || chunk.index < 0)) {\n throw new TypeError('chunk index must be a non-negative safe integer')\n }\n switch (chunk.type) {\n case 'block-start':\n if (typeof chunk.blockType !== 'string' || chunk.blockType.length === 0) throw new TypeError('blockType must be non-empty')\n return\n case 'text-delta':\n if (typeof chunk.text !== 'string') throw new TypeError('text delta must be a string')\n if (chunk.phase !== undefined && chunk.phase !== 'commentary' && chunk.phase !== 'final-answer') {\n throw new TypeError('text phase is invalid')\n }\n return\n case 'reasoning-delta':\n if (typeof chunk.text !== 'string') throw new TypeError('reasoning delta must be a string')\n return\n case 'image-delta':\n if (typeof chunk.itemId !== 'string' || typeof chunk.data !== 'string' || typeof chunk.mediaType !== 'string') {\n throw new TypeError('image delta fields must be strings')\n }\n if (chunk.partialIndex !== undefined\n && (!Number.isSafeInteger(chunk.partialIndex) || chunk.partialIndex < 0)) {\n throw new TypeError('image partialIndex must be a non-negative safe integer')\n }\n return\n case 'tool-call-delta':\n if (typeof chunk.id !== 'string' || chunk.id.length === 0\n || (chunk.name !== undefined && typeof chunk.name !== 'string')\n || typeof chunk.argumentsDelta !== 'string') {\n throw new TypeError('tool-call delta fields are invalid')\n }\n return\n case 'block-end':\n if (typeof chunk.block !== 'object' || chunk.block === null || typeof chunk.block.type !== 'string') {\n throw new TypeError('block-end must contain a content block')\n }\n validateContentBlock(chunk.block, maxBlockNodes)\n return\n case 'usage-progress':\n for (const key of ['inputTokens', 'outputTokens', 'totalTokens', 'cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens'] as const) {\n if (chunk.usage[key] !== undefined) validateUsageCount(chunk.usage[key], key)\n }\n return\n case 'usage':\n validateUsageCount(chunk.usage.inputTokens, 'inputTokens')\n validateUsageCount(chunk.usage.outputTokens, 'outputTokens')\n for (const key of ['totalTokens', 'cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens'] as const) {\n if (chunk.usage[key] !== undefined) validateUsageCount(chunk.usage[key], key)\n }\n return\n case 'finish':\n if (typeof chunk.reason !== 'object' || chunk.reason === null || typeof chunk.reason.kind !== 'string') {\n throw new TypeError('finish reason is invalid')\n }\n if ((chunk.reason.kind === 'error' || chunk.reason.kind === 'aborted')\n && (typeof chunk.reason.failure !== 'object' || chunk.reason.failure === null\n || typeof chunk.reason.failure.message !== 'string'\n || typeof chunk.reason.failure.code !== 'string')) {\n throw new TypeError('finish failure is invalid')\n }\n return\n default:\n throw new TypeError(`unknown chunk type '${String((chunk as { type?: unknown }).type)}'`)\n }\n}\n\nexport function validateContentBlock(root: ContentBlock, maxNodes: number): void {\n const pending: unknown[] = [root]\n let nodes = 0\n while (pending.length > 0) {\n const value = pending.pop()\n if (!record(value) || typeof value.type !== 'string' || value.type.length === 0) {\n throw new TypeError('content block must be an object with a non-empty type')\n }\n nodes++\n if (nodes > maxNodes) throw new TypeError(`content block tree exceeds ${maxNodes} nodes`)\n switch (value.type) {\n case 'text':\n if (typeof value.text !== 'string') throw new TypeError('text block text must be a string')\n if (value.phase !== undefined && value.phase !== 'commentary' && value.phase !== 'final-answer') {\n throw new TypeError('text block phase is invalid')\n }\n break\n case 'reasoning':\n if (typeof value.text !== 'string') throw new TypeError('reasoning block text must be a string')\n break\n case 'image':\n if (!record(value.source) || typeof value.source.kind !== 'string') {\n throw new TypeError('image block source is invalid')\n }\n if (value.source.kind === 'base64') {\n if (typeof value.source.data !== 'string' || typeof value.source.mediaType !== 'string') {\n throw new TypeError('base64 image source is invalid')\n }\n } else if (value.source.kind === 'url') {\n if (typeof value.source.url !== 'string') throw new TypeError('URL image source is invalid')\n } else if (value.source.kind === 'file') {\n if (typeof value.source.fileId !== 'string') throw new TypeError('file image source is invalid')\n } else {\n throw new TypeError('image source kind is invalid')\n }\n break\n case 'document':\n if (!record(value.source) || typeof value.source.kind !== 'string') {\n throw new TypeError('document block source is invalid')\n }\n if (value.source.kind === 'base64') {\n if (typeof value.source.data !== 'string' || typeof value.source.mediaType !== 'string') {\n throw new TypeError('base64 document source is invalid')\n }\n } else if (value.source.kind === 'url') {\n if (typeof value.source.url !== 'string') throw new TypeError('URL document source is invalid')\n } else if (value.source.kind === 'file') {\n if (typeof value.source.fileId !== 'string') throw new TypeError('file document source is invalid')\n } else {\n throw new TypeError('document source kind is invalid')\n }\n break\n case 'tool-call':\n if (typeof value.id !== 'string' || value.id.length === 0\n || typeof value.name !== 'string' || value.name.length === 0\n || typeof value.arguments !== 'string') {\n throw new TypeError('tool-call block fields are invalid')\n }\n break\n case 'tool-result':\n if (typeof value.toolCallId !== 'string' || value.toolCallId.length === 0\n || !Array.isArray(value.content)\n || (value.isError !== undefined && typeof value.isError !== 'boolean')) {\n throw new TypeError('tool-result block fields are invalid')\n }\n for (let index = value.content.length - 1; index >= 0; index--) pending.push(value.content[index])\n break\n case 'native-tool-call':\n if (typeof value.id !== 'string' || value.id.length === 0\n || typeof value.name !== 'string' || value.name.length === 0\n || (value.status !== undefined && typeof value.status !== 'string')\n || !Array.isArray(value.content)) {\n throw new TypeError('native-tool-call block fields are invalid')\n }\n for (let index = value.content.length - 1; index >= 0; index--) pending.push(value.content[index])\n break\n default:\n // ContentBlockMap is declaration-merge extensible. The core can only\n // validate the tags it owns; extension blocks remain adapter-defined.\n break\n }\n }\n}\n\nexport function record(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\nexport function validateUsageCount(value: number, field: string): void {\n if (!Number.isSafeInteger(value) || value < 0) throw new TypeError(`usage ${field} must be a non-negative safe integer`)\n}\n"],"mappings":"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"}
|
|
@@ -29,7 +29,15 @@ interface CompactionResult {
|
|
|
29
29
|
}
|
|
30
30
|
interface ContextCompactorOptions {
|
|
31
31
|
readonly registry: ModelRegistry;
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* The call configuration in force RIGHT NOW, not when the compactor was built.
|
|
34
|
+
*
|
|
35
|
+
* A supplier rather than a value because a run may target a different model
|
|
36
|
+
* than the session it belongs to: the context window a checkpoint is budgeted
|
|
37
|
+
* against, and the model a summary is written by, both have to follow that
|
|
38
|
+
* override or compaction would reason about a window nobody is calling.
|
|
39
|
+
*/
|
|
40
|
+
readonly config: () => CallConfig;
|
|
33
41
|
readonly history: () => History;
|
|
34
42
|
readonly system: () => string;
|
|
35
43
|
readonly pinnedMessages?: () => readonly Message[];
|
|
@@ -43,6 +51,7 @@ declare class ContextCompactor {
|
|
|
43
51
|
private overflowTurn;
|
|
44
52
|
private overflowRetries;
|
|
45
53
|
private recoveringOverflow;
|
|
54
|
+
/** Keyed by route + model + output reserve: an override changes all three. */
|
|
46
55
|
private modelBudget;
|
|
47
56
|
private pressureCooldown;
|
|
48
57
|
constructor(input: ContextCompactorOptions);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.d.ts","names":[],"sources":["../../../src/agent/memory/compaction.ts"],"mappings":";;;;;;;;;;;UAuBiB;WACN;WACA,SAAS;WACT;WACA;WACA;WACA;WACA;WACA;WACA,gBAAgB;WAChB;WACA;WACA;WACA,QAAQ;;WAER;WACA,SAAS;;UAGH;WACN,UAAU
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","names":[],"sources":["../../../src/agent/memory/compaction.ts"],"mappings":";;;;;;;;;;;UAuBiB;WACN;WACA,SAAS;WACT;WACA;WACA;WACA;WACA;WACA;WACA,gBAAgB;WAChB;WACA;WACA;WACA,QAAQ;;WAER;WACA,SAAS;;UAGH;WACN,UAAU;;;;;;;;;WASV,cAAc;WACd,eAAe;WACf;WACA,gCAAgC;WAChC,sBAAsB;WACtB,QAAQ;;cAiBN;cAyBA;mBACM;UACT;UACA;UACA;UACA;;UAEA;UAIA;EAER,YAAY,OAAO;;EAKb,WAAW,SAAS,oBAAoB;;EA2CxC,eAAe,SAAS,sBAAsB;;EAmB9C,WAAW,SAAS,cAAc,QAAQ;UAOlC;UA8JA;UA8CA;UASA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import{ReasoningEffortId as e}from"../../primitives/brand.js";import{waitForSettlement as t}from"../../async/settlement.js";import{systemRandomId as n}from"../../platform/adapter.js";import{createMessage as r,createUserMessage as i}from"../../message/message.js";import{BlockAssembler as a}from"../../stream/assembler.js";import{normalizeToolPairing as o}from"../history/normalize.js";import{compactionAccounting as s}from"./accounting-binding.js";import{estimateContextTokens as c,estimateMessageTokens as l}from"./token-estimator.js";import{pruneToolResults as u,selectCompactablePrefix as d}from"./surface-compaction.js";const f=[`You are performing a CONTEXT CHECKPOINT COMPACTION for a long-running AI agent task.`,`Condense the conversation above into a handoff that lets another model continue without forgetting the original purpose.`,``,`Output exactly these Markdown sections, in order, using terse bullets. Write "(none)" for an empty section.`,`## Primary Request and Intent`,`## Progress and Completed Work`,`## Decisions and Rationale`,`## Constraints and User Preferences`,`## Important Files, Symbols, and Evidence`,`## Errors and Failed Approaches`,`## Pending Work`,`## Current Work`,`## Next Step`,`## Critical Context`,``,`Preserve exact paths, identifiers, commands, error strings, numeric limits, and user corrections when they matter.`,`Under Important Files, mark relevant files as inspected or modified and preserve the exact declarations or findings needed next.`,`Under Current Work, record the last successful tool action, the latest verification result, and whether any edit is still partial.`,`Under Next Step, name one direct edit or command. Do not recommend rereading an unchanged file whose relevant contents are already recorded.`,`Do not reveal hidden chain-of-thought. Record only public progress, observed evidence, decisions, and actionable context.`,`If an earlier <compacted-summary> exists, merge still-valid facts with newer information and drop stale facts.`,`Output only the checkpoint. Do not call tools and do not acknowledge the compaction.`].join(`
|
|
2
|
-
`);var p=class{input;active=!1;overflowTurn=-1;overflowRetries=0;recoveringOverflow=!1;modelBudget;pressureCooldown=0;constructor(e){this.input=e}async beforeStep(e){if(!(!this.input.policy.auto||e.signal.aborted)){if(this.pressureCooldown>0){this.pressureCooldown--;return}this.overflowTurn===e.turn?this.recoveringOverflow||(this.overflowRetries=0):(this.overflowTurn=e.turn,this.overflowRetries=0),this.recoveringOverflow=!1;try{let t;for(let n=0;n<=this.input.policy.compactionRetries;n++){let n=await this.compactIfNeeded(`pressure`,e.signal,e.emit);if(n===null)break;if(t=n,n.backoffReason!==void 0){this.pressureCooldown=n.cooldownSteps??4;break}}t!==void 0&&t.thresholdTokens!==void 0&&t.estimatedTokensAfter>=t.thresholdTokens&&(this.pressureCooldown=Math.max(this.pressureCooldown,4))}catch{this.pressureCooldown=2}}}async onRequestError(e){if(!(e.failure.code!==`CONTEXT_WINDOW_EXCEEDED`||e.signal.aborted)&&(this.overflowTurn!==e.turn&&(this.overflowTurn=e.turn,this.overflowRetries=0),!(this.overflowRetries>=this.input.policy.maxOverflowRetries)))try{return await this.compactIfNeeded(`context-overflow`,e.signal,e.emit)===null||e.signal.aborted?void 0:(this.overflowRetries++,this.recoveringOverflow=!0,`retry`)}catch{return}}async compactNow(e){let t=e===void 0?new AbortController:void 0,n=e??t?.signal;if(n===void 0)throw Error(`failed to create compaction signal`);return this.compactIfNeeded(`manual`,n)}async compactIfNeeded(e,t,n){if(this.active)return null;let r=AbortSignal.timeout(this.input.policy.summaryTimeoutMs),a=AbortSignal.any([t,r]);a.throwIfAborted(),this.active=!0;try{let o=this.input.history(),s=o.surface();if(s.length<2)return null;let f=this.input.tools(),p=this.input.system(),m=this.input.pinnedMessages?.()??[],h=c({system:p,messages:[...m,...s.map(e=>e.message)],tools:f}),g=await this.resolveBudget(h,a);if(a.throwIfAborted(),e===`pressure`&&(g===null||h<g.thresholdTokens))return null;if(u(o,s,this.input.policy.maxToolResultChars)>0){if(s=o.surface(),h=c({system:p,messages:[...m,...s.map(e=>e.message)],tools:f}),e===`pressure`&&g!==null&&h<g.thresholdTokens)return null;g=await this.resolveBudget(h,a),a.throwIfAborted()}let _=e===`context-overflow`?Math.max(1,l(s.at(-1)?.message)):g?.retainTokens??Math.max(1,Math.floor(h*.25)),v=d(s,_);if(v.length===0)return null;let y=new Set(v.map(e=>e.seq)),C=c({system:p,messages:[...m,...s.filter(e=>!y.has(e.seq)).map(e=>e.message)],tools:f}),w=b(),T=new Date().toISOString();o.append({kind:`compaction-start`,compactionId:w,trigger:e,at:T});try{await this.emitObserver(n,{type:`compaction-start`,compactionId:w,trigger:e,estimatedInputTokens:h});let t=await this.summarize([...m,...v.map(e=>e.message)],p,f,a);a.throwIfAborted();let r=i({source:{kind:`app`,producer:`agent-compaction:${w}`},content:[{type:`text`,text:`This is an automatically generated checkpoint of earlier conversation context. Treat it as established background, preserve the original objective and constraints, and continue directly from the messages that follow.\n\n<compacted-summary>\n${t.summary}\n</compacted-summary>`}]}),s=v.reduce((e,t)=>e+l(t.message),0),c=l(r);if(c>=s)throw Error(`compaction summary did not shrink selected context (${c} >= ${s} estimated tokens)`);let u=Object.freeze(v.map(e=>e.seq)),d=Math.max(0,h-s+c),_=g?.thresholdTokens,y=O({trigger:e,thresholdTokens:_,estimatedTokensBefore:h,estimatedTokensAfter:d,estimatedNonCompactableTokens:C});o.appendBatch([{event:{kind:`compaction-summary`,compactionId:w,summary:t.summary,shadowedSeqs:u,estimatedTokensBefore:h,estimatedTokensAfter:d,provider:t.provider,model:t.model,...t.usage===void 0?{}:{usage:t.usage}}},{event:{kind:`user`,message:r},surfaceOp:{op:`replace`,from:Math.min(...u),to:Math.max(...u),targets:u}},{event:{kind:`compaction-end`,compactionId:w,status:`completed`,at:new Date().toISOString(),..._===void 0?{}:{thresholdTokens:_},estimatedNonCompactableTokens:C,...y===void 0?{}:{backoffReason:y,cooldownSteps:4}}}]);let b=Object.freeze({compactionId:w,trigger:e,summary:t.summary,shadowedSeqs:u,estimatedTokensBefore:h,estimatedTokensAfter:d,..._===void 0?{}:{thresholdTokens:_},estimatedNonCompactableTokens:C,...y===void 0?{}:{backoffReason:y,cooldownSteps:4},provider:t.provider,model:t.model,...t.usage===void 0?{}:{usage:t.usage}});return await this.emitObserver(n,{type:`compaction-end`,compactionId:w,trigger:e,status:`completed`,shadowedSeqs:u,estimatedTokensBefore:h,estimatedTokensAfter:d,summary:t.summary,..._===void 0?{}:{thresholdTokens:_},estimatedNonCompactableTokens:C,...y===void 0?{}:{backoffReason:y,cooldownSteps:4},...t.usage===void 0?{}:{usage:t.usage}}),b}catch(i){let a=r.aborted&&!t.aborted&&S(i)!==`MODEL_TEARDOWN_TIMEOUT`?E(this.input.policy.summaryTimeoutMs,i):i,s=x(a);try{o.append({kind:`compaction-end`,compactionId:w,status:`failed`,at:new Date().toISOString(),error:s})}catch{}throw await this.emitObserver(n,{type:`compaction-end`,compactionId:w,trigger:e,status:`failed`,shadowedSeqs:[],estimatedTokensBefore:h,estimatedTokensAfter:h,error:s}),a}}finally{this.active=!1}}async resolveBudget(e,t){let n=this.input.policy
|
|
3
|
-
`).trim();if(
|
|
2
|
+
`);var p=class{input;active=!1;overflowTurn=-1;overflowRetries=0;recoveringOverflow=!1;modelBudget;pressureCooldown=0;constructor(e){this.input=e}async beforeStep(e){if(!(!this.input.policy.auto||e.signal.aborted)){if(this.pressureCooldown>0){this.pressureCooldown--;return}this.overflowTurn===e.turn?this.recoveringOverflow||(this.overflowRetries=0):(this.overflowTurn=e.turn,this.overflowRetries=0),this.recoveringOverflow=!1;try{let t;for(let n=0;n<=this.input.policy.compactionRetries;n++){let n=await this.compactIfNeeded(`pressure`,e.signal,e.emit);if(n===null)break;if(t=n,n.backoffReason!==void 0){this.pressureCooldown=n.cooldownSteps??4;break}}t!==void 0&&t.thresholdTokens!==void 0&&t.estimatedTokensAfter>=t.thresholdTokens&&(this.pressureCooldown=Math.max(this.pressureCooldown,4))}catch{this.pressureCooldown=2}}}async onRequestError(e){if(!(e.failure.code!==`CONTEXT_WINDOW_EXCEEDED`||e.signal.aborted)&&(this.overflowTurn!==e.turn&&(this.overflowTurn=e.turn,this.overflowRetries=0),!(this.overflowRetries>=this.input.policy.maxOverflowRetries)))try{return await this.compactIfNeeded(`context-overflow`,e.signal,e.emit)===null||e.signal.aborted?void 0:(this.overflowRetries++,this.recoveringOverflow=!0,`retry`)}catch{return}}async compactNow(e){let t=e===void 0?new AbortController:void 0,n=e??t?.signal;if(n===void 0)throw Error(`failed to create compaction signal`);return this.compactIfNeeded(`manual`,n)}async compactIfNeeded(e,t,n){if(this.active)return null;let r=AbortSignal.timeout(this.input.policy.summaryTimeoutMs),a=AbortSignal.any([t,r]);a.throwIfAborted(),this.active=!0;try{let o=this.input.history(),s=o.surface();if(s.length<2)return null;let f=this.input.tools(),p=this.input.system(),m=this.input.pinnedMessages?.()??[],h=c({system:p,messages:[...m,...s.map(e=>e.message)],tools:f}),g=await this.resolveBudget(h,a);if(a.throwIfAborted(),e===`pressure`&&(g===null||h<g.thresholdTokens))return null;if(u(o,s,this.input.policy.maxToolResultChars)>0){if(s=o.surface(),h=c({system:p,messages:[...m,...s.map(e=>e.message)],tools:f}),e===`pressure`&&g!==null&&h<g.thresholdTokens)return null;g=await this.resolveBudget(h,a),a.throwIfAborted()}let _=e===`context-overflow`?Math.max(1,l(s.at(-1)?.message)):g?.retainTokens??Math.max(1,Math.floor(h*.25)),v=d(s,_);if(v.length===0)return null;let y=new Set(v.map(e=>e.seq)),C=c({system:p,messages:[...m,...s.filter(e=>!y.has(e.seq)).map(e=>e.message)],tools:f}),w=b(),T=new Date().toISOString();o.append({kind:`compaction-start`,compactionId:w,trigger:e,at:T});try{await this.emitObserver(n,{type:`compaction-start`,compactionId:w,trigger:e,estimatedInputTokens:h});let t=await this.summarize([...m,...v.map(e=>e.message)],p,f,a);a.throwIfAborted();let r=i({source:{kind:`app`,producer:`agent-compaction:${w}`},content:[{type:`text`,text:`This is an automatically generated checkpoint of earlier conversation context. Treat it as established background, preserve the original objective and constraints, and continue directly from the messages that follow.\n\n<compacted-summary>\n${t.summary}\n</compacted-summary>`}]}),s=v.reduce((e,t)=>e+l(t.message),0),c=l(r);if(c>=s)throw Error(`compaction summary did not shrink selected context (${c} >= ${s} estimated tokens)`);let u=Object.freeze(v.map(e=>e.seq)),d=Math.max(0,h-s+c),_=g?.thresholdTokens,y=O({trigger:e,thresholdTokens:_,estimatedTokensBefore:h,estimatedTokensAfter:d,estimatedNonCompactableTokens:C});o.appendBatch([{event:{kind:`compaction-summary`,compactionId:w,summary:t.summary,shadowedSeqs:u,estimatedTokensBefore:h,estimatedTokensAfter:d,provider:t.provider,model:t.model,...t.usage===void 0?{}:{usage:t.usage}}},{event:{kind:`user`,message:r},surfaceOp:{op:`replace`,from:Math.min(...u),to:Math.max(...u),targets:u}},{event:{kind:`compaction-end`,compactionId:w,status:`completed`,at:new Date().toISOString(),..._===void 0?{}:{thresholdTokens:_},estimatedNonCompactableTokens:C,...y===void 0?{}:{backoffReason:y,cooldownSteps:4}}}]);let b=Object.freeze({compactionId:w,trigger:e,summary:t.summary,shadowedSeqs:u,estimatedTokensBefore:h,estimatedTokensAfter:d,..._===void 0?{}:{thresholdTokens:_},estimatedNonCompactableTokens:C,...y===void 0?{}:{backoffReason:y,cooldownSteps:4},provider:t.provider,model:t.model,...t.usage===void 0?{}:{usage:t.usage}});return await this.emitObserver(n,{type:`compaction-end`,compactionId:w,trigger:e,status:`completed`,shadowedSeqs:u,estimatedTokensBefore:h,estimatedTokensAfter:d,summary:t.summary,..._===void 0?{}:{thresholdTokens:_},estimatedNonCompactableTokens:C,...y===void 0?{}:{backoffReason:y,cooldownSteps:4},...t.usage===void 0?{}:{usage:t.usage}}),b}catch(i){let a=r.aborted&&!t.aborted&&S(i)!==`MODEL_TEARDOWN_TIMEOUT`?E(this.input.policy.summaryTimeoutMs,i):i,s=x(a);try{o.append({kind:`compaction-end`,compactionId:w,status:`failed`,at:new Date().toISOString(),error:s})}catch{}throw await this.emitObserver(n,{type:`compaction-end`,compactionId:w,trigger:e,status:`failed`,shadowedSeqs:[],estimatedTokensBefore:h,estimatedTokensAfter:h,error:s}),a}}finally{this.active=!1}}async resolveBudget(e,t){let n=this.input.policy,r=this.input.config(),i=`${r.provider}\u0000${r.model}\u0000${String(r.maxTokens??``)}`;if(this.modelBudget?.key!==i)try{let e=await D(this.input.registry.resolveModelInfo(r.provider,r.model,t),t),n=e.context?.contextWindow;this.modelBudget={key:i,budget:n===void 0?null:{contextWindow:n,outputReserve:r.maxTokens??e.defaultMaxTokens??e.maxOutputTokens??0}}}catch{if(n.maxInputTokens===void 0)return null;this.modelBudget={key:i,budget:null}}let a=this.modelBudget?.budget?.contextWindow,o=a===void 0?void 0:Math.max(1,a-(this.modelBudget?.budget?.outputReserve??0)),s=a===void 0?void 0:Math.floor(a*n.thresholdRatio),c=o===void 0||s===void 0?void 0:Math.min(o,s),l=n.maxInputTokens===void 0?c:o===void 0?n.maxInputTokens:Math.min(n.maxInputTokens,o);if(l===void 0)return null;let u=o??Math.max(e,Math.ceil(l/n.thresholdRatio)),d=n.retainTokens??Math.floor(u*(n.retainRatio??.2));return{thresholdTokens:l,retainTokens:Math.max(1,d)}}async emitObserver(e,n){if(e===void 0)return;let r=Promise.resolve().then(()=>e(n));await t(r,this.input.policy.teardownTimeoutMs)}async summarize(n,r,c,l){let u=this.input.policy,d=this.input.config(),p=u.summarizationProvider??d.provider,h=u.summarizationModel??d.model,g=s(this);w(g);let _=await D(this.input.registry.resolveModelInfo(p,h,l),l),v=Math.min(u.maxSummaryTokens,_.maxOutputTokens??2**53-1,_.context===void 0?2**53-1:Math.max(1,_.context.contextWindow-1)),y=await D(this.input.registry.prepareCall({provider:p,model:h,...u.summarizationEffort===void 0?{}:{reasoningEffort:e(u.summarizationEffort)},maxTokens:v},l,g?.modelInvocation),l),b={remaining:u.maxSummaryRequestChars},x=o(n).map(e=>m(e,u.maxSummaryInputChars,b)),S=i({source:{kind:`app`,producer:`agent-compaction`},content:[{type:`text`,text:f}]}),E=new a,O={...y.config,messages:[...x,S],...r.length===0?{}:{system:r},...c.length===0?{}:{tools:c},toolChoice:`none`,signal:l},{signal:k,...A}=O;if(C(A)>u.maxSummaryRequestBytes)throw T(`compaction summary request exceeds the ${u.maxSummaryRequestBytes}-byte limit`,`MODEL_REQUEST_TOO_LARGE`);w(g);let j=y.stream(O,g?.modelInvocation),M=j[Symbol.asyncIterator](),N=!1,P=0,F=0,I=!1,L;try{for(;;){let e=await D(M.next(),l);if(e.done===!0){N=!0;break}if(P++,F+=C(e.value),P>u.maxSummaryStreamEvents||F>u.maxSummaryResponseBytes)throw T(`compaction summary response exceeded its resource limit`,`MODEL_RESPONSE_TOO_LARGE`);if(I)throw T(`compaction summarizer emitted data after its terminal finish chunk`,`INVALID_MODEL_STREAM`);E.push(e.value),e.value.type===`finish`&&(I=!0)}}catch(e){L=e}finally{if(!N){let e=M.return?.bind(M);if(e!==void 0)try{let n=Promise.resolve().then(async()=>{await e()});await t(n,u.teardownTimeoutMs)||(L=T(`compaction model stream ignored cancellation for more than ${u.teardownTimeoutMs}ms`,`MODEL_TEARDOWN_TIMEOUT`))}catch(e){L??=e}}}try{let e=await j.report,t=await g?.recordModelCall(e,O);t?.usageRequired===!0&&(L??=T(`compaction model usage is required by the configured run policy`,`USAGE_REQUIRED`)),t?.usageUnavailable===!0&&(L??=T(`compaction model usage is unavailable for the configured budget`,`USAGE_UNAVAILABLE`))}catch(e){L??=e}if(L!==void 0)throw L;let R=E.finish;if(R.kind===`error`||R.kind===`aborted`){let e=Error(R.failure.message);throw e.code=R.failure.code,e}if(R.kind===`max-tokens`)throw Error(`compaction summary was truncated at maxSummaryTokens`);if(R.kind===`tool-calls`)throw Error(`compaction summarizer attempted a tool call`);let z=E.blocks().flatMap(e=>e.type===`text`?[e.text]:[]).join(`
|
|
3
|
+
`).trim();if(z.length===0)throw Error(`compaction summarizer produced no text`);return{summary:z,provider:p,model:h,...E.usage===void 0?{}:{usage:E.usage}}}};function m(e,t,n){let i=e.content.flatMap(e=>h(e,t,n)),a=e.source.kind===`model`?{kind:`model`,provider:e.source.provider,model:e.source.model}:e.source;return r({role:e.role,source:a,content:i})}function h(e,t,n){switch(e.type){case`text`:return[{type:`text`,text:g(e.text,t,n)}];case`reasoning`:return e.text.length===0?[]:[{type:`text`,text:g(`[Reasoning summary] ${e.text}`,t,n)}];case`image`:return[{type:`text`,text:g(`[Image input: ${e.source.kind}]`,t,n)}];case`document`:return[{type:`text`,text:g(`[Document input: ${e.filename??e.source.kind}]`,t,n)}];case`tool-call`:return[{...e,arguments:_(e.arguments,t,n)}];case`tool-result`:return[{...e,content:e.content.flatMap(e=>h(e,t,n))}];case`native-tool-call`:return[{type:`text`,text:g(`[Native tool ${e.name} (${e.status??`unknown`})] ${v(e.arguments??{})}`,t,n)}];default:return[{type:`text`,text:g(`[Unsupported content block: ${v(e)}]`,t,n)}]}}function g(e,t,n){let r=y(e,Math.max(0,Math.min(t,n.remaining)));return n.remaining-=r.length,r}function _(e,t,n){let r=Math.max(0,Math.min(t,n.remaining));return e.length<=r?(n.remaining-=e.length,e):19<=r?(n.remaining-=19,`{"_compacted":true}`):`{}`}function v(e){try{return JSON.stringify(e)??``}catch{return String(e)}}function y(e,t){if(e.length<=t)return e;if(t<=30)return e.slice(0,t);let n=Math.ceil((t-30)/2),r=Math.floor((t-30)/2);return e.slice(0,n)+`
|
|
4
4
|
…[truncated for compaction]…
|
|
5
5
|
`+e.slice(e.length-r)}function b(){return n()}function x(e){return e instanceof Error?e.message:String(e)}function S(e){return typeof e==`object`&&e&&`code`in e&&typeof e.code==`string`?e.code:void 0}function C(e){let t=JSON.stringify(e);if(t===void 0)throw TypeError(`compaction model payload is not JSON serializable`);return new TextEncoder().encode(t).byteLength}function w(e){let t=e?.usageStop;if(t!==void 0)throw T(`compaction cannot dispatch after a mandatory usage stop`,t.usageRequired?`USAGE_REQUIRED`:`USAGE_UNAVAILABLE`)}function T(e,t,n){let r=Error(e,n===void 0?void 0:{cause:n});return r.code=t,r}function E(e,t){return T(`compaction model operation exceeded ${e}ms`,`MODEL_TIMEOUT`,t)}async function D(e,t){if(t.aborted)throw e.catch(()=>void 0),t.reason??Error(`operation aborted`);return await new Promise((n,r)=>{let i=()=>{t.removeEventListener(`abort`,i),r(t.reason??Error(`operation aborted`))};t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function O(e){if(!(e.trigger!==`pressure`||e.thresholdTokens===void 0||e.estimatedTokensAfter<e.thresholdTokens))return e.estimatedNonCompactableTokens>=e.thresholdTokens?`unreachable-threshold`:e.estimatedTokensBefore-e.estimatedTokensAfter<Math.max(256,Math.ceil(e.estimatedTokensBefore*.01))?`low-savings`:void 0}export{f as COMPACTION_INSTRUCTION,p as ContextCompactor};
|
|
6
6
|
//# sourceMappingURL=compaction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.js","names":[],"sources":["../../../src/agent/memory/compaction.ts"],"sourcesContent":["import { systemRandomId } from '../../platform/adapter.ts'\n/** Context-pressure compaction inspired by Codex checkpoints and deepseek-harness surface replacement. */\n\nimport type { CallConfig } from '../../contract/index.ts'\nimport type { ModelToolSchema } from '../../contract/index.ts'\nimport type { ContentBlock, ToolCallBlock, ToolResultBlock } from '../../message/index.ts'\nimport { createMessage, createUserMessage, type Message } from '../../message/index.ts'\nimport { ReasoningEffortId } from '../../primitives/index.ts'\nimport type { ModelRegistry } from '../../runtime/index.ts'\nimport { waitForSettlement } from '../../async/index.ts'\nimport { BlockAssembler } from '../../stream/index.ts'\nimport type { TokenUsage } from '../../stream/index.ts'\nimport type { History } from '../history/history.ts'\nimport { normalizeToolPairing } from '../history/normalize.ts'\nimport type {\n AgentMaintenanceEvent, BeforeStepContext, CompactionBackoffReason, CompactionTrigger, RequestErrorContext,\n} from '../loop/events.ts'\nimport type { AgentCompactionConfig } from './compaction-config.ts'\nimport { compactionAccounting } from './accounting-binding.ts'\nimport type { RunReport } from '../accounting/delivery-types.ts'\nimport { pruneToolResults, selectCompactablePrefix } from './surface-compaction.ts'\nimport { estimateContextTokens, estimateMessageTokens } from './token-estimator.ts'\n\nexport interface CompactionResult {\n readonly compactionId: string\n readonly trigger: CompactionTrigger\n readonly summary: string\n readonly shadowedSeqs: readonly number[]\n readonly estimatedTokensBefore: number\n readonly estimatedTokensAfter: number\n readonly thresholdTokens?: number\n readonly estimatedNonCompactableTokens: number\n readonly backoffReason?: CompactionBackoffReason\n readonly cooldownSteps?: number\n readonly provider: string\n readonly model: string\n readonly usage?: TokenUsage\n /** Additive runtime projection; absent on the preserved low-level compactor path. */\n readonly status?: 'completed'\n readonly report?: RunReport\n}\n\nexport interface ContextCompactorOptions {\n readonly registry: ModelRegistry\n readonly config: CallConfig\n readonly history: () => History\n readonly system: () => string\n readonly pinnedMessages?: () => readonly Message[]\n readonly tools: () => readonly ModelToolSchema[]\n readonly policy: AgentCompactionConfig\n}\n\ninterface ResolvedBudget {\n readonly thresholdTokens: number\n readonly retainTokens: number\n}\n\ninterface CharacterBudget { remaining: number }\n\nconst CHECKPOINT_PREAMBLE =\n 'This is an automatically generated checkpoint of earlier conversation context. Treat it as established background, preserve the original objective and constraints, and continue directly from the messages that follow.'\n\nconst MIN_PRESSURE_SAVINGS_TOKENS = 256\nconst MIN_PRESSURE_SAVINGS_RATIO = 0.01\nconst PRESSURE_BACKOFF_STEPS = 4\n\nexport const COMPACTION_INSTRUCTION = [\n 'You are performing a CONTEXT CHECKPOINT COMPACTION for a long-running AI agent task.',\n 'Condense the conversation above into a handoff that lets another model continue without forgetting the original purpose.',\n '',\n 'Output exactly these Markdown sections, in order, using terse bullets. Write \"(none)\" for an empty section.',\n '## Primary Request and Intent',\n '## Progress and Completed Work',\n '## Decisions and Rationale',\n '## Constraints and User Preferences',\n '## Important Files, Symbols, and Evidence',\n '## Errors and Failed Approaches',\n '## Pending Work',\n '## Current Work',\n '## Next Step',\n '## Critical Context',\n '',\n 'Preserve exact paths, identifiers, commands, error strings, numeric limits, and user corrections when they matter.',\n 'Under Important Files, mark relevant files as inspected or modified and preserve the exact declarations or findings needed next.',\n 'Under Current Work, record the last successful tool action, the latest verification result, and whether any edit is still partial.',\n 'Under Next Step, name one direct edit or command. Do not recommend rereading an unchanged file whose relevant contents are already recorded.',\n 'Do not reveal hidden chain-of-thought. Record only public progress, observed evidence, decisions, and actionable context.',\n 'If an earlier <compacted-summary> exists, merge still-valid facts with newer information and drop stale facts.',\n 'Output only the checkpoint. Do not call tools and do not acknowledge the compaction.',\n].join('\\n')\n\nexport class ContextCompactor {\n private readonly input: ContextCompactorOptions\n private active = false\n private overflowTurn = -1\n private overflowRetries = 0\n private recoveringOverflow = false\n private modelBudget: {\n readonly contextWindow: number\n readonly outputReserve: number\n } | null | undefined\n private pressureCooldown = 0\n\n constructor(input: ContextCompactorOptions) {\n this.input = input\n }\n\n /** Fail-open pressure maintenance for a pre-step hook. */\n async beforeStep(context: BeforeStepContext): Promise<void> {\n if (!this.input.policy.auto || context.signal.aborted) return\n if (this.pressureCooldown > 0) {\n this.pressureCooldown--\n return\n }\n if (this.overflowTurn !== context.turn) {\n this.overflowTurn = context.turn\n this.overflowRetries = 0\n } else if (!this.recoveringOverflow) {\n this.overflowRetries = 0\n }\n this.recoveringOverflow = false\n try {\n let lastResult: CompactionResult | undefined\n for (let attempt = 0; attempt <= this.input.policy.compactionRetries; attempt++) {\n const result = await this.compactIfNeeded('pressure', context.signal, context.emit)\n if (result === null) break\n lastResult = result\n if (result.backoffReason !== undefined) {\n this.pressureCooldown = result.cooldownSteps ?? PRESSURE_BACKOFF_STEPS\n break\n }\n }\n if (lastResult !== undefined\n && lastResult.thresholdTokens !== undefined\n && lastResult.estimatedTokensAfter >= lastResult.thresholdTokens) {\n this.pressureCooldown = Math.max(\n this.pressureCooldown,\n PRESSURE_BACKOFF_STEPS,\n )\n }\n } catch {\n // Pressure maintenance is fail-open; the provider's canonical overflow\n // error still gets one forced recovery path below. Avoid retrying the same\n // broken maintenance request on every tool step and flooding logs/traces.\n // Mandatory usage decisions stay latched in the owning ledger and are\n // checked by modelRound after this hook, before any main dispatch.\n this.pressureCooldown = 2\n }\n }\n\n /** Compact and retry only when a provider confirmed context overflow. */\n async onRequestError(context: RequestErrorContext): Promise<'retry' | undefined> {\n if (context.failure.code !== 'CONTEXT_WINDOW_EXCEEDED' || context.signal.aborted) return undefined\n if (this.overflowTurn !== context.turn) {\n this.overflowTurn = context.turn\n this.overflowRetries = 0\n }\n if (this.overflowRetries >= this.input.policy.maxOverflowRetries) return undefined\n try {\n const result = await this.compactIfNeeded('context-overflow', context.signal, context.emit)\n if (result === null || context.signal.aborted) return undefined\n this.overflowRetries++\n this.recoveringOverflow = true\n return 'retry'\n } catch {\n return undefined\n }\n }\n\n /** Explicit idle-session checkpoint even below automatic pressure. */\n async compactNow(signal?: AbortSignal): Promise<CompactionResult | null> {\n const controller = signal === undefined ? new AbortController() : undefined\n const effectiveSignal = signal ?? controller?.signal\n if (effectiveSignal === undefined) throw new Error('failed to create compaction signal')\n return this.compactIfNeeded('manual', effectiveSignal)\n }\n\n private async compactIfNeeded(\n trigger: CompactionTrigger,\n signal: AbortSignal,\n emit?: (event: AgentMaintenanceEvent) => Promise<void>,\n ): Promise<CompactionResult | null> {\n if (this.active) return null\n const deadline = AbortSignal.timeout(this.input.policy.summaryTimeoutMs)\n const operationSignal = AbortSignal.any([signal, deadline])\n operationSignal.throwIfAborted()\n this.active = true\n try {\n const history = this.input.history()\n let surface = history.surface()\n if (surface.length < 2) return null\n const tools = this.input.tools()\n const system = this.input.system()\n const pinned = this.input.pinnedMessages?.() ?? []\n let totalBefore = estimateContextTokens({\n system, messages: [...pinned, ...surface.map(node => node.message)], tools,\n })\n let budget = await this.resolveBudget(totalBefore, operationSignal)\n operationSignal.throwIfAborted()\n if (trigger === 'pressure' && (budget === null || totalBefore < budget.thresholdTokens)) return null\n const pruned = pruneToolResults(history, surface, this.input.policy.maxToolResultChars)\n if (pruned > 0) {\n surface = history.surface()\n totalBefore = estimateContextTokens({\n system, messages: [...pinned, ...surface.map(node => node.message)], tools,\n })\n if (trigger === 'pressure' && budget !== null && totalBefore < budget.thresholdTokens) return null\n // With an absolute threshold and no provider context metadata, retainRatio\n // is inferred from the measured request. Pruning can change that request\n // by orders of magnitude, so selection must use the post-prune budget.\n budget = await this.resolveBudget(totalBefore, operationSignal)\n operationSignal.throwIfAborted()\n }\n const retainTokens = trigger === 'context-overflow'\n ? Math.max(1, estimateMessageTokens(surface.at(-1)?.message))\n : budget?.retainTokens ?? Math.max(1, Math.floor(totalBefore * 0.25))\n const selected = selectCompactablePrefix(surface, retainTokens)\n if (selected.length === 0) return null\n const selectedSeqs = new Set(selected.map(node => node.seq))\n const estimatedNonCompactableTokens = estimateContextTokens({\n system,\n messages: [\n ...pinned,\n ...surface.filter(node => !selectedSeqs.has(node.seq)).map(node => node.message),\n ],\n tools,\n })\n const compactionId = newCompactionId()\n const startedAt = new Date().toISOString()\n history.append({ kind: 'compaction-start', compactionId, trigger, at: startedAt })\n try {\n await this.emitObserver(emit, {\n type: 'compaction-start', compactionId, trigger, estimatedInputTokens: totalBefore,\n })\n const summarized = await this.summarize(\n [...pinned, ...selected.map(node => node.message)], system, tools, operationSignal,\n )\n // Adapters are contractually expected to honor cancellation, but the\n // compactor must not commit stale maintenance if one fails to do so.\n operationSignal.throwIfAborted()\n const checkpoint = createUserMessage({\n source: { kind: 'app', producer: `agent-compaction:${compactionId}` },\n content: [{\n type: 'text',\n text: `${CHECKPOINT_PREAMBLE}\\n\\n<compacted-summary>\\n${summarized.summary}\\n</compacted-summary>`,\n }],\n })\n const shadowedTokens = selected.reduce((total, node) => total + estimateMessageTokens(node.message), 0)\n const checkpointTokens = estimateMessageTokens(checkpoint)\n if (checkpointTokens >= shadowedTokens) {\n throw new Error(\n `compaction summary did not shrink selected context (${checkpointTokens} >= ${shadowedTokens} estimated tokens)`,\n )\n }\n const shadowedSeqs = Object.freeze(selected.map(node => node.seq))\n const estimatedTokensAfter = Math.max(0, totalBefore - shadowedTokens + checkpointTokens)\n const thresholdTokens = budget?.thresholdTokens\n const pressureBackoff = pressureBackoffReason({\n trigger,\n thresholdTokens,\n estimatedTokensBefore: totalBefore,\n estimatedTokensAfter,\n estimatedNonCompactableTokens,\n })\n history.appendBatch([\n { event: {\n kind: 'compaction-summary', compactionId, summary: summarized.summary, shadowedSeqs,\n estimatedTokensBefore: totalBefore, estimatedTokensAfter,\n provider: summarized.provider, model: summarized.model,\n ...(summarized.usage === undefined ? {} : { usage: summarized.usage }),\n } },\n { event: { kind: 'user', message: checkpoint }, surfaceOp: {\n op: 'replace',\n from: Math.min(...shadowedSeqs),\n to: Math.max(...shadowedSeqs),\n targets: shadowedSeqs,\n } },\n { event: {\n kind: 'compaction-end', compactionId, status: 'completed', at: new Date().toISOString(),\n ...(thresholdTokens === undefined ? {} : { thresholdTokens }),\n estimatedNonCompactableTokens,\n ...(pressureBackoff === undefined ? {} : {\n backoffReason: pressureBackoff,\n cooldownSteps: PRESSURE_BACKOFF_STEPS,\n }),\n } },\n ])\n const result: CompactionResult = Object.freeze({\n compactionId, trigger, summary: summarized.summary, shadowedSeqs,\n estimatedTokensBefore: totalBefore, estimatedTokensAfter,\n ...(thresholdTokens === undefined ? {} : { thresholdTokens }),\n estimatedNonCompactableTokens,\n ...(pressureBackoff === undefined ? {} : {\n backoffReason: pressureBackoff,\n cooldownSteps: PRESSURE_BACKOFF_STEPS,\n }),\n provider: summarized.provider, model: summarized.model,\n ...(summarized.usage === undefined ? {} : { usage: summarized.usage }),\n })\n await this.emitObserver(emit, {\n type: 'compaction-end', compactionId, trigger, status: 'completed', shadowedSeqs,\n estimatedTokensBefore: totalBefore, estimatedTokensAfter, summary: summarized.summary,\n ...(thresholdTokens === undefined ? {} : { thresholdTokens }),\n estimatedNonCompactableTokens,\n ...(pressureBackoff === undefined ? {} : {\n backoffReason: pressureBackoff,\n cooldownSteps: PRESSURE_BACKOFF_STEPS,\n }),\n ...(summarized.usage === undefined ? {} : { usage: summarized.usage }),\n })\n return result\n } catch (error: unknown) {\n const failure = deadline.aborted && !signal.aborted && errorCode(error) !== 'MODEL_TEARDOWN_TIMEOUT'\n ? modelTimeoutError(this.input.policy.summaryTimeoutMs, error)\n : error\n const message = errorMessage(failure)\n try {\n history.append({\n kind: 'compaction-end', compactionId, status: 'failed', at: new Date().toISOString(), error: message,\n })\n } catch {\n // Preserve the original compaction failure when the append-only history\n // has no remaining capacity for the diagnostic end marker.\n }\n await this.emitObserver(emit, {\n type: 'compaction-end', compactionId, trigger, status: 'failed', shadowedSeqs: [],\n estimatedTokensBefore: totalBefore, estimatedTokensAfter: totalBefore, error: message,\n })\n throw failure\n }\n } finally {\n this.active = false\n }\n }\n\n private async resolveBudget(totalTokens: number, signal: AbortSignal): Promise<ResolvedBudget | null> {\n const policy = this.input.policy\n if (this.modelBudget === undefined) {\n try {\n const info = await raceWithSignal(this.input.registry.resolveModelInfo(\n this.input.config.provider, this.input.config.model, signal,\n ), signal)\n const contextWindow = info.context?.contextWindow\n this.modelBudget = contextWindow === undefined\n ? null\n : {\n contextWindow,\n outputReserve: this.input.config.maxTokens\n ?? info.defaultMaxTokens\n ?? info.maxOutputTokens\n ?? 0,\n }\n } catch {\n if (policy.maxInputTokens === undefined) return null\n this.modelBudget = null\n }\n }\n const contextWindow = this.modelBudget?.contextWindow\n const inputWindow = contextWindow === undefined\n ? undefined\n : Math.max(1, contextWindow - (this.modelBudget?.outputReserve ?? 0))\n const ratioThreshold = contextWindow === undefined\n ? undefined\n : Math.floor(contextWindow * policy.thresholdRatio)\n const safeThreshold = inputWindow === undefined || ratioThreshold === undefined\n ? undefined\n : Math.min(inputWindow, ratioThreshold)\n const thresholdTokens = policy.maxInputTokens === undefined\n ? safeThreshold\n : inputWindow === undefined\n ? policy.maxInputTokens\n : Math.min(policy.maxInputTokens, inputWindow)\n if (thresholdTokens === undefined) return null\n const inferredWindow = inputWindow ?? Math.max(totalTokens, Math.ceil(thresholdTokens / policy.thresholdRatio))\n const retainTokens = policy.retainTokens\n ?? Math.floor(inferredWindow * (policy.retainRatio ?? 0.2))\n return { thresholdTokens, retainTokens: Math.max(1, retainTokens) }\n }\n\n private async emitObserver(\n emit: ((event: AgentMaintenanceEvent) => Promise<void>) | undefined,\n event: AgentMaintenanceEvent,\n ): Promise<void> {\n if (emit === undefined) return\n const pending = Promise.resolve().then(() => emit(event))\n await waitForSettlement(pending, this.input.policy.teardownTimeoutMs)\n }\n\n private async summarize(\n messages: readonly Message[],\n system: string,\n tools: readonly ModelToolSchema[],\n signal: AbortSignal,\n ): Promise<{ summary: string; provider: string; model: string; usage?: TokenUsage }> {\n const policy = this.input.policy\n const provider = policy.summarizationProvider ?? this.input.config.provider\n const model = policy.summarizationModel ?? this.input.config.model\n const accounting = compactionAccounting(this)\n assertUsageAdmission(accounting)\n const summaryInfo = await raceWithSignal(\n this.input.registry.resolveModelInfo(provider, model, signal),\n signal,\n )\n const maxSummaryTokens = Math.min(\n policy.maxSummaryTokens,\n summaryInfo.maxOutputTokens ?? Number.MAX_SAFE_INTEGER,\n summaryInfo.context === undefined\n ? Number.MAX_SAFE_INTEGER\n : Math.max(1, summaryInfo.context.contextWindow - 1),\n )\n const prepared = await raceWithSignal(this.input.registry.prepareCall({\n provider,\n model,\n ...(policy.summarizationEffort === undefined\n ? {}\n : { reasoningEffort: ReasoningEffortId(policy.summarizationEffort) }),\n maxTokens: maxSummaryTokens,\n }, signal, accounting?.modelInvocation), signal)\n // Compaction can encounter history written by an older runtime or a process\n // interrupted between a tool call and its result. Repair the replay just as\n // normal model requests do so a maintenance request cannot be provider-invalid.\n const characterBudget: CharacterBudget = { remaining: policy.maxSummaryRequestChars }\n const replay = normalizeToolPairing(messages)\n .map(message => sanitizeForSummary(message, policy.maxSummaryInputChars, characterBudget))\n const instruction = createUserMessage({\n source: { kind: 'app', producer: 'agent-compaction' },\n content: [{ type: 'text', text: COMPACTION_INSTRUCTION }],\n })\n const assembler = new BlockAssembler()\n const request = {\n ...prepared.config,\n messages: [...replay, instruction],\n ...(system.length === 0 ? {} : { system }),\n ...(tools.length === 0 ? {} : { tools }),\n toolChoice: 'none',\n signal,\n } as const\n const { signal: _signal, ...serializableRequest } = request\n if (serializedBytes(serializableRequest) > policy.maxSummaryRequestBytes) {\n throw codedError(\n `compaction summary request exceeds the ${policy.maxSummaryRequestBytes}-byte limit`,\n 'MODEL_REQUEST_TOO_LARGE',\n )\n }\n assertUsageAdmission(accounting)\n const handle = prepared.stream(request, accounting?.modelInvocation)\n const iterator = handle[Symbol.asyncIterator]()\n let exhausted = false\n let events = 0\n let responseBytes = 0\n let sawFinish = false\n let failure: unknown\n try {\n while (true) {\n const next = await raceWithSignal(iterator.next(), signal)\n if (next.done === true) {\n exhausted = true\n break\n }\n events++\n responseBytes += serializedBytes(next.value)\n if (events > policy.maxSummaryStreamEvents\n || responseBytes > policy.maxSummaryResponseBytes) {\n throw codedError('compaction summary response exceeded its resource limit', 'MODEL_RESPONSE_TOO_LARGE')\n }\n if (sawFinish) {\n throw codedError('compaction summarizer emitted data after its terminal finish chunk', 'INVALID_MODEL_STREAM')\n }\n assembler.push(next.value)\n if (next.value.type === 'finish') sawFinish = true\n }\n } catch (error: unknown) {\n failure = error\n } finally {\n if (!exhausted) {\n const close = iterator.return?.bind(iterator)\n if (close !== undefined) {\n try {\n const closing = Promise.resolve().then(async () => { await close() })\n if (!await waitForSettlement(closing, policy.teardownTimeoutMs)) failure = codedError(\n `compaction model stream ignored cancellation for more than ${policy.teardownTimeoutMs}ms`,\n 'MODEL_TEARDOWN_TIMEOUT',\n )\n } catch (error: unknown) { failure ??= error }\n }\n }\n }\n try {\n const report = await handle.report\n const decision = await accounting?.recordModelCall(report, request)\n if (decision?.usageRequired === true) {\n failure ??= codedError('compaction model usage is required by the configured run policy', 'USAGE_REQUIRED')\n }\n if (decision?.usageUnavailable === true) {\n failure ??= codedError('compaction model usage is unavailable for the configured budget', 'USAGE_UNAVAILABLE')\n }\n } catch (error: unknown) { failure ??= error }\n if (failure !== undefined) throw failure\n const finish = assembler.finish\n if (finish.kind === 'error' || finish.kind === 'aborted') {\n const error = new Error(finish.failure.message) as Error & { code?: string }\n error.code = finish.failure.code\n throw error\n }\n if (finish.kind === 'max-tokens') throw new Error('compaction summary was truncated at maxSummaryTokens')\n if (finish.kind === 'tool-calls') throw new Error('compaction summarizer attempted a tool call')\n const summary = assembler.blocks().flatMap(block => block.type === 'text' ? [block.text] : []).join('\\n').trim()\n if (summary.length === 0) throw new Error('compaction summarizer produced no text')\n return {\n summary, provider, model,\n ...(assembler.usage === undefined ? {} : { usage: assembler.usage }),\n }\n }\n}\n\nfunction sanitizeForSummary(\n message: Message,\n maxChars: number,\n budget: CharacterBudget,\n): Message {\n const content = message.content.flatMap(block => sanitizeBlock(block, maxChars, budget))\n const source = message.source.kind === 'model'\n ? { kind: 'model' as const, provider: message.source.provider, model: message.source.model }\n : message.source\n return createMessage({ role: message.role, source, content })\n}\n\nfunction sanitizeBlock(\n block: ContentBlock,\n maxChars: number,\n budget: CharacterBudget,\n): ContentBlock[] {\n switch (block.type) {\n case 'text': return [{ type: 'text', text: boundedText(block.text, maxChars, budget) }]\n case 'reasoning': return block.text.length === 0 ? [] : [{\n type: 'text', text: boundedText(`[Reasoning summary] ${block.text}`, maxChars, budget),\n }]\n case 'image': return [{ type: 'text', text: boundedText(`[Image input: ${block.source.kind}]`, maxChars, budget) }]\n case 'tool-call': return [{\n ...block, arguments: boundedToolArguments(block.arguments, maxChars, budget),\n } satisfies ToolCallBlock]\n case 'tool-result': return [{\n ...block,\n content: block.content.flatMap(child => sanitizeBlock(child, maxChars, budget)),\n } satisfies ToolResultBlock]\n case 'native-tool-call': return [{\n type: 'text',\n text: boundedText(\n `[Native tool ${block.name} (${block.status ?? 'unknown'})] ${safeJson(block.arguments ?? {})}`,\n maxChars,\n budget,\n ),\n }]\n default: return [{\n type: 'text', text: boundedText(`[Unsupported content block: ${safeJson(block)}]`, maxChars, budget),\n }]\n }\n}\n\nfunction boundedText(value: string, maxChars: number, budget: CharacterBudget): string {\n const allowed = Math.max(0, Math.min(maxChars, budget.remaining))\n const result = truncateMiddle(value, allowed)\n budget.remaining -= result.length\n return result\n}\n\nfunction boundedToolArguments(value: string, maxChars: number, budget: CharacterBudget): string {\n const allowed = Math.max(0, Math.min(maxChars, budget.remaining))\n if (value.length <= allowed) {\n budget.remaining -= value.length\n return value\n }\n const placeholder = '{\"_compacted\":true}'\n if (placeholder.length <= allowed) {\n budget.remaining -= placeholder.length\n return placeholder\n }\n return '{}'\n}\n\nfunction safeJson(value: unknown): string {\n try { return JSON.stringify(value) ?? '' } catch { return String(value) }\n}\nfunction truncateMiddle(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value\n const marker = '\\n…[truncated for compaction]…\\n'\n if (maxChars <= marker.length) return value.slice(0, maxChars)\n const head = Math.ceil((maxChars - marker.length) / 2)\n const tail = Math.floor((maxChars - marker.length) / 2)\n return value.slice(0, head) + marker + value.slice(value.length - tail)\n}\nfunction newCompactionId(): string {\n return systemRandomId()\n}\nfunction errorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error) }\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === 'object' && error !== null && 'code' in error && typeof error.code === 'string'\n ? error.code\n : undefined\n}\n\nfunction serializedBytes(value: unknown): number {\n const serialized = JSON.stringify(value)\n if (serialized === undefined) throw new TypeError('compaction model payload is not JSON serializable')\n return new TextEncoder().encode(serialized).byteLength\n}\n\nfunction assertUsageAdmission(accounting: ReturnType<typeof compactionAccounting>): void {\n const stop = accounting?.usageStop\n if (stop !== undefined) throw codedError(\n 'compaction cannot dispatch after a mandatory usage stop',\n stop.usageRequired ? 'USAGE_REQUIRED' : 'USAGE_UNAVAILABLE',\n )\n}\n\nfunction codedError(message: string, code: string, cause?: unknown): Error & { code: string } {\n const error = new Error(message, cause === undefined ? undefined : { cause }) as Error & { code: string }\n error.code = code\n return error\n}\n\nfunction modelTimeoutError(timeoutMs: number, cause: unknown): Error & { code: string } {\n return codedError(`compaction model operation exceeded ${timeoutMs}ms`, 'MODEL_TIMEOUT', cause)\n}\n\nasync function raceWithSignal<T>(pending: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) {\n void pending.catch(() => undefined)\n throw signal.reason ?? new Error('operation aborted')\n }\n return await new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n signal.removeEventListener('abort', onAbort)\n reject(signal.reason ?? new Error('operation aborted'))\n }\n signal.addEventListener('abort', onAbort, { once: true })\n void pending.then(\n value => {\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n },\n error => {\n signal.removeEventListener('abort', onAbort)\n reject(error)\n },\n )\n })\n}\n\nfunction pressureBackoffReason(input: {\n readonly trigger: CompactionTrigger\n readonly thresholdTokens: number | undefined\n readonly estimatedTokensBefore: number\n readonly estimatedTokensAfter: number\n readonly estimatedNonCompactableTokens: number\n}): CompactionBackoffReason | undefined {\n if (input.trigger !== 'pressure' || input.thresholdTokens === undefined\n || input.estimatedTokensAfter < input.thresholdTokens) return undefined\n if (input.estimatedNonCompactableTokens >= input.thresholdTokens) {\n return 'unreachable-threshold'\n }\n const savings = input.estimatedTokensBefore - input.estimatedTokensAfter\n const minimum = Math.max(\n MIN_PRESSURE_SAVINGS_TOKENS,\n Math.ceil(input.estimatedTokensBefore * MIN_PRESSURE_SAVINGS_RATIO),\n )\n return savings < minimum ? 'low-savings' : undefined\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compaction.js","names":[],"sources":["../../../src/agent/memory/compaction.ts"],"sourcesContent":["import { systemRandomId } from '../../platform/adapter.ts'\n/** Context-pressure compaction inspired by Codex checkpoints and deepseek-harness surface replacement. */\n\nimport type { CallConfig } from '../../contract/index.ts'\nimport type { ModelToolSchema } from '../../contract/index.ts'\nimport type { ContentBlock, ToolCallBlock, ToolResultBlock } from '../../message/index.ts'\nimport { createMessage, createUserMessage, type Message } from '../../message/index.ts'\nimport { ReasoningEffortId } from '../../primitives/index.ts'\nimport type { ModelRegistry } from '../../runtime/index.ts'\nimport { waitForSettlement } from '../../async/index.ts'\nimport { BlockAssembler } from '../../stream/index.ts'\nimport type { TokenUsage } from '../../stream/index.ts'\nimport type { History } from '../history/history.ts'\nimport { normalizeToolPairing } from '../history/normalize.ts'\nimport type {\n AgentMaintenanceEvent, BeforeStepContext, CompactionBackoffReason, CompactionTrigger, RequestErrorContext,\n} from '../loop/events.ts'\nimport type { AgentCompactionConfig } from './compaction-config.ts'\nimport { compactionAccounting } from './accounting-binding.ts'\nimport type { RunReport } from '../accounting/delivery-types.ts'\nimport { pruneToolResults, selectCompactablePrefix } from './surface-compaction.ts'\nimport { estimateContextTokens, estimateMessageTokens } from './token-estimator.ts'\n\nexport interface CompactionResult {\n readonly compactionId: string\n readonly trigger: CompactionTrigger\n readonly summary: string\n readonly shadowedSeqs: readonly number[]\n readonly estimatedTokensBefore: number\n readonly estimatedTokensAfter: number\n readonly thresholdTokens?: number\n readonly estimatedNonCompactableTokens: number\n readonly backoffReason?: CompactionBackoffReason\n readonly cooldownSteps?: number\n readonly provider: string\n readonly model: string\n readonly usage?: TokenUsage\n /** Additive runtime projection; absent on the preserved low-level compactor path. */\n readonly status?: 'completed'\n readonly report?: RunReport\n}\n\nexport interface ContextCompactorOptions {\n readonly registry: ModelRegistry\n /**\n * The call configuration in force RIGHT NOW, not when the compactor was built.\n *\n * A supplier rather than a value because a run may target a different model\n * than the session it belongs to: the context window a checkpoint is budgeted\n * against, and the model a summary is written by, both have to follow that\n * override or compaction would reason about a window nobody is calling.\n */\n readonly config: () => CallConfig\n readonly history: () => History\n readonly system: () => string\n readonly pinnedMessages?: () => readonly Message[]\n readonly tools: () => readonly ModelToolSchema[]\n readonly policy: AgentCompactionConfig\n}\n\ninterface ResolvedBudget {\n readonly thresholdTokens: number\n readonly retainTokens: number\n}\n\ninterface CharacterBudget { remaining: number }\n\nconst CHECKPOINT_PREAMBLE =\n 'This is an automatically generated checkpoint of earlier conversation context. Treat it as established background, preserve the original objective and constraints, and continue directly from the messages that follow.'\n\nconst MIN_PRESSURE_SAVINGS_TOKENS = 256\nconst MIN_PRESSURE_SAVINGS_RATIO = 0.01\nconst PRESSURE_BACKOFF_STEPS = 4\n\nexport const COMPACTION_INSTRUCTION = [\n 'You are performing a CONTEXT CHECKPOINT COMPACTION for a long-running AI agent task.',\n 'Condense the conversation above into a handoff that lets another model continue without forgetting the original purpose.',\n '',\n 'Output exactly these Markdown sections, in order, using terse bullets. Write \"(none)\" for an empty section.',\n '## Primary Request and Intent',\n '## Progress and Completed Work',\n '## Decisions and Rationale',\n '## Constraints and User Preferences',\n '## Important Files, Symbols, and Evidence',\n '## Errors and Failed Approaches',\n '## Pending Work',\n '## Current Work',\n '## Next Step',\n '## Critical Context',\n '',\n 'Preserve exact paths, identifiers, commands, error strings, numeric limits, and user corrections when they matter.',\n 'Under Important Files, mark relevant files as inspected or modified and preserve the exact declarations or findings needed next.',\n 'Under Current Work, record the last successful tool action, the latest verification result, and whether any edit is still partial.',\n 'Under Next Step, name one direct edit or command. Do not recommend rereading an unchanged file whose relevant contents are already recorded.',\n 'Do not reveal hidden chain-of-thought. Record only public progress, observed evidence, decisions, and actionable context.',\n 'If an earlier <compacted-summary> exists, merge still-valid facts with newer information and drop stale facts.',\n 'Output only the checkpoint. Do not call tools and do not acknowledge the compaction.',\n].join('\\n')\n\nexport class ContextCompactor {\n private readonly input: ContextCompactorOptions\n private active = false\n private overflowTurn = -1\n private overflowRetries = 0\n private recoveringOverflow = false\n /** Keyed by route + model + output reserve: an override changes all three. */\n private modelBudget: {\n readonly key: string\n readonly budget: { readonly contextWindow: number; readonly outputReserve: number } | null\n } | undefined\n private pressureCooldown = 0\n\n constructor(input: ContextCompactorOptions) {\n this.input = input\n }\n\n /** Fail-open pressure maintenance for a pre-step hook. */\n async beforeStep(context: BeforeStepContext): Promise<void> {\n if (!this.input.policy.auto || context.signal.aborted) return\n if (this.pressureCooldown > 0) {\n this.pressureCooldown--\n return\n }\n if (this.overflowTurn !== context.turn) {\n this.overflowTurn = context.turn\n this.overflowRetries = 0\n } else if (!this.recoveringOverflow) {\n this.overflowRetries = 0\n }\n this.recoveringOverflow = false\n try {\n let lastResult: CompactionResult | undefined\n for (let attempt = 0; attempt <= this.input.policy.compactionRetries; attempt++) {\n const result = await this.compactIfNeeded('pressure', context.signal, context.emit)\n if (result === null) break\n lastResult = result\n if (result.backoffReason !== undefined) {\n this.pressureCooldown = result.cooldownSteps ?? PRESSURE_BACKOFF_STEPS\n break\n }\n }\n if (lastResult !== undefined\n && lastResult.thresholdTokens !== undefined\n && lastResult.estimatedTokensAfter >= lastResult.thresholdTokens) {\n this.pressureCooldown = Math.max(\n this.pressureCooldown,\n PRESSURE_BACKOFF_STEPS,\n )\n }\n } catch {\n // Pressure maintenance is fail-open; the provider's canonical overflow\n // error still gets one forced recovery path below. Avoid retrying the same\n // broken maintenance request on every tool step and flooding logs/traces.\n // Mandatory usage decisions stay latched in the owning ledger and are\n // checked by modelRound after this hook, before any main dispatch.\n this.pressureCooldown = 2\n }\n }\n\n /** Compact and retry only when a provider confirmed context overflow. */\n async onRequestError(context: RequestErrorContext): Promise<'retry' | undefined> {\n if (context.failure.code !== 'CONTEXT_WINDOW_EXCEEDED' || context.signal.aborted) return undefined\n if (this.overflowTurn !== context.turn) {\n this.overflowTurn = context.turn\n this.overflowRetries = 0\n }\n if (this.overflowRetries >= this.input.policy.maxOverflowRetries) return undefined\n try {\n const result = await this.compactIfNeeded('context-overflow', context.signal, context.emit)\n if (result === null || context.signal.aborted) return undefined\n this.overflowRetries++\n this.recoveringOverflow = true\n return 'retry'\n } catch {\n return undefined\n }\n }\n\n /** Explicit idle-session checkpoint even below automatic pressure. */\n async compactNow(signal?: AbortSignal): Promise<CompactionResult | null> {\n const controller = signal === undefined ? new AbortController() : undefined\n const effectiveSignal = signal ?? controller?.signal\n if (effectiveSignal === undefined) throw new Error('failed to create compaction signal')\n return this.compactIfNeeded('manual', effectiveSignal)\n }\n\n private async compactIfNeeded(\n trigger: CompactionTrigger,\n signal: AbortSignal,\n emit?: (event: AgentMaintenanceEvent) => Promise<void>,\n ): Promise<CompactionResult | null> {\n if (this.active) return null\n const deadline = AbortSignal.timeout(this.input.policy.summaryTimeoutMs)\n const operationSignal = AbortSignal.any([signal, deadline])\n operationSignal.throwIfAborted()\n this.active = true\n try {\n const history = this.input.history()\n let surface = history.surface()\n if (surface.length < 2) return null\n const tools = this.input.tools()\n const system = this.input.system()\n const pinned = this.input.pinnedMessages?.() ?? []\n let totalBefore = estimateContextTokens({\n system, messages: [...pinned, ...surface.map(node => node.message)], tools,\n })\n let budget = await this.resolveBudget(totalBefore, operationSignal)\n operationSignal.throwIfAborted()\n if (trigger === 'pressure' && (budget === null || totalBefore < budget.thresholdTokens)) return null\n const pruned = pruneToolResults(history, surface, this.input.policy.maxToolResultChars)\n if (pruned > 0) {\n surface = history.surface()\n totalBefore = estimateContextTokens({\n system, messages: [...pinned, ...surface.map(node => node.message)], tools,\n })\n if (trigger === 'pressure' && budget !== null && totalBefore < budget.thresholdTokens) return null\n // With an absolute threshold and no provider context metadata, retainRatio\n // is inferred from the measured request. Pruning can change that request\n // by orders of magnitude, so selection must use the post-prune budget.\n budget = await this.resolveBudget(totalBefore, operationSignal)\n operationSignal.throwIfAborted()\n }\n const retainTokens = trigger === 'context-overflow'\n ? Math.max(1, estimateMessageTokens(surface.at(-1)?.message))\n : budget?.retainTokens ?? Math.max(1, Math.floor(totalBefore * 0.25))\n const selected = selectCompactablePrefix(surface, retainTokens)\n if (selected.length === 0) return null\n const selectedSeqs = new Set(selected.map(node => node.seq))\n const estimatedNonCompactableTokens = estimateContextTokens({\n system,\n messages: [\n ...pinned,\n ...surface.filter(node => !selectedSeqs.has(node.seq)).map(node => node.message),\n ],\n tools,\n })\n const compactionId = newCompactionId()\n const startedAt = new Date().toISOString()\n history.append({ kind: 'compaction-start', compactionId, trigger, at: startedAt })\n try {\n await this.emitObserver(emit, {\n type: 'compaction-start', compactionId, trigger, estimatedInputTokens: totalBefore,\n })\n const summarized = await this.summarize(\n [...pinned, ...selected.map(node => node.message)], system, tools, operationSignal,\n )\n // Adapters are contractually expected to honor cancellation, but the\n // compactor must not commit stale maintenance if one fails to do so.\n operationSignal.throwIfAborted()\n const checkpoint = createUserMessage({\n source: { kind: 'app', producer: `agent-compaction:${compactionId}` },\n content: [{\n type: 'text',\n text: `${CHECKPOINT_PREAMBLE}\\n\\n<compacted-summary>\\n${summarized.summary}\\n</compacted-summary>`,\n }],\n })\n const shadowedTokens = selected.reduce((total, node) => total + estimateMessageTokens(node.message), 0)\n const checkpointTokens = estimateMessageTokens(checkpoint)\n if (checkpointTokens >= shadowedTokens) {\n throw new Error(\n `compaction summary did not shrink selected context (${checkpointTokens} >= ${shadowedTokens} estimated tokens)`,\n )\n }\n const shadowedSeqs = Object.freeze(selected.map(node => node.seq))\n const estimatedTokensAfter = Math.max(0, totalBefore - shadowedTokens + checkpointTokens)\n const thresholdTokens = budget?.thresholdTokens\n const pressureBackoff = pressureBackoffReason({\n trigger,\n thresholdTokens,\n estimatedTokensBefore: totalBefore,\n estimatedTokensAfter,\n estimatedNonCompactableTokens,\n })\n history.appendBatch([\n { event: {\n kind: 'compaction-summary', compactionId, summary: summarized.summary, shadowedSeqs,\n estimatedTokensBefore: totalBefore, estimatedTokensAfter,\n provider: summarized.provider, model: summarized.model,\n ...(summarized.usage === undefined ? {} : { usage: summarized.usage }),\n } },\n { event: { kind: 'user', message: checkpoint }, surfaceOp: {\n op: 'replace',\n from: Math.min(...shadowedSeqs),\n to: Math.max(...shadowedSeqs),\n targets: shadowedSeqs,\n } },\n { event: {\n kind: 'compaction-end', compactionId, status: 'completed', at: new Date().toISOString(),\n ...(thresholdTokens === undefined ? {} : { thresholdTokens }),\n estimatedNonCompactableTokens,\n ...(pressureBackoff === undefined ? {} : {\n backoffReason: pressureBackoff,\n cooldownSteps: PRESSURE_BACKOFF_STEPS,\n }),\n } },\n ])\n const result: CompactionResult = Object.freeze({\n compactionId, trigger, summary: summarized.summary, shadowedSeqs,\n estimatedTokensBefore: totalBefore, estimatedTokensAfter,\n ...(thresholdTokens === undefined ? {} : { thresholdTokens }),\n estimatedNonCompactableTokens,\n ...(pressureBackoff === undefined ? {} : {\n backoffReason: pressureBackoff,\n cooldownSteps: PRESSURE_BACKOFF_STEPS,\n }),\n provider: summarized.provider, model: summarized.model,\n ...(summarized.usage === undefined ? {} : { usage: summarized.usage }),\n })\n await this.emitObserver(emit, {\n type: 'compaction-end', compactionId, trigger, status: 'completed', shadowedSeqs,\n estimatedTokensBefore: totalBefore, estimatedTokensAfter, summary: summarized.summary,\n ...(thresholdTokens === undefined ? {} : { thresholdTokens }),\n estimatedNonCompactableTokens,\n ...(pressureBackoff === undefined ? {} : {\n backoffReason: pressureBackoff,\n cooldownSteps: PRESSURE_BACKOFF_STEPS,\n }),\n ...(summarized.usage === undefined ? {} : { usage: summarized.usage }),\n })\n return result\n } catch (error: unknown) {\n const failure = deadline.aborted && !signal.aborted && errorCode(error) !== 'MODEL_TEARDOWN_TIMEOUT'\n ? modelTimeoutError(this.input.policy.summaryTimeoutMs, error)\n : error\n const message = errorMessage(failure)\n try {\n history.append({\n kind: 'compaction-end', compactionId, status: 'failed', at: new Date().toISOString(), error: message,\n })\n } catch {\n // Preserve the original compaction failure when the append-only history\n // has no remaining capacity for the diagnostic end marker.\n }\n await this.emitObserver(emit, {\n type: 'compaction-end', compactionId, trigger, status: 'failed', shadowedSeqs: [],\n estimatedTokensBefore: totalBefore, estimatedTokensAfter: totalBefore, error: message,\n })\n throw failure\n }\n } finally {\n this.active = false\n }\n }\n\n private async resolveBudget(totalTokens: number, signal: AbortSignal): Promise<ResolvedBudget | null> {\n const policy = this.input.policy\n const config = this.input.config()\n const key = `${config.provider}\\u0000${config.model}\\u0000${String(config.maxTokens ?? '')}`\n if (this.modelBudget?.key !== key) {\n try {\n const info = await raceWithSignal(this.input.registry.resolveModelInfo(\n config.provider, config.model, signal,\n ), signal)\n const contextWindow = info.context?.contextWindow\n this.modelBudget = { key, budget: contextWindow === undefined\n ? null\n : {\n contextWindow,\n outputReserve: config.maxTokens\n ?? info.defaultMaxTokens\n ?? info.maxOutputTokens\n ?? 0,\n } }\n } catch {\n if (policy.maxInputTokens === undefined) return null\n this.modelBudget = { key, budget: null }\n }\n }\n const contextWindow = this.modelBudget?.budget?.contextWindow\n const inputWindow = contextWindow === undefined\n ? undefined\n : Math.max(1, contextWindow - (this.modelBudget?.budget?.outputReserve ?? 0))\n const ratioThreshold = contextWindow === undefined\n ? undefined\n : Math.floor(contextWindow * policy.thresholdRatio)\n const safeThreshold = inputWindow === undefined || ratioThreshold === undefined\n ? undefined\n : Math.min(inputWindow, ratioThreshold)\n const thresholdTokens = policy.maxInputTokens === undefined\n ? safeThreshold\n : inputWindow === undefined\n ? policy.maxInputTokens\n : Math.min(policy.maxInputTokens, inputWindow)\n if (thresholdTokens === undefined) return null\n const inferredWindow = inputWindow ?? Math.max(totalTokens, Math.ceil(thresholdTokens / policy.thresholdRatio))\n const retainTokens = policy.retainTokens\n ?? Math.floor(inferredWindow * (policy.retainRatio ?? 0.2))\n return { thresholdTokens, retainTokens: Math.max(1, retainTokens) }\n }\n\n private async emitObserver(\n emit: ((event: AgentMaintenanceEvent) => Promise<void>) | undefined,\n event: AgentMaintenanceEvent,\n ): Promise<void> {\n if (emit === undefined) return\n const pending = Promise.resolve().then(() => emit(event))\n await waitForSettlement(pending, this.input.policy.teardownTimeoutMs)\n }\n\n private async summarize(\n messages: readonly Message[],\n system: string,\n tools: readonly ModelToolSchema[],\n signal: AbortSignal,\n ): Promise<{ summary: string; provider: string; model: string; usage?: TokenUsage }> {\n const policy = this.input.policy\n const active = this.input.config()\n const provider = policy.summarizationProvider ?? active.provider\n const model = policy.summarizationModel ?? active.model\n const accounting = compactionAccounting(this)\n assertUsageAdmission(accounting)\n const summaryInfo = await raceWithSignal(\n this.input.registry.resolveModelInfo(provider, model, signal),\n signal,\n )\n const maxSummaryTokens = Math.min(\n policy.maxSummaryTokens,\n summaryInfo.maxOutputTokens ?? Number.MAX_SAFE_INTEGER,\n summaryInfo.context === undefined\n ? Number.MAX_SAFE_INTEGER\n : Math.max(1, summaryInfo.context.contextWindow - 1),\n )\n const prepared = await raceWithSignal(this.input.registry.prepareCall({\n provider,\n model,\n ...(policy.summarizationEffort === undefined\n ? {}\n : { reasoningEffort: ReasoningEffortId(policy.summarizationEffort) }),\n maxTokens: maxSummaryTokens,\n }, signal, accounting?.modelInvocation), signal)\n // Compaction can encounter history written by an older runtime or a process\n // interrupted between a tool call and its result. Repair the replay just as\n // normal model requests do so a maintenance request cannot be provider-invalid.\n const characterBudget: CharacterBudget = { remaining: policy.maxSummaryRequestChars }\n const replay = normalizeToolPairing(messages)\n .map(message => sanitizeForSummary(message, policy.maxSummaryInputChars, characterBudget))\n const instruction = createUserMessage({\n source: { kind: 'app', producer: 'agent-compaction' },\n content: [{ type: 'text', text: COMPACTION_INSTRUCTION }],\n })\n const assembler = new BlockAssembler()\n const request = {\n ...prepared.config,\n messages: [...replay, instruction],\n ...(system.length === 0 ? {} : { system }),\n ...(tools.length === 0 ? {} : { tools }),\n toolChoice: 'none',\n signal,\n } as const\n const { signal: _signal, ...serializableRequest } = request\n if (serializedBytes(serializableRequest) > policy.maxSummaryRequestBytes) {\n throw codedError(\n `compaction summary request exceeds the ${policy.maxSummaryRequestBytes}-byte limit`,\n 'MODEL_REQUEST_TOO_LARGE',\n )\n }\n assertUsageAdmission(accounting)\n const handle = prepared.stream(request, accounting?.modelInvocation)\n const iterator = handle[Symbol.asyncIterator]()\n let exhausted = false\n let events = 0\n let responseBytes = 0\n let sawFinish = false\n let failure: unknown\n try {\n while (true) {\n const next = await raceWithSignal(iterator.next(), signal)\n if (next.done === true) {\n exhausted = true\n break\n }\n events++\n responseBytes += serializedBytes(next.value)\n if (events > policy.maxSummaryStreamEvents\n || responseBytes > policy.maxSummaryResponseBytes) {\n throw codedError('compaction summary response exceeded its resource limit', 'MODEL_RESPONSE_TOO_LARGE')\n }\n if (sawFinish) {\n throw codedError('compaction summarizer emitted data after its terminal finish chunk', 'INVALID_MODEL_STREAM')\n }\n assembler.push(next.value)\n if (next.value.type === 'finish') sawFinish = true\n }\n } catch (error: unknown) {\n failure = error\n } finally {\n if (!exhausted) {\n const close = iterator.return?.bind(iterator)\n if (close !== undefined) {\n try {\n const closing = Promise.resolve().then(async () => { await close() })\n if (!await waitForSettlement(closing, policy.teardownTimeoutMs)) failure = codedError(\n `compaction model stream ignored cancellation for more than ${policy.teardownTimeoutMs}ms`,\n 'MODEL_TEARDOWN_TIMEOUT',\n )\n } catch (error: unknown) { failure ??= error }\n }\n }\n }\n try {\n const report = await handle.report\n const decision = await accounting?.recordModelCall(report, request)\n if (decision?.usageRequired === true) {\n failure ??= codedError('compaction model usage is required by the configured run policy', 'USAGE_REQUIRED')\n }\n if (decision?.usageUnavailable === true) {\n failure ??= codedError('compaction model usage is unavailable for the configured budget', 'USAGE_UNAVAILABLE')\n }\n } catch (error: unknown) { failure ??= error }\n if (failure !== undefined) throw failure\n const finish = assembler.finish\n if (finish.kind === 'error' || finish.kind === 'aborted') {\n const error = new Error(finish.failure.message) as Error & { code?: string }\n error.code = finish.failure.code\n throw error\n }\n if (finish.kind === 'max-tokens') throw new Error('compaction summary was truncated at maxSummaryTokens')\n if (finish.kind === 'tool-calls') throw new Error('compaction summarizer attempted a tool call')\n const summary = assembler.blocks().flatMap(block => block.type === 'text' ? [block.text] : []).join('\\n').trim()\n if (summary.length === 0) throw new Error('compaction summarizer produced no text')\n return {\n summary, provider, model,\n ...(assembler.usage === undefined ? {} : { usage: assembler.usage }),\n }\n }\n}\n\nfunction sanitizeForSummary(\n message: Message,\n maxChars: number,\n budget: CharacterBudget,\n): Message {\n const content = message.content.flatMap(block => sanitizeBlock(block, maxChars, budget))\n const source = message.source.kind === 'model'\n ? { kind: 'model' as const, provider: message.source.provider, model: message.source.model }\n : message.source\n return createMessage({ role: message.role, source, content })\n}\n\nfunction sanitizeBlock(\n block: ContentBlock,\n maxChars: number,\n budget: CharacterBudget,\n): ContentBlock[] {\n switch (block.type) {\n case 'text': return [{ type: 'text', text: boundedText(block.text, maxChars, budget) }]\n case 'reasoning': return block.text.length === 0 ? [] : [{\n type: 'text', text: boundedText(`[Reasoning summary] ${block.text}`, maxChars, budget),\n }]\n case 'image': return [{ type: 'text', text: boundedText(`[Image input: ${block.source.kind}]`, maxChars, budget) }]\n case 'document': return [{\n type: 'text',\n text: boundedText(`[Document input: ${block.filename ?? block.source.kind}]`, maxChars, budget),\n }]\n case 'tool-call': return [{\n ...block, arguments: boundedToolArguments(block.arguments, maxChars, budget),\n } satisfies ToolCallBlock]\n case 'tool-result': return [{\n ...block,\n content: block.content.flatMap(child => sanitizeBlock(child, maxChars, budget)),\n } satisfies ToolResultBlock]\n case 'native-tool-call': return [{\n type: 'text',\n text: boundedText(\n `[Native tool ${block.name} (${block.status ?? 'unknown'})] ${safeJson(block.arguments ?? {})}`,\n maxChars,\n budget,\n ),\n }]\n default: return [{\n type: 'text', text: boundedText(`[Unsupported content block: ${safeJson(block)}]`, maxChars, budget),\n }]\n }\n}\n\nfunction boundedText(value: string, maxChars: number, budget: CharacterBudget): string {\n const allowed = Math.max(0, Math.min(maxChars, budget.remaining))\n const result = truncateMiddle(value, allowed)\n budget.remaining -= result.length\n return result\n}\n\nfunction boundedToolArguments(value: string, maxChars: number, budget: CharacterBudget): string {\n const allowed = Math.max(0, Math.min(maxChars, budget.remaining))\n if (value.length <= allowed) {\n budget.remaining -= value.length\n return value\n }\n const placeholder = '{\"_compacted\":true}'\n if (placeholder.length <= allowed) {\n budget.remaining -= placeholder.length\n return placeholder\n }\n return '{}'\n}\n\nfunction safeJson(value: unknown): string {\n try { return JSON.stringify(value) ?? '' } catch { return String(value) }\n}\nfunction truncateMiddle(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value\n const marker = '\\n…[truncated for compaction]…\\n'\n if (maxChars <= marker.length) return value.slice(0, maxChars)\n const head = Math.ceil((maxChars - marker.length) / 2)\n const tail = Math.floor((maxChars - marker.length) / 2)\n return value.slice(0, head) + marker + value.slice(value.length - tail)\n}\nfunction newCompactionId(): string {\n return systemRandomId()\n}\nfunction errorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error) }\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === 'object' && error !== null && 'code' in error && typeof error.code === 'string'\n ? error.code\n : undefined\n}\n\nfunction serializedBytes(value: unknown): number {\n const serialized = JSON.stringify(value)\n if (serialized === undefined) throw new TypeError('compaction model payload is not JSON serializable')\n return new TextEncoder().encode(serialized).byteLength\n}\n\nfunction assertUsageAdmission(accounting: ReturnType<typeof compactionAccounting>): void {\n const stop = accounting?.usageStop\n if (stop !== undefined) throw codedError(\n 'compaction cannot dispatch after a mandatory usage stop',\n stop.usageRequired ? 'USAGE_REQUIRED' : 'USAGE_UNAVAILABLE',\n )\n}\n\nfunction codedError(message: string, code: string, cause?: unknown): Error & { code: string } {\n const error = new Error(message, cause === undefined ? undefined : { cause }) as Error & { code: string }\n error.code = code\n return error\n}\n\nfunction modelTimeoutError(timeoutMs: number, cause: unknown): Error & { code: string } {\n return codedError(`compaction model operation exceeded ${timeoutMs}ms`, 'MODEL_TIMEOUT', cause)\n}\n\nasync function raceWithSignal<T>(pending: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) {\n void pending.catch(() => undefined)\n throw signal.reason ?? new Error('operation aborted')\n }\n return await new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n signal.removeEventListener('abort', onAbort)\n reject(signal.reason ?? new Error('operation aborted'))\n }\n signal.addEventListener('abort', onAbort, { once: true })\n void pending.then(\n value => {\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n },\n error => {\n signal.removeEventListener('abort', onAbort)\n reject(error)\n },\n )\n })\n}\n\nfunction pressureBackoffReason(input: {\n readonly trigger: CompactionTrigger\n readonly thresholdTokens: number | undefined\n readonly estimatedTokensBefore: number\n readonly estimatedTokensAfter: number\n readonly estimatedNonCompactableTokens: number\n}): CompactionBackoffReason | undefined {\n if (input.trigger !== 'pressure' || input.thresholdTokens === undefined\n || input.estimatedTokensAfter < input.thresholdTokens) return undefined\n if (input.estimatedNonCompactableTokens >= input.thresholdTokens) {\n return 'unreachable-threshold'\n }\n const savings = input.estimatedTokensBefore - input.estimatedTokensAfter\n const minimum = Math.max(\n MIN_PRESSURE_SAVINGS_TOKENS,\n Math.ceil(input.estimatedTokensBefore * MIN_PRESSURE_SAVINGS_RATIO),\n )\n return savings < minimum ? 'low-savings' : undefined\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(e){let n=e.system===void 0?0:
|
|
1
|
+
function e(e){let n=e.system===void 0?0:o(e.system),r=e.messages.reduce((e,n)=>e+t(n),0),i=e.tools?.reduce((e,t)=>e+o(s(t))+8,0)??0;return n+r+i+8}function t(e){return e===void 0?0:4+e.content.reduce((e,t)=>e+n(t),0)}function n(e){switch(e.type){case`text`:return o(e.text)+2;case`reasoning`:return o(e.text)+o(s(e.providerState))+2;case`image`:return i(e.detail);case`document`:return a(e.pages);case`tool-call`:return o(e.name)+o(e.arguments)+8;case`tool-result`:return e.content.reduce((e,t)=>e+n(t),8);case`native-tool-call`:return o(s(e))+8;default:return o(s(e))+4}}const r={low:256,high:2500,auto:2500,original:1e4};function i(e){return Math.ceil(r[e??`auto`]*1.2)}function a(e){return(e!==void 0&&Number.isSafeInteger(e)&&e>0?e:8)*3e3}function o(e){return Math.ceil(e.length/4)}function s(e){try{return JSON.stringify(e)??``}catch{return String(e)}}export{e as estimateContextTokens,t as estimateMessageTokens};
|
|
2
2
|
//# sourceMappingURL=token-estimator.js.map
|