@bastani/atomic 0.8.27 → 0.8.28-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +75 -0
- package/README.md +120 -118
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +22 -0
- package/dist/builtin/workflows/README.md +11 -9
- package/dist/builtin/workflows/builtin/open-claude-design.ts +150 -13
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/authoring.d.ts +5 -2
- package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +3 -1
- package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +17 -25
- package/dist/builtin/workflows/src/extension/index.ts +133 -18
- package/dist/builtin/workflows/src/extension/render-result.ts +22 -2
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +3 -3
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +210 -16
- package/dist/builtin/workflows/src/sdk-surface.ts +1 -1
- package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +42 -5
- package/dist/builtin/workflows/src/shared/store-types.ts +8 -2
- package/dist/builtin/workflows/src/shared/store.ts +51 -0
- package/dist/builtin/workflows/src/shared/types.ts +14 -4
- package/dist/builtin/workflows/src/tui/chat-surface.ts +32 -33
- package/dist/builtin/workflows/src/tui/graph-view.ts +4 -1
- package/dist/builtin/workflows/src/tui/prompt-card.ts +6 -0
- package/dist/builtin/workflows/src/tui/run-detail.ts +11 -4
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +11 -1
- package/dist/builtin/workflows/src/tui/status-list.ts +32 -2
- package/dist/cli/args.d.ts +4 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +35 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/project-trust.d.ts +10 -0
- package/dist/cli/project-trust.d.ts.map +1 -0
- package/dist/cli/project-trust.js +36 -0
- package/dist/cli/project-trust.js.map +1 -0
- package/dist/cli/startup-ui.d.ts +7 -0
- package/dist/cli/startup-ui.d.ts.map +1 -0
- package/dist/cli/startup-ui.js +57 -0
- package/dist/cli/startup-ui.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +24 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +3 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +1 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +2 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +9 -5
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +205 -51
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts +10 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +26 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +4 -3
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +5 -3
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +16 -10
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -84
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +20 -502
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/context-compaction.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction.js +39 -82
- package/dist/core/compaction/context-compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts +1 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +1 -1
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/experimental.d.ts +2 -0
- package/dist/core/experimental.d.ts.map +1 -0
- package/dist/core/experimental.js +5 -0
- package/dist/core/experimental.js.map +1 -0
- package/dist/core/export-html/template.js +19 -6
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -4
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +11 -4
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +53 -3
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +44 -12
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +2 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +27 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/messages.d.ts +1 -11
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +10 -25
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +64 -7
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +1 -0
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js +52 -22
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +20 -8
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/project-trust.d.ts +15 -0
- package/dist/core/project-trust.d.ts.map +1 -0
- package/dist/core/project-trust.js +58 -0
- package/dist/core/project-trust.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +5 -4
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +30 -29
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-attribution.d.ts +4 -0
- package/dist/core/provider-attribution.d.ts.map +1 -0
- package/dist/core/provider-attribution.js +73 -0
- package/dist/core/provider-attribution.js.map +1 -0
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +3 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +9 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +134 -11
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +12 -2
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +108 -18
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +12 -42
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +11 -15
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +111 -111
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +15 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +69 -14
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +0 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +7 -10
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/oversized-tool-result.d.ts +53 -0
- package/dist/core/tools/oversized-tool-result.d.ts.map +1 -0
- package/dist/core/tools/oversized-tool-result.js +206 -0
- package/dist/core/tools/oversized-tool-result.js.map +1 -0
- package/dist/core/tools/read.d.ts +12 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +99 -34
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +6 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +17 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +6 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +2 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/tool-limits.d.ts +25 -0
- package/dist/core/tools/tool-limits.d.ts.map +1 -0
- package/dist/core/tools/tool-limits.js +25 -0
- package/dist/core/tools/tool-limits.js.map +1 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts +31 -0
- package/dist/core/trust-manager.d.ts.map +1 -0
- package/dist/core/trust-manager.js +196 -0
- package/dist/core/trust-manager.js.map +1 -0
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +142 -30
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +3 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +325 -7
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -2
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -5
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +5 -9
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +0 -3
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +6 -0
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +9 -16
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +22 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/trust-selector.js +85 -0
- package/dist/modes/interactive/components/trust-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +1 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +134 -36
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +10 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +1 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +4 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +52 -8
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +24 -5
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +6 -2
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +104 -10
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/changelog.d.ts +1 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +72 -0
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +54 -22
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +22 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/docs/compaction.md +210 -181
- package/docs/containerization.md +111 -0
- package/docs/custom-provider.md +9 -9
- package/docs/development.md +1 -1
- package/docs/docs.json +2 -0
- package/docs/extensions.md +71 -24
- package/docs/index.md +2 -0
- package/docs/json.md +3 -4
- package/docs/models.md +10 -10
- package/docs/packages.md +1 -1
- package/docs/prompt-templates.md +9 -2
- package/docs/providers.md +18 -5
- package/docs/quickstart.md +1 -0
- package/docs/rpc.md +3 -2
- package/docs/sdk.md +5 -0
- package/docs/security.md +56 -0
- package/docs/session-format.md +14 -23
- package/docs/sessions.md +11 -1
- package/docs/settings.md +23 -9
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +44 -2
- package/docs/themes.md +1 -1
- package/docs/tmux.md +4 -2
- package/docs/tui.md +14 -5
- package/docs/usage.md +17 -3
- package/docs/workflows.md +11 -9
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +9 -6
- package/examples/extensions/bash-spawn-hook.ts +1 -1
- package/examples/extensions/built-in-tool-renderer.ts +1 -1
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/custom-compaction.ts +43 -106
- package/examples/extensions/custom-header.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
- package/examples/extensions/custom-provider-anthropic/package.json +6 -6
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +55 -4
- package/examples/extensions/custom-provider-gitlab-duo/package.json +3 -3
- package/examples/extensions/doom-overlay/README.md +1 -1
- package/examples/extensions/doom-overlay/index.ts +2 -2
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/gondolin/index.ts +523 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +7 -45
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +2 -2
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +3 -3
- package/examples/extensions/interactive-shell.ts +2 -2
- package/examples/extensions/mac-system-theme.ts +2 -2
- package/examples/extensions/minimal-mode.ts +1 -1
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/overlay-qa-tests.ts +198 -179
- package/examples/extensions/overlay-test.ts +1 -1
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/preset.ts +14 -12
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/qna.ts +1 -1
- package/examples/extensions/question.ts +1 -1
- package/examples/extensions/questionnaire.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/sandbox/index.ts +16 -14
- package/examples/extensions/sandbox/package-lock.json +90 -90
- package/examples/extensions/sandbox/package.json +17 -17
- package/examples/extensions/snake.ts +1 -1
- package/examples/extensions/space-invaders.ts +1 -1
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/subagent/README.md +13 -13
- package/examples/extensions/subagent/agents.ts +4 -2
- package/examples/extensions/subagent/index.ts +6 -6
- package/examples/extensions/summarize.ts +1 -1
- package/examples/extensions/tic-tac-toe.ts +1 -1
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/todo.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +6 -1
- package/examples/extensions/trigger-compact.ts +5 -4
- package/examples/extensions/with-deps/package-lock.json +4 -4
- package/examples/extensions/with-deps/package.json +7 -7
- package/examples/extensions/working-indicator.ts +4 -4
- package/examples/extensions/working-message-test.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/03-custom-prompt.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/06-extensions.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
- package/examples/sdk/README.md +2 -2
- package/package.json +8 -8
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +0 -43
- package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { randomBytes, randomUUID } from "crypto";
|
|
2
|
-
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync,
|
|
2
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readSync, statSync, writeFileSync, } from "fs";
|
|
3
3
|
import { readdir, readFile, stat } from "fs/promises";
|
|
4
4
|
import { join, resolve } from "path";
|
|
5
|
+
import { StringDecoder } from "string_decoder";
|
|
5
6
|
import { getAgentDir as getDefaultAgentDir, getSessionsDir } from "../config.js";
|
|
6
7
|
import { normalizePath, resolvePath } from "../utils/paths.js";
|
|
7
|
-
import { createBranchSummaryMessage,
|
|
8
|
+
import { createBranchSummaryMessage, createCustomMessage, } from "./messages.js";
|
|
8
9
|
export const CURRENT_SESSION_VERSION = 3;
|
|
9
10
|
function createUuidV7() {
|
|
10
11
|
const bytes = randomBytes(16);
|
|
@@ -23,6 +24,11 @@ function createUuidV7() {
|
|
|
23
24
|
function createSessionId() {
|
|
24
25
|
return createUuidV7();
|
|
25
26
|
}
|
|
27
|
+
export function assertValidSessionId(id) {
|
|
28
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {
|
|
29
|
+
throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
26
32
|
/** Generate a unique short ID (8 hex chars, collision-checked) */
|
|
27
33
|
function generateId(byId) {
|
|
28
34
|
for (let i = 0; i < 100; i++) {
|
|
@@ -110,18 +116,10 @@ export function parseSessionEntries(content) {
|
|
|
110
116
|
}
|
|
111
117
|
return entries;
|
|
112
118
|
}
|
|
113
|
-
export function getLatestCompactionEntry(entries) {
|
|
114
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
115
|
-
if (entries[i].type === "compaction") {
|
|
116
|
-
return entries[i];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
119
|
export function getLatestCompactionBoundaryEntry(entries) {
|
|
122
120
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
123
121
|
const entry = entries[i];
|
|
124
|
-
if (entry.type === "
|
|
122
|
+
if (entry.type === "context_compaction") {
|
|
125
123
|
return entry;
|
|
126
124
|
}
|
|
127
125
|
}
|
|
@@ -184,7 +182,6 @@ function filterMessageContentBlocks(message, deletedBlocks) {
|
|
|
184
182
|
}
|
|
185
183
|
case "bashExecution":
|
|
186
184
|
case "branchSummary":
|
|
187
|
-
case "compactionSummary":
|
|
188
185
|
return message;
|
|
189
186
|
}
|
|
190
187
|
}
|
|
@@ -222,7 +219,7 @@ export function buildContextDeletionFilteredPath(path, filters = buildContextDel
|
|
|
222
219
|
/**
|
|
223
220
|
* Build the session context from entries using tree traversal.
|
|
224
221
|
* If leafId is provided, walks from that entry to root.
|
|
225
|
-
*
|
|
222
|
+
* Applies context-deletion filtering and includes branch summaries along the path.
|
|
226
223
|
*/
|
|
227
224
|
export function buildSessionContext(entries, leafId, byId) {
|
|
228
225
|
// Build uuid index if not available
|
|
@@ -255,10 +252,9 @@ export function buildSessionContext(entries, leafId, byId) {
|
|
|
255
252
|
path.unshift(current);
|
|
256
253
|
current = current.parentId ? byId.get(current.parentId) : undefined;
|
|
257
254
|
}
|
|
258
|
-
// Extract settings
|
|
255
|
+
// Extract settings
|
|
259
256
|
let thinkingLevel = "off";
|
|
260
257
|
let model = null;
|
|
261
|
-
let compaction = null;
|
|
262
258
|
for (const entry of path) {
|
|
263
259
|
if (entry.type === "thinking_level_change") {
|
|
264
260
|
thinkingLevel = entry.thinkingLevel;
|
|
@@ -269,25 +265,12 @@ export function buildSessionContext(entries, leafId, byId) {
|
|
|
269
265
|
else if (entry.type === "message" && entry.message.role === "assistant") {
|
|
270
266
|
model = { provider: entry.message.provider, modelId: entry.message.model };
|
|
271
267
|
}
|
|
272
|
-
else if (entry.type === "compaction") {
|
|
273
|
-
compaction = entry;
|
|
274
|
-
}
|
|
275
268
|
}
|
|
276
|
-
const latestCompactionIndex = compaction
|
|
277
|
-
? path.findIndex((e) => e.type === "compaction" && e.id === compaction.id)
|
|
278
|
-
: -1;
|
|
279
269
|
const filteredPath = buildContextDeletionFilteredPath(path);
|
|
280
|
-
|
|
281
|
-
//
|
|
282
|
-
// When there's a compaction, we need to:
|
|
283
|
-
// 1. Emit summary first (entry = compaction)
|
|
284
|
-
// 2. Emit kept messages (from firstKeptEntryId up to compaction)
|
|
285
|
-
// 3. Emit messages after compaction
|
|
270
|
+
// Build active context messages from the filtered path. Legacy "compaction"
|
|
271
|
+
// entries are archival metadata and intentionally inert here.
|
|
286
272
|
const messages = [];
|
|
287
|
-
const appendMessage = (
|
|
288
|
-
const entry = filteredEntryById.get(rawEntry.id);
|
|
289
|
-
if (!entry)
|
|
290
|
-
return;
|
|
273
|
+
const appendMessage = (entry) => {
|
|
291
274
|
let message;
|
|
292
275
|
if (entry.type === "message") {
|
|
293
276
|
message = entry.message;
|
|
@@ -301,33 +284,8 @@ export function buildSessionContext(entries, leafId, byId) {
|
|
|
301
284
|
if (message)
|
|
302
285
|
messages.push(message);
|
|
303
286
|
};
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
// logical context compaction, so existing /compact rebuild behavior is preserved.
|
|
307
|
-
messages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));
|
|
308
|
-
const compactionIdx = latestCompactionIndex;
|
|
309
|
-
// Emit kept messages (before compaction, starting from firstKeptEntryId)
|
|
310
|
-
let foundFirstKept = false;
|
|
311
|
-
for (let i = 0; i < compactionIdx; i++) {
|
|
312
|
-
const entry = path[i];
|
|
313
|
-
if (entry.id === compaction.firstKeptEntryId) {
|
|
314
|
-
foundFirstKept = true;
|
|
315
|
-
}
|
|
316
|
-
if (foundFirstKept) {
|
|
317
|
-
appendMessage(entry);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
// Emit messages after compaction
|
|
321
|
-
for (let i = compactionIdx + 1; i < path.length; i++) {
|
|
322
|
-
const entry = path[i];
|
|
323
|
-
appendMessage(entry);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
// No compaction - emit all messages, handle branch summaries and custom messages
|
|
328
|
-
for (const entry of path) {
|
|
329
|
-
appendMessage(entry);
|
|
330
|
-
}
|
|
287
|
+
for (const entry of filteredPath) {
|
|
288
|
+
appendMessage(entry);
|
|
331
289
|
}
|
|
332
290
|
return { messages, thinkingLevel, model };
|
|
333
291
|
}
|
|
@@ -335,34 +293,64 @@ export function buildSessionContext(entries, leafId, byId) {
|
|
|
335
293
|
* Compute the default session directory for a cwd.
|
|
336
294
|
* Encodes cwd into a safe directory name under ~/.atomic/agent/sessions/.
|
|
337
295
|
*/
|
|
338
|
-
|
|
296
|
+
function getDefaultSessionDirPath(cwd, agentDir = getDefaultAgentDir()) {
|
|
339
297
|
const resolvedCwd = resolvePath(cwd);
|
|
340
298
|
const resolvedAgentDir = resolvePath(agentDir);
|
|
341
299
|
const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
|
|
342
|
-
|
|
300
|
+
return join(resolvedAgentDir, "sessions", safePath);
|
|
301
|
+
}
|
|
302
|
+
export function getDefaultSessionDir(cwd, agentDir = getDefaultAgentDir()) {
|
|
303
|
+
const sessionDir = getDefaultSessionDirPath(cwd, agentDir);
|
|
343
304
|
if (!existsSync(sessionDir)) {
|
|
344
305
|
mkdirSync(sessionDir, { recursive: true });
|
|
345
306
|
}
|
|
346
307
|
return sessionDir;
|
|
347
308
|
}
|
|
309
|
+
const SESSION_READ_BUFFER_SIZE = 1024 * 1024;
|
|
310
|
+
function parseSessionEntryLine(line) {
|
|
311
|
+
if (!line.trim())
|
|
312
|
+
return null;
|
|
313
|
+
try {
|
|
314
|
+
return JSON.parse(line);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
348
320
|
/** Exported for testing */
|
|
349
321
|
export function loadEntriesFromFile(filePath) {
|
|
350
322
|
const resolvedFilePath = normalizePath(filePath);
|
|
351
323
|
if (!existsSync(resolvedFilePath))
|
|
352
324
|
return [];
|
|
353
|
-
const content = readFileSync(resolvedFilePath, "utf8");
|
|
354
325
|
const entries = [];
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
326
|
+
const fd = openSync(resolvedFilePath, "r");
|
|
327
|
+
try {
|
|
328
|
+
const decoder = new StringDecoder("utf8");
|
|
329
|
+
const buffer = Buffer.allocUnsafe(SESSION_READ_BUFFER_SIZE);
|
|
330
|
+
let pending = "";
|
|
331
|
+
while (true) {
|
|
332
|
+
const bytesRead = readSync(fd, buffer, 0, buffer.length, null);
|
|
333
|
+
if (bytesRead === 0)
|
|
334
|
+
break;
|
|
335
|
+
pending += decoder.write(buffer.subarray(0, bytesRead));
|
|
336
|
+
let lineStart = 0;
|
|
337
|
+
let newlineIndex = pending.indexOf("\n", lineStart);
|
|
338
|
+
while (newlineIndex !== -1) {
|
|
339
|
+
const entry = parseSessionEntryLine(pending.slice(lineStart, newlineIndex));
|
|
340
|
+
if (entry)
|
|
341
|
+
entries.push(entry);
|
|
342
|
+
lineStart = newlineIndex + 1;
|
|
343
|
+
newlineIndex = pending.indexOf("\n", lineStart);
|
|
344
|
+
}
|
|
345
|
+
pending = pending.slice(lineStart);
|
|
365
346
|
}
|
|
347
|
+
pending += decoder.end();
|
|
348
|
+
const finalEntry = parseSessionEntryLine(pending);
|
|
349
|
+
if (finalEntry)
|
|
350
|
+
entries.push(finalEntry);
|
|
351
|
+
}
|
|
352
|
+
finally {
|
|
353
|
+
closeSync(fd);
|
|
366
354
|
}
|
|
367
355
|
// Validate session header
|
|
368
356
|
if (entries.length === 0)
|
|
@@ -373,7 +361,7 @@ export function loadEntriesFromFile(filePath) {
|
|
|
373
361
|
}
|
|
374
362
|
return entries;
|
|
375
363
|
}
|
|
376
|
-
function
|
|
364
|
+
function readSessionHeader(filePath) {
|
|
377
365
|
try {
|
|
378
366
|
const fd = openSync(filePath, "r");
|
|
379
367
|
const buffer = Buffer.alloc(512);
|
|
@@ -381,23 +369,36 @@ function isValidSessionFile(filePath) {
|
|
|
381
369
|
closeSync(fd);
|
|
382
370
|
const firstLine = buffer.toString("utf8", 0, bytesRead).split("\n")[0];
|
|
383
371
|
if (!firstLine)
|
|
384
|
-
return
|
|
372
|
+
return null;
|
|
385
373
|
const header = JSON.parse(firstLine);
|
|
386
|
-
|
|
374
|
+
if (header.type !== "session" || typeof header.id !== "string") {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
return header;
|
|
387
378
|
}
|
|
388
379
|
catch {
|
|
389
|
-
return
|
|
380
|
+
return null;
|
|
390
381
|
}
|
|
391
382
|
}
|
|
383
|
+
function getSessionHeaderCwd(header) {
|
|
384
|
+
const cwd = header.cwd;
|
|
385
|
+
return typeof cwd === "string" ? cwd : undefined;
|
|
386
|
+
}
|
|
387
|
+
function sessionCwdMatches(cwd, resolvedCwd) {
|
|
388
|
+
return cwd !== undefined && cwd !== "" && resolvePath(cwd) === resolvedCwd;
|
|
389
|
+
}
|
|
392
390
|
/** Exported for testing */
|
|
393
|
-
export function findMostRecentSession(sessionDir) {
|
|
391
|
+
export function findMostRecentSession(sessionDir, cwd) {
|
|
394
392
|
const resolvedSessionDir = normalizePath(sessionDir);
|
|
393
|
+
const resolvedCwd = cwd ? resolvePath(cwd) : undefined;
|
|
395
394
|
try {
|
|
396
395
|
const files = readdirSync(resolvedSessionDir)
|
|
397
396
|
.filter((f) => f.endsWith(".jsonl"))
|
|
398
397
|
.map((f) => join(resolvedSessionDir, f))
|
|
399
|
-
.
|
|
400
|
-
.
|
|
398
|
+
.map((path) => ({ path, header: readSessionHeader(path) }))
|
|
399
|
+
.filter((file) => file.header !== null &&
|
|
400
|
+
(!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(file.header), resolvedCwd)))
|
|
401
|
+
.map(({ path }) => ({ path, mtime: statSync(path).mtime }))
|
|
401
402
|
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
402
403
|
return files[0]?.path || null;
|
|
403
404
|
}
|
|
@@ -554,10 +555,10 @@ async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progress
|
|
|
554
555
|
* modifying history.
|
|
555
556
|
*
|
|
556
557
|
* Use buildSessionContext() to get the resolved message list for the LLM, which
|
|
557
|
-
*
|
|
558
|
+
* applies context-deletion filtering and follows the path from root to current leaf.
|
|
558
559
|
*/
|
|
559
560
|
export class SessionManager {
|
|
560
|
-
constructor(cwd, sessionDir, sessionFile, persist) {
|
|
561
|
+
constructor(cwd, sessionDir, sessionFile, persist, newSessionOptions) {
|
|
561
562
|
this.sessionId = "";
|
|
562
563
|
this.flushed = false;
|
|
563
564
|
this.fileEntries = [];
|
|
@@ -575,7 +576,7 @@ export class SessionManager {
|
|
|
575
576
|
this.setSessionFile(sessionFile);
|
|
576
577
|
}
|
|
577
578
|
else {
|
|
578
|
-
this.newSession();
|
|
579
|
+
this.newSession(newSessionOptions);
|
|
579
580
|
}
|
|
580
581
|
}
|
|
581
582
|
/** Switch to a different session file (used for resume and branching) */
|
|
@@ -608,6 +609,9 @@ export class SessionManager {
|
|
|
608
609
|
}
|
|
609
610
|
}
|
|
610
611
|
newSession(options) {
|
|
612
|
+
if (options?.id !== undefined) {
|
|
613
|
+
assertValidSessionId(options.id);
|
|
614
|
+
}
|
|
611
615
|
this.sessionId = options?.id ?? createSessionId();
|
|
612
616
|
const timestamp = new Date().toISOString();
|
|
613
617
|
const header = {
|
|
@@ -666,6 +670,9 @@ export class SessionManager {
|
|
|
666
670
|
getSessionDir() {
|
|
667
671
|
return this.sessionDir;
|
|
668
672
|
}
|
|
673
|
+
usesDefaultSessionDir() {
|
|
674
|
+
return this.sessionDir === getDefaultSessionDirPath(this.cwd);
|
|
675
|
+
}
|
|
669
676
|
getSessionId() {
|
|
670
677
|
return this.sessionId;
|
|
671
678
|
}
|
|
@@ -698,10 +705,10 @@ export class SessionManager {
|
|
|
698
705
|
this._persist(entry);
|
|
699
706
|
}
|
|
700
707
|
/** Append a message as child of current leaf, then advance leaf. Returns entry id.
|
|
701
|
-
* Does not allow writing
|
|
708
|
+
* Does not allow writing branch summaries or context compaction metadata as regular messages.
|
|
702
709
|
* Reason: we want these to be top-level entries in the session, not message session entries,
|
|
703
710
|
* so it is easier to find them.
|
|
704
|
-
*
|
|
711
|
+
* Branch summaries are appended via appendBranchSummary(), and context compaction metadata via appendContextCompaction().
|
|
705
712
|
*/
|
|
706
713
|
appendMessage(message) {
|
|
707
714
|
const entry = {
|
|
@@ -739,22 +746,6 @@ export class SessionManager {
|
|
|
739
746
|
this._appendEntry(entry);
|
|
740
747
|
return entry.id;
|
|
741
748
|
}
|
|
742
|
-
/** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */
|
|
743
|
-
appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
|
|
744
|
-
const entry = {
|
|
745
|
-
type: "compaction",
|
|
746
|
-
id: generateId(this.byId),
|
|
747
|
-
parentId: this.leafId,
|
|
748
|
-
timestamp: new Date().toISOString(),
|
|
749
|
-
summary,
|
|
750
|
-
firstKeptEntryId,
|
|
751
|
-
tokensBefore,
|
|
752
|
-
details,
|
|
753
|
-
fromHook,
|
|
754
|
-
};
|
|
755
|
-
this._appendEntry(entry);
|
|
756
|
-
return entry.id;
|
|
757
|
-
}
|
|
758
749
|
/** Append logical deletion metadata for deletion-only context compaction. */
|
|
759
750
|
appendContextCompaction(deletedTargets, protectedEntryIds, stats, backupPath) {
|
|
760
751
|
const entry = {
|
|
@@ -1122,9 +1113,9 @@ export class SessionManager {
|
|
|
1122
1113
|
* @param cwd Working directory (stored in session header)
|
|
1123
1114
|
* @param sessionDir Optional session directory. If omitted, uses default (~/.atomic/agent/sessions/<encoded-cwd>/).
|
|
1124
1115
|
*/
|
|
1125
|
-
static create(cwd, sessionDir) {
|
|
1116
|
+
static create(cwd, sessionDir, options) {
|
|
1126
1117
|
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1127
|
-
return new SessionManager(cwd, dir, undefined, true);
|
|
1118
|
+
return new SessionManager(cwd, dir, undefined, true, options);
|
|
1128
1119
|
}
|
|
1129
1120
|
/**
|
|
1130
1121
|
* Open a specific session file.
|
|
@@ -1149,7 +1140,8 @@ export class SessionManager {
|
|
|
1149
1140
|
*/
|
|
1150
1141
|
static continueRecent(cwd, sessionDir) {
|
|
1151
1142
|
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1152
|
-
const
|
|
1143
|
+
const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
|
|
1144
|
+
const mostRecent = findMostRecentSession(dir, filterCwd ? cwd : undefined);
|
|
1153
1145
|
if (mostRecent) {
|
|
1154
1146
|
return new SessionManager(cwd, dir, mostRecent, true);
|
|
1155
1147
|
}
|
|
@@ -1166,7 +1158,7 @@ export class SessionManager {
|
|
|
1166
1158
|
* @param targetCwd Target working directory (where the new session will be stored)
|
|
1167
1159
|
* @param sessionDir Optional session directory. If omitted, uses default for targetCwd.
|
|
1168
1160
|
*/
|
|
1169
|
-
static forkFrom(sourcePath, targetCwd, sessionDir) {
|
|
1161
|
+
static forkFrom(sourcePath, targetCwd, sessionDir, options) {
|
|
1170
1162
|
const resolvedSourcePath = resolvePath(sourcePath);
|
|
1171
1163
|
const resolvedTargetCwd = resolvePath(targetCwd);
|
|
1172
1164
|
const sourceEntries = loadEntriesFromFile(resolvedSourcePath);
|
|
@@ -1182,7 +1174,10 @@ export class SessionManager {
|
|
|
1182
1174
|
mkdirSync(dir, { recursive: true });
|
|
1183
1175
|
}
|
|
1184
1176
|
// Create new session file with new ID but forked content
|
|
1185
|
-
|
|
1177
|
+
if (options?.id !== undefined) {
|
|
1178
|
+
assertValidSessionId(options.id);
|
|
1179
|
+
}
|
|
1180
|
+
const newSessionId = options?.id ?? createSessionId();
|
|
1186
1181
|
const timestamp = new Date().toISOString();
|
|
1187
1182
|
const fileTimestamp = timestamp.replace(/[:.]/g, "-");
|
|
1188
1183
|
const newSessionFile = join(dir, `${fileTimestamp}_${newSessionId}.jsonl`);
|
|
@@ -1212,15 +1207,20 @@ export class SessionManager {
|
|
|
1212
1207
|
*/
|
|
1213
1208
|
static async list(cwd, sessionDir, onProgress) {
|
|
1214
1209
|
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1215
|
-
const
|
|
1210
|
+
const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
|
|
1211
|
+
const resolvedCwd = resolvePath(cwd);
|
|
1212
|
+
const sessions = (await listSessionsFromDir(dir, onProgress)).filter((session) => !filterCwd || sessionCwdMatches(session.cwd, resolvedCwd));
|
|
1216
1213
|
sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
1217
1214
|
return sessions;
|
|
1218
1215
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1216
|
+
static async listAll(sessionDirOrOnProgress, onProgress) {
|
|
1217
|
+
const customSessionDir = typeof sessionDirOrOnProgress === "string" ? normalizePath(sessionDirOrOnProgress) : undefined;
|
|
1218
|
+
const progress = typeof sessionDirOrOnProgress === "function" ? sessionDirOrOnProgress : onProgress;
|
|
1219
|
+
if (customSessionDir) {
|
|
1220
|
+
const sessions = await listSessionsFromDir(customSessionDir, progress);
|
|
1221
|
+
sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
1222
|
+
return sessions;
|
|
1223
|
+
}
|
|
1224
1224
|
const sessionsDir = getSessionsDir();
|
|
1225
1225
|
try {
|
|
1226
1226
|
if (!existsSync(sessionsDir)) {
|
|
@@ -1248,7 +1248,7 @@ export class SessionManager {
|
|
|
1248
1248
|
const results = await Promise.all(allFiles.map(async (file) => {
|
|
1249
1249
|
const info = await buildSessionInfo(file);
|
|
1250
1250
|
loaded++;
|
|
1251
|
-
|
|
1251
|
+
progress?.(loaded, totalFiles);
|
|
1252
1252
|
return info;
|
|
1253
1253
|
}));
|
|
1254
1254
|
for (const info of results) {
|