@caupulican/pi-adaptative 0.86.17 → 0.90.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/CHANGELOG.md +43 -0
- package/README.md +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +14 -15
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +14 -16
- package/dist/bundled-resources/skills/worker-profile-writer/SKILL.md +4 -4
- package/dist/core/agent-session.d.ts +23 -33
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +81 -110
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/gates.d.ts.map +1 -1
- package/dist/core/autonomy/gates.js +16 -0
- package/dist/core/autonomy/gates.js.map +1 -1
- package/dist/core/autonomy/subagent-prompt.d.ts +2 -1
- package/dist/core/autonomy/subagent-prompt.d.ts.map +1 -1
- package/dist/core/autonomy/subagent-prompt.js +2 -18
- package/dist/core/autonomy/subagent-prompt.js.map +1 -1
- package/dist/core/background-tool-task-controller.js +5 -5
- package/dist/core/background-tool-task-controller.js.map +1 -1
- package/dist/core/compaction-controller.d.ts +22 -2
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +75 -39
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/context/brain-curator.d.ts +2 -3
- package/dist/core/context/brain-curator.d.ts.map +1 -1
- package/dist/core/context/brain-curator.js +3 -20
- package/dist/core/context/brain-curator.js.map +1 -1
- package/dist/core/context/context-composition.d.ts +2 -1
- package/dist/core/context/context-composition.d.ts.map +1 -1
- package/dist/core/context/context-composition.js +6 -1
- package/dist/core/context/context-composition.js.map +1 -1
- package/dist/core/context/memory-prompt-block.js +1 -1
- package/dist/core/context/memory-prompt-block.js.map +1 -1
- package/dist/core/context/tool-output-packer.js +1 -1
- package/dist/core/context/tool-output-packer.js.map +1 -1
- package/dist/core/context-gc.js +10 -10
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +4 -4
- package/dist/core/context-pipeline.js +4 -4
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +1 -2
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/session-worker-claim.d.ts +2 -2
- package/dist/core/delegation/session-worker-claim.js +2 -2
- package/dist/core/delegation/session-worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-resource-materializer.js +3 -3
- package/dist/core/delegation/worker-resource-materializer.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +2 -13
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +5 -67
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/extensions/builtin.js +4 -4
- package/dist/core/extensions/builtin.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +6 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +21 -9
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +9 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.js +2 -2
- package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
- package/dist/core/goals/compact-goal-context.js +13 -9
- package/dist/core/goals/compact-goal-context.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +1 -1
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +6 -0
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +16 -13
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/human-input-controller.js +1 -1
- package/dist/core/human-input-controller.js.map +1 -1
- package/dist/core/improvement-loop.js +13 -13
- package/dist/core/improvement-loop.js.map +1 -1
- package/dist/core/learning/reflection-engine.d.ts +2 -1
- package/dist/core/learning/reflection-engine.d.ts.map +1 -1
- package/dist/core/learning/reflection-engine.js +4 -24
- package/dist/core/learning/reflection-engine.js.map +1 -1
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +1 -1
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-router/route-judge.d.ts +2 -1
- package/dist/core/model-router/route-judge.d.ts.map +1 -1
- package/dist/core/model-router/route-judge.js +4 -12
- package/dist/core/model-router/route-judge.js.map +1 -1
- package/dist/core/models/perf-profile.d.ts +1 -1
- package/dist/core/models/perf-profile.d.ts.map +1 -1
- package/dist/core/models/perf-profile.js +2 -8
- package/dist/core/models/perf-profile.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js +1 -6
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/process-matrix/resume-launcher.js +3 -3
- package/dist/core/process-matrix/resume-launcher.js.map +1 -1
- package/dist/core/process-matrix/runtime.d.ts +2 -0
- package/dist/core/process-matrix/runtime.d.ts.map +1 -1
- package/dist/core/process-matrix/runtime.js +23 -19
- package/dist/core/process-matrix/runtime.js.map +1 -1
- package/dist/core/provider-prompt-contracts.d.ts +34 -0
- package/dist/core/provider-prompt-contracts.d.ts.map +1 -0
- package/dist/core/provider-prompt-contracts.js +133 -0
- package/dist/core/provider-prompt-contracts.js.map +1 -0
- package/dist/core/provider-request-context-controller.d.ts +40 -0
- package/dist/core/provider-request-context-controller.d.ts.map +1 -0
- package/dist/core/provider-request-context-controller.js +68 -0
- package/dist/core/provider-request-context-controller.js.map +1 -0
- package/dist/core/provider-request-runtime-controller.d.ts +22 -0
- package/dist/core/provider-request-runtime-controller.d.ts.map +1 -0
- package/dist/core/provider-request-runtime-controller.js +87 -0
- package/dist/core/provider-request-runtime-controller.js.map +1 -0
- package/dist/core/provider-tool-text.d.ts +7 -0
- package/dist/core/provider-tool-text.d.ts.map +1 -0
- package/dist/core/provider-tool-text.js +42 -0
- package/dist/core/provider-tool-text.js.map +1 -0
- package/dist/core/research/model-fitness.d.ts +2 -5
- package/dist/core/research/model-fitness.d.ts.map +1 -1
- package/dist/core/research/model-fitness.js +2 -20
- package/dist/core/research/model-fitness.js.map +1 -1
- package/dist/core/research/research-runner.d.ts +2 -1
- package/dist/core/research/research-runner.d.ts.map +1 -1
- package/dist/core/research/research-runner.js +6 -21
- package/dist/core/research/research-runner.js.map +1 -1
- package/dist/core/risk-classifier.d.ts.map +1 -1
- package/dist/core/risk-classifier.js +9 -1
- package/dist/core/risk-classifier.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +3 -0
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +20 -25
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/scout-controller.d.ts +2 -1
- package/dist/core/scout-controller.d.ts.map +1 -1
- package/dist/core/scout-controller.js +2 -16
- package/dist/core/scout-controller.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +6 -6
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/secrets/credential-manager.d.ts +11 -1
- package/dist/core/secrets/credential-manager.d.ts.map +1 -1
- package/dist/core/secrets/credential-manager.js +28 -7
- package/dist/core/secrets/credential-manager.js.map +1 -1
- package/dist/core/secrets/credential-migration-source.d.ts +20 -0
- package/dist/core/secrets/credential-migration-source.d.ts.map +1 -0
- package/dist/core/secrets/credential-migration-source.js +113 -0
- package/dist/core/secrets/credential-migration-source.js.map +1 -0
- package/dist/core/secrets/credential-session-connection.d.ts +9 -0
- package/dist/core/secrets/credential-session-connection.d.ts.map +1 -0
- package/dist/core/secrets/credential-session-connection.js +39 -0
- package/dist/core/secrets/credential-session-connection.js.map +1 -0
- package/dist/core/security/untrusted-boundary.d.ts +2 -2
- package/dist/core/security/untrusted-boundary.d.ts.map +1 -1
- package/dist/core/security/untrusted-boundary.js +3 -10
- package/dist/core/security/untrusted-boundary.js.map +1 -1
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +1 -2
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/skill-vault.d.ts +98 -0
- package/dist/core/skill-vault.d.ts.map +1 -0
- package/dist/core/skill-vault.js +270 -0
- package/dist/core/skill-vault.js.map +1 -0
- package/dist/core/skills.d.ts +10 -9
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +42 -50
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +1 -1
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +20 -60
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.d.ts +4 -4
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +87 -121
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/task-state.d.ts.map +1 -1
- package/dist/core/tasks/task-state.js +6 -7
- package/dist/core/tasks/task-state.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts.map +1 -1
- package/dist/core/tool-capability-policy.js +2 -1
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tool-protocol-controller.d.ts.map +1 -1
- package/dist/core/tool-protocol-controller.js +4 -7
- package/dist/core/tool-protocol-controller.js.map +1 -1
- package/dist/core/tool-selection/promotion.d.ts.map +1 -1
- package/dist/core/tool-selection/promotion.js +2 -6
- package/dist/core/tool-selection/promotion.js.map +1 -1
- package/dist/core/toolkit/reflex-interpreter.d.ts +2 -1
- package/dist/core/toolkit/reflex-interpreter.d.ts.map +1 -1
- package/dist/core/toolkit/reflex-interpreter.js +2 -14
- package/dist/core/toolkit/reflex-interpreter.js.map +1 -1
- package/dist/core/tools/ask-question.js +6 -6
- package/dist/core/tools/ask-question.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +8 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +17 -13
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +111 -226
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +29 -2
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +149 -48
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/edit.js +3 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/extensionify-runtime.js +4 -4
- package/dist/core/tools/extensionify-runtime.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +2 -4
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/goal.js +3 -3
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/grep.js +2 -2
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/model-fitness.js +4 -4
- package/dist/core/tools/model-fitness.js.map +1 -1
- package/dist/core/tools/profile-writer.d.ts +30 -16
- package/dist/core/tools/profile-writer.d.ts.map +1 -1
- package/dist/core/tools/profile-writer.js +98 -59
- package/dist/core/tools/profile-writer.js.map +1 -1
- package/dist/core/tools/python.js +6 -6
- package/dist/core/tools/python.js.map +1 -1
- package/dist/core/tools/run-process.js +4 -4
- package/dist/core/tools/run-process.js.map +1 -1
- package/dist/core/tools/run-toolkit-script.js +4 -4
- package/dist/core/tools/run-toolkit-script.js.map +1 -1
- package/dist/core/tools/secret-store.d.ts +32 -3
- package/dist/core/tools/secret-store.d.ts.map +1 -1
- package/dist/core/tools/secret-store.js +141 -34
- package/dist/core/tools/secret-store.js.map +1 -1
- package/dist/core/tools/skill.d.ts +29 -0
- package/dist/core/tools/skill.d.ts.map +1 -0
- package/dist/core/tools/skill.js +79 -0
- package/dist/core/tools/skill.js.map +1 -0
- package/dist/core/tools/task-steps.js +4 -4
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +2 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/tool-task.d.ts.map +1 -1
- package/dist/core/tools/tool-task.js +4 -0
- package/dist/core/tools/tool-task.js.map +1 -1
- package/dist/core/tools/worktree-sync.js +6 -6
- package/dist/core/tools/worktree-sync.js.map +1 -1
- package/dist/core/tools/write.js +3 -3
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.js +1 -1
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/report-commands.js +1 -1
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -1
- package/dist/modes/interactive/secret-menu-controller.js +2 -18
- package/dist/modes/interactive/secret-menu-controller.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +1 -1
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/docs/compaction.md +45 -25
- package/docs/extensions.md +23 -7
- package/docs/settings.md +3 -3
- package/docs/skills.md +14 -10
- package/docs/task-steps.md +2 -2
- package/docs/tmux-agent-manager.md +1 -1
- package/docs/tool-repair.md +18 -1
- package/docs/usage.md +4 -2
- package/docs/worker-profiles.md +3 -3
- package/docs/worktree-sync.md +2 -2
- package/examples/extensions/custom-compaction.ts +5 -17
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +3 -5
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
- package/dist/core/util/json-size.d.ts +0 -3
- package/dist/core/util/json-size.d.ts.map +0 -1
- package/dist/core/util/json-size.js +0 -95
- package/dist/core/util/json-size.js.map +0 -1
|
@@ -27,7 +27,6 @@ export const MODEL_CAPABILITY_SYSTEM_PROMPT_MAX_CHARS = {
|
|
|
27
27
|
};
|
|
28
28
|
export const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS = [
|
|
29
29
|
"delegate",
|
|
30
|
-
"profile_writer",
|
|
31
30
|
"context_audit",
|
|
32
31
|
"goal",
|
|
33
32
|
"worktree_sync",
|
|
@@ -40,6 +39,7 @@ export const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS = [
|
|
|
40
39
|
];
|
|
41
40
|
export const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS = [
|
|
42
41
|
"read",
|
|
42
|
+
"skill",
|
|
43
43
|
"bash",
|
|
44
44
|
"python",
|
|
45
45
|
"powershell",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-capability.js","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in the stable prompt, tool schemas, and\n * background-lane prompts. The same class is the single input to prompt shaping and tool/lane gates.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Hard aggregate character envelope for the stable system prompt; undefined = intentionally unbounded. */\n\tsystemPromptMaxChars: number | undefined;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\n/**\n * Aggregate stable-prompt envelopes. These are deliberately owned beside the classification\n * thresholds so every harness expansion must fit the same profile that owns tools and lanes.\n * Full/off profiles are intentionally unbounded; constrained profiles fail visibly on overflow.\n */\nexport const MODEL_CAPABILITY_SYSTEM_PROMPT_MAX_CHARS: Readonly<Record<ModelCapabilityClass, number | undefined>> = {\n\tfull: undefined,\n\tlean: 8_192,\n\tminimal: 4_096,\n\tchat: 2_048,\n};\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\n\t\"delegate\",\n\t\"profile_writer\",\n\t\"context_audit\",\n\t\"goal\",\n\t\"worktree_sync\",\n\t\"improvement_loop\",\n\t\"extensionify\",\n\t\"skillify\",\n\t\"model_fitness\",\n\t\"context_scout\",\n\t\"tmux_agent_manager\",\n];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"bash\",\n\t\"python\",\n\t\"powershell\",\n\t\"edit\",\n\t\"write\",\n\t\"ask_question\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tsystemPromptMaxChars: MODEL_CAPABILITY_SYSTEM_PROMPT_MAX_CHARS[capabilityClass],\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\n/**\n * Mandatory provider-neutral gate for a final system prompt. This intentionally rejects rather\n * than truncates: arbitrary truncation can silently remove security, repair, or project rules.\n */\nexport function enforceModelCapabilitySystemPromptBudget(\n\tsystemPrompt: string,\n\tprofile: Pick<ModelCapabilityProfile, \"class\" | \"systemPromptMaxChars\">,\n): string {\n\tconst maxChars = profile.systemPromptMaxChars;\n\tif (maxChars === undefined || systemPrompt.length <= maxChars) return systemPrompt;\n\tthrow new Error(\n\t\t`${profile.class} system prompt exceeds its ${maxChars}-character capability budget (${systemPrompt.length} characters). Reduce custom, extension, or harness prompt guidance, or select a more capable profile.`,\n\t);\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n\n/**\n * Lane-worker eligibility: a session bound to a worktree-sync lane (`--worktree-lane` /\n * `PI_WORKTREE_LANE`, see worktree-sync/runtime.ts) is expected to drive the FULL multi-step\n * lane-gate/recovery surface -- sync, conflict recovery, land -- unattended. A sub-full capability\n * class or a model with no working native tool-call path cannot reliably drive that surface. This\n * rides the SAME capability system every other adaptation in this file rides (class + context\n * window + the `/toolprobe` verdict) -- no parallel mechanism, no new env var, no new registry field.\n */\nexport type LaneWorkerRefusalReason =\n\t| \"capability_class_below_full\"\n\t| \"context_window_unknown\"\n\t| \"tool_calling_unadvertised\"\n\t| \"tool_calling_demoted\";\n\nexport interface LaneWorkerRefusal {\n\treason: LaneWorkerRefusalReason;\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow?: number;\n}\n\n/**\n * Decide whether the model described by `args` may drive a worktree-sync lane worker. First\n * failure wins, in order: capability class below full; an unknown/undeclared context window (the\n * classifier's own registry-derived SSOT -- see `deriveModelCapabilityProfile`; a full class can\n * still carry an undefined window via the `unknown_context_window_defaults` fallback); no\n * ADVERTISED native tool-call path (`Model.textToolCallProtocol` unset/false -- set true means\n * phone-only); or a GRADED `/toolprobe` demotion to \"text-protocol\"/\"none\". An UNPROBED model (no\n * verdict on record yet) is eligible on its advertised support alone -- unprobed is never treated\n * as demoted. `undefined` means eligible.\n */\nexport function evaluateLaneWorkerRefusal(args: {\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow: number | undefined;\n\ttoolCallingAdvertised: boolean;\n\ttoolCallingDemoted: boolean;\n}): LaneWorkerRefusal | undefined {\n\tconst { capabilityClass, contextWindow, toolCallingAdvertised, toolCallingDemoted } = args;\n\tif (capabilityClass !== \"full\") return { reason: \"capability_class_below_full\", capabilityClass, contextWindow };\n\tif (contextWindow === undefined) return { reason: \"context_window_unknown\", capabilityClass, contextWindow };\n\tif (!toolCallingAdvertised) return { reason: \"tool_calling_unadvertised\", capabilityClass, contextWindow };\n\tif (toolCallingDemoted) return { reason: \"tool_calling_demoted\", capabilityClass, contextWindow };\n\treturn undefined;\n}\n\n/** Stable, greppable prefix for {@link formatLaneWorkerRefusal}'s output. */\nexport const LANE_WORKER_REFUSAL_PREFIX = \"worktree-sync lane-worker refusal:\";\n\n/** Format a refusal into one deterministic, greppable line naming the lane, class, window, and reason. */\nexport function formatLaneWorkerRefusal(refusal: LaneWorkerRefusal, laneKey?: string): string {\n\tconst laneSuffix = laneKey !== undefined ? ` lane=${laneKey}` : \"\";\n\tconst windowText = refusal.contextWindow !== undefined ? String(refusal.contextWindow) : \"unknown\";\n\treturn `${LANE_WORKER_REFUSAL_PREFIX}${laneSuffix} class=${refusal.capabilityClass} contextWindow=${windowText} reason=${refusal.reason}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-capability.js","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in the stable prompt, tool schemas, and\n * background-lane prompts. The same class is the single input to prompt shaping and tool/lane gates.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Hard aggregate character envelope for the stable system prompt; undefined = intentionally unbounded. */\n\tsystemPromptMaxChars: number | undefined;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\n/**\n * Aggregate stable-prompt envelopes. These are deliberately owned beside the classification\n * thresholds so every harness expansion must fit the same profile that owns tools and lanes.\n * Full/off profiles are intentionally unbounded; constrained profiles fail visibly on overflow.\n */\nexport const MODEL_CAPABILITY_SYSTEM_PROMPT_MAX_CHARS: Readonly<Record<ModelCapabilityClass, number | undefined>> = {\n\tfull: undefined,\n\tlean: 8_192,\n\tminimal: 4_096,\n\tchat: 2_048,\n};\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\n\t\"delegate\",\n\t\"context_audit\",\n\t\"goal\",\n\t\"worktree_sync\",\n\t\"improvement_loop\",\n\t\"extensionify\",\n\t\"skillify\",\n\t\"model_fitness\",\n\t\"context_scout\",\n\t\"tmux_agent_manager\",\n];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"skill\",\n\t\"bash\",\n\t\"python\",\n\t\"powershell\",\n\t\"edit\",\n\t\"write\",\n\t\"ask_question\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tsystemPromptMaxChars: MODEL_CAPABILITY_SYSTEM_PROMPT_MAX_CHARS[capabilityClass],\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\n/**\n * Mandatory provider-neutral gate for a final system prompt. This intentionally rejects rather\n * than truncates: arbitrary truncation can silently remove security, repair, or project rules.\n */\nexport function enforceModelCapabilitySystemPromptBudget(\n\tsystemPrompt: string,\n\tprofile: Pick<ModelCapabilityProfile, \"class\" | \"systemPromptMaxChars\">,\n): string {\n\tconst maxChars = profile.systemPromptMaxChars;\n\tif (maxChars === undefined || systemPrompt.length <= maxChars) return systemPrompt;\n\tthrow new Error(\n\t\t`${profile.class} system prompt exceeds its ${maxChars}-character capability budget (${systemPrompt.length} characters). Reduce custom, extension, or harness prompt guidance, or select a more capable profile.`,\n\t);\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n\n/**\n * Lane-worker eligibility: a session bound to a worktree-sync lane (`--worktree-lane` /\n * `PI_WORKTREE_LANE`, see worktree-sync/runtime.ts) is expected to drive the FULL multi-step\n * lane-gate/recovery surface -- sync, conflict recovery, land -- unattended. A sub-full capability\n * class or a model with no working native tool-call path cannot reliably drive that surface. This\n * rides the SAME capability system every other adaptation in this file rides (class + context\n * window + the `/toolprobe` verdict) -- no parallel mechanism, no new env var, no new registry field.\n */\nexport type LaneWorkerRefusalReason =\n\t| \"capability_class_below_full\"\n\t| \"context_window_unknown\"\n\t| \"tool_calling_unadvertised\"\n\t| \"tool_calling_demoted\";\n\nexport interface LaneWorkerRefusal {\n\treason: LaneWorkerRefusalReason;\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow?: number;\n}\n\n/**\n * Decide whether the model described by `args` may drive a worktree-sync lane worker. First\n * failure wins, in order: capability class below full; an unknown/undeclared context window (the\n * classifier's own registry-derived SSOT -- see `deriveModelCapabilityProfile`; a full class can\n * still carry an undefined window via the `unknown_context_window_defaults` fallback); no\n * ADVERTISED native tool-call path (`Model.textToolCallProtocol` unset/false -- set true means\n * phone-only); or a GRADED `/toolprobe` demotion to \"text-protocol\"/\"none\". An UNPROBED model (no\n * verdict on record yet) is eligible on its advertised support alone -- unprobed is never treated\n * as demoted. `undefined` means eligible.\n */\nexport function evaluateLaneWorkerRefusal(args: {\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow: number | undefined;\n\ttoolCallingAdvertised: boolean;\n\ttoolCallingDemoted: boolean;\n}): LaneWorkerRefusal | undefined {\n\tconst { capabilityClass, contextWindow, toolCallingAdvertised, toolCallingDemoted } = args;\n\tif (capabilityClass !== \"full\") return { reason: \"capability_class_below_full\", capabilityClass, contextWindow };\n\tif (contextWindow === undefined) return { reason: \"context_window_unknown\", capabilityClass, contextWindow };\n\tif (!toolCallingAdvertised) return { reason: \"tool_calling_unadvertised\", capabilityClass, contextWindow };\n\tif (toolCallingDemoted) return { reason: \"tool_calling_demoted\", capabilityClass, contextWindow };\n\treturn undefined;\n}\n\n/** Stable, greppable prefix for {@link formatLaneWorkerRefusal}'s output. */\nexport const LANE_WORKER_REFUSAL_PREFIX = \"worktree-sync lane-worker refusal:\";\n\n/** Format a refusal into one deterministic, greppable line naming the lane, class, window, and reason. */\nexport function formatLaneWorkerRefusal(refusal: LaneWorkerRefusal, laneKey?: string): string {\n\tconst laneSuffix = laneKey !== undefined ? ` lane=${laneKey}` : \"\";\n\tconst windowText = refusal.contextWindow !== undefined ? String(refusal.contextWindow) : \"unknown\";\n\treturn `${LANE_WORKER_REFUSAL_PREFIX}${laneSuffix} class=${refusal.capabilityClass} contextWindow=${windowText} reason=${refusal.reason}`;\n}\n"]}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { RouteDecision } from "../autonomy/contracts.ts";
|
|
2
|
+
import { ROUTE_JUDGE_SYSTEM_PROMPT } from "../provider-prompt-contracts.ts";
|
|
3
|
+
export { ROUTE_JUDGE_SYSTEM_PROMPT };
|
|
2
4
|
/**
|
|
3
5
|
* Routing-only judge: a bounded, tool-less completion (default: the medium model) that decides the
|
|
4
6
|
* final cheap/medium/expensive tier for a user prompt, refining the regex classifier's baseline.
|
|
@@ -8,7 +10,6 @@ import type { RouteDecision } from "../autonomy/contracts.ts";
|
|
|
8
10
|
* reasonCode, never silently.
|
|
9
11
|
*/
|
|
10
12
|
/** Static across calls — callers pass cacheRetention "short" so only the variable tail is billed. */
|
|
11
|
-
export declare const ROUTE_JUDGE_SYSTEM_PROMPT: string;
|
|
12
13
|
export declare const ROUTE_JUDGE_MAX_OUTPUT_TOKENS = 128;
|
|
13
14
|
export declare const ROUTE_JUDGE_MAX_WALL_CLOCK_MS = 10000;
|
|
14
15
|
export interface RouteJudgeVerdict {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-judge.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/route-judge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"route-judge.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/route-judge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,OAAO,EAAE,yBAAyB,EAAE,CAAC;AAErC;;;;;;;GAOG;AAEH,qGAAqG;AACrG,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;IACvC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GAAG,MAAM,CAMnG;AAKD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAgBlF;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAczG;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CAChB;AAUD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC;QAChG,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAsC/B"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { runBoundedCompletion } from "../autonomy/bounded-completion.js";
|
|
2
2
|
import { parseModelOutputJsonObject } from "../model-output-json.js";
|
|
3
|
+
import { ROUTE_JUDGE_SYSTEM_PROMPT } from "../provider-prompt-contracts.js";
|
|
4
|
+
export { ROUTE_JUDGE_SYSTEM_PROMPT };
|
|
3
5
|
/**
|
|
4
6
|
* Routing-only judge: a bounded, tool-less completion (default: the medium model) that decides the
|
|
5
7
|
* final cheap/medium/expensive tier for a user prompt, refining the regex classifier's baseline.
|
|
@@ -9,22 +11,12 @@ import { parseModelOutputJsonObject } from "../model-output-json.js";
|
|
|
9
11
|
* reasonCode, never silently.
|
|
10
12
|
*/
|
|
11
13
|
/** Static across calls — callers pass cacheRetention "short" so only the variable tail is billed. */
|
|
12
|
-
export const ROUTE_JUDGE_SYSTEM_PROMPT = [
|
|
13
|
-
"You are a routing judge for a coding agent. You only route; you never answer the task.",
|
|
14
|
-
"Pick which model tier should handle the user prompt:",
|
|
15
|
-
'- "cheap": trivial, mechanical, read-only lookups only.',
|
|
16
|
-
'- "medium": normal implementation, scoped edits, tests, and NON-trivial planning/design.',
|
|
17
|
-
'- "expensive": architecture, ambiguity, security/auth, destructive or release operations, high-impact changes.',
|
|
18
|
-
"Planning, design, and strategy prompts are NEVER cheap unless the task is genuinely trivial.",
|
|
19
|
-
"Respond with STRICT JSON only - no prose:",
|
|
20
|
-
'{"tier":"cheap"|"medium"|"expensive","risk":"read-only"|"scoped-write"|"high-impact"|"approval-required","trivial":true|false,"reason":"<short reason>"}',
|
|
21
|
-
].join("\n");
|
|
22
14
|
export const ROUTE_JUDGE_MAX_OUTPUT_TOKENS = 128;
|
|
23
15
|
export const ROUTE_JUDGE_MAX_WALL_CLOCK_MS = 10_000;
|
|
24
16
|
export function buildRouteJudgeUserPrompt(args) {
|
|
25
17
|
return [
|
|
26
|
-
`
|
|
27
|
-
"
|
|
18
|
+
`BASELINE tier=${args.baseline.tier} risk=${args.baseline.risk} reason=${args.baseline.reasonCode}`,
|
|
19
|
+
"USER PROMPT",
|
|
28
20
|
args.prompt.slice(0, 4000),
|
|
29
21
|
].join("\n");
|
|
30
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-judge.js","sourceRoot":"","sources":["../../../src/core/model-router/route-judge.ts"],"names":[],"mappings":"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","sourcesContent":["import { runBoundedCompletion } from \"../autonomy/bounded-completion.ts\";\nimport type { RouteDecision } from \"../autonomy/contracts.ts\";\nimport { parseModelOutputJsonObject } from \"../model-output-json.ts\";\n\n/**\n * Routing-only judge: a bounded, tool-less completion (default: the medium model) that decides the\n * final cheap/medium/expensive tier for a user prompt, refining the regex classifier's baseline.\n * Core rule: planning is never cheap unless the judge explicitly deems the task trivial. The judge\n * proposes; the existing pipeline (model resolution, auth, escalation, gates) still decides.\n * Failure is honest: unparseable/timeout/unavailable falls back to the baseline with a visible\n * reasonCode, never silently.\n */\n\n/** Static across calls — callers pass cacheRetention \"short\" so only the variable tail is billed. */\nexport const ROUTE_JUDGE_SYSTEM_PROMPT = [\n\t\"You are a routing judge for a coding agent. You only route; you never answer the task.\",\n\t\"Pick which model tier should handle the user prompt:\",\n\t'- \"cheap\": trivial, mechanical, read-only lookups only.',\n\t'- \"medium\": normal implementation, scoped edits, tests, and NON-trivial planning/design.',\n\t'- \"expensive\": architecture, ambiguity, security/auth, destructive or release operations, high-impact changes.',\n\t\"Planning, design, and strategy prompts are NEVER cheap unless the task is genuinely trivial.\",\n\t\"Respond with STRICT JSON only - no prose:\",\n\t'{\"tier\":\"cheap\"|\"medium\"|\"expensive\",\"risk\":\"read-only\"|\"scoped-write\"|\"high-impact\"|\"approval-required\",\"trivial\":true|false,\"reason\":\"<short reason>\"}',\n].join(\"\\n\");\n\nexport const ROUTE_JUDGE_MAX_OUTPUT_TOKENS = 128;\nexport const ROUTE_JUDGE_MAX_WALL_CLOCK_MS = 10_000;\n\nexport interface RouteJudgeVerdict {\n\ttier: \"cheap\" | \"medium\" | \"expensive\";\n\trisk: RouteDecision[\"risk\"];\n\ttrivial: boolean;\n\treason: string;\n}\n\nexport function buildRouteJudgeUserPrompt(args: { prompt: string; baseline: RouteDecision }): string {\n\treturn [\n\t\t`Baseline (regex) verdict: tier=${args.baseline.tier}, risk=${args.baseline.risk}, reason=${args.baseline.reasonCode}.`,\n\t\t\"User prompt:\",\n\t\targs.prompt.slice(0, 4000),\n\t].join(\"\\n\");\n}\n\nconst JUDGE_TIERS: readonly string[] = [\"cheap\", \"medium\", \"expensive\"];\nconst JUDGE_RISKS: readonly string[] = [\"read-only\", \"scoped-write\", \"high-impact\", \"approval-required\"];\n\nexport function parseRouteJudgeVerdict(text: string): RouteJudgeVerdict | undefined {\n\tconst record = parseModelOutputJsonObject(text);\n\tif (!record) return undefined;\n\t// The judge may never select the learning tier or anything outside the three foreground tiers.\n\tif (typeof record.tier !== \"string\" || !JUDGE_TIERS.includes(record.tier)) return undefined;\n\tconst risk =\n\t\ttypeof record.risk === \"string\" && JUDGE_RISKS.includes(record.risk)\n\t\t\t? (record.risk as RouteDecision[\"risk\"])\n\t\t\t: undefined;\n\tif (!risk) return undefined;\n\treturn {\n\t\ttier: record.tier as RouteJudgeVerdict[\"tier\"],\n\t\trisk,\n\t\ttrivial: record.trivial === true,\n\t\treason: typeof record.reason === \"string\" ? record.reason.slice(0, 200) : \"\",\n\t};\n}\n\n/** Merge a judge verdict into the baseline decision (pure; never returns learning). */\nexport function applyRouteJudgeVerdict(baseline: RouteDecision, verdict: RouteJudgeVerdict): RouteDecision {\n\t// Enforce the core rule in code, not just in the judge prompt: downgrading a non-cheap\n\t// baseline to cheap requires an EXPLICIT trivial verdict. An untrusted judge saying\n\t// {tier:\"cheap\", trivial:false} for an elevated prompt keeps the baseline tier.\n\tconst tier =\n\t\tverdict.tier === \"cheap\" && baseline.tier !== \"cheap\" && !verdict.trivial ? baseline.tier : verdict.tier;\n\treturn {\n\t\t...baseline,\n\t\ttier,\n\t\trisk: verdict.risk,\n\t\tconfidence: Math.max(baseline.confidence, 0.75),\n\t\treasonCode: `judge_${tier}${verdict.trivial ? \"_trivial\" : \"\"}`,\n\t\treasons: [...baseline.reasons, `Route judge: ${verdict.reason || \"no reason given\"}`],\n\t};\n}\n\nexport interface RouteJudgeRunResult {\n\tdecision: RouteDecision;\n\tverdict?: RouteJudgeVerdict;\n\t/** Set when the judge could not decide and the baseline was kept. */\n\tfallbackReason?: string;\n\tcostUsd: number;\n}\n\nfunction judgeFallbackDecision(baseline: RouteDecision, reason: string): RouteDecision {\n\treturn {\n\t\t...baseline,\n\t\treasonCode: \"judge_unavailable_fallback\",\n\t\treasons: [...baseline.reasons, reason],\n\t};\n}\n\n/**\n * Run the judge over a baseline decision. The completion executor is injected (production:\n * AgentSession.runIsolatedCompletion on the judge model). Never throws; every failure keeps the\n * baseline with a visible fallbackReason.\n */\nexport async function runRouteJudge(args: {\n\tprompt: string;\n\tbaseline: RouteDecision;\n\tcomplete: (input: { systemPrompt: string; userPrompt: string; signal?: AbortSignal }) => Promise<{\n\t\ttext: string;\n\t\tcostUsd: number;\n\t\tstopReason: string;\n\t}>;\n\tsignal?: AbortSignal;\n\tmaxWallClockMs?: number;\n}): Promise<RouteJudgeRunResult> {\n\tconst bounded = await runBoundedCompletion({\n\t\tmaxWallClockMs: args.maxWallClockMs ?? ROUTE_JUDGE_MAX_WALL_CLOCK_MS,\n\t\tsignal: args.signal,\n\t\texecute: (signal) =>\n\t\t\targs.complete({\n\t\t\t\tsystemPrompt: ROUTE_JUDGE_SYSTEM_PROMPT,\n\t\t\t\tuserPrompt: buildRouteJudgeUserPrompt({ prompt: args.prompt, baseline: args.baseline }),\n\t\t\t\tsignal,\n\t\t\t}),\n\t});\n\tconst costUsd = bounded.completion?.costUsd ?? 0;\n\n\tif (bounded.failure || !bounded.completion) {\n\t\treturn {\n\t\t\tdecision: judgeFallbackDecision(args.baseline, \"Route judge unavailable; baseline kept\"),\n\t\t\tfallbackReason: bounded.failure ? `judge_${bounded.failure.reasonCode}` : \"judge_unavailable_fallback\",\n\t\t\tcostUsd,\n\t\t};\n\t}\n\tif (bounded.completion.stopReason === \"error\" || bounded.completion.stopReason === \"aborted\") {\n\t\treturn {\n\t\t\tdecision: judgeFallbackDecision(args.baseline, \"Route judge errored; baseline kept\"),\n\t\t\tfallbackReason: \"judge_model_error\",\n\t\t\tcostUsd,\n\t\t};\n\t}\n\n\tconst verdict = parseRouteJudgeVerdict(bounded.completion.text);\n\tif (!verdict) {\n\t\treturn {\n\t\t\tdecision: judgeFallbackDecision(args.baseline, \"Route judge unparseable; baseline kept\"),\n\t\t\tfallbackReason: \"judge_unparseable_fallback\",\n\t\t\tcostUsd,\n\t\t};\n\t}\n\n\treturn { decision: applyRouteJudgeVerdict(args.baseline, verdict), verdict, costUsd };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"route-judge.js","sourceRoot":"","sources":["../../../src/core/model-router/route-judge.ts"],"names":[],"mappings":"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","sourcesContent":["import { runBoundedCompletion } from \"../autonomy/bounded-completion.ts\";\nimport type { RouteDecision } from \"../autonomy/contracts.ts\";\nimport { parseModelOutputJsonObject } from \"../model-output-json.ts\";\nimport { ROUTE_JUDGE_SYSTEM_PROMPT } from \"../provider-prompt-contracts.ts\";\n\nexport { ROUTE_JUDGE_SYSTEM_PROMPT };\n\n/**\n * Routing-only judge: a bounded, tool-less completion (default: the medium model) that decides the\n * final cheap/medium/expensive tier for a user prompt, refining the regex classifier's baseline.\n * Core rule: planning is never cheap unless the judge explicitly deems the task trivial. The judge\n * proposes; the existing pipeline (model resolution, auth, escalation, gates) still decides.\n * Failure is honest: unparseable/timeout/unavailable falls back to the baseline with a visible\n * reasonCode, never silently.\n */\n\n/** Static across calls — callers pass cacheRetention \"short\" so only the variable tail is billed. */\nexport const ROUTE_JUDGE_MAX_OUTPUT_TOKENS = 128;\nexport const ROUTE_JUDGE_MAX_WALL_CLOCK_MS = 10_000;\n\nexport interface RouteJudgeVerdict {\n\ttier: \"cheap\" | \"medium\" | \"expensive\";\n\trisk: RouteDecision[\"risk\"];\n\ttrivial: boolean;\n\treason: string;\n}\n\nexport function buildRouteJudgeUserPrompt(args: { prompt: string; baseline: RouteDecision }): string {\n\treturn [\n\t\t`BASELINE tier=${args.baseline.tier} risk=${args.baseline.risk} reason=${args.baseline.reasonCode}`,\n\t\t\"USER PROMPT\",\n\t\targs.prompt.slice(0, 4000),\n\t].join(\"\\n\");\n}\n\nconst JUDGE_TIERS: readonly string[] = [\"cheap\", \"medium\", \"expensive\"];\nconst JUDGE_RISKS: readonly string[] = [\"read-only\", \"scoped-write\", \"high-impact\", \"approval-required\"];\n\nexport function parseRouteJudgeVerdict(text: string): RouteJudgeVerdict | undefined {\n\tconst record = parseModelOutputJsonObject(text);\n\tif (!record) return undefined;\n\t// The judge may never select the learning tier or anything outside the three foreground tiers.\n\tif (typeof record.tier !== \"string\" || !JUDGE_TIERS.includes(record.tier)) return undefined;\n\tconst risk =\n\t\ttypeof record.risk === \"string\" && JUDGE_RISKS.includes(record.risk)\n\t\t\t? (record.risk as RouteDecision[\"risk\"])\n\t\t\t: undefined;\n\tif (!risk) return undefined;\n\treturn {\n\t\ttier: record.tier as RouteJudgeVerdict[\"tier\"],\n\t\trisk,\n\t\ttrivial: record.trivial === true,\n\t\treason: typeof record.reason === \"string\" ? record.reason.slice(0, 200) : \"\",\n\t};\n}\n\n/** Merge a judge verdict into the baseline decision (pure; never returns learning). */\nexport function applyRouteJudgeVerdict(baseline: RouteDecision, verdict: RouteJudgeVerdict): RouteDecision {\n\t// Enforce the core rule in code, not just in the judge prompt: downgrading a non-cheap\n\t// baseline to cheap requires an EXPLICIT trivial verdict. An untrusted judge saying\n\t// {tier:\"cheap\", trivial:false} for an elevated prompt keeps the baseline tier.\n\tconst tier =\n\t\tverdict.tier === \"cheap\" && baseline.tier !== \"cheap\" && !verdict.trivial ? baseline.tier : verdict.tier;\n\treturn {\n\t\t...baseline,\n\t\ttier,\n\t\trisk: verdict.risk,\n\t\tconfidence: Math.max(baseline.confidence, 0.75),\n\t\treasonCode: `judge_${tier}${verdict.trivial ? \"_trivial\" : \"\"}`,\n\t\treasons: [...baseline.reasons, `Route judge: ${verdict.reason || \"no reason given\"}`],\n\t};\n}\n\nexport interface RouteJudgeRunResult {\n\tdecision: RouteDecision;\n\tverdict?: RouteJudgeVerdict;\n\t/** Set when the judge could not decide and the baseline was kept. */\n\tfallbackReason?: string;\n\tcostUsd: number;\n}\n\nfunction judgeFallbackDecision(baseline: RouteDecision, reason: string): RouteDecision {\n\treturn {\n\t\t...baseline,\n\t\treasonCode: \"judge_unavailable_fallback\",\n\t\treasons: [...baseline.reasons, reason],\n\t};\n}\n\n/**\n * Run the judge over a baseline decision. The completion executor is injected (production:\n * AgentSession.runIsolatedCompletion on the judge model). Never throws; every failure keeps the\n * baseline with a visible fallbackReason.\n */\nexport async function runRouteJudge(args: {\n\tprompt: string;\n\tbaseline: RouteDecision;\n\tcomplete: (input: { systemPrompt: string; userPrompt: string; signal?: AbortSignal }) => Promise<{\n\t\ttext: string;\n\t\tcostUsd: number;\n\t\tstopReason: string;\n\t}>;\n\tsignal?: AbortSignal;\n\tmaxWallClockMs?: number;\n}): Promise<RouteJudgeRunResult> {\n\tconst bounded = await runBoundedCompletion({\n\t\tmaxWallClockMs: args.maxWallClockMs ?? ROUTE_JUDGE_MAX_WALL_CLOCK_MS,\n\t\tsignal: args.signal,\n\t\texecute: (signal) =>\n\t\t\targs.complete({\n\t\t\t\tsystemPrompt: ROUTE_JUDGE_SYSTEM_PROMPT,\n\t\t\t\tuserPrompt: buildRouteJudgeUserPrompt({ prompt: args.prompt, baseline: args.baseline }),\n\t\t\t\tsignal,\n\t\t\t}),\n\t});\n\tconst costUsd = bounded.completion?.costUsd ?? 0;\n\n\tif (bounded.failure || !bounded.completion) {\n\t\treturn {\n\t\t\tdecision: judgeFallbackDecision(args.baseline, \"Route judge unavailable; baseline kept\"),\n\t\t\tfallbackReason: bounded.failure ? `judge_${bounded.failure.reasonCode}` : \"judge_unavailable_fallback\",\n\t\t\tcostUsd,\n\t\t};\n\t}\n\tif (bounded.completion.stopReason === \"error\" || bounded.completion.stopReason === \"aborted\") {\n\t\treturn {\n\t\t\tdecision: judgeFallbackDecision(args.baseline, \"Route judge errored; baseline kept\"),\n\t\t\tfallbackReason: \"judge_model_error\",\n\t\t\tcostUsd,\n\t\t};\n\t}\n\n\tconst verdict = parseRouteJudgeVerdict(bounded.completion.text);\n\tif (!verdict) {\n\t\treturn {\n\t\t\tdecision: judgeFallbackDecision(args.baseline, \"Route judge unparseable; baseline kept\"),\n\t\t\tfallbackReason: \"judge_unparseable_fallback\",\n\t\t\tcostUsd,\n\t\t};\n\t}\n\n\treturn { decision: applyRouteJudgeVerdict(args.baseline, verdict), verdict, costUsd };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type StreamFn, type StreamIdleOptions } from "@caupulican/pi-agent-core";
|
|
2
2
|
import type { Api, Context, Model } from "@caupulican/pi-ai/types";
|
|
3
3
|
export declare const DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS: number;
|
|
4
4
|
export interface ModelPerfProfile {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perf-profile.d.ts","sourceRoot":"","sources":["../../../src/core/models/perf-profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"perf-profile.d.ts","sourceRoot":"","sources":["../../../src/core/models/perf-profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEjH,OAAO,KAAK,EACX,GAAG,EAGH,OAAO,EACP,KAAK,EAEL,MAAM,yBAAyB,CAAC;AAMjC,eAAO,MAAM,uCAAuC,QAAiB,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,uBAAuB;IACvC,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IACpD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAClE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAa5E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAMzE;AAED,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAE,MAA8C,GAChD,gBAAgB,GAAG,SAAS,CAyB9B;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0B3G;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEpE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,8BAA8B,GAAG,QAAQ,CA4D3G"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { estimateProviderRequestTokens } from "@caupulican/pi-agent-core";
|
|
1
2
|
import { createAssistantMessageEventStream } from "@caupulican/pi-ai/event-stream";
|
|
2
3
|
import { createEmptyUsage } from "@caupulican/pi-ai/usage";
|
|
3
|
-
import { measureJsonLength } from "../util/json-size.js";
|
|
4
4
|
const PERF_EWMA_ALPHA = 0.3;
|
|
5
|
-
const CHARS_PER_TOKEN_ESTIMATE = 4;
|
|
6
5
|
const DEFERRED_HEADERS_MAX_GAP_MS = 100;
|
|
7
6
|
const DEFERRED_HEADERS_MIN_REQUEST_MS = 1_000;
|
|
8
7
|
export const DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS = 30 * 60 * 1000;
|
|
@@ -75,12 +74,7 @@ export function resolveAdaptiveStreamIdleOptions(input) {
|
|
|
75
74
|
return result;
|
|
76
75
|
}
|
|
77
76
|
export function estimateContextPromptTokens(context) {
|
|
78
|
-
|
|
79
|
-
systemPrompt: context.systemPrompt,
|
|
80
|
-
messages: context.messages,
|
|
81
|
-
tools: context.tools,
|
|
82
|
-
});
|
|
83
|
-
return serializedLength === undefined ? 0 : Math.ceil(serializedLength / CHARS_PER_TOKEN_ESTIMATE);
|
|
77
|
+
return estimateProviderRequestTokens(context);
|
|
84
78
|
}
|
|
85
79
|
export function withModelPerfProfile(streamFn, recorder) {
|
|
86
80
|
return async (model, context, streamOptions) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perf-profile.js","sourceRoot":"","sources":["../../../src/core/models/perf-profile.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StreamFn, StreamIdleOptions } from \"@caupulican/pi-agent-core\";\nimport { createAssistantMessageEventStream } from \"@caupulican/pi-ai/event-stream\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tContext,\n\tModel,\n\tProviderResponse,\n} from \"@caupulican/pi-ai/types\";\nimport { createEmptyUsage } from \"@caupulican/pi-ai/usage\";\nimport { measureJsonLength } from \"../util/json-size.ts\";\n\nconst PERF_EWMA_ALPHA = 0.3;\nconst CHARS_PER_TOKEN_ESTIMATE = 4;\nconst DEFERRED_HEADERS_MAX_GAP_MS = 100;\nconst DEFERRED_HEADERS_MIN_REQUEST_MS = 1_000;\nexport const DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS = 30 * 60 * 1000;\n\nexport interface ModelPerfProfile {\n\tprefillTokensPerSecond?: number;\n\tdecodeTokensPerSecond?: number;\n\tloadMs?: number;\n\tsamples: number;\n\tupdatedAt: string;\n}\n\nexport interface ModelPerfSample {\n\tpromptTokens?: number;\n\tcompletionTokens?: number;\n\theadersToFirstTokenMs?: number;\n\trequestToFirstTokenMs?: number;\n\tfirstTokenToDoneMs?: number;\n\tloadMs?: number;\n\tat?: string;\n}\n\nexport interface AdaptiveStreamIdleInput {\n\tbase: StreamIdleOptions;\n\tprofile?: ModelPerfProfile;\n\tpromptTokens: number;\n\tceilingMs?: number;\n\tlocalClass?: boolean;\n}\n\nexport interface ModelPerfProfileStreamRecorder {\n\tmodelKey: (model: Model<Api>) => string | undefined;\n\trecordSample: (modelKey: string, sample: ModelPerfSample) => void;\n\tnowMs?: () => number;\n\tnowIso?: () => string;\n}\n\nexport function isModelPerfProfile(value: unknown): value is ModelPerfProfile {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n\tconst record = value as Record<string, unknown>;\n\tconst samples = record.samples;\n\treturn (\n\t\t(record.prefillTokensPerSecond === undefined || isPositiveFiniteNumber(record.prefillTokensPerSecond)) &&\n\t\t(record.decodeTokensPerSecond === undefined || isPositiveFiniteNumber(record.decodeTokensPerSecond)) &&\n\t\t(record.loadMs === undefined || isPositiveFiniteNumber(record.loadMs)) &&\n\t\ttypeof samples === \"number\" &&\n\t\tNumber.isInteger(samples) &&\n\t\tsamples >= 0 &&\n\t\ttypeof record.updatedAt === \"string\"\n\t);\n}\n\nexport function hasUsableModelPerfSample(sample: ModelPerfSample): boolean {\n\treturn (\n\t\tprefillRateFromSample(sample) !== undefined ||\n\t\tdecodeRateFromSample(sample) !== undefined ||\n\t\tisPositiveFiniteNumber(sample.loadMs)\n\t);\n}\n\nexport function updateModelPerfProfile(\n\tcurrent: ModelPerfProfile | undefined,\n\tsample: ModelPerfSample,\n\tat: string = sample.at ?? new Date().toISOString(),\n): ModelPerfProfile | undefined {\n\tconst prefillRate = prefillRateFromSample(sample);\n\tconst decodeRate = decodeRateFromSample(sample);\n\tconst loadMs = isPositiveFiniteNumber(sample.loadMs) ? sample.loadMs : undefined;\n\tif (prefillRate === undefined && decodeRate === undefined && loadMs === undefined) return current;\n\n\tconst previousSamples = current?.samples ?? 0;\n\treturn {\n\t\t...(prefillRate !== undefined && {\n\t\t\tprefillTokensPerSecond: updateEwma(current?.prefillTokensPerSecond, prefillRate, previousSamples),\n\t\t}),\n\t\t...(prefillRate === undefined && current?.prefillTokensPerSecond !== undefined\n\t\t\t? { prefillTokensPerSecond: current.prefillTokensPerSecond }\n\t\t\t: {}),\n\t\t...(decodeRate !== undefined && {\n\t\t\tdecodeTokensPerSecond: updateEwma(current?.decodeTokensPerSecond, decodeRate, previousSamples),\n\t\t}),\n\t\t...(decodeRate === undefined && current?.decodeTokensPerSecond !== undefined\n\t\t\t? { decodeTokensPerSecond: current.decodeTokensPerSecond }\n\t\t\t: {}),\n\t\t...(loadMs !== undefined && { loadMs: updateEwma(current?.loadMs, loadMs, previousSamples) }),\n\t\t...(loadMs === undefined && current?.loadMs !== undefined ? { loadMs: current.loadMs } : {}),\n\t\tsamples: previousSamples + 1,\n\t\tupdatedAt: at,\n\t};\n}\n\nexport function resolveAdaptiveStreamIdleOptions(input: AdaptiveStreamIdleInput): Partial<StreamIdleOptions> {\n\tconst profile = input.profile;\n\tconst result: Partial<StreamIdleOptions> = {};\n\tconst localConnectDefaultMs = input.localClass\n\t\t? Math.max(input.base.connectMs, input.base.quietIdleMs)\n\t\t: input.base.connectMs;\n\tconst quietCeilingMs = Math.max(input.base.quietIdleMs, input.ceilingMs ?? DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS);\n\tconst connectCeilingMs = Math.max(localConnectDefaultMs, input.ceilingMs ?? DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS);\n\n\tconst expectedPrefillMs = expectedPrefillFromProfile(profile, input.promptTokens);\n\tif (expectedPrefillMs !== undefined) {\n\t\tconst quietIdleMs = adaptiveBound(input.base.quietIdleMs, quietCeilingMs, expectedPrefillMs);\n\t\tif (quietIdleMs > input.base.quietIdleMs) result.quietIdleMs = quietIdleMs;\n\t}\n\n\tif (input.localClass) {\n\t\tconst expectedConnectWorkMs =\n\t\t\texpectedPrefillMs !== undefined ? expectedPrefillMs + (profile?.loadMs ?? 0) : profile?.loadMs;\n\t\tconst connectMs =\n\t\t\texpectedConnectWorkMs !== undefined\n\t\t\t\t? adaptiveBound(localConnectDefaultMs, connectCeilingMs, expectedConnectWorkMs)\n\t\t\t\t: localConnectDefaultMs;\n\t\tif (connectMs > input.base.connectMs) result.connectMs = connectMs;\n\t}\n\n\treturn result;\n}\n\nexport function estimateContextPromptTokens(context: Context): number {\n\tconst serializedLength = measureJsonLength({\n\t\tsystemPrompt: context.systemPrompt,\n\t\tmessages: context.messages,\n\t\ttools: context.tools,\n\t});\n\treturn serializedLength === undefined ? 0 : Math.ceil(serializedLength / CHARS_PER_TOKEN_ESTIMATE);\n}\n\nexport function withModelPerfProfile(streamFn: StreamFn, recorder: ModelPerfProfileStreamRecorder): StreamFn {\n\treturn async (model, context, streamOptions) => {\n\t\tconst nowMs = recorder.nowMs ?? Date.now;\n\t\tconst nowIso = recorder.nowIso ?? (() => new Date().toISOString());\n\t\tconst requestStartedAtMs = nowMs();\n\t\tlet responseHeadersAtMs: number | undefined;\n\t\tlet firstTokenAtMs: number | undefined;\n\t\tconst originalOnResponse = streamOptions?.onResponse;\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tlet latest = emptyAssistantMessage(model);\n\t\tlet inner: Awaited<ReturnType<StreamFn>>;\n\t\ttry {\n\t\t\tinner = await streamFn(model, context, {\n\t\t\t\t...streamOptions,\n\t\t\t\tonResponse: async (response: ProviderResponse, responseModel: Model<Api>) => {\n\t\t\t\t\tresponseHeadersAtMs ??= nowMs();\n\t\t\t\t\tawait originalOnResponse?.(response, responseModel);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true, error));\n\t\t\treturn outer;\n\t\t}\n\n\t\tvoid (async () => {\n\t\t\tlet terminalPushed = false;\n\t\t\ttry {\n\t\t\t\tfor await (const event of inner) {\n\t\t\t\t\tlatest = assistantMessageFromEvent(event);\n\t\t\t\t\tif (firstTokenAtMs === undefined && isFirstTokenEvent(event)) {\n\t\t\t\t\t\tfirstTokenAtMs = nowMs();\n\t\t\t\t\t}\n\t\t\t\t\tif (event.type === \"done\") {\n\t\t\t\t\t\tterminalPushed = true;\n\t\t\t\t\t\trecordSuccessfulStreamSample({\n\t\t\t\t\t\t\tcompletionTokens: event.message.usage.output,\n\t\t\t\t\t\t\tdoneAtMs: nowMs(),\n\t\t\t\t\t\t\tfirstTokenAtMs,\n\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\tnowIso,\n\t\t\t\t\t\t\tpromptTokens:\n\t\t\t\t\t\t\t\tevent.message.usage.input + event.message.usage.cacheRead + event.message.usage.cacheWrite,\n\t\t\t\t\t\t\trecorder,\n\t\t\t\t\t\t\trequestStartedAtMs,\n\t\t\t\t\t\t\tresponseHeadersAtMs,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (event.type === \"error\") {\n\t\t\t\t\t\tterminalPushed = true;\n\t\t\t\t\t}\n\t\t\t\t\touter.push(event);\n\t\t\t\t\tif (terminalPushed) return;\n\t\t\t\t}\n\t\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true));\n\t\t\t} catch (error) {\n\t\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true, error));\n\t\t\t}\n\t\t})();\n\n\t\treturn outer;\n\t};\n}\n\nfunction assistantMessageFromEvent(event: AssistantMessageEvent): AssistantMessage {\n\tif (event.type === \"done\") return event.message;\n\tif (event.type === \"error\") return event.error;\n\treturn event.partial;\n}\n\nfunction emptyAssistantMessage(model: Model<Api>): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction perfStreamFailure(latest: AssistantMessage, aborted: boolean, error?: unknown): AssistantMessageEvent {\n\tconst stopReason = aborted ? \"aborted\" : \"error\";\n\tconst detail = error instanceof Error ? `: ${error.message}` : error === undefined ? \"\" : `: ${String(error)}`;\n\treturn {\n\t\ttype: \"error\",\n\t\treason: stopReason,\n\t\terror: {\n\t\t\t...latest,\n\t\t\tstopReason,\n\t\t\terrorMessage: aborted\n\t\t\t\t? `stream aborted before terminal event${detail}`\n\t\t\t\t: `stream ended without terminal event${detail}`,\n\t\t},\n\t};\n}\n\nfunction recordSuccessfulStreamSample(input: {\n\tmodel: Model<Api>;\n\trecorder: ModelPerfProfileStreamRecorder;\n\trequestStartedAtMs: number;\n\tresponseHeadersAtMs: number | undefined;\n\tfirstTokenAtMs: number | undefined;\n\tdoneAtMs: number;\n\tpromptTokens: number;\n\tcompletionTokens: number;\n\tnowIso: () => string;\n}): void {\n\tif (input.firstTokenAtMs === undefined) return;\n\tconst modelKey = input.recorder.modelKey(input.model);\n\tif (!modelKey) return;\n\tconst requestToFirstTokenMs = input.firstTokenAtMs - input.requestStartedAtMs;\n\tconst sample: ModelPerfSample = {\n\t\tpromptTokens: input.promptTokens,\n\t\tcompletionTokens: input.completionTokens,\n\t\trequestToFirstTokenMs,\n\t\tfirstTokenToDoneMs: input.doneAtMs - input.firstTokenAtMs,\n\t\tat: input.nowIso(),\n\t};\n\tif (input.responseHeadersAtMs !== undefined) {\n\t\tconst headersToFirstTokenMs = input.firstTokenAtMs - input.responseHeadersAtMs;\n\t\tconst headersWereEffectivelyDeferred =\n\t\t\trequestToFirstTokenMs >= DEFERRED_HEADERS_MIN_REQUEST_MS &&\n\t\t\theadersToFirstTokenMs <= DEFERRED_HEADERS_MAX_GAP_MS;\n\t\tif (!headersWereEffectivelyDeferred) sample.headersToFirstTokenMs = headersToFirstTokenMs;\n\t}\n\tif (!hasUsableModelPerfSample(sample)) return;\n\ttry {\n\t\tinput.recorder.recordSample(modelKey, sample);\n\t} catch {\n\t\t// Perf profiling must never fail the user turn.\n\t}\n}\n\nfunction isFirstTokenEvent(event: AssistantMessageEvent): boolean {\n\treturn (\n\t\t(event.type === \"text_delta\" || event.type === \"thinking_delta\" || event.type === \"toolcall_delta\") &&\n\t\tevent.delta.length > 0\n\t);\n}\n\nfunction expectedPrefillFromProfile(profile: ModelPerfProfile | undefined, promptTokens: number): number | undefined {\n\tconst prefillRate = profile?.prefillTokensPerSecond;\n\tif (!profile || profile.samples < 1 || !prefillRate || promptTokens <= 0) return undefined;\n\tconst expectedPrefillMs = (promptTokens / prefillRate) * 1000;\n\treturn Number.isFinite(expectedPrefillMs) && expectedPrefillMs > 0 ? expectedPrefillMs : undefined;\n}\n\nfunction adaptiveBound(defaultMs: number, ceilingMs: number, expectedMs: number): number {\n\treturn Math.min(Math.ceil(Math.max(defaultMs, expectedMs * 3)), ceilingMs);\n}\n\nfunction prefillRateFromSample(sample: ModelPerfSample): number | undefined {\n\tconst durationMs = isPositiveFiniteNumber(sample.headersToFirstTokenMs)\n\t\t? sample.headersToFirstTokenMs\n\t\t: sample.requestToFirstTokenMs;\n\treturn tokensPerSecond(sample.promptTokens, durationMs);\n}\n\nfunction decodeRateFromSample(sample: ModelPerfSample): number | undefined {\n\treturn tokensPerSecond(sample.completionTokens, sample.firstTokenToDoneMs);\n}\n\nfunction tokensPerSecond(tokens: number | undefined, durationMs: number | undefined): number | undefined {\n\tif (!isPositiveFiniteNumber(tokens) || !isPositiveFiniteNumber(durationMs)) return undefined;\n\treturn tokens / (durationMs / 1000);\n}\n\nfunction updateEwma(previous: number | undefined, next: number, previousSamples: number): number {\n\tif (previous === undefined || previousSamples === 0) return next;\n\treturn previous * (1 - PERF_EWMA_ALPHA) + next * PERF_EWMA_ALPHA;\n}\n\nfunction isPositiveFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"perf-profile.js","sourceRoot":"","sources":["../../../src/core/models/perf-profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAyC,MAAM,2BAA2B,CAAC;AACjH,OAAO,EAAE,iCAAiC,EAAE,MAAM,gCAAgC,CAAC;AASnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,2BAA2B,GAAG,GAAG,CAAC;AACxC,MAAM,+BAA+B,GAAG,KAAK,CAAC;AAC9C,MAAM,CAAC,MAAM,uCAAuC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAmCtE,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtF,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,OAAO,CACN,CAAC,MAAM,CAAC,sBAAsB,KAAK,SAAS,IAAI,sBAAsB,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QACtG,CAAC,MAAM,CAAC,qBAAqB,KAAK,SAAS,IAAI,sBAAsB,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACpG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtE,OAAO,OAAO,KAAK,QAAQ;QAC3B,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC;QACzB,OAAO,IAAI,CAAC;QACZ,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CACpC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAuB;IAC/D,OAAO,CACN,qBAAqB,CAAC,MAAM,CAAC,KAAK,SAAS;QAC3C,oBAAoB,CAAC,MAAM,CAAC,KAAK,SAAS;QAC1C,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CACrC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACrC,OAAqC,EACrC,MAAuB,EACvB,EAAE,GAAW,MAAM,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IAElD,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,IAAI,WAAW,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAElG,MAAM,eAAe,GAAG,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC;IAC9C,OAAO;QACN,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI;YAChC,sBAAsB,EAAE,UAAU,CAAC,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,eAAe,CAAC;SACjG,CAAC;QACF,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,EAAE,sBAAsB,KAAK,SAAS;YAC7E,CAAC,CAAC,EAAE,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,EAAE;YAC5D,CAAC,CAAC,EAAE,CAAC;QACN,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI;YAC/B,qBAAqB,EAAE,UAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,eAAe,CAAC;SAC9F,CAAC;QACF,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,EAAE,qBAAqB,KAAK,SAAS;YAC3E,CAAC,CAAC,EAAE,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,EAAE;YAC1D,CAAC,CAAC,EAAE,CAAC;QACN,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC;QAC7F,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,OAAO,EAAE,eAAe,GAAG,CAAC;QAC5B,SAAS,EAAE,EAAE;KACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,KAA8B;IAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,MAAM,MAAM,GAA+B,EAAE,CAAC;IAC9C,MAAM,qBAAqB,GAAG,KAAK,CAAC,UAAU;QAC7C,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;QACxD,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;IACxB,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,IAAI,uCAAuC,CAAC,CAAC;IACpH,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC,SAAS,IAAI,uCAAuC,CAAC,CAAC;IAErH,MAAM,iBAAiB,GAAG,0BAA0B,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAClF,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC;QAC7F,IAAI,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW;YAAE,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;IAC5E,CAAC;IAED,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,qBAAqB,GAC1B,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC;QAChG,MAAM,SAAS,GACd,qBAAqB,KAAK,SAAS;YAClC,CAAC,CAAC,aAAa,CAAC,qBAAqB,EAAE,gBAAgB,EAAE,qBAAqB,CAAC;YAC/E,CAAC,CAAC,qBAAqB,CAAC;QAC1B,IAAI,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IACpE,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC3D,OAAO,6BAA6B,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAkB,EAAE,QAAwC;IAChG,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE;QAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC;QACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QACnE,MAAM,kBAAkB,GAAG,KAAK,EAAE,CAAC;QACnC,IAAI,mBAAuC,CAAC;QAC5C,IAAI,cAAkC,CAAC;QACvC,MAAM,kBAAkB,GAAG,aAAa,EAAE,UAAU,CAAC;QACrD,MAAM,KAAK,GAAG,iCAAiC,EAAE,CAAC;QAClD,IAAI,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,KAAoC,CAAC;QACzC,IAAI,CAAC;YACJ,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE;gBACtC,GAAG,aAAa;gBAChB,UAAU,EAAE,KAAK,EAAE,QAA0B,EAAE,aAAyB,EAAE,EAAE;oBAC3E,mBAAmB,KAAK,KAAK,EAAE,CAAC;oBAChC,MAAM,kBAAkB,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;gBACrD,CAAC;aACD,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACtF,OAAO,KAAK,CAAC;QACd,CAAC;QAED,KAAK,CAAC,KAAK,IAAI,EAAE;YAChB,IAAI,cAAc,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC;gBACJ,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;oBACjC,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;oBAC1C,IAAI,cAAc,KAAK,SAAS,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC9D,cAAc,GAAG,KAAK,EAAE,CAAC;oBAC1B,CAAC;oBACD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBAC3B,cAAc,GAAG,IAAI,CAAC;wBACtB,4BAA4B,CAAC;4BAC5B,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM;4BAC5C,QAAQ,EAAE,KAAK,EAAE;4BACjB,cAAc;4BACd,KAAK;4BACL,MAAM;4BACN,YAAY,EACX,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU;4BAC3F,QAAQ;4BACR,kBAAkB;4BAClB,mBAAmB;yBACnB,CAAC,CAAC;oBACJ,CAAC;yBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBACnC,cAAc,GAAG,IAAI,CAAC;oBACvB,CAAC;oBACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAClB,IAAI,cAAc;wBAAE,OAAO;gBAC5B,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC;YAChF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACvF,CAAC;QACF,CAAC,CAAC,EAAE,CAAC;QAEL,OAAO,KAAK,CAAC;IACd,CAAC,CAAC;AACH,CAAC;AAED,SAAS,yBAAyB,CAAC,KAA4B;IAC9D,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IAChD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC;IAC/C,OAAO,KAAK,CAAC,OAAO,CAAC;AACtB,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAiB;IAC/C,OAAO;QACN,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,EAAE;QACX,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,EAAE;QACf,KAAK,EAAE,gBAAgB,EAAE;QACzB,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAwB,EAAE,OAAgB,EAAE,KAAe;IACrF,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IACjD,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAC/G,OAAO;QACN,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,UAAU;QAClB,KAAK,EAAE;YACN,GAAG,MAAM;YACT,UAAU;YACV,YAAY,EAAE,OAAO;gBACpB,CAAC,CAAC,uCAAuC,MAAM,EAAE;gBACjD,CAAC,CAAC,sCAAsC,MAAM,EAAE;SACjD;KACD,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CAAC,KAUrC;IACA,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS;QAAE,OAAO;IAC/C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,qBAAqB,GAAG,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,kBAAkB,CAAC;IAC9E,MAAM,MAAM,GAAoB;QAC/B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,qBAAqB;QACrB,kBAAkB,EAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,cAAc;QACzD,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE;KAClB,CAAC;IACF,IAAI,KAAK,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;QAC7C,MAAM,qBAAqB,GAAG,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,mBAAmB,CAAC;QAC/E,MAAM,8BAA8B,GACnC,qBAAqB,IAAI,+BAA+B;YACxD,qBAAqB,IAAI,2BAA2B,CAAC;QACtD,IAAI,CAAC,8BAA8B;YAAE,MAAM,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;IAC3F,CAAC;IACD,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC;QAAE,OAAO;IAC9C,IAAI,CAAC;QACJ,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACR,gDAAgD;IACjD,CAAC;AACF,CAAC;AAED,SAAS,iBAAiB,CAAC,KAA4B;IACtD,OAAO,CACN,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,CAAC;QACnG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CACtB,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CAAC,OAAqC,EAAE,YAAoB;IAC9F,MAAM,WAAW,GAAG,OAAO,EAAE,sBAAsB,CAAC;IACpD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3F,MAAM,iBAAiB,GAAG,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC;IAC9D,OAAO,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,iBAAiB,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC;AACpG,CAAC;AAED,SAAS,aAAa,CAAC,SAAiB,EAAE,SAAiB,EAAE,UAAkB;IAC9E,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,qBAAqB,CAAC,MAAuB;IACrD,MAAM,UAAU,GAAG,sBAAsB,CAAC,MAAM,CAAC,qBAAqB,CAAC;QACtE,CAAC,CAAC,MAAM,CAAC,qBAAqB;QAC9B,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC;IAChC,OAAO,eAAe,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAuB;IACpD,OAAO,eAAe,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,eAAe,CAAC,MAA0B,EAAE,UAA8B;IAClF,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7F,OAAO,MAAM,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,UAAU,CAAC,QAA4B,EAAE,IAAY,EAAE,eAAuB;IACtF,IAAI,QAAQ,KAAK,SAAS,IAAI,eAAe,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,QAAQ,GAAG,CAAC,CAAC,GAAG,eAAe,CAAC,GAAG,IAAI,GAAG,eAAe,CAAC;AAClE,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AACzE,CAAC","sourcesContent":["import { estimateProviderRequestTokens, type StreamFn, type StreamIdleOptions } from \"@caupulican/pi-agent-core\";\nimport { createAssistantMessageEventStream } from \"@caupulican/pi-ai/event-stream\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tContext,\n\tModel,\n\tProviderResponse,\n} from \"@caupulican/pi-ai/types\";\nimport { createEmptyUsage } from \"@caupulican/pi-ai/usage\";\n\nconst PERF_EWMA_ALPHA = 0.3;\nconst DEFERRED_HEADERS_MAX_GAP_MS = 100;\nconst DEFERRED_HEADERS_MIN_REQUEST_MS = 1_000;\nexport const DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS = 30 * 60 * 1000;\n\nexport interface ModelPerfProfile {\n\tprefillTokensPerSecond?: number;\n\tdecodeTokensPerSecond?: number;\n\tloadMs?: number;\n\tsamples: number;\n\tupdatedAt: string;\n}\n\nexport interface ModelPerfSample {\n\tpromptTokens?: number;\n\tcompletionTokens?: number;\n\theadersToFirstTokenMs?: number;\n\trequestToFirstTokenMs?: number;\n\tfirstTokenToDoneMs?: number;\n\tloadMs?: number;\n\tat?: string;\n}\n\nexport interface AdaptiveStreamIdleInput {\n\tbase: StreamIdleOptions;\n\tprofile?: ModelPerfProfile;\n\tpromptTokens: number;\n\tceilingMs?: number;\n\tlocalClass?: boolean;\n}\n\nexport interface ModelPerfProfileStreamRecorder {\n\tmodelKey: (model: Model<Api>) => string | undefined;\n\trecordSample: (modelKey: string, sample: ModelPerfSample) => void;\n\tnowMs?: () => number;\n\tnowIso?: () => string;\n}\n\nexport function isModelPerfProfile(value: unknown): value is ModelPerfProfile {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n\tconst record = value as Record<string, unknown>;\n\tconst samples = record.samples;\n\treturn (\n\t\t(record.prefillTokensPerSecond === undefined || isPositiveFiniteNumber(record.prefillTokensPerSecond)) &&\n\t\t(record.decodeTokensPerSecond === undefined || isPositiveFiniteNumber(record.decodeTokensPerSecond)) &&\n\t\t(record.loadMs === undefined || isPositiveFiniteNumber(record.loadMs)) &&\n\t\ttypeof samples === \"number\" &&\n\t\tNumber.isInteger(samples) &&\n\t\tsamples >= 0 &&\n\t\ttypeof record.updatedAt === \"string\"\n\t);\n}\n\nexport function hasUsableModelPerfSample(sample: ModelPerfSample): boolean {\n\treturn (\n\t\tprefillRateFromSample(sample) !== undefined ||\n\t\tdecodeRateFromSample(sample) !== undefined ||\n\t\tisPositiveFiniteNumber(sample.loadMs)\n\t);\n}\n\nexport function updateModelPerfProfile(\n\tcurrent: ModelPerfProfile | undefined,\n\tsample: ModelPerfSample,\n\tat: string = sample.at ?? new Date().toISOString(),\n): ModelPerfProfile | undefined {\n\tconst prefillRate = prefillRateFromSample(sample);\n\tconst decodeRate = decodeRateFromSample(sample);\n\tconst loadMs = isPositiveFiniteNumber(sample.loadMs) ? sample.loadMs : undefined;\n\tif (prefillRate === undefined && decodeRate === undefined && loadMs === undefined) return current;\n\n\tconst previousSamples = current?.samples ?? 0;\n\treturn {\n\t\t...(prefillRate !== undefined && {\n\t\t\tprefillTokensPerSecond: updateEwma(current?.prefillTokensPerSecond, prefillRate, previousSamples),\n\t\t}),\n\t\t...(prefillRate === undefined && current?.prefillTokensPerSecond !== undefined\n\t\t\t? { prefillTokensPerSecond: current.prefillTokensPerSecond }\n\t\t\t: {}),\n\t\t...(decodeRate !== undefined && {\n\t\t\tdecodeTokensPerSecond: updateEwma(current?.decodeTokensPerSecond, decodeRate, previousSamples),\n\t\t}),\n\t\t...(decodeRate === undefined && current?.decodeTokensPerSecond !== undefined\n\t\t\t? { decodeTokensPerSecond: current.decodeTokensPerSecond }\n\t\t\t: {}),\n\t\t...(loadMs !== undefined && { loadMs: updateEwma(current?.loadMs, loadMs, previousSamples) }),\n\t\t...(loadMs === undefined && current?.loadMs !== undefined ? { loadMs: current.loadMs } : {}),\n\t\tsamples: previousSamples + 1,\n\t\tupdatedAt: at,\n\t};\n}\n\nexport function resolveAdaptiveStreamIdleOptions(input: AdaptiveStreamIdleInput): Partial<StreamIdleOptions> {\n\tconst profile = input.profile;\n\tconst result: Partial<StreamIdleOptions> = {};\n\tconst localConnectDefaultMs = input.localClass\n\t\t? Math.max(input.base.connectMs, input.base.quietIdleMs)\n\t\t: input.base.connectMs;\n\tconst quietCeilingMs = Math.max(input.base.quietIdleMs, input.ceilingMs ?? DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS);\n\tconst connectCeilingMs = Math.max(localConnectDefaultMs, input.ceilingMs ?? DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS);\n\n\tconst expectedPrefillMs = expectedPrefillFromProfile(profile, input.promptTokens);\n\tif (expectedPrefillMs !== undefined) {\n\t\tconst quietIdleMs = adaptiveBound(input.base.quietIdleMs, quietCeilingMs, expectedPrefillMs);\n\t\tif (quietIdleMs > input.base.quietIdleMs) result.quietIdleMs = quietIdleMs;\n\t}\n\n\tif (input.localClass) {\n\t\tconst expectedConnectWorkMs =\n\t\t\texpectedPrefillMs !== undefined ? expectedPrefillMs + (profile?.loadMs ?? 0) : profile?.loadMs;\n\t\tconst connectMs =\n\t\t\texpectedConnectWorkMs !== undefined\n\t\t\t\t? adaptiveBound(localConnectDefaultMs, connectCeilingMs, expectedConnectWorkMs)\n\t\t\t\t: localConnectDefaultMs;\n\t\tif (connectMs > input.base.connectMs) result.connectMs = connectMs;\n\t}\n\n\treturn result;\n}\n\nexport function estimateContextPromptTokens(context: Context): number {\n\treturn estimateProviderRequestTokens(context);\n}\n\nexport function withModelPerfProfile(streamFn: StreamFn, recorder: ModelPerfProfileStreamRecorder): StreamFn {\n\treturn async (model, context, streamOptions) => {\n\t\tconst nowMs = recorder.nowMs ?? Date.now;\n\t\tconst nowIso = recorder.nowIso ?? (() => new Date().toISOString());\n\t\tconst requestStartedAtMs = nowMs();\n\t\tlet responseHeadersAtMs: number | undefined;\n\t\tlet firstTokenAtMs: number | undefined;\n\t\tconst originalOnResponse = streamOptions?.onResponse;\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tlet latest = emptyAssistantMessage(model);\n\t\tlet inner: Awaited<ReturnType<StreamFn>>;\n\t\ttry {\n\t\t\tinner = await streamFn(model, context, {\n\t\t\t\t...streamOptions,\n\t\t\t\tonResponse: async (response: ProviderResponse, responseModel: Model<Api>) => {\n\t\t\t\t\tresponseHeadersAtMs ??= nowMs();\n\t\t\t\t\tawait originalOnResponse?.(response, responseModel);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true, error));\n\t\t\treturn outer;\n\t\t}\n\n\t\tvoid (async () => {\n\t\t\tlet terminalPushed = false;\n\t\t\ttry {\n\t\t\t\tfor await (const event of inner) {\n\t\t\t\t\tlatest = assistantMessageFromEvent(event);\n\t\t\t\t\tif (firstTokenAtMs === undefined && isFirstTokenEvent(event)) {\n\t\t\t\t\t\tfirstTokenAtMs = nowMs();\n\t\t\t\t\t}\n\t\t\t\t\tif (event.type === \"done\") {\n\t\t\t\t\t\tterminalPushed = true;\n\t\t\t\t\t\trecordSuccessfulStreamSample({\n\t\t\t\t\t\t\tcompletionTokens: event.message.usage.output,\n\t\t\t\t\t\t\tdoneAtMs: nowMs(),\n\t\t\t\t\t\t\tfirstTokenAtMs,\n\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\tnowIso,\n\t\t\t\t\t\t\tpromptTokens:\n\t\t\t\t\t\t\t\tevent.message.usage.input + event.message.usage.cacheRead + event.message.usage.cacheWrite,\n\t\t\t\t\t\t\trecorder,\n\t\t\t\t\t\t\trequestStartedAtMs,\n\t\t\t\t\t\t\tresponseHeadersAtMs,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (event.type === \"error\") {\n\t\t\t\t\t\tterminalPushed = true;\n\t\t\t\t\t}\n\t\t\t\t\touter.push(event);\n\t\t\t\t\tif (terminalPushed) return;\n\t\t\t\t}\n\t\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true));\n\t\t\t} catch (error) {\n\t\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true, error));\n\t\t\t}\n\t\t})();\n\n\t\treturn outer;\n\t};\n}\n\nfunction assistantMessageFromEvent(event: AssistantMessageEvent): AssistantMessage {\n\tif (event.type === \"done\") return event.message;\n\tif (event.type === \"error\") return event.error;\n\treturn event.partial;\n}\n\nfunction emptyAssistantMessage(model: Model<Api>): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction perfStreamFailure(latest: AssistantMessage, aborted: boolean, error?: unknown): AssistantMessageEvent {\n\tconst stopReason = aborted ? \"aborted\" : \"error\";\n\tconst detail = error instanceof Error ? `: ${error.message}` : error === undefined ? \"\" : `: ${String(error)}`;\n\treturn {\n\t\ttype: \"error\",\n\t\treason: stopReason,\n\t\terror: {\n\t\t\t...latest,\n\t\t\tstopReason,\n\t\t\terrorMessage: aborted\n\t\t\t\t? `stream aborted before terminal event${detail}`\n\t\t\t\t: `stream ended without terminal event${detail}`,\n\t\t},\n\t};\n}\n\nfunction recordSuccessfulStreamSample(input: {\n\tmodel: Model<Api>;\n\trecorder: ModelPerfProfileStreamRecorder;\n\trequestStartedAtMs: number;\n\tresponseHeadersAtMs: number | undefined;\n\tfirstTokenAtMs: number | undefined;\n\tdoneAtMs: number;\n\tpromptTokens: number;\n\tcompletionTokens: number;\n\tnowIso: () => string;\n}): void {\n\tif (input.firstTokenAtMs === undefined) return;\n\tconst modelKey = input.recorder.modelKey(input.model);\n\tif (!modelKey) return;\n\tconst requestToFirstTokenMs = input.firstTokenAtMs - input.requestStartedAtMs;\n\tconst sample: ModelPerfSample = {\n\t\tpromptTokens: input.promptTokens,\n\t\tcompletionTokens: input.completionTokens,\n\t\trequestToFirstTokenMs,\n\t\tfirstTokenToDoneMs: input.doneAtMs - input.firstTokenAtMs,\n\t\tat: input.nowIso(),\n\t};\n\tif (input.responseHeadersAtMs !== undefined) {\n\t\tconst headersToFirstTokenMs = input.firstTokenAtMs - input.responseHeadersAtMs;\n\t\tconst headersWereEffectivelyDeferred =\n\t\t\trequestToFirstTokenMs >= DEFERRED_HEADERS_MIN_REQUEST_MS &&\n\t\t\theadersToFirstTokenMs <= DEFERRED_HEADERS_MAX_GAP_MS;\n\t\tif (!headersWereEffectivelyDeferred) sample.headersToFirstTokenMs = headersToFirstTokenMs;\n\t}\n\tif (!hasUsableModelPerfSample(sample)) return;\n\ttry {\n\t\tinput.recorder.recordSample(modelKey, sample);\n\t} catch {\n\t\t// Perf profiling must never fail the user turn.\n\t}\n}\n\nfunction isFirstTokenEvent(event: AssistantMessageEvent): boolean {\n\treturn (\n\t\t(event.type === \"text_delta\" || event.type === \"thinking_delta\" || event.type === \"toolcall_delta\") &&\n\t\tevent.delta.length > 0\n\t);\n}\n\nfunction expectedPrefillFromProfile(profile: ModelPerfProfile | undefined, promptTokens: number): number | undefined {\n\tconst prefillRate = profile?.prefillTokensPerSecond;\n\tif (!profile || profile.samples < 1 || !prefillRate || promptTokens <= 0) return undefined;\n\tconst expectedPrefillMs = (promptTokens / prefillRate) * 1000;\n\treturn Number.isFinite(expectedPrefillMs) && expectedPrefillMs > 0 ? expectedPrefillMs : undefined;\n}\n\nfunction adaptiveBound(defaultMs: number, ceilingMs: number, expectedMs: number): number {\n\treturn Math.min(Math.ceil(Math.max(defaultMs, expectedMs * 3)), ceilingMs);\n}\n\nfunction prefillRateFromSample(sample: ModelPerfSample): number | undefined {\n\tconst durationMs = isPositiveFiniteNumber(sample.headersToFirstTokenMs)\n\t\t? sample.headersToFirstTokenMs\n\t\t: sample.requestToFirstTokenMs;\n\treturn tokensPerSecond(sample.promptTokens, durationMs);\n}\n\nfunction decodeRateFromSample(sample: ModelPerfSample): number | undefined {\n\treturn tokensPerSecond(sample.completionTokens, sample.firstTokenToDoneMs);\n}\n\nfunction tokensPerSecond(tokens: number | undefined, durationMs: number | undefined): number | undefined {\n\tif (!isPositiveFiniteNumber(tokens) || !isPositiveFiniteNumber(durationMs)) return undefined;\n\treturn tokens / (durationMs / 1000);\n}\n\nfunction updateEwma(previous: number | undefined, next: number, previousSamples: number): number {\n\tif (previous === undefined || previousSamples === 0) return next;\n\treturn previous * (1 - PERF_EWMA_ALPHA) + next * PERF_EWMA_ALPHA;\n}\n\nfunction isPositiveFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { OrchestrationProfile, ToolCapabilityManifest } from "./contracts.ts";
|
|
2
2
|
export declare const CLASSIFIED_LANE_TOOL_NAMES: readonly ["read", "grep", "find", "ls", "write", "edit", "memory", "python", "run_process", "bash"];
|
|
3
|
-
export declare const ORCHESTRATION_PROFILE_TOOL_NAMES: readonly ["read", "grep", "find", "ls", "write", "edit", "memory", "python", "run_process", "bash", "delegate"
|
|
3
|
+
export declare const ORCHESTRATION_PROFILE_TOOL_NAMES: readonly ["read", "grep", "find", "ls", "write", "edit", "memory", "python", "run_process", "bash", "delegate"];
|
|
4
4
|
/**
|
|
5
5
|
* Manifest-only lane catalogue. It contains no tool factories, so policy compilation can omit
|
|
6
6
|
* denied tools before their executable implementations are constructed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lane-tool-manifests.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/lane-tool-manifests.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEnF,eAAO,MAAM,0BAA0B,YACtC,MAAM,EACN,MAAM,EACN,MAAM,EACN,IAAI,EACJ,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,MAAM,CACG,CAAC;AACX,eAAO,MAAM,gCAAgC,
|
|
1
|
+
{"version":3,"file":"lane-tool-manifests.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/lane-tool-manifests.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEnF,eAAO,MAAM,0BAA0B,YACtC,MAAM,EACN,MAAM,EACN,MAAM,EACN,IAAI,EACJ,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,MAAM,CACG,CAAC;AACX,eAAO,MAAM,gCAAgC,iHAAuD,CAAC;AAErG;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,oBAAoB,EAC7B,gBAAgB,EAAE,SAAS,MAAM,EAAE,GACjC,sBAAsB,EAAE,CAkB1B"}
|
|
@@ -12,12 +12,7 @@ export const CLASSIFIED_LANE_TOOL_NAMES = [
|
|
|
12
12
|
"run_process",
|
|
13
13
|
"bash",
|
|
14
14
|
];
|
|
15
|
-
export const ORCHESTRATION_PROFILE_TOOL_NAMES = [
|
|
16
|
-
...CLASSIFIED_LANE_TOOL_NAMES,
|
|
17
|
-
"delegate",
|
|
18
|
-
"delegate_status",
|
|
19
|
-
"profile_writer",
|
|
20
|
-
];
|
|
15
|
+
export const ORCHESTRATION_PROFILE_TOOL_NAMES = [...CLASSIFIED_LANE_TOOL_NAMES, "delegate"];
|
|
21
16
|
/**
|
|
22
17
|
* Manifest-only lane catalogue. It contains no tool factories, so policy compilation can omit
|
|
23
18
|
* denied tools before their executable implementations are constructed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lane-tool-manifests.js","sourceRoot":"","sources":["../../../src/core/orchestration/lane-tool-manifests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAGrG,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACzC,MAAM;IACN,MAAM;IACN,MAAM;IACN,IAAI;IACJ,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,MAAM;CACG,CAAC;AACX,MAAM,CAAC,MAAM,gCAAgC,GAAG
|
|
1
|
+
{"version":3,"file":"lane-tool-manifests.js","sourceRoot":"","sources":["../../../src/core/orchestration/lane-tool-manifests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAGrG,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACzC,MAAM;IACN,MAAM;IACN,MAAM;IACN,IAAI;IACJ,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,MAAM;CACG,CAAC;AACX,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,GAAG,0BAA0B,EAAE,UAAU,CAAU,CAAC;AAErG;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACrC,OAA6B,EAC7B,gBAAmC;IAEnC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC1C,MAAM,SAAS,GAA6B,EAAE,CAAC;IAE/C,KAAK,MAAM,QAAQ,IAAI,IAAI,GAAG,CAAC,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACrC,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,4BAA4B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnE,IAAI,CAAC,UAAU,IAAI,CAAC,MAAM;YAAE,SAAS;QACrC,SAAS,CAAC,IAAI,CAAC;YACd,QAAQ;YACR,eAAe,EAAE,YAAY,QAAQ,KAAK;YAC1C,YAAY,EAAE,CAAC,UAAU,CAAC;YAC1B,KAAK,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;YACrB,YAAY,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;SAClC,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC","sourcesContent":["import { mapToolNamesForPlatform } from \"../default-tool-surface.ts\";\nimport { getToolCapabilityPolicy, resolveProfileToolCapability } from \"../tool-capability-policy.ts\";\nimport type { OrchestrationProfile, ToolCapabilityManifest } from \"./contracts.ts\";\n\nexport const CLASSIFIED_LANE_TOOL_NAMES = [\n\t\"read\",\n\t\"grep\",\n\t\"find\",\n\t\"ls\",\n\t\"write\",\n\t\"edit\",\n\t\"memory\",\n\t\"python\",\n\t\"run_process\",\n\t\"bash\",\n] as const;\nexport const ORCHESTRATION_PROFILE_TOOL_NAMES = [...CLASSIFIED_LANE_TOOL_NAMES, \"delegate\"] as const;\n\n/**\n * Manifest-only lane catalogue. It contains no tool factories, so policy compilation can omit\n * denied tools before their executable implementations are constructed.\n */\nexport function buildLaneToolManifests(\n\tprofile: OrchestrationProfile,\n\tenabledToolNames: readonly string[],\n): ToolCapabilityManifest[] {\n\tconst enabled = new Set(enabledToolNames);\n\tconst manifests: ToolCapabilityManifest[] = [];\n\n\tfor (const toolName of new Set(mapToolNamesForPlatform(profile.toolNames))) {\n\t\tif (!enabled.has(toolName)) continue;\n\t\tconst policy = getToolCapabilityPolicy(toolName);\n\t\tconst capability = resolveProfileToolCapability(profile, toolName);\n\t\tif (!capability || !policy) continue;\n\t\tmanifests.push({\n\t\t\ttoolName,\n\t\t\tmoduleSpecifier: `../tools/${toolName}.ts`,\n\t\t\tcapabilities: [capability],\n\t\t\troles: [profile.role],\n\t\t\tenforcements: [policy.enforcement],\n\t\t});\n\t}\n\treturn manifests;\n}\n"]}
|
|
@@ -7,11 +7,11 @@ export function buildResumablePiAgentWakePrompt(payload) {
|
|
|
7
7
|
.slice(0, 20)
|
|
8
8
|
.map((pointer) => `- ${JSON.stringify({ id: pointer.id, kind: pointer.kind, uri: pointer.uri, readOnly: pointer.readOnly }).slice(0, 1_000)}`);
|
|
9
9
|
return [
|
|
10
|
-
"Resume
|
|
10
|
+
"Resume interrupted delegated task; same logical agent/session.",
|
|
11
11
|
...(taskSummary ? [`Task: ${taskSummary}`] : []),
|
|
12
12
|
...(context.latestCheckpointId ? [`Latest checkpoint: ${context.latestCheckpointId}`] : []),
|
|
13
|
-
...(contextPointers.length > 0 ? ["
|
|
14
|
-
"Continue
|
|
13
|
+
...(contextPointers.length > 0 ? ["Context pointers:", ...contextPointers] : []),
|
|
14
|
+
"Continue persisted transcript/checkpoints/artifacts; finish with persisted terminal result.",
|
|
15
15
|
].join("\n");
|
|
16
16
|
}
|
|
17
17
|
/** Launches one exact persisted Pi session; completion is observed only through process events. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume-launcher.js","sourceRoot":"","sources":["../../../src/core/process-matrix/resume-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAgB3E,MAAM,UAAU,+BAA+B,CAAC,OAAyB;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;IAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAChE,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe;SAC7C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CACH,CAAC,OAAO,EAAE,EAAE,CACX,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAC5H,CAAC;IACH,OAAO;QACN,
|
|
1
|
+
{"version":3,"file":"resume-launcher.js","sourceRoot":"","sources":["../../../src/core/process-matrix/resume-launcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { buildPiResumeLaunchSpec } from \"../orchestration/agent-resume.ts\";\nimport type { ResumablePayload } from \"./codes.ts\";\n\nexport interface PiSelfLaunchTarget {\n\texecutable: string;\n\targsPrefix: readonly string[];\n}\n\nexport type ResumablePiAgentLaunchOutcome =\n\t| {\n\t\t\tstarted: true;\n\t\t\tpid: number;\n\t\t\tcompletion: Promise<{ code: number | null; signal: NodeJS.Signals | null }>;\n\t }\n\t| { started: false; reason: string };\n\nexport function buildResumablePiAgentWakePrompt(payload: ResumablePayload): string {\n\tconst context = payload.agent.resumeContext;\n\tconst taskSummary = payload.taskSummary?.trim().slice(0, 2_000);\n\tconst contextPointers = context.contextPointers\n\t\t.slice(0, 20)\n\t\t.map(\n\t\t\t(pointer) =>\n\t\t\t\t`- ${JSON.stringify({ id: pointer.id, kind: pointer.kind, uri: pointer.uri, readOnly: pointer.readOnly }).slice(0, 1_000)}`,\n\t\t);\n\treturn [\n\t\t\"Resume interrupted delegated task; same logical agent/session.\",\n\t\t...(taskSummary ? [`Task: ${taskSummary}`] : []),\n\t\t...(context.latestCheckpointId ? [`Latest checkpoint: ${context.latestCheckpointId}`] : []),\n\t\t...(contextPointers.length > 0 ? [\"Context pointers:\", ...contextPointers] : []),\n\t\t\"Continue persisted transcript/checkpoints/artifacts; finish with persisted terminal result.\",\n\t].join(\"\\n\");\n}\n\n/** Launches one exact persisted Pi session; completion is observed only through process events. */\nexport async function launchResumablePiAgent(options: {\n\tpayload: ResumablePayload;\n\ttarget: PiSelfLaunchTarget;\n\tparentPid: number;\n\tparentSessionId: string;\n\tenvironment: NodeJS.ProcessEnv;\n}): Promise<ResumablePiAgentLaunchOutcome> {\n\tconst context = options.payload.agent.resumeContext;\n\tif (!context || context.provider !== \"pi\") {\n\t\treturn { started: false, reason: \"Pi resume context is unavailable.\" };\n\t}\n\tconst spec = buildPiResumeLaunchSpec(options.payload.agent, {\n\t\texecutable: options.target.executable,\n\t\targsPrefix: options.target.argsPrefix,\n\t\tparentPid: options.parentPid,\n\t\tparentSessionId: options.parentSessionId,\n\t\ttaskRef: options.payload.taskRef,\n\t\twakePrompt: buildResumablePiAgentWakePrompt(options.payload),\n\t});\n\tif ([spec.executable, spec.cwd, ...spec.args].some((value) => value.includes(\"\\0\"))) {\n\t\treturn { started: false, reason: \"Resume launch data contains a null byte.\" };\n\t}\n\ttry {\n\t\tconst child = spawn(spec.executable, spec.args, {\n\t\t\tcwd: spec.cwd,\n\t\t\tdetached: true,\n\t\t\tstdio: \"ignore\",\n\t\t\tenv: { ...options.environment, ...spec.env },\n\t\t});\n\t\treturn await new Promise<ResumablePiAgentLaunchOutcome>((resolve) => {\n\t\t\tchild.once(\"error\", (error) => resolve({ started: false, reason: error.message }));\n\t\t\tchild.once(\"spawn\", () => {\n\t\t\t\tconst childPid = child.pid;\n\t\t\t\tif (childPid === undefined || !Number.isSafeInteger(childPid) || childPid <= 0) {\n\t\t\t\t\tresolve({ started: false, reason: \"Resume process started without a valid pid.\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst completion = new Promise<{ code: number | null; signal: NodeJS.Signals | null }>(\n\t\t\t\t\t(resolveCompletion, rejectCompletion) => {\n\t\t\t\t\t\tchild.once(\"exit\", (code, signal) => resolveCompletion({ code, signal }));\n\t\t\t\t\t\tchild.once(\"error\", rejectCompletion);\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tchild.unref();\n\t\t\t\tresolve({ started: true, pid: childPid, completion });\n\t\t\t});\n\t\t});\n\t} catch (error) {\n\t\treturn { started: false, reason: error instanceof Error ? error.message : String(error) };\n\t}\n}\n"]}
|
|
@@ -81,6 +81,8 @@ export type ResumeWorkerLaunchOutcome = {
|
|
|
81
81
|
};
|
|
82
82
|
export interface ProcessMatrixRuntimeHandle {
|
|
83
83
|
stop(): Promise<void> | void;
|
|
84
|
+
/** Resolve after every watcher task that is active at the call boundary has settled. */
|
|
85
|
+
waitForIdle(): Promise<void>;
|
|
84
86
|
}
|
|
85
87
|
export declare const PROCESS_MATRIX_RESUMABLE_RETENTION_MS: number;
|
|
86
88
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/process-matrix/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAE3E,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAEN,WAAW,EACX,SAAS,EACT,sBAAsB,EACtB,UAAU,EACV,qBAAqB,EACrB,yBAAyB,EACzB,MAAM,YAAY,CAAC;AAgBpB,OAAO,EACN,uBAAuB,EACvB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,6BAA6B,EAC7B,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,GACf,MAAM,wBAAwB,CAAC;AAEhC;sFACsF;AACtF,MAAM,WAAW,sBAAsB;IACtC,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,yBAAyB,EAAE,OAAO,yBAAyB,CAAC;CAC5D;AAED,eAAO,MAAM,uBAAuB,EAAE,sBAOpC,CAAC;AAEH,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,EAAE,qBAAqB,CAAC;IAC7B,qFAAqF;IACrF,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,6BAA6B,CAAC;IACxC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,4FAA4F;IAC5F,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,wDAAwD;IACxD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,yFAAyF;IACzF,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD;yFACqF;IACrF,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0FAA0F;IAC1F,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;qFACiF;IACjF,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACjF,gGAAgG;IAChG,KAAK,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED,MAAM,MAAM,yBAAyB,GAClC;IACA,OAAO,EAAE,IAAI,CAAC;IACd,4FAA4F;IAC5F,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC3E,GACD;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,MAAM,WAAW,0BAA0B;IAC1C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC7B;AAGD,eAAO,MAAM,qCAAqC,QAAwB,CAAC;AAwB3E;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC9C,MAAM,EAAE,0BAA0B,GAChC,OAAO,CAAC,0BAA0B,CAAC,CAerC"}
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/process-matrix/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,7 +37,7 @@ export const localProcessMatrixStore = Object.freeze({
|
|
|
37
37
|
writeEntryIfUnchanged,
|
|
38
38
|
writeEntryIfUnchangedSync,
|
|
39
39
|
});
|
|
40
|
-
const NOOP_HANDLE = { stop: () => { } };
|
|
40
|
+
const NOOP_HANDLE = { stop: () => { }, waitForIdle: async () => { } };
|
|
41
41
|
export const PROCESS_MATRIX_RESUMABLE_RETENTION_MS = 30 * 24 * 60 * 60_000;
|
|
42
42
|
function resolveProcessMatrixStore(config) {
|
|
43
43
|
return config.store ?? localProcessMatrixStore;
|
|
@@ -147,6 +147,10 @@ async function startMasterBranch(config, now) {
|
|
|
147
147
|
config.onDiagnostic?.(`process-matrix: maintenance failed: ${describeError(error)}`);
|
|
148
148
|
});
|
|
149
149
|
return {
|
|
150
|
+
async waitForIdle() {
|
|
151
|
+
await maintenance;
|
|
152
|
+
await heartbeatTask;
|
|
153
|
+
},
|
|
150
154
|
async stop() {
|
|
151
155
|
if (stopped)
|
|
152
156
|
return;
|
|
@@ -490,7 +494,7 @@ async function startWorkerBranch(config, initialParentPid, now) {
|
|
|
490
494
|
let currentParentSessionId = parentSessionId;
|
|
491
495
|
let stopped = false;
|
|
492
496
|
let timer;
|
|
493
|
-
let
|
|
497
|
+
let watchTask;
|
|
494
498
|
let preserveResumableOnExit = false;
|
|
495
499
|
let stopTask;
|
|
496
500
|
const generationStartedAt = entry.startedAt;
|
|
@@ -576,15 +580,22 @@ async function startWorkerBranch(config, initialParentPid, now) {
|
|
|
576
580
|
await stop();
|
|
577
581
|
await config.requestExit();
|
|
578
582
|
};
|
|
583
|
+
const runWatchTick = (tick) => {
|
|
584
|
+
if (watchTask)
|
|
585
|
+
return watchTask;
|
|
586
|
+
const task = tick().finally(() => {
|
|
587
|
+
if (watchTask === task)
|
|
588
|
+
watchTask = undefined;
|
|
589
|
+
});
|
|
590
|
+
watchTask = task;
|
|
591
|
+
return task;
|
|
592
|
+
};
|
|
593
|
+
const waitForIdle = async () => {
|
|
594
|
+
while (watchTask)
|
|
595
|
+
await watchTask;
|
|
596
|
+
};
|
|
579
597
|
const startHealthyWatch = () => {
|
|
580
|
-
timer = setInterval(() =>
|
|
581
|
-
if (ticking)
|
|
582
|
-
return;
|
|
583
|
-
ticking = true;
|
|
584
|
-
void healthyTick().finally(() => {
|
|
585
|
-
ticking = false;
|
|
586
|
-
});
|
|
587
|
-
}, config.settings.watcherPollMs);
|
|
598
|
+
timer = setInterval(() => runWatchTick(healthyTick), config.settings.watcherPollMs);
|
|
588
599
|
timer.unref?.();
|
|
589
600
|
};
|
|
590
601
|
const declaredParentIsAlive = async () => {
|
|
@@ -638,14 +649,7 @@ async function startWorkerBranch(config, initialParentPid, now) {
|
|
|
638
649
|
};
|
|
639
650
|
const startGraceWatch = () => {
|
|
640
651
|
const graceDeadline = now() + config.settings.adoptionGraceMs;
|
|
641
|
-
timer = setInterval(() =>
|
|
642
|
-
if (ticking)
|
|
643
|
-
return;
|
|
644
|
-
ticking = true;
|
|
645
|
-
void graceTick(graceDeadline).finally(() => {
|
|
646
|
-
ticking = false;
|
|
647
|
-
});
|
|
648
|
-
}, config.settings.watcherPollMs);
|
|
652
|
+
timer = setInterval(() => runWatchTick(() => graceTick(graceDeadline)), config.settings.watcherPollMs);
|
|
649
653
|
timer.unref?.();
|
|
650
654
|
};
|
|
651
655
|
const graceTick = async (graceDeadline) => {
|
|
@@ -681,6 +685,6 @@ async function startWorkerBranch(config, initialParentPid, now) {
|
|
|
681
685
|
}
|
|
682
686
|
};
|
|
683
687
|
startHealthyWatch();
|
|
684
|
-
return { stop };
|
|
688
|
+
return { stop, waitForIdle };
|
|
685
689
|
}
|
|
686
690
|
//# sourceMappingURL=runtime.js.map
|