@zhin.js/agent 1.1.39 → 1.1.40
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/lib/assistant/job-storage.d.ts +238 -0
- package/lib/assistant/job-storage.js +143 -0
- package/lib/assistant/job-storage.js.map +1 -0
- package/lib/assistant/job-store.d.ts +7 -0
- package/lib/assistant/job-store.js +41 -3
- package/lib/assistant/job-store.js.map +1 -1
- package/lib/config/perception-config.d.ts +9 -0
- package/lib/config/perception-config.js +27 -0
- package/lib/config/perception-config.js.map +1 -1
- package/lib/context/context-system.d.ts +1 -0
- package/lib/context/context-system.js +8 -8
- package/lib/context/context-system.js.map +1 -1
- package/lib/context/im-turn-context-adapter.js +2 -0
- package/lib/context/im-turn-context-adapter.js.map +1 -1
- package/lib/context/skill-context.d.ts +3 -0
- package/lib/context/skill-context.js +6 -0
- package/lib/context/skill-context.js.map +1 -0
- package/lib/context/turn-envelope.d.ts +4 -0
- package/lib/context/turn-envelope.js +24 -7
- package/lib/context/turn-envelope.js.map +1 -1
- package/lib/context/turn-user-message.d.ts +3 -1
- package/lib/context/turn-user-message.js +14 -1
- package/lib/context/turn-user-message.js.map +1 -1
- package/lib/core/agent-core-run.d.ts +1 -0
- package/lib/core/agent-core-run.js +47 -20
- package/lib/core/agent-core-run.js.map +1 -1
- package/lib/core/structured-reply-recovery.d.ts +6 -2
- package/lib/core/structured-reply-recovery.js +22 -8
- package/lib/core/structured-reply-recovery.js.map +1 -1
- package/lib/core/turn-completion-usage.d.ts +2 -1
- package/lib/core/turn-completion-usage.js +14 -5
- package/lib/core/turn-completion-usage.js.map +1 -1
- package/lib/core/turn-event-mapper.d.ts +1 -1
- package/lib/core/turn-event-mapper.js +8 -5
- package/lib/core/turn-event-mapper.js.map +1 -1
- package/lib/event/turn-event.d.ts +7 -1
- package/lib/event/turn-event.js.map +1 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/media/perception.d.ts +3 -4
- package/lib/media/perception.js +59 -37
- package/lib/media/perception.js.map +1 -1
- package/lib/memory/compaction-runtime.d.ts +3 -2
- package/lib/memory/compaction-runtime.js +22 -14
- package/lib/memory/compaction-runtime.js.map +1 -1
- package/lib/outbound/agent-output.js +2 -0
- package/lib/outbound/agent-output.js.map +1 -1
- package/lib/outbound/chat-failure.d.ts +27 -0
- package/lib/outbound/chat-failure.js +53 -0
- package/lib/outbound/chat-failure.js.map +1 -0
- package/lib/outbound/structured-reply.d.ts +7 -0
- package/lib/outbound/structured-reply.js +52 -16
- package/lib/outbound/structured-reply.js.map +1 -1
- package/lib/plugin-runtime/agent-runtime.js +49 -8
- package/lib/plugin-runtime/agent-runtime.js.map +1 -1
- package/lib/plugin-runtime/ai-completion.d.ts +4 -3
- package/lib/plugin-runtime/ai-completion.js +64 -10
- package/lib/plugin-runtime/ai-completion.js.map +1 -1
- package/lib/plugin-runtime/capability-ingress.js +3 -1
- package/lib/plugin-runtime/capability-ingress.js.map +1 -1
- package/lib/plugin-runtime/deferred-capability-plan.d.ts +4 -1
- package/lib/plugin-runtime/deferred-capability-plan.js +25 -9
- package/lib/plugin-runtime/deferred-capability-plan.js.map +1 -1
- package/lib/plugin-runtime/full-agent-turn-engine.js +1 -0
- package/lib/plugin-runtime/full-agent-turn-engine.js.map +1 -1
- package/lib/plugin-runtime/index.d.ts +2 -0
- package/lib/plugin-runtime/index.js +2 -0
- package/lib/plugin-runtime/index.js.map +1 -1
- package/lib/prompt/assembly.js +0 -9
- package/lib/prompt/assembly.js.map +1 -1
- package/lib/prompt/git-context.js +1 -1
- package/lib/prompt/git-context.js.map +1 -1
- package/lib/prompt/rules/chat-rules.js +8 -9
- package/lib/prompt/rules/chat-rules.js.map +1 -1
- package/lib/prompt/rules/critical-rules.js +10 -10
- package/lib/prompt/rules/critical-rules.js.map +1 -1
- package/lib/prompt/system-prompt.js +4 -5
- package/lib/prompt/system-prompt.js.map +1 -1
- package/lib/security/file-role-policy.js +6 -6
- package/lib/security/file-role-policy.js.map +1 -1
- package/lib/security/policy-facade.js +1 -1
- package/lib/security/policy-facade.js.map +1 -1
- package/lib/security/usage-quota.d.ts +4 -0
- package/lib/security/usage-quota.js +23 -2
- package/lib/security/usage-quota.js.map +1 -1
- package/lib/session/approval-port.d.ts +2 -0
- package/lib/session/approval-port.js.map +1 -1
- package/lib/session/approval-review-agent.d.ts +1 -1
- package/lib/session/approval-review-agent.js +19 -4
- package/lib/session/approval-review-agent.js.map +1 -1
- package/lib/session/turn-ingress-session.js +7 -1
- package/lib/session/turn-ingress-session.js.map +1 -1
- package/lib/tool/tool-approval-gate.js +4 -2
- package/lib/tool/tool-approval-gate.js.map +1 -1
- package/lib/tool/turn-tool-runtime.js +24 -5
- package/lib/tool/turn-tool-runtime.js.map +1 -1
- package/lib/tool-catalog/deferred-turn-controller.js +1 -4
- package/lib/tool-catalog/deferred-turn-controller.js.map +1 -1
- package/lib/trace/context-budget.d.ts +4 -3
- package/lib/trace/context-budget.js +28 -8
- package/lib/trace/context-budget.js.map +1 -1
- package/lib/trace/turn-trace-format.js +4 -1
- package/lib/trace/turn-trace-format.js.map +1 -1
- package/lib/trace/turn-trace.d.ts +6 -0
- package/lib/trace/turn-trace.js +8 -2
- package/lib/trace/turn-trace.js.map +1 -1
- package/lib/trace/turn-usage-log.d.ts +14 -0
- package/lib/trace/turn-usage-log.js +83 -0
- package/lib/trace/turn-usage-log.js.map +1 -0
- package/lib/usage/usage-store.d.ts +199 -0
- package/lib/usage/usage-store.js +121 -0
- package/lib/usage/usage-store.js.map +1 -0
- package/package.json +12 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-trace-format.js","sourceRoot":"","sources":["../../src/trace/turn-trace-format.ts"],"names":[],"mappings":"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","sourcesContent":["/** Human-readable terminal rendering of a TurnTrace for `zhin trace`. */\nimport type { TurnTrace, TurnTraceToolCall } from './turn-trace.js';\nimport { CONTEXT_BUDGET_SEGMENTS, type ContextBudgetReport, type ContextBudgetSegment } from './context-budget.js';\n\nconst STATUS_LABEL: Record<TurnTrace['termination']['status'], string> = {\n running: '进行中',\n completed: '完成',\n failed: '失败',\n cancelled: '已取消',\n budget_exceeded: '超出预算',\n unknown: '未知',\n};\n\nconst TOOL_MARK: Record<TurnTraceToolCall['status'], string> = {\n running: '…',\n ok: '✓',\n failed: '✗',\n denied: '⊘',\n cancelled: '-',\n};\n\nexport interface FormatTurnTraceOptions {\n /** Include the chronological timeline (default true). */\n readonly timeline?: boolean;\n}\n\nexport function formatTurnTrace(trace: TurnTrace, options: FormatTurnTraceOptions = {}): string {\n return renderTrace(trace, '', options.timeline ?? true).join('\\n');\n}\n\n/** One line per trace, newest last. */\nexport function formatTurnTraceList(traces: readonly TurnTrace[]): string {\n if (traces.length === 0) return '还没有记录到任何回合。';\n return traces.map(trace => [\n new Date(trace.started_at).toLocaleString(),\n STATUS_LABEL[trace.termination.status],\n trace.turn_id,\n trace.session_key,\n `${trace.tool_calls.length} tools`,\n `${trace.usage.total_tokens} tokens`,\n ].join(' ')).join('\\n');\n}\n\nfunction renderTrace(trace: TurnTrace, indent: string, withTimeline: boolean): string[] {\n const lines: string[] = [];\n const termination = trace.termination;\n const failingTool = trace.tool_calls.find(tool => tool.status === 'failed' || tool.status === 'denied');\n lines.push(`${indent}回合 ${trace.turn_id} [${STATUS_LABEL[termination.status]}]`);\n lines.push(`${indent} 会话: ${trace.session_key}`);\n if (trace.principal) {\n const name = trace.principal.display_name ? ` (${trace.principal.display_name})` : '';\n lines.push(`${indent} 发起人: ${trace.principal.subject_id}${name} 角色: ${trace.principal.roles.join(', ') || '-'}`\n + (trace.principal.trust_level ? ` 信任级别: ${trace.principal.trust_level}` : ''));\n }\n lines.push(`${indent} 开始: ${new Date(trace.started_at).toLocaleString()} 耗时: ${formatDuration(trace.duration_ms)}`);\n if (termination.code || termination.reason) {\n lines.push(`${indent} 结束原因: ${[termination.code, termination.reason].filter(Boolean).join(' — ')}`);\n }\n if (failingTool) {\n lines.push(`${indent} 首个失败步骤: ${failingTool.tool_name} ${failingTool.status}${failingTool.error ? ` — ${failingTool.error}` : ''}`);\n }\n\n lines.push(`${indent} 模型调用 ${trace.model_calls.length} 次,tokens 输入 ${trace.usage.prompt_tokens} / 输出 ${trace.usage.completion_tokens} / 合计 ${trace.usage.total_tokens}`);\n const cached = trace.model_calls.reduce((sum, call) => sum + (call.cache_read_tokens ?? 0), 0);\n if (cached > 0 && trace.usage.prompt_tokens > 0) {\n lines.push(`${indent} 提示缓存命中 ${cached} tokens(占输入 ${Math.round((cached / trace.usage.prompt_tokens) * 100)}%)`);\n }\n for (const call of trace.model_calls) {\n const cache = call.cache_read_tokens ? ` cache=${call.cache_read_tokens}` : '';\n const reasoning = call.reasoning_tokens ? ` reasoning=${call.reasoning_tokens}` : '';\n lines.push(`${indent} #${call.index} in=${call.prompt_tokens} out=${call.completion_tokens}${cache}${reasoning}`);\n }\n\n if (trace.context_budget) lines.push(...renderContextBudget(trace.context_budget, indent));\n\n lines.push(`${indent} 工具调用 ${trace.tool_calls.length} 次`);\n for (const tool of trace.tool_calls) {\n const details = [\n tool.duration_ms !== undefined ? `${tool.duration_ms}ms` : undefined,\n tool.result_size !== undefined ? `${tool.result_size} 字符` : undefined,\n tool.policy ? `策略 ${tool.policy}` : undefined,\n ].filter(Boolean).join(', ');\n lines.push(`${indent} ${TOOL_MARK[tool.status]} ${tool.tool_name}${details ? ` (${details})` : ''} ${tool.args_summary}`.trimEnd());\n if (tool.error) lines.push(`${indent} ${tool.error}`);\n }\n\n if (trace.budget.extensions.length > 0 || trace.budget.continuations > 0) {\n const extensions = trace.budget.extensions.map(item => `${item.from}→${item.to}`).join(', ');\n lines.push(`${indent} 预算: 延长 ${trace.budget.extensions.length} 次${extensions ? ` (${extensions})` : ''},自动续跑 ${trace.budget.continuations} 次`);\n }\n\n for (const task of trace.subagent_tasks) {\n lines.push(`${indent} 子任务 ${task.task_id} [${task.status}] ${task.description}`);\n }\n for (const child of trace.subagents) {\n lines.push(`${indent} 子 agent:`);\n lines.push(...renderTrace(child, `${indent} `, false));\n }\n\n if (withTimeline && trace.timeline.length > 0) {\n lines.push(`${indent} 时间线:`);\n for (const entry of trace.timeline) {\n lines.push(`${indent} +${formatDuration(entry.at_ms).padStart(7)} ${entry.kind.padEnd(14)} ${entry.detail}`.trimEnd());\n }\n }\n if (trace.dropped > 0) lines.push(`${indent} (有 ${trace.dropped} 条记录因超出上限被省略)`);\n return lines;\n}\n\nconst SEGMENT_LABEL: Record<ContextBudgetSegment, string> = {\n system: '系统提示',\n tool_schemas: '工具 schema',\n tool_index: '按需工具索引',\n skill_catalog: '技能目录',\n agent_catalog: '专家 agent 目录',\n active_skills: '已加载技能',\n memory: '记忆',\n bootstrap: 'bootstrap',\n history: '历史消息',\n user: '本轮输入',\n};\n\nconst TOP_SECTIONS = 5;\n\n/** Estimated prompt cost of the first model request, by segment. */\nfunction renderContextBudget(budget: ContextBudgetReport, indent: string): string[] {\n const parts = CONTEXT_BUDGET_SEGMENTS\n .filter(segment => budget.segments[segment] > 0)\n .map(segment => `${SEGMENT_LABEL[segment]} ${budget.segments[segment]}`);\n const lines = [\n `${indent} 上下文估算 ~${budget.total_tokens} tokens(固定开销 ~${budget.fixed_tokens};工具 ${budget.tools.loaded} 个常驻 / ${budget.tools.deferred} 个按需)`,\n ];\n if (parts.length > 0) lines.push(`${indent} ${parts.join(' · ')}`);\n const top = budget.sections.slice(0, TOP_SECTIONS).filter(section => section.tokens > 0);\n if (top.length > 0) lines.push(`${indent} 最大的提示段: ${top.map(section => `${section.id} ${section.tokens}`).join(', ')}`);\n return lines;\n}\n\nfunction formatDuration(ms: number | undefined): string {\n if (ms === undefined) return '-';\n if (ms < 1000) return `${Math.round(ms)}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.floor(ms / 60_000)}m${Math.round((ms % 60_000) / 1000)}s`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"turn-trace-format.js","sourceRoot":"","sources":["../../src/trace/turn-trace-format.ts"],"names":[],"mappings":"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","sourcesContent":["/** Human-readable terminal rendering of a TurnTrace for `zhin trace`. */\nimport type { TurnTrace, TurnTraceToolCall } from './turn-trace.js';\nimport { CONTEXT_BUDGET_SEGMENTS, type ContextBudgetReport, type ContextBudgetSegment } from './context-budget.js';\n\nconst STATUS_LABEL: Record<TurnTrace['termination']['status'], string> = {\n running: '进行中',\n completed: '完成',\n failed: '失败',\n cancelled: '已取消',\n budget_exceeded: '超出预算',\n unknown: '未知',\n};\n\nconst TOOL_MARK: Record<TurnTraceToolCall['status'], string> = {\n running: '…',\n ok: '✓',\n failed: '✗',\n denied: '⊘',\n cancelled: '-',\n};\n\nexport interface FormatTurnTraceOptions {\n /** Include the chronological timeline (default true). */\n readonly timeline?: boolean;\n}\n\nexport function formatTurnTrace(trace: TurnTrace, options: FormatTurnTraceOptions = {}): string {\n return renderTrace(trace, '', options.timeline ?? true).join('\\n');\n}\n\n/** One line per trace, newest last. */\nexport function formatTurnTraceList(traces: readonly TurnTrace[]): string {\n if (traces.length === 0) return '还没有记录到任何回合。';\n return traces.map(trace => [\n new Date(trace.started_at).toLocaleString(),\n STATUS_LABEL[trace.termination.status],\n trace.turn_id,\n trace.session_key,\n `${trace.tool_calls.length} tools`,\n `${trace.usage.total_tokens} tokens`,\n ].join(' ')).join('\\n');\n}\n\nfunction renderTrace(trace: TurnTrace, indent: string, withTimeline: boolean): string[] {\n const lines: string[] = [];\n const termination = trace.termination;\n const failingTool = trace.tool_calls.find(tool => tool.status === 'failed' || tool.status === 'denied');\n lines.push(`${indent}回合 ${trace.turn_id} [${STATUS_LABEL[termination.status]}]`);\n lines.push(`${indent} 会话: ${trace.session_key}`);\n if (trace.principal) {\n const name = trace.principal.display_name ? ` (${trace.principal.display_name})` : '';\n lines.push(`${indent} 发起人: ${trace.principal.subject_id}${name} 角色: ${trace.principal.roles.join(', ') || '-'}`\n + (trace.principal.trust_level ? ` 信任级别: ${trace.principal.trust_level}` : ''));\n }\n lines.push(`${indent} 开始: ${new Date(trace.started_at).toLocaleString()} 耗时: ${formatDuration(trace.duration_ms)}`);\n if (termination.code || termination.reason) {\n lines.push(`${indent} 结束原因: ${[termination.code, termination.reason].filter(Boolean).join(' — ')}`);\n }\n if (failingTool) {\n lines.push(`${indent} 首个失败步骤: ${failingTool.tool_name} ${failingTool.status}${failingTool.error ? ` — ${failingTool.error}` : ''}`);\n }\n\n lines.push(`${indent} 模型调用 ${trace.model_calls.length} 次,tokens 输入 ${trace.usage.prompt_tokens} / 输出 ${trace.usage.completion_tokens} / 合计 ${trace.usage.total_tokens}`);\n const cached = trace.model_calls.reduce((sum, call) => sum + (call.cache_read_tokens ?? 0), 0);\n if (cached > 0 && trace.usage.prompt_tokens > 0) {\n lines.push(`${indent} 提示缓存命中 ${cached} tokens(占输入 ${Math.round((cached / trace.usage.prompt_tokens) * 100)}%)`);\n }\n for (const call of trace.model_calls) {\n const cache = call.cache_read_tokens ? ` cache=${call.cache_read_tokens}` : '';\n const reasoning = call.reasoning_tokens ? ` reasoning=${call.reasoning_tokens}` : '';\n const cacheWrite = call.cache_write_tokens !== undefined ? ` cache_write=${call.cache_write_tokens}` : '';\n const model = call.model ? ` model=${call.provider ?? '?'}/${call.model}` : '';\n lines.push(`${indent} #${call.index} in=${call.prompt_tokens} out=${call.completion_tokens}${cache}${reasoning}${cacheWrite}${model}`);\n }\n\n if (trace.context_budget) lines.push(...renderContextBudget(trace.context_budget, indent));\n\n lines.push(`${indent} 工具调用 ${trace.tool_calls.length} 次`);\n for (const tool of trace.tool_calls) {\n const details = [\n tool.duration_ms !== undefined ? `${tool.duration_ms}ms` : undefined,\n tool.result_size !== undefined ? `${tool.result_size} 字符` : undefined,\n tool.policy ? `策略 ${tool.policy}` : undefined,\n ].filter(Boolean).join(', ');\n lines.push(`${indent} ${TOOL_MARK[tool.status]} ${tool.tool_name}${details ? ` (${details})` : ''} ${tool.args_summary}`.trimEnd());\n if (tool.error) lines.push(`${indent} ${tool.error}`);\n }\n\n if (trace.budget.extensions.length > 0 || trace.budget.continuations > 0) {\n const extensions = trace.budget.extensions.map(item => `${item.from}→${item.to}`).join(', ');\n lines.push(`${indent} 预算: 延长 ${trace.budget.extensions.length} 次${extensions ? ` (${extensions})` : ''},自动续跑 ${trace.budget.continuations} 次`);\n }\n\n for (const task of trace.subagent_tasks) {\n lines.push(`${indent} 子任务 ${task.task_id} [${task.status}] ${task.description}`);\n }\n for (const child of trace.subagents) {\n lines.push(`${indent} 子 agent:`);\n lines.push(...renderTrace(child, `${indent} `, false));\n }\n\n if (withTimeline && trace.timeline.length > 0) {\n lines.push(`${indent} 时间线:`);\n for (const entry of trace.timeline) {\n lines.push(`${indent} +${formatDuration(entry.at_ms).padStart(7)} ${entry.kind.padEnd(14)} ${entry.detail}`.trimEnd());\n }\n }\n if (trace.dropped > 0) lines.push(`${indent} (有 ${trace.dropped} 条记录因超出上限被省略)`);\n return lines;\n}\n\nconst SEGMENT_LABEL: Record<ContextBudgetSegment, string> = {\n system: '系统提示',\n tool_schemas: '工具 schema',\n output_schema: '输出 schema',\n tool_index: '按需工具索引',\n skill_catalog: '技能目录',\n agent_catalog: '专家 agent 目录',\n active_skills: '已加载技能',\n memory: '记忆',\n bootstrap: 'bootstrap',\n history: '历史消息',\n user: '本轮输入',\n};\n\nconst TOP_SECTIONS = 5;\n\n/** Estimated prompt cost of the first model request, by segment. */\nfunction renderContextBudget(budget: ContextBudgetReport, indent: string): string[] {\n const parts = CONTEXT_BUDGET_SEGMENTS\n .filter(segment => budget.segments[segment] > 0)\n .map(segment => `${SEGMENT_LABEL[segment]} ${budget.segments[segment]}`);\n const lines = [\n `${indent} 上下文估算 ~${budget.total_tokens} tokens(固定开销 ~${budget.fixed_tokens};工具 ${budget.tools.loaded} 个常驻 / ${budget.tools.deferred} 个按需)`,\n ];\n if (parts.length > 0) lines.push(`${indent} ${parts.join(' · ')}`);\n const top = budget.sections.slice(0, TOP_SECTIONS).filter(section => section.tokens > 0);\n if (top.length > 0) lines.push(`${indent} 最大的提示段: ${top.map(section => `${section.id} ${section.tokens}`).join(', ')}`);\n return lines;\n}\n\nfunction formatDuration(ms: number | undefined): string {\n if (ms === undefined) return '-';\n if (ms < 1000) return `${Math.round(ms)}ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;\n return `${Math.floor(ms / 60_000)}m${Math.round((ms % 60_000) / 1000)}s`;\n}\n"]}
|
|
@@ -20,6 +20,12 @@ export interface TurnTracePrincipal {
|
|
|
20
20
|
readonly trust_level?: string;
|
|
21
21
|
}
|
|
22
22
|
export interface TurnTraceModelCall {
|
|
23
|
+
readonly provider?: string;
|
|
24
|
+
readonly model?: string;
|
|
25
|
+
readonly duration_ms?: number;
|
|
26
|
+
readonly stop_reason?: string;
|
|
27
|
+
readonly cache_write_tokens?: number;
|
|
28
|
+
readonly reported?: import('@zhin.js/ai').TokenUsage['reported'];
|
|
23
29
|
readonly index: number;
|
|
24
30
|
readonly prompt_tokens: number;
|
|
25
31
|
readonly completion_tokens: number;
|
package/lib/trace/turn-trace.js
CHANGED
|
@@ -98,11 +98,17 @@ export class TurnTraceCollector {
|
|
|
98
98
|
case 'usage': {
|
|
99
99
|
const call = Object.freeze({
|
|
100
100
|
index: this.#modelCalls.length + 1,
|
|
101
|
+
...(event.provider !== undefined ? { provider: event.provider } : {}),
|
|
102
|
+
...(event.model !== undefined ? { model: event.model } : {}),
|
|
103
|
+
...(event.durationMs !== undefined ? { duration_ms: event.durationMs } : {}),
|
|
104
|
+
...(event.stopReason !== undefined ? { stop_reason: event.stopReason } : {}),
|
|
105
|
+
...(event.usage.reported ? { reported: Object.freeze({ ...event.usage.reported }) } : {}),
|
|
106
|
+
...(event.usage.cacheWriteTokens !== undefined ? { cache_write_tokens: event.usage.cacheWriteTokens } : {}),
|
|
101
107
|
prompt_tokens: event.usage.promptTokens,
|
|
102
108
|
completion_tokens: event.usage.completionTokens,
|
|
103
109
|
total_tokens: event.usage.totalTokens,
|
|
104
|
-
...(event.usage.cacheReadTokens ? { cache_read_tokens: event.usage.cacheReadTokens } : {}),
|
|
105
|
-
...(event.usage.reasoningTokens ? { reasoning_tokens: event.usage.reasoningTokens } : {}),
|
|
110
|
+
...(event.usage.cacheReadTokens !== undefined ? { cache_read_tokens: event.usage.cacheReadTokens } : {}),
|
|
111
|
+
...(event.usage.reasoningTokens !== undefined ? { reasoning_tokens: event.usage.reasoningTokens } : {}),
|
|
106
112
|
});
|
|
107
113
|
this.#modelCalls.push(call);
|
|
108
114
|
this.#addTimeline('model_call', `#${call.index} in=${call.prompt_tokens} out=${call.completion_tokens}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-trace.js","sourceRoot":"","sources":["../../src/trace/turn-trace.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TurnTrace — one readable, redacted record of what happened in a single\n * Agent turn: who asked, every model call and its tokens, every tool call\n * with an argument summary, duration and result size, approval denials,\n * budget extensions, nested sub-agent turns and how the turn ended.\n *\n * The collector only folds TurnEvents (plus a few trace notes), so it never\n * influences execution. Persisted JSON uses snake_case keys.\n */\nimport type { TurnEvent } from '../event/turn-event.js';\nimport { redactTraceValue } from '../plugin-runtime/agent-trace-runtime.js';\nimport type { ContextBudgetReport } from './context-budget.js';\n\nexport const TURN_TRACE_VERSION = 1;\n\nconst MAX_TOOL_CALLS = 200;\nconst MAX_TIMELINE_ENTRIES = 300;\nconst MAX_SUBAGENTS = 20;\nconst ARGS_SUMMARY_LENGTH = 200;\nconst TEXT_SUMMARY_LENGTH = 300;\n\nexport type TurnTraceStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'budget_exceeded' | 'unknown';\nexport type TurnTraceToolStatus = 'running' | 'ok' | 'failed' | 'denied' | 'cancelled';\n\nexport interface TurnTracePrincipal {\n readonly subject_id: string;\n readonly display_name?: string;\n readonly roles: readonly string[];\n /** Initiator trust level (#726); every tool call in this trace ran under it. */\n readonly trust_level?: string;\n}\n\nexport interface TurnTraceModelCall {\n readonly index: number;\n readonly prompt_tokens: number;\n readonly completion_tokens: number;\n readonly total_tokens: number;\n /** Prompt tokens served from the provider cache (#730). */\n readonly cache_read_tokens?: number;\n /** Completion tokens spent on reasoning (e.g. Gemini thoughtsTokenCount). */\n readonly reasoning_tokens?: number;\n}\n\nexport interface TurnTraceToolCall {\n readonly tool_use_id: string;\n readonly tool_name: string;\n readonly args_summary: string;\n readonly status: TurnTraceToolStatus;\n /** Milliseconds since the turn started. */\n readonly started_at_ms: number;\n readonly duration_ms?: number;\n /** Size of the tool output in characters (output itself is never stored). */\n readonly result_size?: number;\n readonly error?: string;\n /** Policy that denied the call, for `denied`. */\n readonly policy?: string;\n}\n\nexport interface TurnTraceBudgetExtension {\n readonly from: number;\n readonly to: number;\n readonly at_ms: number;\n}\n\nexport interface TurnTraceSubagentTask {\n readonly task_id: string;\n readonly agent_name?: string;\n readonly description: string;\n readonly status: 'running' | 'ok' | 'error';\n readonly result_summary?: string;\n}\n\nexport interface TurnTraceTimelineEntry {\n readonly at_ms: number;\n readonly kind: string;\n readonly detail: string;\n}\n\nexport interface TurnTraceTermination {\n readonly status: TurnTraceStatus;\n readonly code?: string;\n readonly reason?: string;\n}\n\nexport interface TurnTrace {\n readonly version: typeof TURN_TRACE_VERSION;\n readonly turn_id: string;\n readonly session_key: string;\n readonly principal?: TurnTracePrincipal;\n /** Epoch milliseconds. */\n readonly started_at: number;\n readonly ended_at?: number;\n readonly duration_ms?: number;\n readonly model_calls: readonly TurnTraceModelCall[];\n readonly usage: Readonly<{ prompt_tokens: number; completion_tokens: number; total_tokens: number }>;\n /** Estimated prompt cost by segment for the turn's first model request (#729). */\n readonly context_budget?: ContextBudgetReport;\n readonly tool_calls: readonly TurnTraceToolCall[];\n readonly budget: Readonly<{ extensions: readonly TurnTraceBudgetExtension[]; continuations: number }>;\n readonly subagent_tasks: readonly TurnTraceSubagentTask[];\n /** Nested sub-agent turns (`<parent>:subagent:<n>`). */\n readonly subagents: readonly TurnTrace[];\n readonly timeline: readonly TurnTraceTimelineEntry[];\n readonly termination: TurnTraceTermination;\n /** Entries dropped because a bounded list was full. */\n readonly dropped: number;\n}\n\n/** Facts that are not TurnEvents but belong in the trace. */\nexport type TurnTraceNote =\n | Readonly<{ kind: 'budget_extended'; from: number; to: number }>\n | Readonly<{ kind: 'continuation'; index: number }>\n | Readonly<{ kind: 'context_budget'; report: ContextBudgetReport }>\n /** How the turn was admitted behind other turns of its session (#725). */\n | Readonly<{ kind: 'admission'; queued_ms: number; merged_messages: number; superseded_previous: boolean }>;\n\nexport interface TurnTraceInit {\n readonly turnId: string;\n readonly sessionKey: string;\n readonly principal?: Readonly<{\n subjectId: string;\n displayName?: string;\n roles: readonly string[];\n trustLevel?: string;\n }>;\n}\n\ninterface MutableToolCall {\n tool_use_id: string;\n tool_name: string;\n args_summary: string;\n status: TurnTraceToolStatus;\n started_at_ms: number;\n duration_ms?: number;\n result_size?: number;\n error?: string;\n policy?: string;\n}\n\n/** Folds the events of one turn (and its sub-agent turns) into a TurnTrace. */\nexport class TurnTraceCollector {\n readonly turnId: string;\n readonly sessionKey: string;\n readonly #principal?: TurnTracePrincipal;\n readonly #now: () => number;\n readonly #startedAt: number;\n #endedAt: number | undefined;\n #termination: TurnTraceTermination = { status: 'running' };\n readonly #modelCalls: TurnTraceModelCall[] = [];\n readonly #toolCalls = new Map<string, MutableToolCall>();\n readonly #extensions: TurnTraceBudgetExtension[] = [];\n #continuations = 0;\n #contextBudget: ContextBudgetReport | undefined;\n readonly #subagentTasks = new Map<string, TurnTraceSubagentTask>();\n readonly #children = new Map<string, TurnTraceCollector>();\n readonly #timeline: TurnTraceTimelineEntry[] = [];\n #dropped = 0;\n\n constructor(init: TurnTraceInit, now: () => number = Date.now) {\n this.turnId = init.turnId;\n this.sessionKey = init.sessionKey;\n this.#now = now;\n this.#startedAt = now();\n if (init.principal) {\n this.#principal = Object.freeze({\n subject_id: init.principal.subjectId,\n ...(init.principal.displayName ? { display_name: init.principal.displayName } : {}),\n roles: Object.freeze([...init.principal.roles]),\n ...(init.principal.trustLevel ? { trust_level: init.principal.trustLevel } : {}),\n });\n }\n }\n\n get finished(): boolean {\n return this.#endedAt !== undefined;\n }\n\n /** Nested collector for a sub-agent turn; created on first use. */\n child(turnId: string, sessionKey = `${this.sessionKey}#subagent`): TurnTraceCollector {\n const existing = this.#children.get(turnId);\n if (existing) return existing;\n const created = new TurnTraceCollector({ turnId, sessionKey, principal: this.#principalInit() }, this.#now);\n if (this.#children.size >= MAX_SUBAGENTS) {\n this.#dropped += 1;\n return created;\n }\n this.#children.set(turnId, created);\n this.#addTimeline('subagent_turn', turnId);\n return created;\n }\n\n /** Finds this collector or a nested one by turn id. */\n find(turnId: string): TurnTraceCollector | undefined {\n if (turnId === this.turnId) return this;\n for (const child of this.#children.values()) {\n const found = child.find(turnId);\n if (found) return found;\n }\n return undefined;\n }\n\n note(note: TurnTraceNote): void {\n const at = this.#elapsed();\n if (note.kind === 'budget_extended') {\n this.#extensions.push(Object.freeze({ from: note.from, to: note.to, at_ms: at }));\n this.#addTimeline('budget_extended', `${note.from} → ${note.to} steps`);\n } else if (note.kind === 'context_budget') {\n // Keep the first request's report: it is the fixed cost of the turn.\n if (this.#contextBudget) return;\n this.#contextBudget = note.report;\n this.#addTimeline('context_budget', `~${note.report.total_tokens} tokens (fixed ~${note.report.fixed_tokens})`);\n } else if (note.kind === 'continuation') {\n this.#continuations = Math.max(this.#continuations, note.index);\n this.#addTimeline('continuation', `#${note.index}`);\n } else {\n this.#addTimeline('admission', describeAdmission(note));\n }\n }\n\n record(event: TurnEvent): void {\n switch (event.type) {\n case 'turn_start':\n case 'chunk':\n case 'thinking':\n return;\n case 'iteration_start':\n this.#addTimeline('iteration', `${event.iteration}/${event.maxIterations}`);\n return;\n case 'usage': {\n const call = Object.freeze({\n index: this.#modelCalls.length + 1,\n prompt_tokens: event.usage.promptTokens,\n completion_tokens: event.usage.completionTokens,\n total_tokens: event.usage.totalTokens,\n ...(event.usage.cacheReadTokens ? { cache_read_tokens: event.usage.cacheReadTokens } : {}),\n ...(event.usage.reasoningTokens ? { reasoning_tokens: event.usage.reasoningTokens } : {}),\n });\n this.#modelCalls.push(call);\n this.#addTimeline('model_call', `#${call.index} in=${call.prompt_tokens} out=${call.completion_tokens}`);\n return;\n }\n case 'tool_call':\n this.#startTool(event.toolUseId, event.toolName, summarizeArgs(event.args));\n this.#addTimeline('tool_call', `${event.toolName} ${summarizeArgs(event.args)}`);\n return;\n case 'tool_result': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'ok';\n tool.duration_ms = Math.round(event.durationMs);\n tool.result_size = outputSize(event.output);\n this.#addTimeline('tool_result', `${event.toolName} ok ${tool.duration_ms}ms ${tool.result_size} chars`);\n return;\n }\n case 'tool_failed': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'failed';\n tool.duration_ms = Math.round(event.durationMs);\n tool.error = summarizeText(event.error);\n this.#addTimeline('tool_failed', `${event.toolName}: ${tool.error}`);\n return;\n }\n case 'tool_denied': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'denied';\n tool.policy = event.policy;\n tool.error = summarizeText(event.reason);\n this.#addTimeline('tool_denied', `${event.toolName} (${event.policy}): ${tool.error}`);\n return;\n }\n case 'tool_cancelled': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'cancelled';\n tool.duration_ms = Math.round(event.durationMs);\n tool.error = summarizeText(event.reason);\n this.#addTimeline('tool_cancelled', `${event.toolName}: ${tool.error}`);\n return;\n }\n case 'subagent_start':\n this.#subagentTasks.set(event.taskId, Object.freeze({\n task_id: event.taskId,\n ...(event.agentName ? { agent_name: event.agentName } : {}),\n description: summarizeText(event.description),\n status: 'running',\n }));\n this.#addTimeline('subagent_start', `${event.taskId} ${summarizeText(event.description, 80)}`);\n return;\n case 'subagent_progress':\n this.#addTimeline('subagent_progress', `${event.taskId} ${summarizeText(event.summary, 80)}`);\n return;\n case 'subagent_end': {\n const task = this.#subagentTasks.get(event.taskId);\n this.#subagentTasks.set(event.taskId, Object.freeze({\n task_id: event.taskId,\n ...(task?.agent_name ? { agent_name: task.agent_name } : {}),\n description: task?.description ?? '',\n status: event.status,\n ...(event.result ? { result_summary: summarizeText(event.result) } : {}),\n }));\n this.#addTimeline('subagent_end', `${event.taskId} ${event.status}`);\n return;\n }\n case 'turn_end':\n this.#finish({ status: 'completed' });\n return;\n case 'error':\n this.#finish({\n status: 'failed',\n ...(event.code ? { code: event.code } : {}),\n reason: summarizeText(event.error?.message ?? String(event.error)),\n });\n return;\n case 'turn_cancelled':\n this.#finish({ status: 'cancelled', code: event.code, reason: summarizeText(event.reason) });\n return;\n case 'budget_exceeded':\n this.#finish({ status: 'budget_exceeded', code: event.budget });\n return;\n default:\n this.#addTimeline(event.type, summarizeText(JSON.stringify(redactTraceValue(withoutType(event))), 120));\n }\n }\n\n /** Closes the trace when the turn ended without a terminal event. */\n finalize(fallback: TurnTraceTermination = { status: 'unknown' }): void {\n for (const child of this.#children.values()) child.finalize();\n if (this.finished) return;\n this.#finish(fallback);\n }\n\n snapshot(): TurnTrace {\n const usage = this.#modelCalls.reduce(\n (total, call) => ({\n prompt_tokens: total.prompt_tokens + call.prompt_tokens,\n completion_tokens: total.completion_tokens + call.completion_tokens,\n total_tokens: total.total_tokens + call.total_tokens,\n }),\n { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n );\n return Object.freeze({\n version: TURN_TRACE_VERSION,\n turn_id: this.turnId,\n session_key: this.sessionKey,\n ...(this.#principal ? { principal: this.#principal } : {}),\n started_at: this.#startedAt,\n ...(this.#endedAt !== undefined\n ? { ended_at: this.#endedAt, duration_ms: this.#endedAt - this.#startedAt }\n : {}),\n model_calls: Object.freeze([...this.#modelCalls]),\n usage: Object.freeze(usage),\n ...(this.#contextBudget ? { context_budget: this.#contextBudget } : {}),\n tool_calls: Object.freeze([...this.#toolCalls.values()].map(tool => Object.freeze({ ...tool }))),\n budget: Object.freeze({\n extensions: Object.freeze([...this.#extensions]),\n continuations: this.#continuations,\n }),\n subagent_tasks: Object.freeze([...this.#subagentTasks.values()]),\n subagents: Object.freeze([...this.#children.values()].map(child => child.snapshot())),\n timeline: Object.freeze([...this.#timeline]),\n termination: Object.freeze({ ...this.#termination }),\n dropped: this.#dropped,\n });\n }\n\n #startTool(toolUseId: string, toolName: string, argsSummary: string): MutableToolCall | undefined {\n if (this.#toolCalls.size >= MAX_TOOL_CALLS && !this.#toolCalls.has(toolUseId)) {\n this.#dropped += 1;\n return undefined;\n }\n const existing = this.#toolCalls.get(toolUseId);\n if (existing) return existing;\n const created: MutableToolCall = {\n tool_use_id: toolUseId,\n tool_name: toolName,\n args_summary: argsSummary,\n status: 'running',\n started_at_ms: this.#elapsed(),\n };\n this.#toolCalls.set(toolUseId, created);\n return created;\n }\n\n /** Result/denial events may arrive without a prior tool_call (e.g. pre-call denial). */\n #tool(toolUseId: string, toolName: string): MutableToolCall | undefined {\n return this.#toolCalls.get(toolUseId) ?? this.#startTool(toolUseId, toolName, '');\n }\n\n #finish(termination: TurnTraceTermination): void {\n if (this.finished) return;\n this.#termination = Object.freeze(termination);\n this.#endedAt = this.#now();\n for (const tool of this.#toolCalls.values()) {\n if (tool.status === 'running') tool.status = 'cancelled';\n }\n this.#addTimeline('end', [termination.status, termination.code, termination.reason].filter(Boolean).join(' '));\n }\n\n #addTimeline(kind: string, detail: string): void {\n if (this.#timeline.length >= MAX_TIMELINE_ENTRIES) {\n this.#dropped += 1;\n return;\n }\n this.#timeline.push(Object.freeze({ at_ms: this.#elapsed(), kind, detail }));\n }\n\n #elapsed(): number {\n return Math.max(0, this.#now() - this.#startedAt);\n }\n\n #principalInit(): TurnTraceInit['principal'] {\n if (!this.#principal) return undefined;\n return {\n subjectId: this.#principal.subject_id,\n ...(this.#principal.display_name ? { displayName: this.#principal.display_name } : {}),\n roles: this.#principal.roles,\n ...(this.#principal.trust_level ? { trustLevel: this.#principal.trust_level } : {}),\n };\n }\n}\n\n/** Redacted, single-line, length-bounded summary of tool arguments. */\nfunction describeAdmission(note: Extract<TurnTraceNote, { kind: 'admission' }>): string {\n const parts = [`queued ${Math.round(note.queued_ms)}ms`];\n if (note.merged_messages > 1) parts.push(`merged ${note.merged_messages} messages`);\n if (note.superseded_previous) parts.push('replaced the sender\\'s unanswered turn');\n return parts.join(', ');\n}\n\nexport function summarizeArgs(args: unknown): string {\n if (args == null) return '';\n const redacted = redactTraceValue(args);\n const text = typeof redacted === 'string' ? redacted : JSON.stringify(redacted);\n return clip(scrubSecrets(text ?? ''), ARGS_SUMMARY_LENGTH);\n}\n\nfunction summarizeText(value: unknown, max = TEXT_SUMMARY_LENGTH): string {\n const redacted = redactTraceValue(value);\n const text = typeof redacted === 'string' ? redacted : JSON.stringify(redacted) ?? '';\n return clip(scrubSecrets(text.replace(/\\s+/g, ' ').trim()), max);\n}\n\nconst INLINE_SECRET_RULES: ReadonlyArray<readonly [RegExp, string]> = [\n [/\\b(bearer|basic)\\s+[A-Za-z0-9._~+/=-]{8,}/gi, '$1 [redacted]'],\n [/\\b(?:sk|pk|rk)-[A-Za-z0-9_-]{12,}/g, '[redacted]'],\n [/\\b(?:ghp|gho|ghs|github_pat|xox[abpr])[_-][A-Za-z0-9_-]{12,}/g, '[redacted]'],\n [/(\"?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret)\"?\\s*[:=]\\s*\"?)[^\"\\s,}]+/gi, '$1[redacted]'],\n];\n\n/** Masks credentials that appear inline in free text (error messages, string args). */\nexport function scrubSecrets(text: string): string {\n return INLINE_SECRET_RULES.reduce((current, [pattern, replacement]) => current.replace(pattern, replacement), text);\n}\n\nfunction outputSize(output: unknown): number {\n if (output == null) return 0;\n if (typeof output === 'string') return output.length;\n try {\n return JSON.stringify(output)?.length ?? 0;\n } catch {\n return 0;\n }\n}\n\nfunction clip(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\nfunction withoutType(event: TurnEvent): Record<string, unknown> {\n const { type: _type, ...rest } = event as unknown as Record<string, unknown>;\n return rest;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"turn-trace.js","sourceRoot":"","sources":["../../src/trace/turn-trace.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TurnTrace — one readable, redacted record of what happened in a single\n * Agent turn: who asked, every model call and its tokens, every tool call\n * with an argument summary, duration and result size, approval denials,\n * budget extensions, nested sub-agent turns and how the turn ended.\n *\n * The collector only folds TurnEvents (plus a few trace notes), so it never\n * influences execution. Persisted JSON uses snake_case keys.\n */\nimport type { TurnEvent } from '../event/turn-event.js';\nimport { redactTraceValue } from '../plugin-runtime/agent-trace-runtime.js';\nimport type { ContextBudgetReport } from './context-budget.js';\n\nexport const TURN_TRACE_VERSION = 1;\n\nconst MAX_TOOL_CALLS = 200;\nconst MAX_TIMELINE_ENTRIES = 300;\nconst MAX_SUBAGENTS = 20;\nconst ARGS_SUMMARY_LENGTH = 200;\nconst TEXT_SUMMARY_LENGTH = 300;\n\nexport type TurnTraceStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'budget_exceeded' | 'unknown';\nexport type TurnTraceToolStatus = 'running' | 'ok' | 'failed' | 'denied' | 'cancelled';\n\nexport interface TurnTracePrincipal {\n readonly subject_id: string;\n readonly display_name?: string;\n readonly roles: readonly string[];\n /** Initiator trust level (#726); every tool call in this trace ran under it. */\n readonly trust_level?: string;\n}\n\nexport interface TurnTraceModelCall {\n readonly provider?: string;\n readonly model?: string;\n readonly duration_ms?: number;\n readonly stop_reason?: string;\n readonly cache_write_tokens?: number;\n readonly reported?: import('@zhin.js/ai').TokenUsage['reported'];\n readonly index: number;\n readonly prompt_tokens: number;\n readonly completion_tokens: number;\n readonly total_tokens: number;\n /** Prompt tokens served from the provider cache (#730). */\n readonly cache_read_tokens?: number;\n /** Completion tokens spent on reasoning (e.g. Gemini thoughtsTokenCount). */\n readonly reasoning_tokens?: number;\n}\n\nexport interface TurnTraceToolCall {\n readonly tool_use_id: string;\n readonly tool_name: string;\n readonly args_summary: string;\n readonly status: TurnTraceToolStatus;\n /** Milliseconds since the turn started. */\n readonly started_at_ms: number;\n readonly duration_ms?: number;\n /** Size of the tool output in characters (output itself is never stored). */\n readonly result_size?: number;\n readonly error?: string;\n /** Policy that denied the call, for `denied`. */\n readonly policy?: string;\n}\n\nexport interface TurnTraceBudgetExtension {\n readonly from: number;\n readonly to: number;\n readonly at_ms: number;\n}\n\nexport interface TurnTraceSubagentTask {\n readonly task_id: string;\n readonly agent_name?: string;\n readonly description: string;\n readonly status: 'running' | 'ok' | 'error';\n readonly result_summary?: string;\n}\n\nexport interface TurnTraceTimelineEntry {\n readonly at_ms: number;\n readonly kind: string;\n readonly detail: string;\n}\n\nexport interface TurnTraceTermination {\n readonly status: TurnTraceStatus;\n readonly code?: string;\n readonly reason?: string;\n}\n\nexport interface TurnTrace {\n readonly version: typeof TURN_TRACE_VERSION;\n readonly turn_id: string;\n readonly session_key: string;\n readonly principal?: TurnTracePrincipal;\n /** Epoch milliseconds. */\n readonly started_at: number;\n readonly ended_at?: number;\n readonly duration_ms?: number;\n readonly model_calls: readonly TurnTraceModelCall[];\n readonly usage: Readonly<{ prompt_tokens: number; completion_tokens: number; total_tokens: number }>;\n /** Estimated prompt cost by segment for the turn's first model request (#729). */\n readonly context_budget?: ContextBudgetReport;\n readonly tool_calls: readonly TurnTraceToolCall[];\n readonly budget: Readonly<{ extensions: readonly TurnTraceBudgetExtension[]; continuations: number }>;\n readonly subagent_tasks: readonly TurnTraceSubagentTask[];\n /** Nested sub-agent turns (`<parent>:subagent:<n>`). */\n readonly subagents: readonly TurnTrace[];\n readonly timeline: readonly TurnTraceTimelineEntry[];\n readonly termination: TurnTraceTermination;\n /** Entries dropped because a bounded list was full. */\n readonly dropped: number;\n}\n\n/** Facts that are not TurnEvents but belong in the trace. */\nexport type TurnTraceNote =\n | Readonly<{ kind: 'budget_extended'; from: number; to: number }>\n | Readonly<{ kind: 'continuation'; index: number }>\n | Readonly<{ kind: 'context_budget'; report: ContextBudgetReport }>\n /** How the turn was admitted behind other turns of its session (#725). */\n | Readonly<{ kind: 'admission'; queued_ms: number; merged_messages: number; superseded_previous: boolean }>;\n\nexport interface TurnTraceInit {\n readonly turnId: string;\n readonly sessionKey: string;\n readonly principal?: Readonly<{\n subjectId: string;\n displayName?: string;\n roles: readonly string[];\n trustLevel?: string;\n }>;\n}\n\ninterface MutableToolCall {\n tool_use_id: string;\n tool_name: string;\n args_summary: string;\n status: TurnTraceToolStatus;\n started_at_ms: number;\n duration_ms?: number;\n result_size?: number;\n error?: string;\n policy?: string;\n}\n\n/** Folds the events of one turn (and its sub-agent turns) into a TurnTrace. */\nexport class TurnTraceCollector {\n readonly turnId: string;\n readonly sessionKey: string;\n readonly #principal?: TurnTracePrincipal;\n readonly #now: () => number;\n readonly #startedAt: number;\n #endedAt: number | undefined;\n #termination: TurnTraceTermination = { status: 'running' };\n readonly #modelCalls: TurnTraceModelCall[] = [];\n readonly #toolCalls = new Map<string, MutableToolCall>();\n readonly #extensions: TurnTraceBudgetExtension[] = [];\n #continuations = 0;\n #contextBudget: ContextBudgetReport | undefined;\n readonly #subagentTasks = new Map<string, TurnTraceSubagentTask>();\n readonly #children = new Map<string, TurnTraceCollector>();\n readonly #timeline: TurnTraceTimelineEntry[] = [];\n #dropped = 0;\n\n constructor(init: TurnTraceInit, now: () => number = Date.now) {\n this.turnId = init.turnId;\n this.sessionKey = init.sessionKey;\n this.#now = now;\n this.#startedAt = now();\n if (init.principal) {\n this.#principal = Object.freeze({\n subject_id: init.principal.subjectId,\n ...(init.principal.displayName ? { display_name: init.principal.displayName } : {}),\n roles: Object.freeze([...init.principal.roles]),\n ...(init.principal.trustLevel ? { trust_level: init.principal.trustLevel } : {}),\n });\n }\n }\n\n get finished(): boolean {\n return this.#endedAt !== undefined;\n }\n\n /** Nested collector for a sub-agent turn; created on first use. */\n child(turnId: string, sessionKey = `${this.sessionKey}#subagent`): TurnTraceCollector {\n const existing = this.#children.get(turnId);\n if (existing) return existing;\n const created = new TurnTraceCollector({ turnId, sessionKey, principal: this.#principalInit() }, this.#now);\n if (this.#children.size >= MAX_SUBAGENTS) {\n this.#dropped += 1;\n return created;\n }\n this.#children.set(turnId, created);\n this.#addTimeline('subagent_turn', turnId);\n return created;\n }\n\n /** Finds this collector or a nested one by turn id. */\n find(turnId: string): TurnTraceCollector | undefined {\n if (turnId === this.turnId) return this;\n for (const child of this.#children.values()) {\n const found = child.find(turnId);\n if (found) return found;\n }\n return undefined;\n }\n\n note(note: TurnTraceNote): void {\n const at = this.#elapsed();\n if (note.kind === 'budget_extended') {\n this.#extensions.push(Object.freeze({ from: note.from, to: note.to, at_ms: at }));\n this.#addTimeline('budget_extended', `${note.from} → ${note.to} steps`);\n } else if (note.kind === 'context_budget') {\n // Keep the first request's report: it is the fixed cost of the turn.\n if (this.#contextBudget) return;\n this.#contextBudget = note.report;\n this.#addTimeline('context_budget', `~${note.report.total_tokens} tokens (fixed ~${note.report.fixed_tokens})`);\n } else if (note.kind === 'continuation') {\n this.#continuations = Math.max(this.#continuations, note.index);\n this.#addTimeline('continuation', `#${note.index}`);\n } else {\n this.#addTimeline('admission', describeAdmission(note));\n }\n }\n\n record(event: TurnEvent): void {\n switch (event.type) {\n case 'turn_start':\n case 'chunk':\n case 'thinking':\n return;\n case 'iteration_start':\n this.#addTimeline('iteration', `${event.iteration}/${event.maxIterations}`);\n return;\n case 'usage': {\n const call = Object.freeze({\n index: this.#modelCalls.length + 1,\n ...(event.provider !== undefined ? { provider: event.provider } : {}),\n ...(event.model !== undefined ? { model: event.model } : {}),\n ...(event.durationMs !== undefined ? { duration_ms: event.durationMs } : {}),\n ...(event.stopReason !== undefined ? { stop_reason: event.stopReason } : {}),\n ...(event.usage.reported ? { reported: Object.freeze({ ...event.usage.reported }) } : {}),\n ...(event.usage.cacheWriteTokens !== undefined ? { cache_write_tokens: event.usage.cacheWriteTokens } : {}),\n prompt_tokens: event.usage.promptTokens,\n completion_tokens: event.usage.completionTokens,\n total_tokens: event.usage.totalTokens,\n ...(event.usage.cacheReadTokens !== undefined ? { cache_read_tokens: event.usage.cacheReadTokens } : {}),\n ...(event.usage.reasoningTokens !== undefined ? { reasoning_tokens: event.usage.reasoningTokens } : {}),\n });\n this.#modelCalls.push(call);\n this.#addTimeline('model_call', `#${call.index} in=${call.prompt_tokens} out=${call.completion_tokens}`);\n return;\n }\n case 'tool_call':\n this.#startTool(event.toolUseId, event.toolName, summarizeArgs(event.args));\n this.#addTimeline('tool_call', `${event.toolName} ${summarizeArgs(event.args)}`);\n return;\n case 'tool_result': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'ok';\n tool.duration_ms = Math.round(event.durationMs);\n tool.result_size = outputSize(event.output);\n this.#addTimeline('tool_result', `${event.toolName} ok ${tool.duration_ms}ms ${tool.result_size} chars`);\n return;\n }\n case 'tool_failed': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'failed';\n tool.duration_ms = Math.round(event.durationMs);\n tool.error = summarizeText(event.error);\n this.#addTimeline('tool_failed', `${event.toolName}: ${tool.error}`);\n return;\n }\n case 'tool_denied': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'denied';\n tool.policy = event.policy;\n tool.error = summarizeText(event.reason);\n this.#addTimeline('tool_denied', `${event.toolName} (${event.policy}): ${tool.error}`);\n return;\n }\n case 'tool_cancelled': {\n const tool = this.#tool(event.toolUseId, event.toolName);\n if (!tool) return;\n tool.status = 'cancelled';\n tool.duration_ms = Math.round(event.durationMs);\n tool.error = summarizeText(event.reason);\n this.#addTimeline('tool_cancelled', `${event.toolName}: ${tool.error}`);\n return;\n }\n case 'subagent_start':\n this.#subagentTasks.set(event.taskId, Object.freeze({\n task_id: event.taskId,\n ...(event.agentName ? { agent_name: event.agentName } : {}),\n description: summarizeText(event.description),\n status: 'running',\n }));\n this.#addTimeline('subagent_start', `${event.taskId} ${summarizeText(event.description, 80)}`);\n return;\n case 'subagent_progress':\n this.#addTimeline('subagent_progress', `${event.taskId} ${summarizeText(event.summary, 80)}`);\n return;\n case 'subagent_end': {\n const task = this.#subagentTasks.get(event.taskId);\n this.#subagentTasks.set(event.taskId, Object.freeze({\n task_id: event.taskId,\n ...(task?.agent_name ? { agent_name: task.agent_name } : {}),\n description: task?.description ?? '',\n status: event.status,\n ...(event.result ? { result_summary: summarizeText(event.result) } : {}),\n }));\n this.#addTimeline('subagent_end', `${event.taskId} ${event.status}`);\n return;\n }\n case 'turn_end':\n this.#finish({ status: 'completed' });\n return;\n case 'error':\n this.#finish({\n status: 'failed',\n ...(event.code ? { code: event.code } : {}),\n reason: summarizeText(event.error?.message ?? String(event.error)),\n });\n return;\n case 'turn_cancelled':\n this.#finish({ status: 'cancelled', code: event.code, reason: summarizeText(event.reason) });\n return;\n case 'budget_exceeded':\n this.#finish({ status: 'budget_exceeded', code: event.budget });\n return;\n default:\n this.#addTimeline(event.type, summarizeText(JSON.stringify(redactTraceValue(withoutType(event))), 120));\n }\n }\n\n /** Closes the trace when the turn ended without a terminal event. */\n finalize(fallback: TurnTraceTermination = { status: 'unknown' }): void {\n for (const child of this.#children.values()) child.finalize();\n if (this.finished) return;\n this.#finish(fallback);\n }\n\n snapshot(): TurnTrace {\n const usage = this.#modelCalls.reduce(\n (total, call) => ({\n prompt_tokens: total.prompt_tokens + call.prompt_tokens,\n completion_tokens: total.completion_tokens + call.completion_tokens,\n total_tokens: total.total_tokens + call.total_tokens,\n }),\n { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n );\n return Object.freeze({\n version: TURN_TRACE_VERSION,\n turn_id: this.turnId,\n session_key: this.sessionKey,\n ...(this.#principal ? { principal: this.#principal } : {}),\n started_at: this.#startedAt,\n ...(this.#endedAt !== undefined\n ? { ended_at: this.#endedAt, duration_ms: this.#endedAt - this.#startedAt }\n : {}),\n model_calls: Object.freeze([...this.#modelCalls]),\n usage: Object.freeze(usage),\n ...(this.#contextBudget ? { context_budget: this.#contextBudget } : {}),\n tool_calls: Object.freeze([...this.#toolCalls.values()].map(tool => Object.freeze({ ...tool }))),\n budget: Object.freeze({\n extensions: Object.freeze([...this.#extensions]),\n continuations: this.#continuations,\n }),\n subagent_tasks: Object.freeze([...this.#subagentTasks.values()]),\n subagents: Object.freeze([...this.#children.values()].map(child => child.snapshot())),\n timeline: Object.freeze([...this.#timeline]),\n termination: Object.freeze({ ...this.#termination }),\n dropped: this.#dropped,\n });\n }\n\n #startTool(toolUseId: string, toolName: string, argsSummary: string): MutableToolCall | undefined {\n if (this.#toolCalls.size >= MAX_TOOL_CALLS && !this.#toolCalls.has(toolUseId)) {\n this.#dropped += 1;\n return undefined;\n }\n const existing = this.#toolCalls.get(toolUseId);\n if (existing) return existing;\n const created: MutableToolCall = {\n tool_use_id: toolUseId,\n tool_name: toolName,\n args_summary: argsSummary,\n status: 'running',\n started_at_ms: this.#elapsed(),\n };\n this.#toolCalls.set(toolUseId, created);\n return created;\n }\n\n /** Result/denial events may arrive without a prior tool_call (e.g. pre-call denial). */\n #tool(toolUseId: string, toolName: string): MutableToolCall | undefined {\n return this.#toolCalls.get(toolUseId) ?? this.#startTool(toolUseId, toolName, '');\n }\n\n #finish(termination: TurnTraceTermination): void {\n if (this.finished) return;\n this.#termination = Object.freeze(termination);\n this.#endedAt = this.#now();\n for (const tool of this.#toolCalls.values()) {\n if (tool.status === 'running') tool.status = 'cancelled';\n }\n this.#addTimeline('end', [termination.status, termination.code, termination.reason].filter(Boolean).join(' '));\n }\n\n #addTimeline(kind: string, detail: string): void {\n if (this.#timeline.length >= MAX_TIMELINE_ENTRIES) {\n this.#dropped += 1;\n return;\n }\n this.#timeline.push(Object.freeze({ at_ms: this.#elapsed(), kind, detail }));\n }\n\n #elapsed(): number {\n return Math.max(0, this.#now() - this.#startedAt);\n }\n\n #principalInit(): TurnTraceInit['principal'] {\n if (!this.#principal) return undefined;\n return {\n subjectId: this.#principal.subject_id,\n ...(this.#principal.display_name ? { displayName: this.#principal.display_name } : {}),\n roles: this.#principal.roles,\n ...(this.#principal.trust_level ? { trustLevel: this.#principal.trust_level } : {}),\n };\n }\n}\n\n/** Redacted, single-line, length-bounded summary of tool arguments. */\nfunction describeAdmission(note: Extract<TurnTraceNote, { kind: 'admission' }>): string {\n const parts = [`queued ${Math.round(note.queued_ms)}ms`];\n if (note.merged_messages > 1) parts.push(`merged ${note.merged_messages} messages`);\n if (note.superseded_previous) parts.push('replaced the sender\\'s unanswered turn');\n return parts.join(', ');\n}\n\nexport function summarizeArgs(args: unknown): string {\n if (args == null) return '';\n const redacted = redactTraceValue(args);\n const text = typeof redacted === 'string' ? redacted : JSON.stringify(redacted);\n return clip(scrubSecrets(text ?? ''), ARGS_SUMMARY_LENGTH);\n}\n\nfunction summarizeText(value: unknown, max = TEXT_SUMMARY_LENGTH): string {\n const redacted = redactTraceValue(value);\n const text = typeof redacted === 'string' ? redacted : JSON.stringify(redacted) ?? '';\n return clip(scrubSecrets(text.replace(/\\s+/g, ' ').trim()), max);\n}\n\nconst INLINE_SECRET_RULES: ReadonlyArray<readonly [RegExp, string]> = [\n [/\\b(bearer|basic)\\s+[A-Za-z0-9._~+/=-]{8,}/gi, '$1 [redacted]'],\n [/\\b(?:sk|pk|rk)-[A-Za-z0-9_-]{12,}/g, '[redacted]'],\n [/\\b(?:ghp|gho|ghs|github_pat|xox[abpr])[_-][A-Za-z0-9_-]{12,}/g, '[redacted]'],\n [/(\"?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret)\"?\\s*[:=]\\s*\"?)[^\"\\s,}]+/gi, '$1[redacted]'],\n];\n\n/** Masks credentials that appear inline in free text (error messages, string args). */\nexport function scrubSecrets(text: string): string {\n return INLINE_SECRET_RULES.reduce((current, [pattern, replacement]) => current.replace(pattern, replacement), text);\n}\n\nfunction outputSize(output: unknown): number {\n if (output == null) return 0;\n if (typeof output === 'string') return output.length;\n try {\n return JSON.stringify(output)?.length ?? 0;\n } catch {\n return 0;\n }\n}\n\nfunction clip(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max)}…`;\n}\n\nfunction withoutType(event: TurnEvent): Record<string, unknown> {\n const { type: _type, ...rest } = event as unknown as Record<string, unknown>;\n return rest;\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Logger } from '@zhin.js/logger';
|
|
2
|
+
import type { TurnTrace } from './turn-trace.js';
|
|
3
|
+
export interface UsageLogContext {
|
|
4
|
+
traceId: string;
|
|
5
|
+
scene: string;
|
|
6
|
+
selectedModel?: string;
|
|
7
|
+
status?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function formatTurnUsageLogs(trace: TurnTrace, context: UsageLogContext, includeDetails?: boolean): {
|
|
10
|
+
summary: string;
|
|
11
|
+
details: string[];
|
|
12
|
+
};
|
|
13
|
+
/** Logging is a projection of the existing trace, never execution authority. */
|
|
14
|
+
export declare function logTurnUsage(logger: Pick<Logger, 'info' | 'debug' | 'isLevelEnabled'>, trace: TurnTrace, context: UsageLogContext): void;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { formatCompact } from '@zhin.js/logger';
|
|
2
|
+
const FIELDS = {
|
|
3
|
+
input: 'prompt_tokens', output: 'completion_tokens', totalTokens: 'total_tokens',
|
|
4
|
+
cacheRead: 'cache_read_tokens', cacheWrite: 'cache_write_tokens', reasoning: 'reasoning_tokens',
|
|
5
|
+
};
|
|
6
|
+
// Metadata can contain controls too; preserve one physical line and field boundaries.
|
|
7
|
+
function safe(value) {
|
|
8
|
+
return value.replace(/[\p{Cc}\u2028\u2029|]/gu, ch => `\\u${ch.charCodeAt(0).toString(16).padStart(4, '0')}`).slice(0, 240);
|
|
9
|
+
}
|
|
10
|
+
function known(call, field) {
|
|
11
|
+
const value = call[FIELDS[field]];
|
|
12
|
+
if (value === undefined || !Number.isFinite(value) || value < 0)
|
|
13
|
+
return undefined;
|
|
14
|
+
// Old records lack availability. Positive usage is evidence; normalized zero isn't.
|
|
15
|
+
const reported = call.reported?.[field] ?? (field === 'cacheRead' || field === 'cacheWrite' || field === 'reasoning'
|
|
16
|
+
? true : value > 0);
|
|
17
|
+
return reported ? value : undefined;
|
|
18
|
+
}
|
|
19
|
+
/** A partial sum is explicitly a lower bound, never an apparently complete zero. */
|
|
20
|
+
function sum(calls, field) {
|
|
21
|
+
if (!calls.length)
|
|
22
|
+
return 0;
|
|
23
|
+
const values = calls.map(call => known(call, field));
|
|
24
|
+
const present = values.filter((v) => v !== undefined);
|
|
25
|
+
if (!present.length)
|
|
26
|
+
return '?';
|
|
27
|
+
const total = present.reduce((a, b) => a + b, 0);
|
|
28
|
+
return present.length === calls.length ? total : `>=${total}`;
|
|
29
|
+
}
|
|
30
|
+
function tree(trace) {
|
|
31
|
+
return [trace, ...trace.subagents.flatMap(tree)];
|
|
32
|
+
}
|
|
33
|
+
function tokens(calls) {
|
|
34
|
+
return { input: sum(calls, 'input'), output: sum(calls, 'output'),
|
|
35
|
+
cache_read: sum(calls, 'cacheRead'), cache_write: sum(calls, 'cacheWrite'), reasoning: sum(calls, 'reasoning') };
|
|
36
|
+
}
|
|
37
|
+
export function formatTurnUsageLogs(trace, context, includeDetails = true) {
|
|
38
|
+
const traces = tree(trace);
|
|
39
|
+
const calls = traces.flatMap(item => item.model_calls);
|
|
40
|
+
const identity = { trace: safe(context.traceId), turn: safe(trace.turn_id) };
|
|
41
|
+
const models = [...new Set(calls.map(call => `${call.provider ?? '?'}/${call.model ?? '?'}`))];
|
|
42
|
+
const summary = formatCompact({ op: 'turn', ...identity, scene: safe(context.scene),
|
|
43
|
+
status: context.status ?? trace.termination.status,
|
|
44
|
+
model: safe(models.join(',') || context.selectedModel || '?'),
|
|
45
|
+
calls: calls.length, ...tokens(calls),
|
|
46
|
+
ms: trace.duration_ms === undefined ? '?' : Math.round(trace.duration_ms),
|
|
47
|
+
...(traces.length > 1 ? { subagent_calls: calls.length - trace.model_calls.length } : {}),
|
|
48
|
+
...((context.status ?? trace.termination.status) !== 'completed'
|
|
49
|
+
|| traces.some(item => item.dropped > 0 || item.termination.status !== 'completed')
|
|
50
|
+
? { partial: true } : {}),
|
|
51
|
+
});
|
|
52
|
+
const details = includeDetails ? traces.flatMap(item => {
|
|
53
|
+
const ids = { trace: identity.trace, turn: safe(item.turn_id) };
|
|
54
|
+
const lines = item.model_calls.map(call => formatCompact({ op: 'call', ...ids, index: call.index,
|
|
55
|
+
model: safe(`${call.provider ?? '?'}/${call.model ?? '?'}`), status: safe(call.stop_reason ?? '?'),
|
|
56
|
+
...tokens([call]), ms: call.duration_ms === undefined ? '?' : Math.round(call.duration_ms) }));
|
|
57
|
+
const budget = item.context_budget;
|
|
58
|
+
if (budget)
|
|
59
|
+
lines.push(formatCompact({ op: 'context', ...ids, request: 'first', unit: 'estimated_tokens',
|
|
60
|
+
total: budget.total_tokens, fixed: budget.fixed_tokens,
|
|
61
|
+
segments: Object.entries(budget.segments).map(([key, value]) => `${safe(key)}=${value}`).join(' '),
|
|
62
|
+
loaded_tools: budget.tools.loaded, deferred_tools: budget.tools.deferred }));
|
|
63
|
+
return lines;
|
|
64
|
+
}) : [];
|
|
65
|
+
return { summary, details };
|
|
66
|
+
}
|
|
67
|
+
/** Logging is a projection of the existing trace, never execution authority. */
|
|
68
|
+
export function logTurnUsage(logger, trace, context) {
|
|
69
|
+
try {
|
|
70
|
+
if (!logger.isLevelEnabled('info'))
|
|
71
|
+
return;
|
|
72
|
+
const debug = logger.isLevelEnabled('debug');
|
|
73
|
+
const lines = formatTurnUsageLogs(trace, context, debug);
|
|
74
|
+
logger.info(lines.summary);
|
|
75
|
+
if (debug)
|
|
76
|
+
for (const line of lines.details)
|
|
77
|
+
logger.debug(line);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// A transport/formatter failure must not change the outcome or skip trace persistence.
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=turn-usage-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-usage-log.js","sourceRoot":"","sources":["../../src/trace/turn-usage-log.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatCompact, type Logger } from '@zhin.js/logger';\nimport type { TurnTrace, TurnTraceModelCall } from './turn-trace.js';\n\nexport interface UsageLogContext {\n traceId: string;\n scene: string;\n selectedModel?: string;\n status?: string;\n}\n\ntype Field = 'input' | 'output' | 'totalTokens' | 'cacheRead' | 'cacheWrite' | 'reasoning';\nconst FIELDS = {\n input: 'prompt_tokens', output: 'completion_tokens', totalTokens: 'total_tokens',\n cacheRead: 'cache_read_tokens', cacheWrite: 'cache_write_tokens', reasoning: 'reasoning_tokens',\n} as const;\n\n// Metadata can contain controls too; preserve one physical line and field boundaries.\nfunction safe(value: string): string {\n return value.replace(/[\\p{Cc}\\u2028\\u2029|]/gu, ch => `\\\\u${ch.charCodeAt(0).toString(16).padStart(4, '0')}`).slice(0, 240);\n}\n\nfunction known(call: TurnTraceModelCall, field: Field): number | undefined {\n const value = call[FIELDS[field]];\n if (value === undefined || !Number.isFinite(value) || value < 0) return undefined;\n // Old records lack availability. Positive usage is evidence; normalized zero isn't.\n const reported = call.reported?.[field] ?? (field === 'cacheRead' || field === 'cacheWrite' || field === 'reasoning'\n ? true : value > 0);\n return reported ? value : undefined;\n}\n\n/** A partial sum is explicitly a lower bound, never an apparently complete zero. */\nfunction sum(calls: readonly TurnTraceModelCall[], field: Field): number | string {\n if (!calls.length) return 0;\n const values = calls.map(call => known(call, field));\n const present = values.filter((v): v is number => v !== undefined);\n if (!present.length) return '?';\n const total = present.reduce((a, b) => a + b, 0);\n return present.length === calls.length ? total : `>=${total}`;\n}\n\nfunction tree(trace: TurnTrace): TurnTrace[] {\n return [trace, ...trace.subagents.flatMap(tree)];\n}\n\nfunction tokens(calls: readonly TurnTraceModelCall[]) {\n return { input: sum(calls, 'input'), output: sum(calls, 'output'),\n cache_read: sum(calls, 'cacheRead'), cache_write: sum(calls, 'cacheWrite'), reasoning: sum(calls, 'reasoning') };\n}\n\nexport function formatTurnUsageLogs(trace: TurnTrace, context: UsageLogContext, includeDetails = true): { summary: string; details: string[] } {\n const traces = tree(trace);\n const calls = traces.flatMap(item => item.model_calls);\n const identity = { trace: safe(context.traceId), turn: safe(trace.turn_id) };\n const models = [...new Set(calls.map(call => `${call.provider ?? '?'}/${call.model ?? '?'}`))];\n const summary = formatCompact({ op: 'turn', ...identity, scene: safe(context.scene),\n status: context.status ?? trace.termination.status,\n model: safe(models.join(',') || context.selectedModel || '?'),\n calls: calls.length, ...tokens(calls),\n ms: trace.duration_ms === undefined ? '?' : Math.round(trace.duration_ms),\n ...(traces.length > 1 ? { subagent_calls: calls.length - trace.model_calls.length } : {}),\n ...((context.status ?? trace.termination.status) !== 'completed'\n || traces.some(item => item.dropped > 0 || item.termination.status !== 'completed')\n ? { partial: true } : {}),\n });\n const details = includeDetails ? traces.flatMap(item => {\n const ids = { trace: identity.trace, turn: safe(item.turn_id) };\n const lines = item.model_calls.map(call => formatCompact({ op: 'call', ...ids, index: call.index,\n model: safe(`${call.provider ?? '?'}/${call.model ?? '?'}`), status: safe(call.stop_reason ?? '?'),\n ...tokens([call]), ms: call.duration_ms === undefined ? '?' : Math.round(call.duration_ms) }));\n const budget = item.context_budget;\n if (budget) lines.push(formatCompact({ op: 'context', ...ids, request: 'first', unit: 'estimated_tokens',\n total: budget.total_tokens, fixed: budget.fixed_tokens,\n segments: Object.entries(budget.segments).map(([key, value]) => `${safe(key)}=${value}`).join(' '),\n loaded_tools: budget.tools.loaded, deferred_tools: budget.tools.deferred }));\n return lines;\n }) : [];\n return { summary, details };\n}\n\n/** Logging is a projection of the existing trace, never execution authority. */\nexport function logTurnUsage(logger: Pick<Logger, 'info' | 'debug' | 'isLevelEnabled'>, trace: TurnTrace, context: UsageLogContext): void {\n try {\n if (!logger.isLevelEnabled('info')) return;\n const debug = logger.isLevelEnabled('debug');\n const lines = formatTurnUsageLogs(trace, context, debug);\n logger.info(lines.summary);\n if (debug) for (const line of lines.details) logger.debug(line);\n } catch {\n // A transport/formatter failure must not change the outcome or skip trace persistence.\n }\n}\n"]}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { type DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import type { TurnEvent } from '../event/turn-event.js';
|
|
3
|
+
import type { TurnRequest } from '../turn/turn-ingress.js';
|
|
4
|
+
export declare const AGENT_USAGE_TURN_MODEL: {
|
|
5
|
+
readonly id: {
|
|
6
|
+
readonly type: "text";
|
|
7
|
+
readonly length: 64;
|
|
8
|
+
readonly primary: true;
|
|
9
|
+
};
|
|
10
|
+
readonly fingerprint: {
|
|
11
|
+
readonly type: "text";
|
|
12
|
+
readonly length: 64;
|
|
13
|
+
readonly nullable: false;
|
|
14
|
+
};
|
|
15
|
+
readonly owner: {
|
|
16
|
+
readonly type: "text";
|
|
17
|
+
readonly nullable: true;
|
|
18
|
+
};
|
|
19
|
+
readonly trace_id: {
|
|
20
|
+
readonly type: "text";
|
|
21
|
+
readonly nullable: true;
|
|
22
|
+
};
|
|
23
|
+
readonly turn_id: {
|
|
24
|
+
readonly type: "text";
|
|
25
|
+
readonly nullable: true;
|
|
26
|
+
};
|
|
27
|
+
readonly session_key: {
|
|
28
|
+
readonly type: "text";
|
|
29
|
+
readonly nullable: true;
|
|
30
|
+
};
|
|
31
|
+
readonly principal_id: {
|
|
32
|
+
readonly type: "text";
|
|
33
|
+
readonly nullable: true;
|
|
34
|
+
};
|
|
35
|
+
readonly origin_kind: {
|
|
36
|
+
readonly type: "text";
|
|
37
|
+
readonly nullable: true;
|
|
38
|
+
};
|
|
39
|
+
readonly endpoint_adapter: {
|
|
40
|
+
readonly type: "text";
|
|
41
|
+
readonly nullable: true;
|
|
42
|
+
};
|
|
43
|
+
readonly endpoint_id: {
|
|
44
|
+
readonly type: "text";
|
|
45
|
+
readonly nullable: true;
|
|
46
|
+
};
|
|
47
|
+
readonly conversation_kind: {
|
|
48
|
+
readonly type: "text";
|
|
49
|
+
readonly nullable: true;
|
|
50
|
+
};
|
|
51
|
+
readonly conversation_id: {
|
|
52
|
+
readonly type: "text";
|
|
53
|
+
readonly nullable: true;
|
|
54
|
+
};
|
|
55
|
+
readonly parent_kind: {
|
|
56
|
+
readonly type: "text";
|
|
57
|
+
readonly nullable: true;
|
|
58
|
+
};
|
|
59
|
+
readonly parent_id: {
|
|
60
|
+
readonly type: "text";
|
|
61
|
+
readonly nullable: true;
|
|
62
|
+
};
|
|
63
|
+
readonly thread_id: {
|
|
64
|
+
readonly type: "text";
|
|
65
|
+
readonly nullable: true;
|
|
66
|
+
};
|
|
67
|
+
readonly source_id: {
|
|
68
|
+
readonly type: "text";
|
|
69
|
+
readonly nullable: true;
|
|
70
|
+
};
|
|
71
|
+
readonly selected_provider: {
|
|
72
|
+
readonly type: "text";
|
|
73
|
+
readonly nullable: true;
|
|
74
|
+
};
|
|
75
|
+
readonly selected_model: {
|
|
76
|
+
readonly type: "text";
|
|
77
|
+
readonly nullable: true;
|
|
78
|
+
};
|
|
79
|
+
readonly status: {
|
|
80
|
+
readonly type: "text";
|
|
81
|
+
readonly nullable: true;
|
|
82
|
+
};
|
|
83
|
+
readonly started_at: {
|
|
84
|
+
readonly type: "bigint";
|
|
85
|
+
readonly nullable: true;
|
|
86
|
+
};
|
|
87
|
+
readonly ended_at: {
|
|
88
|
+
readonly type: "bigint";
|
|
89
|
+
readonly nullable: true;
|
|
90
|
+
};
|
|
91
|
+
readonly duration_ms: {
|
|
92
|
+
readonly type: "bigint";
|
|
93
|
+
readonly nullable: true;
|
|
94
|
+
};
|
|
95
|
+
readonly call_count: {
|
|
96
|
+
readonly type: "bigint";
|
|
97
|
+
readonly nullable: true;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
export declare const AGENT_USAGE_CALL_MODEL: {
|
|
101
|
+
readonly id: {
|
|
102
|
+
readonly type: "text";
|
|
103
|
+
readonly length: 64;
|
|
104
|
+
readonly primary: true;
|
|
105
|
+
};
|
|
106
|
+
readonly root_id: {
|
|
107
|
+
readonly type: "text";
|
|
108
|
+
readonly length: 64;
|
|
109
|
+
readonly nullable: false;
|
|
110
|
+
};
|
|
111
|
+
readonly turn_id: {
|
|
112
|
+
readonly type: "text";
|
|
113
|
+
readonly nullable: true;
|
|
114
|
+
};
|
|
115
|
+
readonly call_index: {
|
|
116
|
+
readonly type: "integer";
|
|
117
|
+
readonly nullable: false;
|
|
118
|
+
};
|
|
119
|
+
readonly provider: {
|
|
120
|
+
readonly type: "text";
|
|
121
|
+
readonly nullable: true;
|
|
122
|
+
};
|
|
123
|
+
readonly model: {
|
|
124
|
+
readonly type: "text";
|
|
125
|
+
readonly nullable: true;
|
|
126
|
+
};
|
|
127
|
+
readonly stop_reason: {
|
|
128
|
+
readonly type: "text";
|
|
129
|
+
readonly nullable: true;
|
|
130
|
+
};
|
|
131
|
+
readonly duration_ms: {
|
|
132
|
+
readonly type: "bigint";
|
|
133
|
+
readonly nullable: true;
|
|
134
|
+
};
|
|
135
|
+
readonly input_tokens: {
|
|
136
|
+
readonly type: "bigint";
|
|
137
|
+
readonly nullable: true;
|
|
138
|
+
};
|
|
139
|
+
readonly output_tokens: {
|
|
140
|
+
readonly type: "bigint";
|
|
141
|
+
readonly nullable: true;
|
|
142
|
+
};
|
|
143
|
+
readonly total_tokens: {
|
|
144
|
+
readonly type: "bigint";
|
|
145
|
+
readonly nullable: true;
|
|
146
|
+
};
|
|
147
|
+
readonly cache_read_tokens: {
|
|
148
|
+
readonly type: "bigint";
|
|
149
|
+
readonly nullable: true;
|
|
150
|
+
};
|
|
151
|
+
readonly cache_write_tokens: {
|
|
152
|
+
readonly type: "bigint";
|
|
153
|
+
readonly nullable: true;
|
|
154
|
+
};
|
|
155
|
+
readonly reasoning_tokens: {
|
|
156
|
+
readonly type: "bigint";
|
|
157
|
+
readonly nullable: true;
|
|
158
|
+
};
|
|
159
|
+
readonly ended_at: {
|
|
160
|
+
readonly type: "bigint";
|
|
161
|
+
readonly nullable: true;
|
|
162
|
+
};
|
|
163
|
+
readonly root_ended_at: {
|
|
164
|
+
readonly type: "bigint";
|
|
165
|
+
readonly nullable: true;
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
export type UsageRow = Record<string, string | number | null>;
|
|
169
|
+
export interface AgentUsageRecord {
|
|
170
|
+
readonly turn: UsageRow;
|
|
171
|
+
readonly calls: readonly UsageRow[];
|
|
172
|
+
}
|
|
173
|
+
export interface AgentUsageStore {
|
|
174
|
+
save(record: AgentUsageRecord): Promise<void>;
|
|
175
|
+
prune(): Promise<void>;
|
|
176
|
+
}
|
|
177
|
+
export declare const agentUsageStoreToken: import("@zhin.js/plugin-runtime").Token<AgentUsageStore>;
|
|
178
|
+
/** Minimal numeric facts, independent of log level and trace archive size limits. */
|
|
179
|
+
export declare class AgentUsageCollector {
|
|
180
|
+
#private;
|
|
181
|
+
private readonly owner;
|
|
182
|
+
private readonly request;
|
|
183
|
+
private readonly selected;
|
|
184
|
+
constructor(owner: string, request: TurnRequest, selected: {
|
|
185
|
+
provider: string;
|
|
186
|
+
model: string;
|
|
187
|
+
});
|
|
188
|
+
record(event: TurnEvent): void;
|
|
189
|
+
finish(status: string): AgentUsageRecord;
|
|
190
|
+
}
|
|
191
|
+
/** Tables contain no payload JSON, chat content, prompt, tool arguments or error text. */
|
|
192
|
+
export declare class DatabaseAgentUsageStore implements AgentUsageStore {
|
|
193
|
+
private readonly database;
|
|
194
|
+
readonly retentionDays: number;
|
|
195
|
+
private readonly now;
|
|
196
|
+
constructor(database: DatabaseHost, retentionDays?: number, now?: () => number);
|
|
197
|
+
save(record: AgentUsageRecord): Promise<void>;
|
|
198
|
+
prune(): Promise<void>;
|
|
199
|
+
}
|