@qjp88995/agent-runtime 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-extensions.d.ts +30 -0
- package/dist/agent-extensions.d.ts.map +1 -0
- package/dist/agent-extensions.js +4 -0
- package/dist/agent-extensions.js.map +1 -0
- package/dist/builtins/ask-outcome.d.ts +49 -0
- package/dist/builtins/ask-outcome.d.ts.map +1 -0
- package/dist/builtins/ask-outcome.js +128 -0
- package/dist/builtins/ask-outcome.js.map +1 -0
- package/dist/builtins/ask-schema.d.ts +110 -0
- package/dist/builtins/ask-schema.d.ts.map +1 -0
- package/dist/builtins/ask-schema.js +124 -0
- package/dist/builtins/ask-schema.js.map +1 -0
- package/dist/builtins/ask.service.d.ts +210 -0
- package/dist/builtins/ask.service.d.ts.map +1 -0
- package/dist/builtins/ask.service.js +373 -0
- package/dist/builtins/ask.service.js.map +1 -0
- package/dist/builtins/ask.tool.d.ts +49 -0
- package/dist/builtins/ask.tool.d.ts.map +1 -0
- package/dist/builtins/ask.tool.js +109 -0
- package/dist/builtins/ask.tool.js.map +1 -0
- package/dist/builtins/index.d.ts +8 -0
- package/dist/builtins/index.d.ts.map +1 -0
- package/dist/builtins/index.js +8 -0
- package/dist/builtins/index.js.map +1 -0
- package/dist/builtins/todo-schema.d.ts +90 -0
- package/dist/builtins/todo-schema.d.ts.map +1 -0
- package/dist/builtins/todo-schema.js +97 -0
- package/dist/builtins/todo-schema.js.map +1 -0
- package/dist/builtins/todo-settle.hook.d.ts +110 -0
- package/dist/builtins/todo-settle.hook.d.ts.map +1 -0
- package/dist/builtins/todo-settle.hook.js +174 -0
- package/dist/builtins/todo-settle.hook.js.map +1 -0
- package/dist/builtins/todo.tool.d.ts +59 -0
- package/dist/builtins/todo.tool.d.ts.map +1 -0
- package/dist/builtins/todo.tool.js +107 -0
- package/dist/builtins/todo.tool.js.map +1 -0
- package/dist/context/context-budget-tracker.d.ts +185 -0
- package/dist/context/context-budget-tracker.d.ts.map +1 -0
- package/dist/context/context-budget-tracker.js +400 -0
- package/dist/context/context-budget-tracker.js.map +1 -0
- package/dist/context/context-budget.d.ts +48 -0
- package/dist/context/context-budget.d.ts.map +1 -0
- package/dist/context/context-budget.js +89 -0
- package/dist/context/context-budget.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +3 -0
- package/dist/context/index.js.map +1 -0
- package/dist/extensions/repeat-call.hook.d.ts +32 -0
- package/dist/extensions/repeat-call.hook.d.ts.map +1 -0
- package/dist/extensions/repeat-call.hook.js +54 -0
- package/dist/extensions/repeat-call.hook.js.map +1 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +3 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/turn-hook.registry.d.ts +51 -0
- package/dist/hooks/turn-hook.registry.d.ts.map +1 -0
- package/dist/hooks/turn-hook.registry.js +233 -0
- package/dist/hooks/turn-hook.registry.js.map +1 -0
- package/dist/hooks/turn-hook.types.d.ts +179 -0
- package/dist/hooks/turn-hook.types.d.ts.map +1 -0
- package/dist/hooks/turn-hook.types.js +48 -0
- package/dist/hooks/turn-hook.types.js.map +1 -0
- package/dist/images/byte-cache.d.ts +24 -0
- package/dist/images/byte-cache.d.ts.map +1 -0
- package/dist/images/byte-cache.js +51 -0
- package/dist/images/byte-cache.js.map +1 -0
- package/dist/images/delivery.d.ts +115 -0
- package/dist/images/delivery.d.ts.map +1 -0
- package/dist/images/delivery.js +321 -0
- package/dist/images/delivery.js.map +1 -0
- package/dist/images/index.d.ts +5 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +5 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/prompt.d.ts +151 -0
- package/dist/images/prompt.d.ts.map +1 -0
- package/dist/images/prompt.js +172 -0
- package/dist/images/prompt.js.map +1 -0
- package/dist/images/vendor-files.d.ts +93 -0
- package/dist/images/vendor-files.d.ts.map +1 -0
- package/dist/images/vendor-files.js +156 -0
- package/dist/images/vendor-files.js.map +1 -0
- package/dist/in-process/conversation-store.d.ts +64 -0
- package/dist/in-process/conversation-store.d.ts.map +1 -0
- package/dist/in-process/conversation-store.js +222 -0
- package/dist/in-process/conversation-store.js.map +1 -0
- package/dist/in-process/coordination.d.ts +54 -0
- package/dist/in-process/coordination.d.ts.map +1 -0
- package/dist/in-process/coordination.js +137 -0
- package/dist/in-process/coordination.js.map +1 -0
- package/dist/in-process/image-source.d.ts +15 -0
- package/dist/in-process/image-source.d.ts.map +1 -0
- package/dist/in-process/image-source.js +27 -0
- package/dist/in-process/image-source.js.map +1 -0
- package/dist/in-process/index.d.ts +36 -0
- package/dist/in-process/index.d.ts.map +1 -0
- package/dist/in-process/index.js +37 -0
- package/dist/in-process/index.js.map +1 -0
- package/dist/in-process/question-store.d.ts +28 -0
- package/dist/in-process/question-store.d.ts.map +1 -0
- package/dist/in-process/question-store.js +122 -0
- package/dist/in-process/question-store.js.map +1 -0
- package/dist/in-process/run-store.d.ts +36 -0
- package/dist/in-process/run-store.d.ts.map +1 -0
- package/dist/in-process/run-store.js +81 -0
- package/dist/in-process/run-store.js.map +1 -0
- package/dist/in-process/session-store.d.ts +33 -0
- package/dist/in-process/session-store.d.ts.map +1 -0
- package/dist/in-process/session-store.js +93 -0
- package/dist/in-process/session-store.js.map +1 -0
- package/dist/in-process/stream-bus.d.ts +52 -0
- package/dist/in-process/stream-bus.d.ts.map +1 -0
- package/dist/in-process/stream-bus.js +200 -0
- package/dist/in-process/stream-bus.js.map +1 -0
- package/dist/in-process/vendor-file-cache.d.ts +11 -0
- package/dist/in-process/vendor-file-cache.d.ts.map +1 -0
- package/dist/in-process/vendor-file-cache.js +47 -0
- package/dist/in-process/vendor-file-cache.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/loop/active-tick.registry.d.ts +31 -0
- package/dist/loop/active-tick.registry.d.ts.map +1 -0
- package/dist/loop/active-tick.registry.js +45 -0
- package/dist/loop/active-tick.registry.js.map +1 -0
- package/dist/loop/index.d.ts +6 -0
- package/dist/loop/index.d.ts.map +1 -0
- package/dist/loop/index.js +6 -0
- package/dist/loop/index.js.map +1 -0
- package/dist/loop/loop-driver.d.ts +127 -0
- package/dist/loop/loop-driver.d.ts.map +1 -0
- package/dist/loop/loop-driver.js +199 -0
- package/dist/loop/loop-driver.js.map +1 -0
- package/dist/loop/message-hub.d.ts +236 -0
- package/dist/loop/message-hub.d.ts.map +1 -0
- package/dist/loop/message-hub.js +439 -0
- package/dist/loop/message-hub.js.map +1 -0
- package/dist/loop/orphan-run.sweeper.d.ts +79 -0
- package/dist/loop/orphan-run.sweeper.d.ts.map +1 -0
- package/dist/loop/orphan-run.sweeper.js +145 -0
- package/dist/loop/orphan-run.sweeper.js.map +1 -0
- package/dist/loop/root-host.d.ts +51 -0
- package/dist/loop/root-host.d.ts.map +1 -0
- package/dist/loop/root-host.js +65 -0
- package/dist/loop/root-host.js.map +1 -0
- package/dist/ports/context-store.d.ts +69 -0
- package/dist/ports/context-store.d.ts.map +1 -0
- package/dist/ports/context-store.js +2 -0
- package/dist/ports/context-store.js.map +1 -0
- package/dist/ports/conversation-store.d.ts +144 -0
- package/dist/ports/conversation-store.d.ts.map +1 -0
- package/dist/ports/conversation-store.js +2 -0
- package/dist/ports/conversation-store.js.map +1 -0
- package/dist/ports/coordination.d.ts +76 -0
- package/dist/ports/coordination.d.ts.map +1 -0
- package/dist/ports/coordination.js +12 -0
- package/dist/ports/coordination.js.map +1 -0
- package/dist/ports/image-source.d.ts +26 -0
- package/dist/ports/image-source.d.ts.map +1 -0
- package/dist/ports/image-source.js +2 -0
- package/dist/ports/image-source.js.map +1 -0
- package/dist/ports/index.d.ts +11 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +4 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/ports/logger.d.ts +14 -0
- package/dist/ports/logger.d.ts.map +1 -0
- package/dist/ports/logger.js +23 -0
- package/dist/ports/logger.js.map +1 -0
- package/dist/ports/question-store.d.ts +91 -0
- package/dist/ports/question-store.d.ts.map +1 -0
- package/dist/ports/question-store.js +8 -0
- package/dist/ports/question-store.js.map +1 -0
- package/dist/ports/run-store.d.ts +66 -0
- package/dist/ports/run-store.d.ts.map +1 -0
- package/dist/ports/run-store.js +2 -0
- package/dist/ports/run-store.js.map +1 -0
- package/dist/ports/session-store.d.ts +72 -0
- package/dist/ports/session-store.d.ts.map +1 -0
- package/dist/ports/session-store.js +9 -0
- package/dist/ports/session-store.js.map +1 -0
- package/dist/ports/stream-bus.d.ts +52 -0
- package/dist/ports/stream-bus.d.ts.map +1 -0
- package/dist/ports/stream-bus.js +2 -0
- package/dist/ports/stream-bus.js.map +1 -0
- package/dist/ports/vendor-file-cache.d.ts +46 -0
- package/dist/ports/vendor-file-cache.d.ts.map +1 -0
- package/dist/ports/vendor-file-cache.js +2 -0
- package/dist/ports/vendor-file-cache.js.map +1 -0
- package/dist/schema/agent-event.d.ts +35 -0
- package/dist/schema/agent-event.d.ts.map +1 -0
- package/dist/schema/agent-event.js +46 -0
- package/dist/schema/agent-event.js.map +1 -0
- package/dist/schema/agent-run.d.ts +23 -0
- package/dist/schema/agent-run.d.ts.map +1 -0
- package/dist/schema/agent-run.js +37 -0
- package/dist/schema/agent-run.js.map +1 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +4 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/message-part.d.ts +73 -0
- package/dist/schema/message-part.d.ts.map +1 -0
- package/dist/schema/message-part.js +90 -0
- package/dist/schema/message-part.js.map +1 -0
- package/dist/subagent/delegate.tool.d.ts +145 -0
- package/dist/subagent/delegate.tool.d.ts.map +1 -0
- package/dist/subagent/delegate.tool.js +329 -0
- package/dist/subagent/delegate.tool.js.map +1 -0
- package/dist/subagent/index.d.ts +10 -0
- package/dist/subagent/index.d.ts.map +1 -0
- package/dist/subagent/index.js +10 -0
- package/dist/subagent/index.js.map +1 -0
- package/dist/subagent/milestone-body.d.ts +82 -0
- package/dist/subagent/milestone-body.d.ts.map +1 -0
- package/dist/subagent/milestone-body.js +112 -0
- package/dist/subagent/milestone-body.js.map +1 -0
- package/dist/subagent/output-scan.d.ts +14 -0
- package/dist/subagent/output-scan.d.ts.map +1 -0
- package/dist/subagent/output-scan.js +41 -0
- package/dist/subagent/output-scan.js.map +1 -0
- package/dist/subagent/registry-spawn-policy.d.ts +32 -0
- package/dist/subagent/registry-spawn-policy.d.ts.map +1 -0
- package/dist/subagent/registry-spawn-policy.js +48 -0
- package/dist/subagent/registry-spawn-policy.js.map +1 -0
- package/dist/subagent/roster-block.d.ts +45 -0
- package/dist/subagent/roster-block.d.ts.map +1 -0
- package/dist/subagent/roster-block.js +69 -0
- package/dist/subagent/roster-block.js.map +1 -0
- package/dist/subagent/situation-block.d.ts +16 -0
- package/dist/subagent/situation-block.d.ts.map +1 -0
- package/dist/subagent/situation-block.js +71 -0
- package/dist/subagent/situation-block.js.map +1 -0
- package/dist/subagent/spawn-guards.d.ts +32 -0
- package/dist/subagent/spawn-guards.d.ts.map +1 -0
- package/dist/subagent/spawn-guards.js +39 -0
- package/dist/subagent/spawn-guards.js.map +1 -0
- package/dist/subagent/subagent-registry.d.ts +150 -0
- package/dist/subagent/subagent-registry.d.ts.map +1 -0
- package/dist/subagent/subagent-registry.js +167 -0
- package/dist/subagent/subagent-registry.js.map +1 -0
- package/dist/subagent/subagent-sessions.d.ts +213 -0
- package/dist/subagent/subagent-sessions.d.ts.map +1 -0
- package/dist/subagent/subagent-sessions.js +295 -0
- package/dist/subagent/subagent-sessions.js.map +1 -0
- package/dist/testing/contracts.d.ts +37 -0
- package/dist/testing/contracts.d.ts.map +1 -0
- package/dist/testing/contracts.js +607 -0
- package/dist/testing/contracts.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/stub.d.ts +28 -0
- package/dist/testing/stub.d.ts.map +1 -0
- package/dist/testing/stub.js +3 -0
- package/dist/testing/stub.js.map +1 -0
- package/dist/tools/agent-tool.base.d.ts +186 -0
- package/dist/tools/agent-tool.base.d.ts.map +1 -0
- package/dist/tools/agent-tool.base.js +243 -0
- package/dist/tools/agent-tool.base.js.map +1 -0
- package/dist/tools/agent-tool.interface.d.ts +95 -0
- package/dist/tools/agent-tool.interface.d.ts.map +1 -0
- package/dist/tools/agent-tool.interface.js +2 -0
- package/dist/tools/agent-tool.interface.js.map +1 -0
- package/dist/tools/builtin-names.d.ts +18 -0
- package/dist/tools/builtin-names.d.ts.map +1 -0
- package/dist/tools/builtin-names.js +20 -0
- package/dist/tools/builtin-names.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/tool-definition.d.ts +18 -0
- package/dist/tools/tool-definition.d.ts.map +1 -0
- package/dist/tools/tool-definition.js +77 -0
- package/dist/tools/tool-definition.js.map +1 -0
- package/dist/tools/tool-meta.d.ts +55 -0
- package/dist/tools/tool-meta.d.ts.map +1 -0
- package/dist/tools/tool-meta.js +2 -0
- package/dist/tools/tool-meta.js.map +1 -0
- package/dist/tools/tool-registry.d.ts +190 -0
- package/dist/tools/tool-registry.d.ts.map +1 -0
- package/dist/tools/tool-registry.js +379 -0
- package/dist/tools/tool-registry.js.map +1 -0
- package/dist/tools/tool-result.d.ts +41 -0
- package/dist/tools/tool-result.d.ts.map +1 -0
- package/dist/tools/tool-result.js +19 -0
- package/dist/tools/tool-result.js.map +1 -0
- package/dist/tools/tool-wire.d.ts +24 -0
- package/dist/tools/tool-wire.d.ts.map +1 -0
- package/dist/tools/tool-wire.js +2 -0
- package/dist/tools/tool-wire.js.map +1 -0
- package/dist/turn/agent-runtime.d.ts +31 -0
- package/dist/turn/agent-runtime.d.ts.map +1 -0
- package/dist/turn/agent-runtime.js +30 -0
- package/dist/turn/agent-runtime.js.map +1 -0
- package/dist/turn/chunk-projection.d.ts +32 -0
- package/dist/turn/chunk-projection.d.ts.map +1 -0
- package/dist/turn/chunk-projection.js +62 -0
- package/dist/turn/chunk-projection.js.map +1 -0
- package/dist/turn/compaction.d.ts +48 -0
- package/dist/turn/compaction.d.ts.map +1 -0
- package/dist/turn/compaction.js +89 -0
- package/dist/turn/compaction.js.map +1 -0
- package/dist/turn/context-overflow.d.ts +11 -0
- package/dist/turn/context-overflow.d.ts.map +1 -0
- package/dist/turn/context-overflow.js +53 -0
- package/dist/turn/context-overflow.js.map +1 -0
- package/dist/turn/context-pressure.d.ts +100 -0
- package/dist/turn/context-pressure.d.ts.map +1 -0
- package/dist/turn/context-pressure.js +21 -0
- package/dist/turn/context-pressure.js.map +1 -0
- package/dist/turn/events-to-steps.d.ts +8 -0
- package/dist/turn/events-to-steps.d.ts.map +1 -0
- package/dist/turn/events-to-steps.js +64 -0
- package/dist/turn/events-to-steps.js.map +1 -0
- package/dist/turn/index.d.ts +17 -0
- package/dist/turn/index.d.ts.map +1 -0
- package/dist/turn/index.js +16 -0
- package/dist/turn/index.js.map +1 -0
- package/dist/turn/json-preview.d.ts +22 -0
- package/dist/turn/json-preview.d.ts.map +1 -0
- package/dist/turn/json-preview.js +34 -0
- package/dist/turn/json-preview.js.map +1 -0
- package/dist/turn/json-string-field.d.ts +30 -0
- package/dist/turn/json-string-field.d.ts.map +1 -0
- package/dist/turn/json-string-field.js +125 -0
- package/dist/turn/json-string-field.js.map +1 -0
- package/dist/turn/loop-reminder.d.ts +79 -0
- package/dist/turn/loop-reminder.d.ts.map +1 -0
- package/dist/turn/loop-reminder.js +0 -0
- package/dist/turn/loop-reminder.js.map +1 -0
- package/dist/turn/nul-safe.d.ts +21 -0
- package/dist/turn/nul-safe.d.ts.map +1 -0
- package/dist/turn/nul-safe.js +23 -0
- package/dist/turn/nul-safe.js.map +1 -0
- package/dist/turn/parts-from-events.d.ts +71 -0
- package/dist/turn/parts-from-events.d.ts.map +1 -0
- package/dist/turn/parts-from-events.js +217 -0
- package/dist/turn/parts-from-events.js.map +1 -0
- package/dist/turn/parts-to-model-messages.d.ts +158 -0
- package/dist/turn/parts-to-model-messages.d.ts.map +1 -0
- package/dist/turn/parts-to-model-messages.js +334 -0
- package/dist/turn/parts-to-model-messages.js.map +1 -0
- package/dist/turn/pending-work.d.ts +10 -0
- package/dist/turn/pending-work.d.ts.map +1 -0
- package/dist/turn/pending-work.js +14 -0
- package/dist/turn/pending-work.js.map +1 -0
- package/dist/turn/provider-error.d.ts +45 -0
- package/dist/turn/provider-error.d.ts.map +1 -0
- package/dist/turn/provider-error.js +154 -0
- package/dist/turn/provider-error.js.map +1 -0
- package/dist/turn/tool-input-preview.d.ts +94 -0
- package/dist/turn/tool-input-preview.d.ts.map +1 -0
- package/dist/turn/tool-input-preview.js +143 -0
- package/dist/turn/tool-input-preview.js.map +1 -0
- package/dist/turn/tool-input-progress.d.ts +47 -0
- package/dist/turn/tool-input-progress.d.ts.map +1 -0
- package/dist/turn/tool-input-progress.js +50 -0
- package/dist/turn/tool-input-progress.js.map +1 -0
- package/dist/turn/turn-envelope.d.ts +184 -0
- package/dist/turn/turn-envelope.d.ts.map +1 -0
- package/dist/turn/turn-envelope.js +2 -0
- package/dist/turn/turn-envelope.js.map +1 -0
- package/dist/turn/turn-journal.d.ts +49 -0
- package/dist/turn/turn-journal.d.ts.map +1 -0
- package/dist/turn/turn-journal.js +51 -0
- package/dist/turn/turn-journal.js.map +1 -0
- package/dist/turn/turn-run.d.ts +487 -0
- package/dist/turn/turn-run.d.ts.map +1 -0
- package/dist/turn/turn-run.js +1167 -0
- package/dist/turn/turn-run.js.map +1 -0
- package/dist/turn/usage.d.ts +27 -0
- package/dist/turn/usage.d.ts.map +1 -0
- package/dist/turn/usage.js +51 -0
- package/dist/turn/usage.js.map +1 -0
- package/package.json +55 -3
- package/src/agent-extensions.ts +33 -0
- package/src/builtins/ask-outcome.ts +168 -0
- package/src/builtins/ask-schema.ts +186 -0
- package/src/builtins/ask.service.ts +482 -0
- package/src/builtins/ask.tool.ts +138 -0
- package/src/builtins/index.ts +25 -0
- package/src/builtins/todo-schema.ts +108 -0
- package/src/builtins/todo-settle.hook.ts +221 -0
- package/src/builtins/todo.tool.ts +134 -0
- package/src/context/context-budget-tracker.ts +519 -0
- package/src/context/context-budget.ts +124 -0
- package/src/context/index.ts +17 -0
- package/src/extensions/repeat-call.hook.ts +77 -0
- package/src/hooks/index.ts +19 -0
- package/src/hooks/turn-hook.registry.ts +307 -0
- package/src/hooks/turn-hook.types.ts +210 -0
- package/src/images/byte-cache.ts +61 -0
- package/src/images/delivery.ts +508 -0
- package/src/images/index.ts +35 -0
- package/src/images/prompt.ts +289 -0
- package/src/images/vendor-files.ts +235 -0
- package/src/in-process/conversation-store.ts +304 -0
- package/src/in-process/coordination.ts +177 -0
- package/src/in-process/image-source.ts +29 -0
- package/src/in-process/index.ts +52 -0
- package/src/in-process/question-store.ts +155 -0
- package/src/in-process/run-store.ts +115 -0
- package/src/in-process/session-store.ts +118 -0
- package/src/in-process/stream-bus.ts +244 -0
- package/src/in-process/vendor-file-cache.ts +67 -0
- package/src/index.ts +28 -0
- package/src/loop/active-tick.registry.ts +49 -0
- package/src/loop/index.ts +25 -0
- package/src/loop/loop-driver.ts +275 -0
- package/src/loop/message-hub.ts +532 -0
- package/src/loop/orphan-run.sweeper.ts +204 -0
- package/src/loop/root-host.ts +119 -0
- package/src/ports/context-store.ts +71 -0
- package/src/ports/conversation-store.ts +165 -0
- package/src/ports/coordination.ts +81 -0
- package/src/ports/image-source.ts +26 -0
- package/src/ports/index.ts +56 -0
- package/src/ports/logger.ts +34 -0
- package/src/ports/question-store.ts +117 -0
- package/src/ports/run-store.ts +69 -0
- package/src/ports/session-store.ts +80 -0
- package/src/ports/stream-bus.ts +59 -0
- package/src/ports/vendor-file-cache.ts +54 -0
- package/src/schema/agent-event.ts +69 -0
- package/src/schema/agent-run.ts +44 -0
- package/src/schema/index.ts +25 -0
- package/src/schema/message-part.ts +100 -0
- package/src/subagent/delegate.tool.ts +476 -0
- package/src/subagent/index.ts +63 -0
- package/src/subagent/milestone-body.ts +144 -0
- package/src/subagent/output-scan.ts +56 -0
- package/src/subagent/registry-spawn-policy.ts +85 -0
- package/src/subagent/roster-block.ts +103 -0
- package/src/subagent/situation-block.ts +83 -0
- package/src/subagent/spawn-guards.ts +54 -0
- package/src/subagent/subagent-registry.ts +283 -0
- package/src/subagent/subagent-sessions.ts +496 -0
- package/src/testing/contracts.ts +882 -0
- package/src/testing/index.ts +14 -0
- package/src/testing/stub.ts +28 -0
- package/src/tools/agent-tool.base.ts +361 -0
- package/src/tools/agent-tool.interface.ts +101 -0
- package/src/tools/builtin-names.ts +26 -0
- package/src/tools/index.ts +39 -0
- package/src/tools/tool-definition.ts +93 -0
- package/src/tools/tool-meta.ts +60 -0
- package/src/tools/tool-registry.ts +513 -0
- package/src/tools/tool-result.ts +45 -0
- package/src/tools/tool-wire.ts +24 -0
- package/src/turn/agent-runtime.ts +43 -0
- package/src/turn/chunk-projection.ts +81 -0
- package/src/turn/compaction.ts +103 -0
- package/src/turn/context-overflow.ts +54 -0
- package/src/turn/context-pressure.ts +114 -0
- package/src/turn/events-to-steps.ts +73 -0
- package/src/turn/index.ts +71 -0
- package/src/turn/json-preview.ts +36 -0
- package/src/turn/json-string-field.ts +134 -0
- package/src/turn/loop-reminder.ts +0 -0
- package/src/turn/nul-safe.ts +22 -0
- package/src/turn/parts-from-events.ts +248 -0
- package/src/turn/parts-to-model-messages.ts +428 -0
- package/src/turn/pending-work.ts +14 -0
- package/src/turn/provider-error.ts +160 -0
- package/src/turn/tool-input-preview.ts +223 -0
- package/src/turn/tool-input-progress.ts +76 -0
- package/src/turn/turn-envelope.ts +185 -0
- package/src/turn/turn-journal.ts +102 -0
- package/src/turn/turn-run.ts +1479 -0
- package/src/turn/usage.ts +56 -0
- package/README.md +0 -3
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { extractJsonStringField } from './json-string-field.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 工具入参流式构建的**内容预览器**。
|
|
5
|
+
*
|
|
6
|
+
* 与 `tool-input-progress.ts` 分工:那条 tracker 答「写了多少」(字数,
|
|
7
|
+
* 不看内容),这条答「写了什么」——只对白名单工具实时抽出它入参里那个正文
|
|
8
|
+
* 字段(`Write.content`)的累计前缀,外加解析完整了的 `path`,供对话页的稿栏
|
|
9
|
+
* 边写边显示文件名与正文。
|
|
10
|
+
*
|
|
11
|
+
* 两个 tracker 各管一条事件(`tool-input-progress` / `tool-input-preview`),
|
|
12
|
+
* 互不知道对方;`chunk-projection.ts` 在同一处 `tool-input-delta` 分支里
|
|
13
|
+
* 各喂一遍。
|
|
14
|
+
*
|
|
15
|
+
* ## 成本(这一条决定了下面两道闸的形状)
|
|
16
|
+
*
|
|
17
|
+
* 每次 `delta` 都得**从头**重扫一遍累计的 `raw` 才能抽出字段值
|
|
18
|
+
* (`extractJsonStringField` 是线性扫描,没有可续跑的状态:转义与代理对的
|
|
19
|
+
* 收尾判定依赖上下文)。模型吐一篇长文约 120 块入参增量,若每块都扫一遍
|
|
20
|
+
* 就是 O(n²) 的字符比对,且每帧还要把整段前缀再发一次。
|
|
21
|
+
*
|
|
22
|
+
* 两道闸把它压回可接受:
|
|
23
|
+
* 1. **扫描前先看 `raw` 涨了多少**——解码后的字符数**恒不大于**原始 JSON 的
|
|
24
|
+
* 字符数(转义只会更长、代理对只会更多),所以「raw 涨的还不够一个阈值」
|
|
25
|
+
* 是「正文涨的也不够」的**必要条件**,此时连扫都不必扫。唯一例外是 `path`
|
|
26
|
+
* 还没解析完整那一段:第一帧必须尽早带上路径(稿栏靠它先开栏显示文件名),
|
|
27
|
+
* 那几块一律照扫。
|
|
28
|
+
* 2. **阈值随正文长度自适应**(`previewThreshold`):短文里每 80 码点发一条
|
|
29
|
+
* 才看得出「在写」;长文里正文本身已经几千字,再按 80 发就是每帧重发一份
|
|
30
|
+
* 越来越大的全量前缀。载荷语义仍是**累计前缀**(幂等,断线重放/去重下不会
|
|
31
|
+
* 拼错),只是发得更疏。
|
|
32
|
+
*
|
|
33
|
+
* 零依赖纯函数式实现,同一套单测风格(本仓既有做法:`tool-input-progress.ts`)。
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 阈值下限,也是短正文期间的实际阈值:每积累这么多字符发一条预览。
|
|
38
|
+
*
|
|
39
|
+
* 按「界面上正文多久长一截」定:模型出中文大约 100+ 字符/秒,80 约等于每秒
|
|
40
|
+
* 一次。再密只是徒增事件(每条都带全量前缀),再疏就开始像卡住了。
|
|
41
|
+
*/
|
|
42
|
+
export const TOOL_INPUT_PREVIEW_CHARS = 80;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 阈值上限。一篇 8000 字的稿子按 400 发也有 20 帧,够看出它在长;再放宽就
|
|
46
|
+
* 变成「写了半天才蹦一大段」。
|
|
47
|
+
*/
|
|
48
|
+
export const TOOL_INPUT_PREVIEW_CHARS_MAX = 400;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 已经发出 `chars` 个字符之后,下一条预览要等正文再涨多少。
|
|
52
|
+
*
|
|
53
|
+
* `chars / 8` 意味着「每帧最多把正文推进八分之一」——发出的总字节量随正文
|
|
54
|
+
* 长度线性(而不是平方)增长,界面上的推进感又与正文长度无关(短文每秒一
|
|
55
|
+
* 帧、长文每几秒一大段,都是「一直在长」)。
|
|
56
|
+
*
|
|
57
|
+
* @param floor 阈值下限,默认 `TOOL_INPUT_PREVIEW_CHARS`;测试用它把节流拨快。
|
|
58
|
+
*/
|
|
59
|
+
export function previewThreshold(
|
|
60
|
+
chars: number,
|
|
61
|
+
floor: number = TOOL_INPUT_PREVIEW_CHARS
|
|
62
|
+
): number {
|
|
63
|
+
return Math.max(
|
|
64
|
+
floor,
|
|
65
|
+
Math.min(Math.floor(chars / 8), TOOL_INPUT_PREVIEW_CHARS_MAX)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 白名单:只有登记在这里的工具才会被追踪,且只认这两个字段名。
|
|
71
|
+
*
|
|
72
|
+
* `path` 用来给稿栏定位文件;`text` 是要显示的正文字段,**为 `null` 表示这个
|
|
73
|
+
* 工具没有可预览的正文**——`Edit` 的入参是替换对(`old_string`/`new_string`)
|
|
74
|
+
* 而不是整篇,半截的替换对画不出任何东西。它仍然登记在这里,是因为稿栏需要
|
|
75
|
+
* 在 `Edit` 落盘之前就知道「agent 正在改哪份文件」(栏头显示「生成改动中」,
|
|
76
|
+
* 而不是等几十秒后才跳出一份改好的稿)。
|
|
77
|
+
*/
|
|
78
|
+
export const TOOL_INPUT_PREVIEW_FIELDS: Record<
|
|
79
|
+
string,
|
|
80
|
+
{ path: string; text: string | null }
|
|
81
|
+
> = {
|
|
82
|
+
Write: { path: 'path', text: 'content' },
|
|
83
|
+
Edit: { path: 'path', text: null },
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export interface ToolInputPreviewEvent {
|
|
87
|
+
toolCallId: string;
|
|
88
|
+
toolName: string;
|
|
89
|
+
/** 只有 `path` 字段解析**完整**了才不是 null(首次完整立刻发一条)。 */
|
|
90
|
+
path: string | null;
|
|
91
|
+
/** 正文字段的累计前缀(可能是 `''`;无正文字段的工具恒 `''`)。 */
|
|
92
|
+
text: string;
|
|
93
|
+
/** 至此 `text` 的码点数(与 `tool-input-progress` 同一判据)。 */
|
|
94
|
+
chars: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface ToolInputPreviewTracker {
|
|
98
|
+
/** 模型开始吐某次调用的参数。不在白名单的工具直接忽略,不建账。 */
|
|
99
|
+
start(toolCallId: string, toolName: string): void;
|
|
100
|
+
/**
|
|
101
|
+
* 收到一块入参增量。返回非 null 表示「该发一条预览了」。
|
|
102
|
+
*
|
|
103
|
+
* **未 `start` 过(或起手时就不在白名单)的 toolCallId 一律返回 null**。
|
|
104
|
+
*/
|
|
105
|
+
delta(toolCallId: string, text: string): ToolInputPreviewEvent | null;
|
|
106
|
+
/** 这次调用的参数收齐了,丢掉它的累计。 */
|
|
107
|
+
done(toolCallId: string): void;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** 按码点数,不是 UTF-16 code unit —— 与 tool-input-progress 同一判据。 */
|
|
111
|
+
function countCodePoints(text: string): number {
|
|
112
|
+
return Array.from(text).length;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function createToolInputPreviewTracker(
|
|
116
|
+
fields: Record<
|
|
117
|
+
string,
|
|
118
|
+
{ path: string; text: string | null }
|
|
119
|
+
> = TOOL_INPUT_PREVIEW_FIELDS,
|
|
120
|
+
thresholdChars: number = TOOL_INPUT_PREVIEW_CHARS
|
|
121
|
+
): ToolInputPreviewTracker {
|
|
122
|
+
const entries = new Map<
|
|
123
|
+
string,
|
|
124
|
+
{
|
|
125
|
+
toolName: string;
|
|
126
|
+
pathKey: string;
|
|
127
|
+
textKey: string | null;
|
|
128
|
+
raw: string;
|
|
129
|
+
/**
|
|
130
|
+
* `raw` 至今的码点数。**逐块累加而不是每次量整段**:量整段本身就是又一次
|
|
131
|
+
* O(n) 扫描,正是这道闸要省掉的东西。跨块劈开的代理对会被两半各算一个
|
|
132
|
+
* (多算一个),偏差方向是「以为涨得更多 → 提前扫一次」,只多花一次扫描,
|
|
133
|
+
* 不会漏发。
|
|
134
|
+
*/
|
|
135
|
+
rawChars: number;
|
|
136
|
+
path: string | null;
|
|
137
|
+
/** 上次发出时的正文码点数。 */
|
|
138
|
+
emittedChars: number;
|
|
139
|
+
/** 上次发出时的 `rawChars`。 */
|
|
140
|
+
emittedRawChars: number;
|
|
141
|
+
}
|
|
142
|
+
>();
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
start(toolCallId, toolName) {
|
|
146
|
+
const field = fields[toolName];
|
|
147
|
+
if (field === undefined) return; // 不在白名单,不建账——delta 恒 null
|
|
148
|
+
entries.set(toolCallId, {
|
|
149
|
+
toolName,
|
|
150
|
+
pathKey: field.path,
|
|
151
|
+
textKey: field.text,
|
|
152
|
+
raw: '',
|
|
153
|
+
rawChars: 0,
|
|
154
|
+
path: null,
|
|
155
|
+
emittedChars: 0,
|
|
156
|
+
emittedRawChars: 0,
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
delta(toolCallId, text) {
|
|
160
|
+
const e = entries.get(toolCallId);
|
|
161
|
+
if (e === undefined) return null;
|
|
162
|
+
e.raw += text;
|
|
163
|
+
e.rawChars += countCodePoints(text);
|
|
164
|
+
|
|
165
|
+
// `path` 一旦完整就不会再变(同一个 JSON 里只有一个顶层 `path`),不必
|
|
166
|
+
// 重扫;而它还没完整时**每块都要扫**——第一帧要尽快把路径带出去。
|
|
167
|
+
if (e.path === null) {
|
|
168
|
+
const pathResult = extractJsonStringField(e.raw, e.pathKey);
|
|
169
|
+
// 路径都还没齐,正文更不可能过阈值(正文在 JSON 里排在后面)。
|
|
170
|
+
if (pathResult === null || !pathResult.complete) return null;
|
|
171
|
+
e.path = pathResult.value;
|
|
172
|
+
// 「首次拿到完整 path」是独立于字数阈值的触发点——稿栏靠它在正文
|
|
173
|
+
// 到来之前先打开并显示文件名,晚了就是「先写了半天字才冒出标题」。
|
|
174
|
+
// 正文多半还是空串,但同一块里就带上了正文时也要如实发出去。
|
|
175
|
+
const seed = readText(e);
|
|
176
|
+
return emit(e, toolCallId, seed.text, seed.chars);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 没有正文字段的工具(`Edit`):路径那一条发完就再没有可发的了。
|
|
180
|
+
if (e.textKey === null) return null;
|
|
181
|
+
|
|
182
|
+
// 见头注释「成本」①:raw 涨得还不够一个阈值 → 正文必然也不够,不扫。
|
|
183
|
+
const threshold = previewThreshold(e.emittedChars, thresholdChars);
|
|
184
|
+
if (e.rawChars - e.emittedRawChars < threshold) return null;
|
|
185
|
+
|
|
186
|
+
const next = readText(e);
|
|
187
|
+
if (next.chars - e.emittedChars < threshold) return null;
|
|
188
|
+
|
|
189
|
+
return emit(e, toolCallId, next.text, next.chars);
|
|
190
|
+
},
|
|
191
|
+
done(toolCallId) {
|
|
192
|
+
entries.delete(toolCallId);
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/** 当前累计的正文前缀;无正文字段的工具恒 `('', 0)`。 */
|
|
197
|
+
function readText(e: { raw: string; textKey: string | null }): {
|
|
198
|
+
text: string;
|
|
199
|
+
chars: number;
|
|
200
|
+
} {
|
|
201
|
+
if (e.textKey === null) return { text: '', chars: 0 };
|
|
202
|
+
const result = extractJsonStringField(e.raw, e.textKey);
|
|
203
|
+
const text = result !== null ? result.value : '';
|
|
204
|
+
return { text, chars: countCodePoints(text) };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function emit(
|
|
208
|
+
e: {
|
|
209
|
+
toolName: string;
|
|
210
|
+
path: string | null;
|
|
211
|
+
rawChars: number;
|
|
212
|
+
emittedChars: number;
|
|
213
|
+
emittedRawChars: number;
|
|
214
|
+
},
|
|
215
|
+
toolCallId: string,
|
|
216
|
+
text: string,
|
|
217
|
+
chars: number
|
|
218
|
+
): ToolInputPreviewEvent {
|
|
219
|
+
e.emittedChars = chars;
|
|
220
|
+
e.emittedRawChars = e.rawChars;
|
|
221
|
+
return { toolCallId, toolName: e.toolName, path: e.path, text, chars };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具入参流式构建的**进度节流器**。
|
|
3
|
+
*
|
|
4
|
+
* **为什么需要它**:`emit('tool-call', …)` 发生在整个 step 的流被消费完之后
|
|
5
|
+
* (`runTurn` 里 `emit('text-end')` 之后那个 `for (const tc of toolCalls)`
|
|
6
|
+
* 循环),而模型吐这次调用参数的那段时间——写一篇长文时就是绝大部分时间——
|
|
7
|
+
* 界面上一片死寂:`tool-input-delta` 在 depth 0 从不投影,用户看到的是一个
|
|
8
|
+
* 停住的界面,只能当它卡了。
|
|
9
|
+
*
|
|
10
|
+
* **为什么不直接把 `tool-input-delta` 投出去**:那条流是**有消费方的**——
|
|
11
|
+
* `parts-from-events.ts` 的 abort 兜底靠累积它的原始 JSON 片段,在中断时重建
|
|
12
|
+
* 半截的 tool-call。它必须保持逐块、不节流、原样。而它作为 UI 信号又太碎
|
|
13
|
+
* (实测一次调用约 120 块),且投影层根本没有 `delta` 字段可透。
|
|
14
|
+
*
|
|
15
|
+
* 所以这里另发一条**只服务于界面**的进度事件:累积到一定字数才发一次,
|
|
16
|
+
* 载荷是「已经收到多少字符」而不是内容本身。
|
|
17
|
+
*
|
|
18
|
+
* 零依赖纯函数,便于单测(本仓既有做法:`running-nodes.ts`/`autosave-scheduler.ts`)。
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 每积累这么多字符发一条进度。
|
|
23
|
+
*
|
|
24
|
+
* 按「界面上那个数字多久动一次」定:模型出中文大约 100+ 字符/秒,故 120 约等于
|
|
25
|
+
* 每秒一次。再密只是徒增事件,再疏就又开始像卡住了。
|
|
26
|
+
*/
|
|
27
|
+
export const TOOL_INPUT_PROGRESS_CHARS = 120;
|
|
28
|
+
|
|
29
|
+
export interface ToolInputProgressEvent {
|
|
30
|
+
toolCallId: string;
|
|
31
|
+
toolName: string;
|
|
32
|
+
/** 至此累计收到的入参字符数(不是内容)。 */
|
|
33
|
+
chars: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ToolInputProgressTracker {
|
|
37
|
+
/** 模型开始吐某次调用的参数。 */
|
|
38
|
+
start(toolCallId: string, toolName: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* 收到一块入参增量。返回非 null 表示「该发一条进度了」。
|
|
41
|
+
*
|
|
42
|
+
* **未 `start` 过的 toolCallId 一律返回 null**:没有 `tool-input-start` 就
|
|
43
|
+
* 没有 toolName,发一条不知道是什么工具的进度,界面上无从落位。
|
|
44
|
+
*/
|
|
45
|
+
delta(toolCallId: string, text: string): ToolInputProgressEvent | null;
|
|
46
|
+
/** 这次调用的参数收齐了,丢掉它的累计(一个 turn 可以跑很多步)。 */
|
|
47
|
+
done(toolCallId: string): void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function createToolInputProgressTracker(
|
|
51
|
+
thresholdChars: number = TOOL_INPUT_PROGRESS_CHARS
|
|
52
|
+
): ToolInputProgressTracker {
|
|
53
|
+
const entries = new Map<
|
|
54
|
+
string,
|
|
55
|
+
{ toolName: string; chars: number; emittedAt: number }
|
|
56
|
+
>();
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
start(toolCallId, toolName) {
|
|
60
|
+
entries.set(toolCallId, { toolName, chars: 0, emittedAt: 0 });
|
|
61
|
+
},
|
|
62
|
+
delta(toolCallId, text) {
|
|
63
|
+
const e = entries.get(toolCallId);
|
|
64
|
+
if (e === undefined) return null;
|
|
65
|
+
// 按**码点**数,不是 UTF-16 code unit:中文一字一码点,而 `.length`
|
|
66
|
+
// 对 emoji 之类会翻倍——这个数字是给人看的「已经写了多少字」。
|
|
67
|
+
e.chars += Array.from(text).length;
|
|
68
|
+
if (e.chars - e.emittedAt < thresholdChars) return null;
|
|
69
|
+
e.emittedAt = e.chars;
|
|
70
|
+
return { toolCallId, toolName: e.toolName, chars: e.chars };
|
|
71
|
+
},
|
|
72
|
+
done(toolCallId) {
|
|
73
|
+
entries.delete(toolCallId);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import type { ModelMessage } from 'ai';
|
|
2
|
+
|
|
3
|
+
import type { MessagePart } from '../schema/index.js';
|
|
4
|
+
|
|
5
|
+
export interface TurnEnvelope {
|
|
6
|
+
/** agent 的 id(同 `AgentDefinition.id`)。 */
|
|
7
|
+
agentId: string;
|
|
8
|
+
/**
|
|
9
|
+
* 本轮实际用的模型与推理等级,记进跑次(`RunStore.open` 的 `model`)。取自模型句柄,内核不解释。
|
|
10
|
+
*/
|
|
11
|
+
modelUsed: { modelId: string; label: string; reasoningEffort: string };
|
|
12
|
+
/** 用户输入。 */
|
|
13
|
+
parts: MessagePart[];
|
|
14
|
+
/** 根 turn 的 id;同时是 StreamBus 的 streamId。 */
|
|
15
|
+
streamId: string;
|
|
16
|
+
/** 根会话 id(观测/产物树级作用域键;pre-1b 根 tick = sessionId)。 */
|
|
17
|
+
rootSessionId: string;
|
|
18
|
+
/** 当前 loop 的会话 id。 */
|
|
19
|
+
sessionId: string;
|
|
20
|
+
/** 本次执行的 run id(根 turn 与 streamId 可相同,子 agent 各自不同)。 */
|
|
21
|
+
runId: string;
|
|
22
|
+
parentRunId?: string | null;
|
|
23
|
+
depth?: number;
|
|
24
|
+
/**
|
|
25
|
+
* 宿主给这个跑次的不透明附加列(跑的是哪个 agent、发布版号、账本序号……),原样交给
|
|
26
|
+
* `RunStore.open` 的 `attrs`。内核不解释。
|
|
27
|
+
*/
|
|
28
|
+
runAttrs?: Readonly<Record<string, unknown>>;
|
|
29
|
+
/**
|
|
30
|
+
* 会话上的不透明附加信息,原样进 `ToolContext.sessionMetadata`(派子 Agent 时子会话继承)。
|
|
31
|
+
* 省略 = 空对象。
|
|
32
|
+
*/
|
|
33
|
+
sessionMetadata?: Readonly<Record<string, unknown>>;
|
|
34
|
+
userId?: string | null;
|
|
35
|
+
/**
|
|
36
|
+
* 本轮模型标了哪些能力(模型句柄的 `capabilities`)。内核只透传进
|
|
37
|
+
* `ToolContext.agent.modelCapabilities`。省略 = 空数组。
|
|
38
|
+
*/
|
|
39
|
+
modelCapabilities?: readonly string[];
|
|
40
|
+
/**
|
|
41
|
+
* 子 run 的宿主 agent 名(Plan 3 子 agent 用)。供前端画子轨道标题
|
|
42
|
+
* (Task 9);内核本身不消费。根 run 不传。
|
|
43
|
+
*/
|
|
44
|
+
agentName?: string;
|
|
45
|
+
/**
|
|
46
|
+
* 父写给子的 task prompt(Plan 3 子 agent 用)。供 run-start 事件
|
|
47
|
+
* 携带、UI 展示;内核本身不消费。根 run 不传。
|
|
48
|
+
*/
|
|
49
|
+
prompt?: string;
|
|
50
|
+
/**
|
|
51
|
+
* 子 run 的一句话任务标题(spawn 时模型显式提供,落在子会话 `title`)。
|
|
52
|
+
* 供 run-start 事件携带、前端子 Agent 卡做标题;内核本身不消费。根 run 不传。
|
|
53
|
+
*/
|
|
54
|
+
title?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* loop 从 inbox 领到的一条消息——内核只认 parts,不认 inbox 行结构。
|
|
59
|
+
* `metadata` 是可选的宿主级附加信息(当前唯一用途:tool_result 里程碑回投时
|
|
60
|
+
* 携带 `{ source }`,供 `onUserMessages` 落进 `chat_message.metadata`,供前端
|
|
61
|
+
* 未来渲染来源角标;内核本身不消费)。
|
|
62
|
+
*/
|
|
63
|
+
export interface DrainedTurnMessage {
|
|
64
|
+
/** 预生成的落库 id(root 的用户消息经 start() 预生成、inbox 透传);无则落库自生 uuid。 */
|
|
65
|
+
id?: string;
|
|
66
|
+
/** **落库的那份**——数据本身。`onUserMessages` 写的就是它。 */
|
|
67
|
+
parts: MessagePart[];
|
|
68
|
+
/**
|
|
69
|
+
* **注入模型的那份**——同一条消息的呈现形态,缺省即 `parts`。
|
|
70
|
+
*
|
|
71
|
+
* 当前唯一用途:子 Agent 回执要包进 `<subagent-result …>` 围栏(不可信外部
|
|
72
|
+
* 输入需要一条字节层面可判定的边界,见 `milestone-body.ts#wrapSubagentResult`),
|
|
73
|
+
* 而围栏是给模型看的、不该落进 `chat_message`——否则前端渲染回执气泡时还得
|
|
74
|
+
* 把标签剥回去,等于把一个自己刚拼上的格式再解析一遍。
|
|
75
|
+
*
|
|
76
|
+
* 内核对这层区分一无所知,只负责「push 进 messages 时优先用它」。
|
|
77
|
+
*/
|
|
78
|
+
modelParts?: MessagePart[];
|
|
79
|
+
metadata?: Record<string, unknown>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** 壳提供的宿主能力。内核对"消息存哪、怎么投递"一无所知。 */
|
|
83
|
+
export interface TurnHost {
|
|
84
|
+
/** 历史从哪来。必须返回 ModelMessage[],不许退化成 {role,content:string}[]。 */
|
|
85
|
+
loadContext(): Promise<ModelMessage[]>;
|
|
86
|
+
/** system prompt 拼装(可在 agent.systemPrompt 之上追加时间块等)。 */
|
|
87
|
+
assembleSystem(agentPrompt: string): Promise<string>;
|
|
88
|
+
/**
|
|
89
|
+
* 取出本会话 inbox 里排队的消息。**实现方必须在取出的同一个事务里落库**
|
|
90
|
+
* —— 取出是 DELETE,拆成「先取后写」两步的话,中间失败就两边都没有了。
|
|
91
|
+
* 内核因此不再有 `onUserMessages` 钩子(那正是被忘掉的第二步)。
|
|
92
|
+
*
|
|
93
|
+
* **一轮只调一次**(本轮第一次迭代),之后改用 `hasPendingInbox` 探测并
|
|
94
|
+
* 换轮,见那个方法。缺省(裸 host)视为恒空。
|
|
95
|
+
*/
|
|
96
|
+
drainInbox?(): Promise<DrainedTurnMessage[]>;
|
|
97
|
+
/**
|
|
98
|
+
* 探一眼 inbox 还有没有排队的消息 —— **只探不取**。
|
|
99
|
+
*
|
|
100
|
+
* 内核用它决定「换轮」:本轮第一次迭代照常 `drainInbox` 真取,之后每次调
|
|
101
|
+
* 模型前只探这一下,见货就收尾这一轮,把消息留给**下一个 tick** 的首次
|
|
102
|
+
* drain。新 runId / 新 `agent_run` / 新 assistant 行 / 新流全由既有的
|
|
103
|
+
* re-wake 白拿(`LoopDriverService.onWake` 释放锁后本来就查一次 inbox)。
|
|
104
|
+
*
|
|
105
|
+
* 这样插话在 `created_at` 上天然落在它引发的那段文字**之前**,不必再在
|
|
106
|
+
* 宿主里封口当前段落、把后续输出切到新的一行 —— 那套分段连同它散在六处
|
|
107
|
+
* 的判据(`persist` 盖哪一行、前端按 runId 聚合/收段…)由此整块消失。
|
|
108
|
+
*
|
|
109
|
+
* **第一次为什么不能也只探不取**:那样会话空闲时用户发一条消息就会
|
|
110
|
+
* 收尾 → re-wake → 又探到有货 → 收尾 …… 永远没人取走它。判据是 `TurnRun`
|
|
111
|
+
* 内部的一个局部标志(`drainedOnce`),投递方什么都不用知道。
|
|
112
|
+
*
|
|
113
|
+
* 缺省(不实现)= 恒 false = 永不换轮,裸 host 的行为因此不变。
|
|
114
|
+
*/
|
|
115
|
+
hasPendingInbox?(): Promise<boolean>;
|
|
116
|
+
/**
|
|
117
|
+
* 本轮又产出了这一截 parts(从事件账本重建,见 `TurnRun.flushStep`)——增量
|
|
118
|
+
* 落库。**只交增量**:调用方带着游标,同一条 part 不会交第二次。
|
|
119
|
+
*
|
|
120
|
+
* **不带 usage**:本轮的 usage 累加到终态一次性交给 `persist`,而这里曾经那个
|
|
121
|
+
* 参数从来没有实现方读过(宿主写的一直是 `usageAcc`)。一个没人读的参数迟早
|
|
122
|
+
* 会有人以为它写进了库。
|
|
123
|
+
*
|
|
124
|
+
* `uptoSeq`:这批 parts 覆盖到的最后一个事件的 seq(见
|
|
125
|
+
* `partsFromEventBufferWithBoundary`)。宿主把它与 parts 一起落库
|
|
126
|
+
* (`metadata.flushedSeq`),再据此让会话流退役 seq ≤ 它的事件。
|
|
127
|
+
*/
|
|
128
|
+
onAssistantStep?(parts: MessagePart[], uptoSeq: number | null): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* 收尾:盖终态。**不再交 parts** —— 这一轮产出过什么,`onAssistantStep` 已经
|
|
131
|
+
* 逐段交过了(终态路径也一样:内核在 `finish()` 里先把账本里剩下的那一截交
|
|
132
|
+
* 出去,再调这里)。宿主因此不必再判「这一轮到底落过库没有」,那套
|
|
133
|
+
* `wroteAnyStep` 分流随之消失。
|
|
134
|
+
*/
|
|
135
|
+
persist(result: TurnResult): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* 宿主为本轮**预置**的插件状态(键 = 插件的 `name`,取用见 `turnStateOf`)。
|
|
138
|
+
* 不给就是一张空表,插件各自懒建自己那一份。
|
|
139
|
+
*
|
|
140
|
+
* **这是个数据字段,不是能力方法**,存在的理由只有一条:有些 per-turn 对象
|
|
141
|
+
* 天生同时服务骨架与插件,而它必须是**同一个实例**。上下文预算的
|
|
142
|
+
* `ContextBudgetTracker` 就是——`loadContext()` 用它投影历史并留下轮初那批行
|
|
143
|
+
* 的快照,`beforeModelCall` 插件用同一份快照算切点、只替换 `messages` 的头部,
|
|
144
|
+
* 终态又用它落 `contextThreshold`。三方各建一个的话,`ContextRelief.replaces`
|
|
145
|
+
* 与内存里真实的头部长度就不是一回事,`splice` 会把尾部整体错位一格——**而那
|
|
146
|
+
* 是静默的**(历史与围栏消息一起被吃掉,没有任何报错)。
|
|
147
|
+
*
|
|
148
|
+
* 所以由**建它的那一方**(宿主,`loadContext` 的实现者)顺手挂在这里,而不是
|
|
149
|
+
* 让插件在切点上懒建:切点跑在第一次 `drainInbox` **之后**,那时本轮的用户
|
|
150
|
+
* 消息已经进库,懒建出来的快照会把它们算进可裁剪的阴影区。
|
|
151
|
+
*/
|
|
152
|
+
turnState?: Map<string, unknown>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export type TurnStatus = 'completed' | 'aborted' | 'rejected' | 'failed';
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 一轮的终态。**没有 `parts` 字段是有意的**(阶段 3):本轮产出过什么由
|
|
159
|
+
* `onAssistantStep` 逐段交出去,终态只回答「怎么结束的、花了多少」。
|
|
160
|
+
*
|
|
161
|
+
* 曾经它带着整轮重建出来的 parts,宿主再按「这一轮落过库没有」分流:落过就只
|
|
162
|
+
* 盖终态、没落过就拿这份补落一条。那套分流有两个已知漏洞(多步中途 abort、
|
|
163
|
+
* reviewOutput 改写:两者的 parts 都会在首步已落库之后才出现,于是被丢掉),
|
|
164
|
+
* 而漏洞的根在「同一批内容有两条落库路径」。现在只剩一条。
|
|
165
|
+
*/
|
|
166
|
+
export interface TurnResult {
|
|
167
|
+
streamId: string;
|
|
168
|
+
runId: string;
|
|
169
|
+
status: TurnStatus;
|
|
170
|
+
/** 最终文本(reviewOutput 改写后的)。 */
|
|
171
|
+
text: string;
|
|
172
|
+
usage?: Record<string, number>;
|
|
173
|
+
stopReason?: string;
|
|
174
|
+
error?: string;
|
|
175
|
+
/**
|
|
176
|
+
* **这一轮结束时上下文有多大** = 末步 provider 报的 `inputTokens` + 那一步的
|
|
177
|
+
* `outputTokens`(那条回复此刻已经在历史里,下一轮就是输入的一部分)。宿主
|
|
178
|
+
* 落进 `chat_message.metadata`,供下一轮开头当压力基线 —— 那一刻还没调过模型,
|
|
179
|
+
* 没有别的办法知道这个会话的上下文有多大。
|
|
180
|
+
*
|
|
181
|
+
* **与 `usage.inputTokens` 不是一回事**:后者是整轮各 step 的累加和(账单
|
|
182
|
+
* 口径,单步轮相等、多步轮按步数放大)。这个是一次快照。
|
|
183
|
+
*/
|
|
184
|
+
contextTokens?: number;
|
|
185
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Logger } from '../ports/logger.js';
|
|
2
|
+
import type { AgentEvent, AgentEventType } from '../schema/agent-event.js';
|
|
3
|
+
import type { TurnEnvelope } from './turn-envelope.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 一轮的事件账本。**同步 append、可回读**——事件流不只是对外广播,它同时是
|
|
7
|
+
* 内核自己的兜底状态源:`eventsToSteps` 靠它落 `agent_run.steps`,abort 与
|
|
8
|
+
* 失败路径靠 `partsFromEventBuffer(entries())` 重建这一轮已经产出的 parts。
|
|
9
|
+
*
|
|
10
|
+
* **绝不要把它改成异步或 fire-and-forget**:那两条路径会就此失去唯一的依据,
|
|
11
|
+
* 症状是「被中断的那一轮,已经打出来的字没了」。
|
|
12
|
+
*/
|
|
13
|
+
export interface TurnJournal {
|
|
14
|
+
/** 记一条并投递出去。**同步**,且在调用点的原位置调用。 */
|
|
15
|
+
append(type: AgentEventType, payload: unknown): void;
|
|
16
|
+
/** 回读:`eventsToSteps` / `partsFromEventBuffer` 的输入。 */
|
|
17
|
+
entries(): readonly AgentEvent[];
|
|
18
|
+
/**
|
|
19
|
+
* 把 `mark`(= 某一刻的 `entries().length`)之后的条目**物理删掉**,返回
|
|
20
|
+
* 被删的那些。
|
|
21
|
+
*
|
|
22
|
+
* 账本原则上只增不改——这是它唯一的例外,且只有一个合法调用方:一步的
|
|
23
|
+
* 模型调用在响应中途断连、内核要作废这一步的半截产出重发时
|
|
24
|
+
* (`turn-run.ts#settleStep`)。合法的前提是**被删的条目没有一条交给过宿主**:
|
|
25
|
+
* 从 `startInference` 到 `settleStep` 之间不会有任何 `flushStep`,所以这一
|
|
26
|
+
* 段账本还没有投影成任何落库 part,删掉它不会让库里出现「已经写进去又消失」
|
|
27
|
+
* 的东西。反过来说,删掉已经 flush 过的条目会让 `flushedParts` 游标指向一个
|
|
28
|
+
* 不再存在的前缀——那种错误不会报,只会让下一次 flush 把同一批 part 再落
|
|
29
|
+
* 一次。**别在别处调它。**
|
|
30
|
+
*
|
|
31
|
+
* 已投递出去的事件收不回来,这是刻意的:由调用方紧接着 append 一条
|
|
32
|
+
* `step-retract` 告诉订阅者「这一段作废」,seq 单调不复用,作废段与重发段
|
|
33
|
+
* 在流里天然可分。
|
|
34
|
+
*/
|
|
35
|
+
discardAfter(mark: number): AgentEvent[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface TurnJournalDeps {
|
|
39
|
+
envelope: TurnEnvelope;
|
|
40
|
+
/** 该 stream 的 seq 分配器(由壳 open 时取得)。 */
|
|
41
|
+
nextSeq: () => number;
|
|
42
|
+
/**
|
|
43
|
+
* 事件往哪去。**内核对此一无所知**:壳传本轮 recorder 的 `emit`(消息中心,
|
|
44
|
+
* 见 `TurnRecorder.emit`),单测传一个数组的 push。
|
|
45
|
+
*/
|
|
46
|
+
sink: (event: AgentEvent) => void;
|
|
47
|
+
/** sink 抛错时记一条 warn。缺省不记。 */
|
|
48
|
+
logger?: Logger;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createTurnJournal(deps: TurnJournalDeps): TurnJournal {
|
|
52
|
+
const { envelope, nextSeq, sink, logger } = deps;
|
|
53
|
+
const entries: AgentEvent[] = [];
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
append(type, payload) {
|
|
57
|
+
const event: AgentEvent = {
|
|
58
|
+
seq: nextSeq(),
|
|
59
|
+
streamId: envelope.streamId,
|
|
60
|
+
rootSessionId: envelope.rootSessionId,
|
|
61
|
+
sessionId: envelope.sessionId,
|
|
62
|
+
runId: envelope.runId,
|
|
63
|
+
// **恒等于 runId**:一轮一行,本轮 assistant 输出全部归属那一条。
|
|
64
|
+
//
|
|
65
|
+
// 曾经这里每次 append 都重新问一次宿主的 `assistantMessageId()`——软
|
|
66
|
+
// 插话会在轮中途封口当前段、把后续输出切到新的一行,缓存一次就等于把
|
|
67
|
+
// 插话之后的全部增量继续投递到已经封口的那条气泡上。那套分段随「换轮」
|
|
68
|
+
// 一起拆掉了(见 `TurnHost.hasPendingInbox`),宿主不再需要被问。
|
|
69
|
+
//
|
|
70
|
+
// **字段本身保留**:它是前端把流式增量路由到气泡的键(`chunk.id`),
|
|
71
|
+
// wire 形状因此逐字不变。
|
|
72
|
+
messageId: envelope.runId,
|
|
73
|
+
parentRunId: envelope.parentRunId ?? null,
|
|
74
|
+
depth: envelope.depth ?? 0,
|
|
75
|
+
ts: Date.now(),
|
|
76
|
+
type,
|
|
77
|
+
payload,
|
|
78
|
+
};
|
|
79
|
+
// **先记账后投递**:账本是承重的(abort 路径靠它重建 parts),sink 不是。
|
|
80
|
+
entries.push(event);
|
|
81
|
+
try {
|
|
82
|
+
sink(event);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
// 观测非承重:投递抛错绝不能把一轮成功的生成变成 failed。
|
|
85
|
+
// `RedisStreamBus.publish` 已经自己吞了序列化异常(那里有判据),但
|
|
86
|
+
// 账本不该假设每个 sink 都这么守规矩——这是最后一道。
|
|
87
|
+
//
|
|
88
|
+
// **不去重、不静默计数**:sink 抛错是 bug 不是常态,压掉只会让它更难
|
|
89
|
+
// 被发现。
|
|
90
|
+
logger?.warn(
|
|
91
|
+
`event sink threw for run ${envelope.runId} (${type}), event still recorded: ${String(err)}`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
entries() {
|
|
96
|
+
return entries;
|
|
97
|
+
},
|
|
98
|
+
discardAfter(mark) {
|
|
99
|
+
return entries.splice(mark);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|