@tomsun28/pizza 0.0.9 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -143
- package/README.zh-CN.md +36 -0
- package/dist/bun/cli.d.ts +2 -0
- package/dist/bun/cli.js +6 -0
- package/dist/bun/register-bedrock.d.ts +1 -0
- package/dist/bun/register-bedrock.js +3 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.js +330 -0
- package/dist/cli/config-selector.d.ts +13 -0
- package/dist/cli/config-selector.js +30 -0
- package/dist/cli/file-processor.d.ts +14 -0
- package/dist/cli/file-processor.js +82 -0
- package/dist/cli/initial-message.d.ts +17 -0
- package/dist/cli/initial-message.js +21 -0
- package/dist/cli/list-models.d.ts +8 -0
- package/dist/cli/list-models.js +96 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +68 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +223 -0
- package/dist/core/agent/index.d.ts +6 -0
- package/dist/core/agent/index.js +6 -0
- package/dist/core/agent/types.d.ts +202 -0
- package/dist/core/agent/types.js +51 -0
- package/dist/core/auth-storage.d.ts +135 -0
- package/dist/core/auth-storage.js +417 -0
- package/dist/core/bash-executor.d.ts +31 -0
- package/dist/core/bash-executor.js +107 -0
- package/dist/core/compaction/branch-summarization.d.ts +87 -0
- package/dist/core/compaction/branch-summarization.js +242 -0
- package/dist/core/compaction/compaction-engine.d.ts +40 -0
- package/dist/core/compaction/compaction-engine.js +292 -0
- package/dist/core/compaction/compaction.d.ts +106 -0
- package/dist/core/compaction/compaction.js +295 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/utils.d.ts +37 -0
- package/dist/core/compaction/utils.js +152 -0
- package/dist/core/defaults.d.ts +2 -0
- package/dist/core/defaults.js +1 -0
- package/dist/core/diagnostics.d.ts +14 -0
- package/dist/core/diagnostics.js +1 -0
- package/dist/core/event-bus.d.ts +8 -0
- package/dist/core/event-bus.js +24 -0
- package/dist/core/event-store/events.d.ts +465 -0
- package/dist/core/event-store/events.js +6 -0
- package/dist/core/event-store/index.d.ts +10 -0
- package/dist/core/event-store/index.js +10 -0
- package/dist/core/event-store/sqlite-store.d.ts +27 -0
- package/dist/core/event-store/sqlite-store.js +275 -0
- package/dist/core/event-store/store.d.ts +91 -0
- package/dist/core/event-store/store.js +7 -0
- package/dist/core/event-store/thread-scoped-store.d.ts +29 -0
- package/dist/core/event-store/thread-scoped-store.js +50 -0
- package/dist/core/event-store/types.d.ts +70 -0
- package/dist/core/event-store/types.js +7 -0
- package/dist/core/event-store/workspace.d.ts +37 -0
- package/dist/core/event-store/workspace.js +71 -0
- package/dist/core/exec.d.ts +28 -0
- package/dist/core/exec.js +74 -0
- package/dist/core/export-html/ansi-to-html.d.ts +21 -0
- package/dist/core/export-html/ansi-to-html.js +248 -0
- package/dist/core/export-html/index.d.ts +29 -0
- package/dist/core/export-html/index.js +186 -0
- package/dist/core/export-html/template.css +1017 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1742 -0
- package/dist/core/export-html/tool-renderer.d.ts +39 -0
- package/dist/core/export-html/tool-renderer.js +94 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.d.ts +12 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/loader.d.ts +24 -0
- package/dist/core/extensions/loader.js +492 -0
- package/dist/core/extensions/runner.d.ts +167 -0
- package/dist/core/extensions/runner.js +898 -0
- package/dist/core/extensions/session-context.d.ts +67 -0
- package/dist/core/extensions/session-context.js +272 -0
- package/dist/core/extensions/types.d.ts +1147 -0
- package/dist/core/extensions/types.js +44 -0
- package/dist/core/extensions/wrapper.d.ts +19 -0
- package/dist/core/extensions/wrapper.js +21 -0
- package/dist/core/footer-data-provider.d.ts +47 -0
- package/dist/core/footer-data-provider.js +321 -0
- package/dist/core/goal/index.d.ts +3 -0
- package/dist/core/goal/index.js +1 -0
- package/dist/core/goal/scheduler.d.ts +83 -0
- package/dist/core/goal/scheduler.js +154 -0
- package/dist/core/goal/types.d.ts +182 -0
- package/dist/core/goal/types.js +11 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +8 -0
- package/dist/core/intent/classifier.d.ts +53 -0
- package/dist/core/intent/classifier.js +353 -0
- package/dist/core/intent/index.d.ts +8 -0
- package/dist/core/intent/index.js +8 -0
- package/dist/core/intent/tool-adapter.d.ts +31 -0
- package/dist/core/intent/tool-adapter.js +168 -0
- package/dist/core/intent/types.d.ts +71 -0
- package/dist/core/intent/types.js +6 -0
- package/dist/core/keybindings.d.ts +297 -0
- package/dist/core/keybindings.js +250 -0
- package/dist/core/messages.d.ts +30 -0
- package/dist/core/messages.js +134 -0
- package/dist/core/model-registry.d.ts +131 -0
- package/dist/core/model-registry.js +634 -0
- package/dist/core/model-resolver.d.ts +109 -0
- package/dist/core/model-resolver.js +486 -0
- package/dist/core/output-guard.d.ts +5 -0
- package/dist/core/output-guard.js +58 -0
- package/dist/core/package-manager.d.ts +196 -0
- package/dist/core/package-manager.js +1873 -0
- package/dist/core/projection/boundary-inferrer.d.ts +58 -0
- package/dist/core/projection/boundary-inferrer.js +122 -0
- package/dist/core/projection/event-to-message.d.ts +35 -0
- package/dist/core/projection/event-to-message.js +253 -0
- package/dist/core/projection/goal-projection.d.ts +67 -0
- package/dist/core/projection/goal-projection.js +339 -0
- package/dist/core/projection/index.d.ts +13 -0
- package/dist/core/projection/index.js +13 -0
- package/dist/core/projection/session-manager.d.ts +100 -0
- package/dist/core/projection/session-manager.js +331 -0
- package/dist/core/projection/session-projection.d.ts +58 -0
- package/dist/core/projection/session-projection.js +257 -0
- package/dist/core/projection/task-history.d.ts +13 -0
- package/dist/core/projection/task-history.js +61 -0
- package/dist/core/projection/timeline-projection.d.ts +82 -0
- package/dist/core/projection/timeline-projection.js +276 -0
- package/dist/core/projection/types.d.ts +69 -0
- package/dist/core/projection/types.js +6 -0
- package/dist/core/prompt-templates.d.ts +51 -0
- package/dist/core/prompt-templates.js +249 -0
- package/dist/core/resolve-config-value.d.ts +22 -0
- package/dist/core/resolve-config-value.js +125 -0
- package/dist/core/resource-loader.d.ts +193 -0
- package/dist/core/resource-loader.js +685 -0
- package/dist/core/runtime/ai-client.d.ts +12 -0
- package/dist/core/runtime/ai-client.js +153 -0
- package/dist/core/runtime/checkpoint.d.ts +12 -0
- package/dist/core/runtime/checkpoint.js +78 -0
- package/dist/core/runtime/index.d.ts +12 -0
- package/dist/core/runtime/index.js +12 -0
- package/dist/core/runtime/llm-types.d.ts +99 -0
- package/dist/core/runtime/llm-types.js +6 -0
- package/dist/core/runtime/local-runtime.d.ts +23 -0
- package/dist/core/runtime/local-runtime.js +59 -0
- package/dist/core/runtime/policies.d.ts +72 -0
- package/dist/core/runtime/policies.js +37 -0
- package/dist/core/runtime/reactor.d.ts +213 -0
- package/dist/core/runtime/reactor.js +992 -0
- package/dist/core/runtime/runtime.d.ts +191 -0
- package/dist/core/runtime/runtime.js +449 -0
- package/dist/core/runtime/types.d.ts +42 -0
- package/dist/core/runtime/types.js +1 -0
- package/dist/core/sdk.d.ts +12 -0
- package/dist/core/sdk.js +10 -0
- package/dist/core/session-context-builder.d.ts +9 -0
- package/dist/core/session-context-builder.js +87 -0
- package/dist/core/session-cwd.d.ts +18 -0
- package/dist/core/session-cwd.js +36 -0
- package/dist/core/session-facade-factory.d.ts +79 -0
- package/dist/core/session-facade-factory.js +460 -0
- package/dist/core/session-facade.d.ts +57 -0
- package/dist/core/session-facade.js +91 -0
- package/dist/core/session-listing.d.ts +30 -0
- package/dist/core/session-listing.js +168 -0
- package/dist/core/session-reader.d.ts +19 -0
- package/dist/core/session-reader.js +101 -0
- package/dist/core/session-ref.d.ts +7 -0
- package/dist/core/session-ref.js +25 -0
- package/dist/core/session-services.d.ts +51 -0
- package/dist/core/session-services.js +90 -0
- package/dist/core/session-stats.d.ts +43 -0
- package/dist/core/session-stats.js +41 -0
- package/dist/core/settings-manager.d.ts +236 -0
- package/dist/core/settings-manager.js +706 -0
- package/dist/core/skill-block-parser.d.ts +12 -0
- package/dist/core/skill-block-parser.js +15 -0
- package/dist/core/skills.d.ts +59 -0
- package/dist/core/skills.js +408 -0
- package/dist/core/slash-commands.d.ts +13 -0
- package/dist/core/slash-commands.js +17 -0
- package/dist/core/source-info.d.ts +17 -0
- package/dist/core/source-info.js +18 -0
- package/dist/core/system-prompt.d.ts +27 -0
- package/dist/core/system-prompt.js +179 -0
- package/dist/core/timings.d.ts +7 -0
- package/dist/core/timings.js +30 -0
- package/dist/core/tools/bash.d.ts +95 -0
- package/dist/core/tools/bash.js +513 -0
- package/dist/core/tools/builtin-commands.d.ts +75 -0
- package/dist/core/tools/builtin-commands.js +503 -0
- package/dist/core/tools/compat-commands.d.ts +12 -0
- package/dist/core/tools/compat-commands.js +1280 -0
- package/dist/core/tools/edit-diff.d.ts +59 -0
- package/dist/core/tools/edit-diff.js +263 -0
- package/dist/core/tools/edit.d.ts +49 -0
- package/dist/core/tools/edit.js +340 -0
- package/dist/core/tools/file-mutation-queue.d.ts +5 -0
- package/dist/core/tools/file-mutation-queue.js +36 -0
- package/dist/core/tools/find.d.ts +34 -0
- package/dist/core/tools/find.js +459 -0
- package/dist/core/tools/grep.d.ts +36 -0
- package/dist/core/tools/grep.js +422 -0
- package/dist/core/tools/index.d.ts +70 -0
- package/dist/core/tools/index.js +129 -0
- package/dist/core/tools/line-anchors.d.ts +33 -0
- package/dist/core/tools/line-anchors.js +151 -0
- package/dist/core/tools/ls.d.ts +36 -0
- package/dist/core/tools/ls.js +268 -0
- package/dist/core/tools/path-utils.d.ts +7 -0
- package/dist/core/tools/path-utils.js +80 -0
- package/dist/core/tools/read.d.ts +35 -0
- package/dist/core/tools/read.js +244 -0
- package/dist/core/tools/render-utils.d.ts +20 -0
- package/dist/core/tools/render-utils.js +48 -0
- package/dist/core/tools/session-split.d.ts +9 -0
- package/dist/core/tools/session-split.js +77 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
- package/dist/core/tools/tool-definition-wrapper.js +32 -0
- package/dist/core/tools/truncate.d.ts +69 -0
- package/dist/core/tools/truncate.js +204 -0
- package/dist/core/tools/write.d.ts +25 -0
- package/dist/core/tools/write.js +211 -0
- package/dist/core/types/session-types.d.ts +123 -0
- package/dist/core/types/session-types.js +8 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +38 -0
- package/dist/main.d.ts +11 -2
- package/dist/main.js +577 -149
- package/dist/modes/event-mapper.d.ts +115 -0
- package/dist/modes/event-mapper.js +200 -0
- package/dist/modes/gui/server.d.ts +14 -0
- package/dist/modes/gui/server.js +1032 -0
- package/dist/modes/index.d.ts +10 -0
- package/dist/modes/index.js +9 -0
- package/dist/modes/interactive/assets/clankolas.png +0 -0
- package/dist/modes/interactive/components/armin.d.ts +33 -0
- package/dist/modes/interactive/components/armin.js +328 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
- package/dist/modes/interactive/components/assistant-message.js +115 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
- package/dist/modes/interactive/components/bash-execution.js +169 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
- package/dist/modes/interactive/components/bordered-loader.js +50 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/branch-summary-message.js +41 -0
- package/dist/modes/interactive/components/brand-header.d.ts +33 -0
- package/dist/modes/interactive/components/brand-header.js +235 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +42 -0
- package/dist/modes/interactive/components/config-selector.d.ts +70 -0
- package/dist/modes/interactive/components/config-selector.js +469 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
- package/dist/modes/interactive/components/countdown-timer.js +27 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +27 -0
- package/dist/modes/interactive/components/custom-editor.js +94 -0
- package/dist/modes/interactive/components/custom-message.d.ts +19 -0
- package/dist/modes/interactive/components/custom-message.js +73 -0
- package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
- package/dist/modes/interactive/components/daxnuts.js +137 -0
- package/dist/modes/interactive/components/diff.d.ts +11 -0
- package/dist/modes/interactive/components/diff.js +132 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
- package/dist/modes/interactive/components/dynamic-border.js +19 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
- package/dist/modes/interactive/components/earendil-announcement.js +39 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
- package/dist/modes/interactive/components/extension-editor.js +105 -0
- package/dist/modes/interactive/components/extension-input.d.ts +22 -0
- package/dist/modes/interactive/components/extension-input.js +54 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +23 -0
- package/dist/modes/interactive/components/extension-selector.js +70 -0
- package/dist/modes/interactive/components/footer.d.ts +55 -0
- package/dist/modes/interactive/components/footer.js +207 -0
- package/dist/modes/interactive/components/index.d.ts +31 -0
- package/dist/modes/interactive/components/index.js +32 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +7 -0
- package/dist/modes/interactive/components/keybinding-hints.js +21 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +41 -0
- package/dist/modes/interactive/components/login-dialog.js +138 -0
- package/dist/modes/interactive/components/model-selector.d.ts +32 -0
- package/dist/modes/interactive/components/model-selector.js +209 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +18 -0
- package/dist/modes/interactive/components/oauth-selector.js +91 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +57 -0
- package/dist/modes/interactive/components/settings-selector.js +299 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
- package/dist/modes/interactive/components/show-images-selector.js +37 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +44 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
- package/dist/modes/interactive/components/theme-selector.js +47 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
- package/dist/modes/interactive/components/thinking-selector.js +50 -0
- package/dist/modes/interactive/components/timeline-view.d.ts +31 -0
- package/dist/modes/interactive/components/timeline-view.js +81 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +64 -0
- package/dist/modes/interactive/components/tool-execution.js +305 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
- package/dist/modes/interactive/components/tree-selector.js +1072 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
- package/dist/modes/interactive/components/user-message-selector.js +110 -0
- package/dist/modes/interactive/components/user-message.d.ts +9 -0
- package/dist/modes/interactive/components/user-message.js +27 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
- package/dist/modes/interactive/components/visual-truncate.js +32 -0
- package/dist/modes/interactive/interactive-mode.d.ts +394 -0
- package/dist/modes/interactive/interactive-mode.js +4116 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.d.ts +80 -0
- package/dist/modes/interactive/theme/theme.js +973 -0
- package/dist/modes/print-mode.d.ts +27 -0
- package/dist/modes/print-mode.js +102 -0
- package/dist/modes/rpc/jsonl.d.ts +16 -0
- package/dist/modes/rpc/jsonl.js +48 -0
- package/dist/modes/rpc/rpc-client.d.ts +219 -0
- package/dist/modes/rpc/rpc-client.js +405 -0
- package/dist/modes/rpc/rpc-mode.d.ts +19 -0
- package/dist/modes/rpc/rpc-mode.js +381 -0
- package/dist/modes/rpc/rpc-types.d.ts +406 -0
- package/dist/modes/rpc/rpc-types.js +7 -0
- package/dist/package-manager-cli.d.ts +3 -0
- package/dist/package-manager-cli.js +233 -0
- package/dist/utils/changelog.d.ts +20 -0
- package/dist/utils/changelog.js +86 -0
- package/dist/utils/child-process.d.ts +10 -0
- package/dist/utils/child-process.js +77 -0
- package/dist/utils/clipboard-image.d.ts +10 -0
- package/dist/utils/clipboard-image.js +244 -0
- package/dist/utils/clipboard-native.d.ts +7 -0
- package/dist/utils/clipboard-native.js +13 -0
- package/dist/utils/clipboard.d.ts +1 -0
- package/dist/utils/clipboard.js +77 -0
- package/dist/utils/exif-orientation.d.ts +4 -0
- package/dist/utils/exif-orientation.js +157 -0
- package/dist/utils/frontmatter.d.ts +7 -0
- package/dist/utils/frontmatter.js +25 -0
- package/dist/utils/git.d.ts +25 -0
- package/dist/utils/git.js +162 -0
- package/dist/utils/image-convert.d.ts +8 -0
- package/dist/utils/image-convert.js +38 -0
- package/dist/utils/image-resize.d.ts +35 -0
- package/dist/utils/image-resize.js +136 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.js +25 -0
- package/dist/utils/path-shims.d.ts +1 -0
- package/dist/utils/path-shims.js +90 -0
- package/dist/utils/paths.d.ts +6 -0
- package/dist/utils/paths.js +18 -0
- package/dist/utils/photon.d.ts +20 -0
- package/dist/utils/photon.js +120 -0
- package/dist/utils/shell.d.ts +29 -0
- package/dist/utils/shell.js +189 -0
- package/dist/utils/sleep.d.ts +4 -0
- package/dist/utils/sleep.js +16 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.js +101 -0
- package/dist/vendor/bin/darwin-arm64/fd +0 -0
- package/dist/vendor/bin/darwin-arm64/rg +0 -0
- package/dist/vendor/bin/darwin-x64/fd +0 -0
- package/dist/vendor/bin/darwin-x64/rg +0 -0
- package/dist/vendor/bin/linux-arm64/fd +0 -0
- package/dist/vendor/bin/linux-arm64/rg +0 -0
- package/dist/vendor/bin/linux-x64/fd +0 -0
- package/dist/vendor/bin/linux-x64/rg +0 -0
- package/dist/vendor/bin/win32-arm64/fd.exe +0 -0
- package/dist/vendor/bin/win32-arm64/rg.exe +0 -0
- package/dist/vendor/bin/win32-x64/fd.exe +0 -0
- package/dist/vendor/bin/win32-x64/rg.exe +0 -0
- package/package.json +90 -26
- package/dist/extension/core.d.ts +0 -69
- package/dist/extension/core.js +0 -270
- package/dist/extension/core.js.map +0 -1
- package/dist/extension/index.d.ts +0 -25
- package/dist/extension/index.js +0 -303
- package/dist/extension/index.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/themes/pizza.json +0 -87
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Manager (Event-Sourced)
|
|
3
|
+
*
|
|
4
|
+
* Manages session descriptors, not session data.
|
|
5
|
+
* Data lives in EventStore. Session is just a query view.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { SessionProjection } from "./session-projection.js";
|
|
9
|
+
import { SessionBoundaryInferrer } from "./boundary-inferrer.js";
|
|
10
|
+
import { getSessionIndexPath } from "../event-store/workspace.js";
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Session Manager
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* SessionManager - manages session descriptors only.
|
|
16
|
+
*
|
|
17
|
+
* Storage: ~/.pizza/agent/workspaces/<workspace_id>/sessions.json
|
|
18
|
+
*
|
|
19
|
+
* Does NOT store messages. Tree structure emerges from EventStore's caused_by chain.
|
|
20
|
+
*/
|
|
21
|
+
export class SessionManager {
|
|
22
|
+
constructor(store, storagePath) {
|
|
23
|
+
this.store = store;
|
|
24
|
+
this.threads = new Map();
|
|
25
|
+
this.sessions = new Map();
|
|
26
|
+
this.inferrer = new SessionBoundaryInferrer();
|
|
27
|
+
this.filePath = storagePath === ":memory:" ? undefined : (storagePath ?? getSessionIndexPath(store.workspace_id));
|
|
28
|
+
if (this.filePath) {
|
|
29
|
+
this._ensureStorageDir();
|
|
30
|
+
this._loadIndex();
|
|
31
|
+
}
|
|
32
|
+
this._subscribeToEvents();
|
|
33
|
+
}
|
|
34
|
+
// =========================================================================
|
|
35
|
+
// Session Operations
|
|
36
|
+
// =========================================================================
|
|
37
|
+
/**
|
|
38
|
+
* Get or create the active session.
|
|
39
|
+
*/
|
|
40
|
+
getActiveSession() {
|
|
41
|
+
if (!this.activeThreadId) {
|
|
42
|
+
this.createThread();
|
|
43
|
+
}
|
|
44
|
+
if (!this.activeSessionId) {
|
|
45
|
+
this.createSession("user_explicit", undefined, { threadId: this.activeThreadId });
|
|
46
|
+
}
|
|
47
|
+
const desc = this.sessions.get(this.activeSessionId);
|
|
48
|
+
return new SessionProjection(this.store, desc);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create a new session.
|
|
52
|
+
*/
|
|
53
|
+
createSession(created_by, name, options = {}) {
|
|
54
|
+
const threadId = options.threadId ?? this.activeThreadId ?? this._createThreadRecord().thread_id;
|
|
55
|
+
const previousActiveId = options.closeActive !== false ? this.activeSessionId : undefined;
|
|
56
|
+
const desc = {
|
|
57
|
+
session_id: this._generateSessionId(),
|
|
58
|
+
thread_id: threadId,
|
|
59
|
+
workspace_id: this.store.workspace_id,
|
|
60
|
+
event_range: {
|
|
61
|
+
start_event_id: options.startEventId ?? this.store.head ?? "ORIGIN",
|
|
62
|
+
end_event_id: "HEAD",
|
|
63
|
+
},
|
|
64
|
+
summary_event_id: options.summaryEventId,
|
|
65
|
+
name,
|
|
66
|
+
created_by,
|
|
67
|
+
parent_session_id: options.parentSessionId,
|
|
68
|
+
created_at: Date.now(),
|
|
69
|
+
};
|
|
70
|
+
this.sessions.set(desc.session_id, desc);
|
|
71
|
+
this.activeSessionId = desc.session_id;
|
|
72
|
+
// Emit session created event
|
|
73
|
+
const createdEvent = this.store.append({
|
|
74
|
+
actor_id: "runtime",
|
|
75
|
+
type: "SESSION_CREATED",
|
|
76
|
+
payload: { session_id: desc.session_id, name, created_by },
|
|
77
|
+
thread_id: desc.thread_id,
|
|
78
|
+
});
|
|
79
|
+
const previousActive = previousActiveId ? this.sessions.get(previousActiveId) : undefined;
|
|
80
|
+
if (previousActive && previousActive.thread_id === threadId && previousActive.event_range.end_event_id === "HEAD") {
|
|
81
|
+
previousActive.event_range.end_event_id = createdEvent.event_id;
|
|
82
|
+
}
|
|
83
|
+
this._persistIndex();
|
|
84
|
+
return desc;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Fork the current session at a specific event.
|
|
88
|
+
*/
|
|
89
|
+
forkAt(event_id) {
|
|
90
|
+
const active = this.getActiveSession();
|
|
91
|
+
const forked = active.fork(event_id);
|
|
92
|
+
this.sessions.set(forked.session_id, forked);
|
|
93
|
+
this.activeSessionId = forked.session_id;
|
|
94
|
+
this._persistIndex();
|
|
95
|
+
this.store.append({
|
|
96
|
+
actor_id: "runtime",
|
|
97
|
+
type: "SESSION_FORKED",
|
|
98
|
+
payload: {
|
|
99
|
+
new_session_id: forked.session_id,
|
|
100
|
+
parent_session_id: forked.parent_session_id,
|
|
101
|
+
fork_at_event_id: event_id,
|
|
102
|
+
},
|
|
103
|
+
thread_id: forked.thread_id,
|
|
104
|
+
});
|
|
105
|
+
return forked;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Fork an existing session while preserving its projected history.
|
|
109
|
+
*
|
|
110
|
+
* The source session is frozen at the current head if it was tracking HEAD,
|
|
111
|
+
* and the forked descriptor reuses the source start boundary so context still
|
|
112
|
+
* includes the source conversation.
|
|
113
|
+
*/
|
|
114
|
+
forkFromSession(session_id) {
|
|
115
|
+
const source = this.sessions.get(session_id);
|
|
116
|
+
if (!source) {
|
|
117
|
+
throw new Error(`Session not found: ${session_id}`);
|
|
118
|
+
}
|
|
119
|
+
const forkAtEventId = source.event_range.end_event_id === "HEAD"
|
|
120
|
+
? this.store.head ?? source.event_range.start_event_id
|
|
121
|
+
: source.event_range.end_event_id;
|
|
122
|
+
if (source.event_range.end_event_id === "HEAD") {
|
|
123
|
+
this.activeSessionId = source.session_id;
|
|
124
|
+
}
|
|
125
|
+
const forked = this.createSession("fork", source.name, {
|
|
126
|
+
parentSessionId: source.session_id,
|
|
127
|
+
startEventId: source.event_range.start_event_id,
|
|
128
|
+
summaryEventId: source.summary_event_id,
|
|
129
|
+
});
|
|
130
|
+
this.store.append({
|
|
131
|
+
actor_id: "runtime",
|
|
132
|
+
type: "SESSION_FORKED",
|
|
133
|
+
payload: {
|
|
134
|
+
new_session_id: forked.session_id,
|
|
135
|
+
parent_session_id: source.session_id,
|
|
136
|
+
fork_at_event_id: forkAtEventId,
|
|
137
|
+
},
|
|
138
|
+
thread_id: forked.thread_id,
|
|
139
|
+
});
|
|
140
|
+
return forked;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* List all sessions.
|
|
144
|
+
*/
|
|
145
|
+
listSessions() {
|
|
146
|
+
return Array.from(this.sessions.values()).sort((a, b) => b.created_at - a.created_at);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Switch to a different session.
|
|
150
|
+
*/
|
|
151
|
+
switchTo(session_id) {
|
|
152
|
+
if (!this.sessions.has(session_id)) {
|
|
153
|
+
throw new Error(`Session not found: ${session_id}`);
|
|
154
|
+
}
|
|
155
|
+
this.activeSessionId = session_id;
|
|
156
|
+
this._persistIndex();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get a session by ID.
|
|
160
|
+
*/
|
|
161
|
+
getSession(session_id) {
|
|
162
|
+
return this.sessions.get(session_id);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get session projection by ID.
|
|
166
|
+
*/
|
|
167
|
+
getSessionProjection(session_id) {
|
|
168
|
+
const desc = this.sessions.get(session_id);
|
|
169
|
+
if (!desc)
|
|
170
|
+
return undefined;
|
|
171
|
+
return new SessionProjection(this.store, desc);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Update session name.
|
|
175
|
+
*/
|
|
176
|
+
renameSession(session_id, name) {
|
|
177
|
+
const desc = this.sessions.get(session_id);
|
|
178
|
+
if (!desc)
|
|
179
|
+
return;
|
|
180
|
+
desc.name = name;
|
|
181
|
+
this._persistIndex();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get the active session ID.
|
|
185
|
+
*/
|
|
186
|
+
getActiveSessionId() {
|
|
187
|
+
return this.activeSessionId;
|
|
188
|
+
}
|
|
189
|
+
getActiveThreadId() {
|
|
190
|
+
return this.activeThreadId;
|
|
191
|
+
}
|
|
192
|
+
getActiveThread() {
|
|
193
|
+
return this.activeThreadId ? this.threads.get(this.activeThreadId) : undefined;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Create a new thread (conversation). Threads are the isolation unit —
|
|
197
|
+
* events are tagged with thread_id. Creates the first session in the thread.
|
|
198
|
+
* Threads are fixed once created; auto-splitting happens at session level.
|
|
199
|
+
*/
|
|
200
|
+
createThread(name) {
|
|
201
|
+
const thread = this._createThreadRecord(name);
|
|
202
|
+
this.createSession("user_explicit", name, { threadId: thread.thread_id });
|
|
203
|
+
this._persistIndex();
|
|
204
|
+
return thread;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Dispose the session manager.
|
|
208
|
+
*/
|
|
209
|
+
dispose() {
|
|
210
|
+
this.unsubscribe?.();
|
|
211
|
+
}
|
|
212
|
+
// =========================================================================
|
|
213
|
+
// Internal Methods
|
|
214
|
+
// =========================================================================
|
|
215
|
+
_subscribeToEvents() {
|
|
216
|
+
this.unsubscribe = this.store.subscribe((event) => {
|
|
217
|
+
if (event.type === "USER_MESSAGE") {
|
|
218
|
+
this._evaluateBoundary(event);
|
|
219
|
+
}
|
|
220
|
+
}, { types: ["USER_MESSAGE"] });
|
|
221
|
+
}
|
|
222
|
+
_evaluateBoundary(event) {
|
|
223
|
+
if (!this.activeSessionId)
|
|
224
|
+
return;
|
|
225
|
+
const current = this.sessions.get(this.activeSessionId);
|
|
226
|
+
if (!current)
|
|
227
|
+
return;
|
|
228
|
+
// Only evaluate if we're at HEAD
|
|
229
|
+
if (current.event_range.end_event_id !== "HEAD")
|
|
230
|
+
return;
|
|
231
|
+
const recent = this._getRecentEventsBefore(event, current);
|
|
232
|
+
const decision = this.inferrer.evaluate(recent, event);
|
|
233
|
+
if (decision.should_split) {
|
|
234
|
+
const lastEventBeforeSplit = recent[recent.length - 1];
|
|
235
|
+
// End the current session before the triggering message.
|
|
236
|
+
// EventStore range queries use exclusive end boundaries.
|
|
237
|
+
current.event_range.end_event_id = event.event_id;
|
|
238
|
+
// Start the inferred session after the previous event so the triggering
|
|
239
|
+
// message becomes the first user-visible message in the new view.
|
|
240
|
+
this.createSession("auto_inferred", decision.suggested_name, {
|
|
241
|
+
startEventId: lastEventBeforeSplit?.event_id ?? current.event_range.start_event_id,
|
|
242
|
+
});
|
|
243
|
+
this.store.append({
|
|
244
|
+
actor_id: "runtime",
|
|
245
|
+
type: "SESSION_BOUNDARY_INFERRED",
|
|
246
|
+
payload: {
|
|
247
|
+
reason: decision.reason,
|
|
248
|
+
new_session_id: this.activeSessionId,
|
|
249
|
+
},
|
|
250
|
+
caused_by: event.event_id,
|
|
251
|
+
thread_id: this.activeThreadId,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
_getRecentEventsBefore(event, current) {
|
|
256
|
+
const query = {
|
|
257
|
+
before_sequence: event.sequence,
|
|
258
|
+
limit: 20,
|
|
259
|
+
reverse: true,
|
|
260
|
+
};
|
|
261
|
+
if (current.event_range.start_event_id !== "ORIGIN") {
|
|
262
|
+
query.after = current.event_range.start_event_id;
|
|
263
|
+
}
|
|
264
|
+
return this.store.query(query).filter((e) => !e.thread_id || e.thread_id === current.thread_id).reverse();
|
|
265
|
+
}
|
|
266
|
+
_ensureStorageDir() {
|
|
267
|
+
if (!this.filePath)
|
|
268
|
+
return;
|
|
269
|
+
const dir = this.filePath.substring(0, this.filePath.lastIndexOf("/"));
|
|
270
|
+
if (!existsSync(dir)) {
|
|
271
|
+
mkdirSync(dir, { recursive: true });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
_loadIndex() {
|
|
275
|
+
if (!this.filePath)
|
|
276
|
+
return;
|
|
277
|
+
if (!existsSync(this.filePath))
|
|
278
|
+
return;
|
|
279
|
+
try {
|
|
280
|
+
const content = readFileSync(this.filePath, "utf8");
|
|
281
|
+
const index = JSON.parse(content);
|
|
282
|
+
for (const thread of index.threads ?? []) {
|
|
283
|
+
this.threads.set(thread.thread_id, thread);
|
|
284
|
+
if (thread.status === "active") {
|
|
285
|
+
this.activeThreadId = thread.thread_id;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
for (const session of index.sessions) {
|
|
289
|
+
this.sessions.set(session.session_id, session);
|
|
290
|
+
if (session.event_range.end_event_id === "HEAD" && session.thread_id === this.activeThreadId) {
|
|
291
|
+
this.activeSessionId = session.session_id;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
// Start fresh if corrupted
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
_persistIndex() {
|
|
300
|
+
if (!this.filePath)
|
|
301
|
+
return;
|
|
302
|
+
const index = {
|
|
303
|
+
threads: Array.from(this.threads.values()),
|
|
304
|
+
sessions: Array.from(this.sessions.values()),
|
|
305
|
+
};
|
|
306
|
+
writeFileSync(this.filePath, JSON.stringify(index, null, 2));
|
|
307
|
+
}
|
|
308
|
+
_generateSessionId() {
|
|
309
|
+
const timestamp = Date.now().toString(36);
|
|
310
|
+
const random = Math.random().toString(36).slice(2, 10);
|
|
311
|
+
return `sess_${timestamp}_${random}`;
|
|
312
|
+
}
|
|
313
|
+
/** Create a thread record (no session). Used by createThread and createSession's auto-thread fallback. */
|
|
314
|
+
_createThreadRecord(name) {
|
|
315
|
+
const thread = {
|
|
316
|
+
thread_id: this._generateThreadId(),
|
|
317
|
+
workspace_id: this.store.workspace_id,
|
|
318
|
+
name,
|
|
319
|
+
created_at: Date.now(),
|
|
320
|
+
status: "active",
|
|
321
|
+
};
|
|
322
|
+
this.threads.set(thread.thread_id, thread);
|
|
323
|
+
this.activeThreadId = thread.thread_id;
|
|
324
|
+
return thread;
|
|
325
|
+
}
|
|
326
|
+
_generateThreadId() {
|
|
327
|
+
const timestamp = Date.now().toString(36);
|
|
328
|
+
const random = Math.random().toString(36).slice(2, 10);
|
|
329
|
+
return `thread_${timestamp}_${random}`;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Projection
|
|
3
|
+
*
|
|
4
|
+
* Session is a query view over EventStore, not a data holder.
|
|
5
|
+
* Builds LLM context from event queries.
|
|
6
|
+
*/
|
|
7
|
+
import type { EventStore } from "../event-store/store.js";
|
|
8
|
+
import type { SessionDescriptor, BuildContextOptions, BuiltContext } from "./types.js";
|
|
9
|
+
import type { TimelineEntry } from "./timeline-projection.js";
|
|
10
|
+
/**
|
|
11
|
+
* SessionProjection builds LLM context from EventStore queries.
|
|
12
|
+
*
|
|
13
|
+
* Session is a projection/view over events, not a data holder.
|
|
14
|
+
* Multiple sessions can coexist - same events can belong to multiple session views.
|
|
15
|
+
*/
|
|
16
|
+
export declare class SessionProjection {
|
|
17
|
+
private store;
|
|
18
|
+
private descriptor;
|
|
19
|
+
constructor(store: EventStore, descriptor: SessionDescriptor);
|
|
20
|
+
/**
|
|
21
|
+
* Build LLM-usable context message list.
|
|
22
|
+
*
|
|
23
|
+
* Logic:
|
|
24
|
+
* 1. Query all context-relevant events from event_range
|
|
25
|
+
* 2. If summary_event_id exists, inject compaction summary first
|
|
26
|
+
* 3. Convert events to AgentMessage[] format
|
|
27
|
+
* 4. Apply token budget truncation if needed
|
|
28
|
+
*/
|
|
29
|
+
buildContext(options?: BuildContextOptions): BuiltContext;
|
|
30
|
+
/**
|
|
31
|
+
* Get timeline view for UI display.
|
|
32
|
+
*
|
|
33
|
+
* Returns all events in the session's event range, ordered by time.
|
|
34
|
+
*/
|
|
35
|
+
getTimeline(): TimelineEntry[];
|
|
36
|
+
/**
|
|
37
|
+
* Get the session descriptor.
|
|
38
|
+
*/
|
|
39
|
+
getDescriptor(): SessionDescriptor;
|
|
40
|
+
/**
|
|
41
|
+
* Update the session descriptor.
|
|
42
|
+
*/
|
|
43
|
+
updateDescriptor(updates: Partial<SessionDescriptor>): void;
|
|
44
|
+
/**
|
|
45
|
+
* Fork: create new session descriptor from a specific event.
|
|
46
|
+
*/
|
|
47
|
+
fork(at_event_id: string): SessionDescriptor;
|
|
48
|
+
/**
|
|
49
|
+
* Get effective start event_id (ORIGIN if not set).
|
|
50
|
+
*/
|
|
51
|
+
getEffectiveStart(): string;
|
|
52
|
+
private _getEventRange;
|
|
53
|
+
private _applyCompactionBoundary;
|
|
54
|
+
private _summarizeEvent;
|
|
55
|
+
private _truncateByTokens;
|
|
56
|
+
private _eventTypeToKind;
|
|
57
|
+
private _generateSessionId;
|
|
58
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Projection
|
|
3
|
+
*
|
|
4
|
+
* Session is a query view over EventStore, not a data holder.
|
|
5
|
+
* Builds LLM context from event queries.
|
|
6
|
+
*/
|
|
7
|
+
import { eventsToMessages } from "./event-to-message.js";
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Constants
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/** Event types that participate in LLM context */
|
|
12
|
+
const CONTEXT_RELEVANT_EVENT_TYPES = [
|
|
13
|
+
"USER_MESSAGE",
|
|
14
|
+
"AGENT_MESSAGE_END",
|
|
15
|
+
"TOOL_EXECUTION_END",
|
|
16
|
+
"COMPACTION_END",
|
|
17
|
+
"FILE_MUTATION_APPLIED",
|
|
18
|
+
"BASH_EXECUTION",
|
|
19
|
+
"CUSTOM_MESSAGE",
|
|
20
|
+
"BRANCH_SUMMARY",
|
|
21
|
+
];
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Session Projection
|
|
24
|
+
// ============================================================================
|
|
25
|
+
/**
|
|
26
|
+
* SessionProjection builds LLM context from EventStore queries.
|
|
27
|
+
*
|
|
28
|
+
* Session is a projection/view over events, not a data holder.
|
|
29
|
+
* Multiple sessions can coexist - same events can belong to multiple session views.
|
|
30
|
+
*/
|
|
31
|
+
export class SessionProjection {
|
|
32
|
+
constructor(store, descriptor) {
|
|
33
|
+
this.store = store;
|
|
34
|
+
this.descriptor = descriptor;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build LLM-usable context message list.
|
|
38
|
+
*
|
|
39
|
+
* Logic:
|
|
40
|
+
* 1. Query all context-relevant events from event_range
|
|
41
|
+
* 2. If summary_event_id exists, inject compaction summary first
|
|
42
|
+
* 3. Convert events to AgentMessage[] format
|
|
43
|
+
* 4. Apply token budget truncation if needed
|
|
44
|
+
*/
|
|
45
|
+
buildContext(options) {
|
|
46
|
+
const { start, end } = this._getEventRange();
|
|
47
|
+
const rawEvents = this.store.query({
|
|
48
|
+
after: start,
|
|
49
|
+
before: end,
|
|
50
|
+
types: CONTEXT_RELEVANT_EVENT_TYPES,
|
|
51
|
+
}).filter((e) => !e.thread_id || e.thread_id === this.descriptor.thread_id);
|
|
52
|
+
const events = this._applyCompactionBoundary(rawEvents);
|
|
53
|
+
let messages = eventsToMessages(events);
|
|
54
|
+
// Inject compaction summary if present
|
|
55
|
+
if (this.descriptor.summary_event_id) {
|
|
56
|
+
const summaryAlreadyInRange = events.some((event) => event.event_id === this.descriptor.summary_event_id);
|
|
57
|
+
const summaryEvent = this.store.get(this.descriptor.summary_event_id);
|
|
58
|
+
if (!summaryAlreadyInRange && summaryEvent && summaryEvent.type === "COMPACTION_END") {
|
|
59
|
+
const summaryPayload = summaryEvent.payload;
|
|
60
|
+
// Use compactionSummary message type
|
|
61
|
+
messages.unshift({
|
|
62
|
+
role: "compactionSummary",
|
|
63
|
+
summary: summaryPayload.summary,
|
|
64
|
+
tokensBefore: summaryPayload.tokens_before,
|
|
65
|
+
timestamp: summaryEvent.timestamp,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Apply token budget if specified
|
|
70
|
+
if (options?.max_tokens) {
|
|
71
|
+
messages = this._truncateByTokens(messages, options.max_tokens);
|
|
72
|
+
}
|
|
73
|
+
return { messages, events, descriptor: this.descriptor };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get timeline view for UI display.
|
|
77
|
+
*
|
|
78
|
+
* Returns all events in the session's event range, ordered by time.
|
|
79
|
+
*/
|
|
80
|
+
getTimeline() {
|
|
81
|
+
const { start, end } = this._getEventRange();
|
|
82
|
+
const events = this.store.query({
|
|
83
|
+
after: start,
|
|
84
|
+
before: end,
|
|
85
|
+
reverse: false,
|
|
86
|
+
}).filter((e) => !e.thread_id || e.thread_id === this.descriptor.thread_id);
|
|
87
|
+
return events.map((e) => ({
|
|
88
|
+
event_id: e.event_id,
|
|
89
|
+
kind: this._eventTypeToKind(e.type),
|
|
90
|
+
actor_id: e.actor_id,
|
|
91
|
+
timestamp: e.timestamp,
|
|
92
|
+
summary: this._summarizeEvent(e),
|
|
93
|
+
caused_by: e.caused_by,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get the session descriptor.
|
|
98
|
+
*/
|
|
99
|
+
getDescriptor() {
|
|
100
|
+
return this.descriptor;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Update the session descriptor.
|
|
104
|
+
*/
|
|
105
|
+
updateDescriptor(updates) {
|
|
106
|
+
Object.assign(this.descriptor, updates);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Fork: create new session descriptor from a specific event.
|
|
110
|
+
*/
|
|
111
|
+
fork(at_event_id) {
|
|
112
|
+
return {
|
|
113
|
+
session_id: this._generateSessionId(),
|
|
114
|
+
thread_id: this.descriptor.thread_id,
|
|
115
|
+
workspace_id: this.store.workspace_id,
|
|
116
|
+
event_range: {
|
|
117
|
+
start_event_id: at_event_id,
|
|
118
|
+
end_event_id: "HEAD",
|
|
119
|
+
},
|
|
120
|
+
created_by: "fork",
|
|
121
|
+
parent_session_id: this.descriptor.session_id,
|
|
122
|
+
created_at: Date.now(),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get effective start event_id (ORIGIN if not set).
|
|
127
|
+
*/
|
|
128
|
+
getEffectiveStart() {
|
|
129
|
+
return this.descriptor.event_range.start_event_id;
|
|
130
|
+
}
|
|
131
|
+
// =========================================================================
|
|
132
|
+
// Private Methods
|
|
133
|
+
// =========================================================================
|
|
134
|
+
_getEventRange() {
|
|
135
|
+
const start = this.descriptor.event_range.start_event_id === "ORIGIN" ? undefined : this.descriptor.event_range.start_event_id;
|
|
136
|
+
const end = this.descriptor.event_range.end_event_id === "HEAD" ? undefined : this.descriptor.event_range.end_event_id;
|
|
137
|
+
return { start, end };
|
|
138
|
+
}
|
|
139
|
+
_applyCompactionBoundary(events) {
|
|
140
|
+
let latestCompaction;
|
|
141
|
+
for (const event of events) {
|
|
142
|
+
if (event.type === "COMPACTION_END") {
|
|
143
|
+
latestCompaction = event;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!latestCompaction)
|
|
147
|
+
return events;
|
|
148
|
+
const payload = latestCompaction.payload;
|
|
149
|
+
const firstKept = payload.first_kept_event_id ? this.store.get(payload.first_kept_event_id) : undefined;
|
|
150
|
+
const firstKeptSequence = firstKept?.sequence ?? latestCompaction.sequence + 1;
|
|
151
|
+
return [
|
|
152
|
+
latestCompaction,
|
|
153
|
+
...events.filter((event) => event.type !== "COMPACTION_END" && event.sequence >= firstKeptSequence),
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
_summarizeEvent(event) {
|
|
157
|
+
switch (event.type) {
|
|
158
|
+
case "USER_MESSAGE": {
|
|
159
|
+
const payload = event.payload;
|
|
160
|
+
const content = typeof payload.content === "string" ? payload.content : "[Content]";
|
|
161
|
+
return `User: ${content.slice(0, 80)}${content.length > 80 ? "..." : ""}`;
|
|
162
|
+
}
|
|
163
|
+
case "AGENT_MESSAGE_END": {
|
|
164
|
+
const payload = event.payload;
|
|
165
|
+
return `Agent (stop: ${payload.stop_reason})`;
|
|
166
|
+
}
|
|
167
|
+
case "TOOL_EXECUTION_END": {
|
|
168
|
+
const payload = event.payload;
|
|
169
|
+
return `${payload.is_error ? "❌" : "✓"} ${payload.tool_name}`;
|
|
170
|
+
}
|
|
171
|
+
case "COMPACTION_END":
|
|
172
|
+
return "📋 Compaction summary applied";
|
|
173
|
+
case "SESSION_CREATED": {
|
|
174
|
+
const payload = event.payload;
|
|
175
|
+
return `Session created: ${payload.name ?? payload.created_by}`;
|
|
176
|
+
}
|
|
177
|
+
case "SESSION_FORKED": {
|
|
178
|
+
const payload = event.payload;
|
|
179
|
+
return `Forked to new session`;
|
|
180
|
+
}
|
|
181
|
+
default:
|
|
182
|
+
return event.type;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
_truncateByTokens(messages, maxTokens) {
|
|
186
|
+
// Simple truncation: keep recent messages up to token limit
|
|
187
|
+
// In production, use proper token counting
|
|
188
|
+
const estimatedTokensPerMessage = 100; // rough estimate
|
|
189
|
+
const maxMessages = Math.floor(maxTokens / estimatedTokensPerMessage);
|
|
190
|
+
if (messages.length <= maxMessages) {
|
|
191
|
+
return messages;
|
|
192
|
+
}
|
|
193
|
+
// Keep system-equivalent messages + most recent messages
|
|
194
|
+
const systemMessages = messages.filter((m) => m.role === "compactionSummary" || m.role === "branchSummary");
|
|
195
|
+
const otherMessages = messages.filter((m) => m.role !== "compactionSummary" && m.role !== "branchSummary");
|
|
196
|
+
const recentMessages = otherMessages.slice(-maxMessages);
|
|
197
|
+
return [...systemMessages, ...recentMessages];
|
|
198
|
+
}
|
|
199
|
+
_eventTypeToKind(type) {
|
|
200
|
+
switch (type) {
|
|
201
|
+
case "USER_MESSAGE":
|
|
202
|
+
return "user_message";
|
|
203
|
+
case "AGENT_MESSAGE_START":
|
|
204
|
+
case "AGENT_MESSAGE_CHUNK":
|
|
205
|
+
case "AGENT_MESSAGE_END":
|
|
206
|
+
return "agent_message";
|
|
207
|
+
case "TOOL_EXECUTION_START":
|
|
208
|
+
case "TOOL_EXECUTION_UPDATE":
|
|
209
|
+
case "TOOL_EXECUTION_END":
|
|
210
|
+
return "tool_execution";
|
|
211
|
+
case "FILE_MUTATION_APPLIED":
|
|
212
|
+
return "file_mutation";
|
|
213
|
+
case "GOAL_CREATED":
|
|
214
|
+
case "GOAL_CLASSIFIED":
|
|
215
|
+
case "GOAL_PLANNED":
|
|
216
|
+
case "GOAL_PAUSED":
|
|
217
|
+
case "GOAL_RESUMED":
|
|
218
|
+
case "GOAL_COMPLETED":
|
|
219
|
+
case "GOAL_CANCELLED":
|
|
220
|
+
return "goal_event";
|
|
221
|
+
case "TASK_CREATED":
|
|
222
|
+
case "TASK_ASSIGNED":
|
|
223
|
+
case "TASK_STARTED":
|
|
224
|
+
case "TASK_PROGRESS":
|
|
225
|
+
case "TASK_COMPLETED":
|
|
226
|
+
case "TASK_FAILED":
|
|
227
|
+
case "TASK_REWORK_REQUESTED":
|
|
228
|
+
case "TASK_ACCEPTED":
|
|
229
|
+
case "TASK_CANCELLED":
|
|
230
|
+
return "task_event";
|
|
231
|
+
case "SESSION_CREATED":
|
|
232
|
+
case "SESSION_BOUNDARY_INFERRED":
|
|
233
|
+
case "SESSION_FORKED":
|
|
234
|
+
return "session_boundary";
|
|
235
|
+
case "COMPACTION_REQUESTED":
|
|
236
|
+
case "COMPACTION_START":
|
|
237
|
+
case "COMPACTION_END":
|
|
238
|
+
case "COMPACTION_ABORTED":
|
|
239
|
+
return "compaction";
|
|
240
|
+
case "AGENT_ERROR":
|
|
241
|
+
case "RUNTIME_ERROR":
|
|
242
|
+
return "error";
|
|
243
|
+
case "CHECKPOINT_CREATED":
|
|
244
|
+
case "CHECKPOINT_RESTORED":
|
|
245
|
+
case "CHECKPOINT_FAILED":
|
|
246
|
+
return "checkpoint";
|
|
247
|
+
default:
|
|
248
|
+
return "agent_message";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
_generateSessionId() {
|
|
252
|
+
// Use UUIDv7-like format
|
|
253
|
+
const timestamp = Date.now().toString(36);
|
|
254
|
+
const random = Math.random().toString(36).slice(2, 10);
|
|
255
|
+
return `sess_${timestamp}_${random}`;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EventType } from "../event-store/types.js";
|
|
2
|
+
import type { TaskDescriptor, TaskStatus } from "../goal/types.js";
|
|
3
|
+
import type { GoalProjection } from "./goal-projection.js";
|
|
4
|
+
export declare const TASK_HISTORY_EVENT_TYPES: EventType[];
|
|
5
|
+
export interface TaskHistoryItem {
|
|
6
|
+
task_id: string;
|
|
7
|
+
status: TaskStatus;
|
|
8
|
+
title: string;
|
|
9
|
+
summary: string;
|
|
10
|
+
updated_at: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function buildRecentTaskHistory(projection: Pick<GoalProjection, "listTasks">, limit?: number): TaskHistoryItem[];
|
|
13
|
+
export declare function summarizeTask(task: TaskDescriptor): string;
|