mu-agent 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/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/bundle/chunks/anthropic-messages-MYU5ZMRF.js +6 -0
- package/dist/bundle/chunks/anthropic.js +75 -0
- package/dist/bundle/chunks/azure-openai-responses-HUSQ3GP2.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +83 -0
- package/dist/bundle/chunks/chunk-4L3WN2XY.js +2 -0
- package/dist/bundle/chunks/chunk-6CYCI3EJ.js +12 -0
- package/dist/bundle/chunks/chunk-6R7UI4IY.js +2 -0
- package/dist/bundle/chunks/chunk-7ZC4UXSL.js +2 -0
- package/dist/bundle/chunks/chunk-A3JYRWB6.js +2 -0
- package/dist/bundle/chunks/chunk-DRQDKNXA.js +2 -0
- package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +42 -0
- package/dist/bundle/chunks/chunk-FUXEF6JQ.js +44 -0
- package/dist/bundle/chunks/chunk-L2ZPNLYD.js +2 -0
- package/dist/bundle/chunks/chunk-NUHFSC37.js +25 -0
- package/dist/bundle/chunks/chunk-PGXDEOVV.js +2 -0
- package/dist/bundle/chunks/chunk-PJACZCIR.js +2 -0
- package/dist/bundle/chunks/chunk-PRRNXB7S.js +2 -0
- package/dist/bundle/chunks/chunk-QB4HYZZE.js +1561 -0
- package/dist/bundle/chunks/chunk-RCZIEVGO.js +11 -0
- package/dist/bundle/chunks/chunk-S7SZN6Z3.js +2 -0
- package/dist/bundle/chunks/chunk-TEPMHNKQ.js +2 -0
- package/dist/bundle/chunks/chunk-TRDNDS6A.js +4 -0
- package/dist/bundle/chunks/chunk-USJZMAIR.js +2 -0
- package/dist/bundle/chunks/chunk-WIUZI2CJ.js +11 -0
- package/dist/bundle/chunks/chunk-XDUWOHPL.js +6 -0
- package/dist/bundle/chunks/chunk-XNGRGP62.js +2 -0
- package/dist/bundle/chunks/chunk-Z2DUOAN4.js +2 -0
- package/dist/bundle/chunks/github-copilot.js +2 -0
- package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +2 -0
- package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +2 -0
- package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +13 -0
- package/dist/bundle/chunks/image-resize-worker.js +2 -0
- package/dist/bundle/chunks/jiti-loader-C3NU2SDH.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-E6ANQD5T.js +2 -0
- package/dist/bundle/chunks/kimi-coding.js +2 -0
- package/dist/bundle/chunks/lib-HGQMNYVT.js +9 -0
- package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +5 -0
- package/dist/bundle/chunks/multipart-parser-SQ6GDJL7.js +3 -0
- package/dist/bundle/chunks/node-O3RIBJRH.js +16 -0
- package/dist/bundle/chunks/node-TWVVAGPO.js +2 -0
- package/dist/bundle/chunks/openai-codex-responses-QDSOTBBO.js +10 -0
- package/dist/bundle/chunks/openai-codex.js +75 -0
- package/dist/bundle/chunks/openai-completions-KQPOPEVM.js +7 -0
- package/dist/bundle/chunks/openai-responses-HWEUZ6WZ.js +2 -0
- package/dist/bundle/chunks/openrouter-images-N4XVVFSD.js +2 -0
- package/dist/bundle/chunks/openrouter.js +75 -0
- package/dist/bundle/chunks/pi-messages-GFKBWJHZ.js +8 -0
- package/dist/bundle/chunks/radius.js +75 -0
- package/dist/bundle/chunks/src-UK77SYZE.js +4 -0
- package/dist/bundle/chunks/virtual-modules-ROULVYS3.js +2 -0
- package/dist/bundle/chunks/xai.js +2 -0
- package/dist/bundle/cli.js +3 -0
- package/dist/bundle/index.js +2 -0
- package/dist/bundle/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/dist/bundle/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/dist/bundle/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/dist/bundle/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/dist/bundle/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/dist/bundle/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/dist/bundle/rpc-entry.js +3 -0
- package/dist/core/export-html/template.css +1066 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1864 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +78 -0
- package/dist/modes/interactive/assets/clankolas.png +0 -0
- package/dist/modes/interactive/theme/dark.json +91 -0
- package/dist/modes/interactive/theme/light.json +90 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +41 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-controller.js +130 -0
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
- package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
- package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-json.js +130 -0
- package/dist/modes/interactive/theme/theme-json.js.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +356 -0
- package/dist/modes/interactive/theme/theme.d.ts +131 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +991 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -0
- package/dist/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/dist/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/dist/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/dist/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/dist/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/dist/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/docs/compaction.md +444 -0
- package/docs/containerization.md +156 -0
- package/docs/custom-provider.md +786 -0
- package/docs/development.md +90 -0
- package/docs/docs.json +160 -0
- package/docs/environment-variables.md +100 -0
- package/docs/extensions.md +3037 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/index.md +84 -0
- package/docs/json.md +98 -0
- package/docs/keybindings.md +239 -0
- package/docs/llama-cpp.md +101 -0
- package/docs/models.md +605 -0
- package/docs/packages.md +228 -0
- package/docs/prompt-templates.md +96 -0
- package/docs/providers.md +317 -0
- package/docs/quickstart.md +167 -0
- package/docs/rpc.md +1618 -0
- package/docs/sdk.md +1226 -0
- package/docs/security.md +59 -0
- package/docs/session-format.md +480 -0
- package/docs/sessions.md +172 -0
- package/docs/settings.md +428 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +232 -0
- package/docs/terminal-setup.md +192 -0
- package/docs/termux.md +126 -0
- package/docs/themes.md +322 -0
- package/docs/tmux.md +63 -0
- package/docs/tui.md +961 -0
- package/docs/usage.md +312 -0
- package/docs/windows.md +39 -0
- package/examples/README.md +28 -0
- package/examples/extensions/README.md +212 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/border-status-editor.ts +150 -0
- package/examples/extensions/built-in-tool-renderer.ts +249 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +117 -0
- package/examples/extensions/custom-footer.ts +64 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +617 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +405 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +81 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/entry-renderer.ts +41 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/github-issue-autocomplete.ts +185 -0
- package/examples/extensions/gondolin/index.ts +531 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +190 -0
- package/examples/extensions/hello.ts +26 -0
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +426 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +57 -0
- package/examples/extensions/overlay-qa-tests.ts +1450 -0
- package/examples/extensions/overlay-test.ts +153 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +66 -0
- package/examples/extensions/plan-mode/index.ts +390 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +436 -0
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +49 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/provider-payload.ts +18 -0
- package/examples/extensions/qna.ts +118 -0
- package/examples/extensions/question.ts +286 -0
- package/examples/extensions/questionnaire.ts +448 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +118 -0
- package/examples/extensions/sandbox/index.ts +321 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +32 -0
- package/examples/extensions/structured-output.ts +65 -0
- package/examples/extensions/subagent/README.md +177 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +157 -0
- package/examples/extensions/subagent/index.ts +1038 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +199 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/tic-tac-toe.ts +1008 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +297 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +50 -0
- package/examples/extensions/truncated-tool.ts +195 -0
- package/examples/extensions/widget-placement.ts +9 -0
- package/examples/extensions/with-deps/index.ts +32 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/extensions/working-indicator.ts +123 -0
- package/examples/extensions/working-message-test.ts +25 -0
- package/examples/plugins/pi-example-plugin/README.md +38 -0
- package/examples/plugins/pi-example-plugin/package.json +10 -0
- package/examples/plugins/pi-example-plugin/src/contract.ts +13 -0
- package/examples/plugins/pi-example-plugin/src/session.ts +23 -0
- package/examples/plugins/pi-example-plugin/src/tui.ts +31 -0
- package/examples/rpc-extension-ui.ts +641 -0
- package/examples/sdk/01-minimal.ts +26 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +75 -0
- package/examples/sdk/04-skills.ts +55 -0
- package/examples/sdk/05-tools.ts +48 -0
- package/examples/sdk/06-extensions.ts +99 -0
- package/examples/sdk/07-context-files.ts +47 -0
- package/examples/sdk/08-prompt-templates.ts +51 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
- package/examples/sdk/10-settings.ts +53 -0
- package/examples/sdk/11-sessions.ts +52 -0
- package/examples/sdk/12-full-control.ts +74 -0
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +140 -0
- package/judge/THIRD_PARTY_NOTICES.md +35 -0
- package/judge/agents/browser.md +17 -0
- package/judge/agents/investigator.md +16 -0
- package/judge/agents/planner.md +15 -0
- package/judge/agents/reviewer.md +17 -0
- package/judge/agents/scout.md +19 -0
- package/judge/agents/worker.md +15 -0
- package/judge/dist/chrome.js +326 -0
- package/judge/dist/kyrn-judge.js +52542 -0
- package/judge/package.json +6 -0
- package/judge/prompts/implement-and-review.md +14 -0
- package/judge/prompts/implement.md +15 -0
- package/judge/prompts/init.md +18 -0
- package/judge/prompts/scout-and-plan.md +12 -0
- package/judge/skills/mu-browser/SKILL.md +30 -0
- package/judge/skills/mu-github/SKILL.md +90 -0
- package/kyrn/bin/kyrn-doctor +202 -0
- package/kyrn/bin/kyrn-judge-local +131 -0
- package/kyrn/bin/kyrn-ledger +90 -0
- package/kyrn/bin/mu.mjs +1120 -0
- package/kyrn/local-judge/requirements.lock.txt +26 -0
- package/kyrn/local-judge/server.py +332 -0
- package/package.json +45 -0
package/docs/security.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Pi is a local coding agent. It runs with the permissions of the user account that starts it, and it treats files writable by that user as inside the same local trust boundary.
|
|
4
|
+
|
|
5
|
+
## Project Trust
|
|
6
|
+
|
|
7
|
+
Project trust controls whether pi loads project-local settings, resources, packages, and extensions. It is not a sandbox and it does not restrict what the model can ask tools to do after you start working in a directory.
|
|
8
|
+
|
|
9
|
+
Pi considers a project to have resources that require trust when it finds any of these from the current working directory:
|
|
10
|
+
|
|
11
|
+
- `.pi/settings.json`
|
|
12
|
+
- `.pi/extensions`, `.pi/skills`, `.pi/prompts`, or `.pi/themes`
|
|
13
|
+
- `.pi/SYSTEM.md` or `.pi/APPEND_SYSTEM.md`
|
|
14
|
+
- project `.agents/skills` in the current directory or an ancestor directory
|
|
15
|
+
|
|
16
|
+
A bare `.pi` directory does not count as a project resource that requires trust.
|
|
17
|
+
|
|
18
|
+
When an interactive session starts in a project with resources that require trust and no saved decision for the current directory or a parent directory, pi follows `defaultProjectTrust` from global settings. The default value is `"ask"`, which asks whether to trust the project when UI is available. Saved decisions are stored by canonical directory in `~/.pi/agent/trust.json`, and the closest saved decision on the current or parent path applies before the global default.
|
|
19
|
+
|
|
20
|
+
Trusting a project allows pi to load project resources that require trust, including:
|
|
21
|
+
|
|
22
|
+
- `.pi/settings.json`
|
|
23
|
+
- `.pi` resources such as extensions, skills, prompt templates, themes, and system prompt files
|
|
24
|
+
- missing project packages configured through project settings
|
|
25
|
+
- project-local extensions and project package-managed extensions
|
|
26
|
+
|
|
27
|
+
Declining trust skips protected resources. Context files such as `AGENTS.override.md`, `AGENTS.md`, and `CLAUDE.md` are loaded regardless of project trust unless context loading is disabled. Before trust is resolved, pi only loads context files, user/global extensions, and CLI `-e` extensions. User/global and CLI extensions can handle the `project_trust` event; the first extension that returns a yes/no decision owns the decision.
|
|
28
|
+
|
|
29
|
+
Non-interactive modes (`-p`, `--mode json`, and `--mode rpc`) do not show a trust prompt. Without an applicable saved trust decision, `defaultProjectTrust: "ask"` and `"never"` ignore such resources, while `"always"` trusts them. Use `--approve`/`-a` or `--no-approve`/`-na` to override project trust for one run.
|
|
30
|
+
|
|
31
|
+
## No Built-in Sandbox
|
|
32
|
+
|
|
33
|
+
Pi does not include a built-in sandbox. Built-in tools can read files, write files, edit files, and run shell commands with the permissions of the pi process. Extensions are TypeScript modules that run with the same permissions. Package installs, shell commands, language servers, test commands, and other developer tools behave as ordinary local processes.
|
|
34
|
+
|
|
35
|
+
This is intentional. Pi is designed to operate on local source trees, invoke project toolchains, and integrate with the user's existing development environment. A partial in-process sandbox would be easy to misunderstand as a security boundary while still depending on the host shell, filesystem, package managers, credentials, and extension code. Real isolation needs to come from the operating system or a virtualization/container boundary.
|
|
36
|
+
|
|
37
|
+
Project trust is only an input-loading guard. It prevents a repository from silently changing pi's settings or extensions before you approve it. It does not make untrusted code, untrusted prompts, or untrusted model output safe. Prompt injection from repository files, comments, documentation, context files, or build output is expected local-agent risk and cannot be reliably prevented by pi.
|
|
38
|
+
|
|
39
|
+
## Running Untrusted or Unmonitored Work
|
|
40
|
+
|
|
41
|
+
For untrusted repositories, generated code you do not intend to monitor closely, or unattended automation, run pi in a contained environment. Use a container, VM, micro-VM, remote sandbox, or policy-controlled sandbox with only the files and credentials required for the task.
|
|
42
|
+
|
|
43
|
+
Common patterns are documented in [Containerization](containerization.md):
|
|
44
|
+
|
|
45
|
+
- run the whole `pi` process inside a container/sandbox
|
|
46
|
+
- run host pi while routing built-in tool execution into a Gondolin micro-VM
|
|
47
|
+
- mount only the workspace paths the agent should access
|
|
48
|
+
- avoid mounting host `~/.pi/agent` unless the container should access host sessions, settings, and credentials
|
|
49
|
+
- pass the minimum required API keys or use short-lived credentials
|
|
50
|
+
- restrict network access when the task does not need it
|
|
51
|
+
- review diffs and outputs before copying results back to trusted systems
|
|
52
|
+
|
|
53
|
+
If you bind-mount a host workspace read/write, writes from inside the container or VM can still modify host files. Use read-only mounts or copy files into and out of the sandbox when you need stronger protection from unintended writes.
|
|
54
|
+
|
|
55
|
+
## Reporting Security Issues
|
|
56
|
+
|
|
57
|
+
To report a security issue, follow the repository [Security Policy](https://github.com/earendil-works/pi/blob/main/SECURITY.md). Do not open a public issue for security-sensitive reports.
|
|
58
|
+
|
|
59
|
+
Expected local-agent behavior, lack of a built-in sandbox, prompt injection from untrusted content, and behavior of user-installed extensions or skills are generally outside the security boundary unless the report demonstrates a real privilege-boundary bypass or shows how pi grants access that the local user did not already have.
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
# Session File Format
|
|
2
|
+
|
|
3
|
+
Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with a `type` field. Session entries form a tree structure via `id`/`parentId` fields, enabling in-place branching without creating new files.
|
|
4
|
+
|
|
5
|
+
## File Location
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
~/.pi/agent/sessions/--<path>--/<timestamp>_<session-id>.jsonl
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
By default, `<session-id>` is a UUID. Callers can supply a custom ID through the SDK or `--session-id`. For `<path>`, Pi removes the leading path separator and replaces `/`, `\\`, and `:` with `-`.
|
|
12
|
+
|
|
13
|
+
## Deleting Sessions
|
|
14
|
+
|
|
15
|
+
Sessions can be removed by deleting their `.jsonl` files under `~/.pi/agent/sessions/`.
|
|
16
|
+
|
|
17
|
+
Pi also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, pi uses the `trash` CLI to avoid permanent deletion.
|
|
18
|
+
|
|
19
|
+
## Session Version
|
|
20
|
+
|
|
21
|
+
Sessions have a version field in the header:
|
|
22
|
+
|
|
23
|
+
- **Version 1**: Linear entry sequence (legacy, auto-migrated on load)
|
|
24
|
+
- **Version 2**: Tree structure with `id`/`parentId` linking
|
|
25
|
+
- **Version 3**: Renamed `hookMessage` role to `custom` (extensions unification)
|
|
26
|
+
|
|
27
|
+
Existing sessions are automatically migrated to the current version (v3) when loaded.
|
|
28
|
+
|
|
29
|
+
## Source Files
|
|
30
|
+
|
|
31
|
+
Source on GitHub ([pi](https://github.com/earendil-works/pi)):
|
|
32
|
+
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
|
|
33
|
+
- [`packages/coding-agent/src/core/messages.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
|
|
34
|
+
- [`packages/ai/src/types.ts`](https://github.com/earendil-works/pi/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
|
|
35
|
+
- [`packages/agent/src/types.ts`](https://github.com/earendil-works/pi/blob/main/packages/agent/src/types.ts) - AgentMessage union type
|
|
36
|
+
|
|
37
|
+
For TypeScript definitions in your project, inspect `node_modules/@earendil-works/pi-coding-agent/dist/` and `node_modules/@earendil-works/pi-ai/dist/`.
|
|
38
|
+
|
|
39
|
+
## Message Types
|
|
40
|
+
|
|
41
|
+
Session entries contain `AgentMessage` objects. Understanding these types is essential for parsing sessions and writing extensions.
|
|
42
|
+
|
|
43
|
+
### Content Blocks
|
|
44
|
+
|
|
45
|
+
Messages contain arrays of typed content blocks:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
interface TextContent {
|
|
49
|
+
type: "text";
|
|
50
|
+
text: string;
|
|
51
|
+
textSignature?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface ImageContent {
|
|
55
|
+
type: "image";
|
|
56
|
+
data: string; // base64 encoded
|
|
57
|
+
mimeType: string; // e.g., "image/jpeg", "image/png"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface ThinkingContent {
|
|
61
|
+
type: "thinking";
|
|
62
|
+
thinking: string;
|
|
63
|
+
thinkingSignature?: string;
|
|
64
|
+
redacted?: boolean;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface ToolCall {
|
|
68
|
+
type: "toolCall";
|
|
69
|
+
id: string;
|
|
70
|
+
name: string;
|
|
71
|
+
arguments: Record<string, any>;
|
|
72
|
+
thoughtSignature?: string;
|
|
73
|
+
namespace?: string;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Base Message Types (from pi-ai)
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
interface SystemMessage {
|
|
81
|
+
role: "system";
|
|
82
|
+
content: string | TextContent[];
|
|
83
|
+
toolsAdded?: Tool[];
|
|
84
|
+
toolsRemoved?: Array<{ name: string }>;
|
|
85
|
+
timestamp: number; // Unix ms
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface UserMessage {
|
|
89
|
+
role: "user";
|
|
90
|
+
content: string | (TextContent | ImageContent)[];
|
|
91
|
+
timestamp: number; // Unix ms
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface AssistantMessage {
|
|
95
|
+
role: "assistant";
|
|
96
|
+
content: (TextContent | ThinkingContent | ToolCall)[];
|
|
97
|
+
api: string;
|
|
98
|
+
provider: string;
|
|
99
|
+
model: string;
|
|
100
|
+
responseModel?: string;
|
|
101
|
+
responseId?: string;
|
|
102
|
+
providerThinkingLevel?: string;
|
|
103
|
+
diagnostics?: AssistantMessageDiagnostic[];
|
|
104
|
+
usage: Usage;
|
|
105
|
+
stopReason: "pending" | "stop" | "length" | "toolUse" | "error" | "aborted" | "deferred";
|
|
106
|
+
deferred?: DeferredHandle;
|
|
107
|
+
errorMessage?: string;
|
|
108
|
+
rawStopReason?: string;
|
|
109
|
+
endTurn?: boolean;
|
|
110
|
+
timestamp: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
interface ToolResultMessage {
|
|
114
|
+
role: "toolResult";
|
|
115
|
+
toolCallId: string;
|
|
116
|
+
toolName: string;
|
|
117
|
+
content: (TextContent | ImageContent)[];
|
|
118
|
+
details?: any; // Tool-specific metadata
|
|
119
|
+
usage?: Usage; // Nested LLM work performed by the tool
|
|
120
|
+
isError: boolean;
|
|
121
|
+
timestamp: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface Usage {
|
|
125
|
+
input: number;
|
|
126
|
+
output: number;
|
|
127
|
+
cacheRead: number;
|
|
128
|
+
cacheWrite: number;
|
|
129
|
+
cacheWrite1h?: number;
|
|
130
|
+
reasoning?: number;
|
|
131
|
+
totalTokens: number;
|
|
132
|
+
cost: {
|
|
133
|
+
input: number;
|
|
134
|
+
output: number;
|
|
135
|
+
cacheRead: number;
|
|
136
|
+
cacheWrite: number;
|
|
137
|
+
total: number;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`"pending"` is reserved for partial messages in streaming events. Terminal events replace it with a completion reason before Pi persists the assistant message, so `"pending"` should never appear in session JSONL. `"deferred"` is a terminal reason for a provider response that will complete later; its `deferred` handle contains the provider data needed to retrieve that response.
|
|
143
|
+
|
|
144
|
+
### Extended Message Types (from pi-coding-agent)
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
interface BashExecutionMessage {
|
|
148
|
+
role: "bashExecution";
|
|
149
|
+
command: string;
|
|
150
|
+
output: string;
|
|
151
|
+
exitCode: number | undefined;
|
|
152
|
+
cancelled: boolean;
|
|
153
|
+
truncated: boolean;
|
|
154
|
+
fullOutputPath?: string;
|
|
155
|
+
excludeFromContext?: boolean; // true for !! prefix commands
|
|
156
|
+
timestamp: number;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface CustomMessage {
|
|
160
|
+
role: "custom";
|
|
161
|
+
customType: string; // Extension identifier
|
|
162
|
+
content: string | (TextContent | ImageContent)[];
|
|
163
|
+
display: boolean; // Show in TUI
|
|
164
|
+
details?: any; // Extension-specific metadata
|
|
165
|
+
timestamp: number;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface BranchSummaryMessage {
|
|
169
|
+
role: "branchSummary";
|
|
170
|
+
summary: string;
|
|
171
|
+
fromId: string | null; // Previous leaf whose abandoned path was summarized
|
|
172
|
+
timestamp: number;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
interface CompactionSummaryMessage {
|
|
176
|
+
role: "compactionSummary";
|
|
177
|
+
summary: string;
|
|
178
|
+
tokensBefore: number;
|
|
179
|
+
timestamp: number;
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### AgentMessage Union
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
type AgentMessage =
|
|
187
|
+
| SystemMessage
|
|
188
|
+
| UserMessage
|
|
189
|
+
| AssistantMessage
|
|
190
|
+
| ToolResultMessage
|
|
191
|
+
| BashExecutionMessage
|
|
192
|
+
| CustomMessage
|
|
193
|
+
| BranchSummaryMessage
|
|
194
|
+
| CompactionSummaryMessage;
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Entry Base
|
|
198
|
+
|
|
199
|
+
All entries (except `SessionHeader`) extend `SessionEntryBase`:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
interface SessionEntryBase {
|
|
203
|
+
type: string;
|
|
204
|
+
id: string; // Usually an 8-char hex ID; may fall back to a full UUID
|
|
205
|
+
parentId: string | null; // Parent entry ID (null for a root entry)
|
|
206
|
+
timestamp: string; // ISO timestamp
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Entry Types
|
|
211
|
+
|
|
212
|
+
### SessionHeader
|
|
213
|
+
|
|
214
|
+
First line of the file. Metadata only, not part of the tree (no `id`/`parentId`).
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{"type":"session","version":3,"id":"uuid","timestamp":"2024-12-03T14:00:00.000Z","cwd":"/path/to/project"}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
For sessions with a parent (created via `/fork`, `/clone`, or `newSession({ parentSession })`):
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{"type":"session","version":3,"id":"uuid","timestamp":"2024-12-03T14:00:00.000Z","cwd":"/path/to/project","parentSession":"/path/to/original/session.jsonl"}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### SessionMessageEntry
|
|
227
|
+
|
|
228
|
+
A message in the conversation. The `message` field contains an `AgentMessage`. System messages carry the prompt and tool loadout: the first request of a session persists one with every prompt section and tool declaration, and later changes persist as system messages that patch `sections` by name (`null` removes one) and list `toolsAdded`/`toolsRemoved`. Replaying them in order yields the current prompt and tools; there is no separate prompt state entry.
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{"type":"message","id":"a0b1c2d3","parentId":null,"timestamp":"2024-12-03T14:00:00.000Z","message":{"role":"system","content":"","sections":{"preamble":"You are an expert coding assistant...","tools":"<tools>\n- read: ...\n</tools>","cwd":"/project"},"toolsAdded":[{"name":"read","description":"...","parameters":{}}],"timestamp":1733234400000}}
|
|
232
|
+
{"type":"message","id":"d4e5f6g7","parentId":"c3d4e5f6","timestamp":"2024-12-03T14:04:00.000Z","message":{"role":"system","content":"","sections":{"skills":"<skills>...</skills>"},"toolsRemoved":[{"name":"write"}],"timestamp":1733234640000}}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Sessions created before system messages existed have no leading system message; the first request declares the current prompt as a later system message, which replays the same way.
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{"type":"message","id":"a1b2c3d4","parentId":"prev1234","timestamp":"2024-12-03T14:00:01.000Z","message":{"role":"user","content":"Hello","timestamp":1733234401000}}
|
|
239
|
+
{"type":"message","id":"b2c3d4e5","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:00:02.000Z","message":{"role":"assistant","content":[{"type":"text","text":"Hi!"}],"api":"anthropic-messages","provider":"anthropic","model":"claude-sonnet-4-5","usage":{...},"stopReason":"stop","timestamp":1733234402000}}
|
|
240
|
+
{"type":"message","id":"c3d4e5f6","parentId":"b2c3d4e5","timestamp":"2024-12-03T14:00:03.000Z","message":{"role":"toolResult","toolCallId":"call_123","toolName":"bash","content":[{"type":"text","text":"output"}],"isError":false,"timestamp":1733234403000}}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### ModelChangeEntry
|
|
244
|
+
|
|
245
|
+
Emitted when the user switches models mid-session.
|
|
246
|
+
|
|
247
|
+
```json
|
|
248
|
+
{"type":"model_change","id":"d4e5f6g7","parentId":"c3d4e5f6","timestamp":"2024-12-03T14:05:00.000Z","provider":"openai","modelId":"gpt-4o"}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### ThinkingLevelChangeEntry
|
|
252
|
+
|
|
253
|
+
Emitted when the user changes the thinking/reasoning level.
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{"type":"thinking_level_change","id":"e5f6g7h8","parentId":"d4e5f6g7","timestamp":"2024-12-03T14:06:00.000Z","thinkingLevel":"high"}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### UsageEntry
|
|
260
|
+
|
|
261
|
+
Records model-attributed usage that is not an assistant message and does not participate in LLM context. `kind` is an arbitrary string identifying the operation; for example, cache warming uses `"cache_warm"`.
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{"type":"usage","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:08:00.000Z","kind":"cache_warm","provider":"anthropic","model":"claude-sonnet-4-5","usage":{"input":0,"output":0,"cacheRead":50000,"cacheWrite":0,"totalTokens":50000,"cost":{"input":0,"output":0,"cacheRead":0.015,"cacheWrite":0,"total":0.015}}}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Usage entries contribute to session token and cost totals. Pi hides them from the conversation tree. Consumers should treat unknown `kind` values as normal usage rather than rejecting them.
|
|
268
|
+
|
|
269
|
+
### CompactionEntry
|
|
270
|
+
|
|
271
|
+
Created when context is compacted. Stores a summary of earlier messages and a complete system prompt/tool checkpoint.
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{"type":"compaction","id":"f6g7h8i9","parentId":"e5f6g7h8","timestamp":"2024-12-03T14:10:00.000Z","summary":"User discussed X, Y, Z...","firstKeptEntryId":"c3d4e5f6","tokensBefore":50000,"systemMessage":{"role":"system","content":"You are a coding assistant.","toolsAdded":[],"timestamp":1733235000000}}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
`firstKeptEntryId` is required. It identifies the first entry retained from before the compaction entry. When rebuilding context, Pi replaces older summarized entries with the compaction summary and keeps the range beginning at this entry.
|
|
278
|
+
|
|
279
|
+
Optional fields:
|
|
280
|
+
- `systemMessage`: The replayed prompt sections and tool declarations at the compaction boundary; it becomes the leading system message of the compacted context, and system messages among the kept entries are dropped in its favor. It is absent on older session entries.
|
|
281
|
+
- `usage`: LLM usage from generating the summary; included in session token and cost totals
|
|
282
|
+
- `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
|
|
283
|
+
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if pi-generated (legacy field name)
|
|
284
|
+
|
|
285
|
+
### BranchSummaryEntry
|
|
286
|
+
|
|
287
|
+
Created when switching branches via `/tree` with an LLM generated summary of the left branch up to the common ancestor. Captures context from the abandoned path.
|
|
288
|
+
|
|
289
|
+
```json
|
|
290
|
+
{"type":"branch_summary","id":"g7h8i9j0","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:15:00.000Z","fromId":"f6g7h8i9","summary":"Branch explored approach A..."}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`parentId` is the entry from which the new branch continues. `fromId` is the previous leaf whose abandoned path was summarized.
|
|
294
|
+
|
|
295
|
+
Optional fields:
|
|
296
|
+
- `usage`: LLM usage from generating the summary; included in session token and cost totals
|
|
297
|
+
- `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
|
|
298
|
+
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if pi-generated (legacy field name)
|
|
299
|
+
|
|
300
|
+
### CustomEntry
|
|
301
|
+
|
|
302
|
+
Extension state persistence. Does NOT participate in LLM context.
|
|
303
|
+
|
|
304
|
+
```json
|
|
305
|
+
{"type":"custom","id":"h8i9j0k1","parentId":"g7h8i9j0","timestamp":"2024-12-03T14:20:00.000Z","customType":"my-extension","data":{"count":42}}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Use `customType` to identify your extension's entries on reload. Interactive mode can render custom entries via `pi.registerEntryRenderer(customType, renderer)`, but they still do not participate in LLM context.
|
|
309
|
+
|
|
310
|
+
### CustomMessageEntry
|
|
311
|
+
|
|
312
|
+
Extension-injected messages that DO participate in LLM context.
|
|
313
|
+
|
|
314
|
+
```json
|
|
315
|
+
{"type":"custom_message","id":"i9j0k1l2","parentId":"h8i9j0k1","timestamp":"2024-12-03T14:25:00.000Z","customType":"my-extension","content":"Injected context...","display":true}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Fields:
|
|
319
|
+
- `content`: String or `(TextContent | ImageContent)[]` (same as UserMessage)
|
|
320
|
+
- `display`: `true` = show in TUI with distinct styling, `false` = hidden
|
|
321
|
+
- `details`: Optional extension-specific metadata (not sent to LLM)
|
|
322
|
+
|
|
323
|
+
### LabelEntry
|
|
324
|
+
|
|
325
|
+
User-defined bookmark/marker on an entry.
|
|
326
|
+
|
|
327
|
+
```json
|
|
328
|
+
{"type":"label","id":"j0k1l2m3","parentId":"i9j0k1l2","timestamp":"2024-12-03T14:30:00.000Z","targetId":"a1b2c3d4","label":"checkpoint-1"}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Set `label` to `undefined` to clear a label.
|
|
332
|
+
|
|
333
|
+
### SessionInfoEntry
|
|
334
|
+
|
|
335
|
+
Session metadata (e.g., user-defined display name). Set via `/name`, `--name` / `-n`, or `pi.setSessionName()` in extensions.
|
|
336
|
+
|
|
337
|
+
```json
|
|
338
|
+
{"type":"session_info","id":"k1l2m3n4","parentId":"j0k1l2m3","timestamp":"2024-12-03T14:35:00.000Z","name":"Refactor auth module"}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
The session name is displayed in the session selector (`/resume`) instead of the first message when set.
|
|
342
|
+
|
|
343
|
+
## Tree Structure
|
|
344
|
+
|
|
345
|
+
Entries normally form one tree, but navigation APIs can create multiple roots:
|
|
346
|
+
- A root entry has `parentId: null`; the first entry is initially the root
|
|
347
|
+
- Each non-root entry points to its parent via `parentId`
|
|
348
|
+
- Branching creates new children from an earlier entry
|
|
349
|
+
- The "leaf" is the current position in the tree
|
|
350
|
+
- Calling `resetLeaf()` or `branchWithSummary(null, ...)` allows a later entry to become another root
|
|
351
|
+
|
|
352
|
+
```
|
|
353
|
+
[user msg] ─── [assistant] ─── [user msg] ─── [assistant] ─┬─ [user msg] ← current leaf
|
|
354
|
+
│
|
|
355
|
+
└─ [branch_summary] ─── [user msg] ← alternate branch
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Context Building
|
|
359
|
+
|
|
360
|
+
`buildContextEntries()` walks from the current leaf to the root, producing the active entry list while honoring compaction:
|
|
361
|
+
|
|
362
|
+
1. Collects all entries on the path
|
|
363
|
+
2. If one or more `CompactionEntry` values are on the path, uses the latest one:
|
|
364
|
+
- Includes the compaction entry first
|
|
365
|
+
- Includes non-system entries from `firstKeptEntryId` up to, but not including, the compaction entry
|
|
366
|
+
- Includes entries after the compaction entry
|
|
367
|
+
3. Preserves non-message entries in the selected range so interactive mode can render them
|
|
368
|
+
|
|
369
|
+
`buildSessionContext()` builds on that entry list to produce the message list for the LLM:
|
|
370
|
+
|
|
371
|
+
1. Extracts current model and thinking level settings from the full path
|
|
372
|
+
2. Converts selected entries to messages:
|
|
373
|
+
- `message` -> stored `AgentMessage`
|
|
374
|
+
- `compaction` -> complete system checkpoint followed by `compactionSummary`
|
|
375
|
+
- `branch_summary` -> `branchSummary`
|
|
376
|
+
- `custom_message` -> `CustomMessage`
|
|
377
|
+
- `usage` and `custom` -> no context message
|
|
378
|
+
|
|
379
|
+
The compaction summary replaces entries before `firstKeptEntryId`. Pre-compaction system messages are folded into the complete checkpoint rather than replayed from the retained range. Retained non-system entries and all entries after the compaction remain available to the LLM.
|
|
380
|
+
|
|
381
|
+
## Parsing Example
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
import { readFileSync } from "fs";
|
|
385
|
+
|
|
386
|
+
const lines = readFileSync("session.jsonl", "utf8").trim().split("\n");
|
|
387
|
+
|
|
388
|
+
for (const line of lines) {
|
|
389
|
+
const entry = JSON.parse(line);
|
|
390
|
+
|
|
391
|
+
switch (entry.type) {
|
|
392
|
+
case "session":
|
|
393
|
+
console.log(`Session v${entry.version ?? 1}: ${entry.id}`);
|
|
394
|
+
break;
|
|
395
|
+
case "message":
|
|
396
|
+
console.log(`[${entry.id}] ${entry.message.role}: ${JSON.stringify(entry.message.content)}`);
|
|
397
|
+
break;
|
|
398
|
+
case "compaction":
|
|
399
|
+
console.log(`[${entry.id}] Compaction: ${entry.tokensBefore} tokens summarized`);
|
|
400
|
+
break;
|
|
401
|
+
case "branch_summary":
|
|
402
|
+
console.log(`[${entry.id}] Branch from ${entry.fromId}`);
|
|
403
|
+
break;
|
|
404
|
+
case "usage":
|
|
405
|
+
console.log(`[${entry.id}] Usage (${entry.kind}): ${entry.usage.totalTokens} tokens`);
|
|
406
|
+
break;
|
|
407
|
+
case "custom":
|
|
408
|
+
console.log(`[${entry.id}] Custom (${entry.customType}): ${JSON.stringify(entry.data)}`);
|
|
409
|
+
break;
|
|
410
|
+
case "custom_message":
|
|
411
|
+
console.log(`[${entry.id}] Extension message (${entry.customType}): ${entry.content}`);
|
|
412
|
+
break;
|
|
413
|
+
case "label":
|
|
414
|
+
console.log(`[${entry.id}] Label "${entry.label}" on ${entry.targetId}`);
|
|
415
|
+
break;
|
|
416
|
+
case "model_change":
|
|
417
|
+
console.log(`[${entry.id}] Model: ${entry.provider}/${entry.modelId}`);
|
|
418
|
+
break;
|
|
419
|
+
case "thinking_level_change":
|
|
420
|
+
console.log(`[${entry.id}] Thinking: ${entry.thinkingLevel}`);
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
## SessionManager API
|
|
427
|
+
|
|
428
|
+
Key methods for working with sessions programmatically.
|
|
429
|
+
|
|
430
|
+
### Static Creation Methods
|
|
431
|
+
- `SessionManager.create(cwd, sessionDir?, options?)` - New session; `options` can set `id` and `parentSession`
|
|
432
|
+
- `SessionManager.open(path, sessionDir?, cwdOverride?)` - Open existing session file
|
|
433
|
+
- `SessionManager.continueRecent(cwd, sessionDir?)` - Continue most recent or create new
|
|
434
|
+
- `SessionManager.inMemory(cwd?, options?, entries?)` - No file persistence, optionally initialized from entries
|
|
435
|
+
- `SessionManager.forkFrom(sourcePath, targetCwd, sessionDir?, options?)` - Fork session from another project
|
|
436
|
+
|
|
437
|
+
### Static Listing Methods
|
|
438
|
+
- `SessionManager.list(cwd, sessionDir?, onProgress?)` - List sessions for a directory
|
|
439
|
+
- `SessionManager.listAll(onProgress?)` - List all sessions across all projects
|
|
440
|
+
- `SessionManager.listAll(sessionDir?, onProgress?)` - List sessions from a custom session root
|
|
441
|
+
|
|
442
|
+
### Instance Methods - Session Management
|
|
443
|
+
- `newSession(options?)` - Start a new session (options: `{ id?: string, parentSession?: string }`)
|
|
444
|
+
- `setSessionFile(path)` - Switch to a different session file
|
|
445
|
+
- `createBranchedSession(leafId)` - Extract branch to new session file
|
|
446
|
+
|
|
447
|
+
### Instance Methods - Appending (all return entry ID)
|
|
448
|
+
- `appendMessage(message)` - Add message
|
|
449
|
+
- `appendThinkingLevelChange(level)` - Record thinking change
|
|
450
|
+
- `appendModelChange(provider, modelId)` - Record model change
|
|
451
|
+
- `appendUsage(kind, provider, model, usage)` - Record model-attributed usage outside the conversation
|
|
452
|
+
- `appendCompaction(summary, firstKeptEntryId, tokensBefore, details?, fromHook?, usage?)` - Add compaction
|
|
453
|
+
- `appendCustomEntry(customType, data?)` - Extension state (not in context)
|
|
454
|
+
- `appendSessionInfo(name)` - Set session display name
|
|
455
|
+
- `appendCustomMessageEntry(customType, content, display, details?)` - Extension message (in context)
|
|
456
|
+
- `appendLabelChange(targetId, label)` - Set/clear label
|
|
457
|
+
|
|
458
|
+
### Instance Methods - Tree Navigation
|
|
459
|
+
- `getLeafId()` - Current position
|
|
460
|
+
- `getLeafEntry()` - Get current leaf entry
|
|
461
|
+
- `getEntry(id)` - Get entry by ID
|
|
462
|
+
- `getBranch(fromId?)` - Walk from entry to root
|
|
463
|
+
- `getTree()` - Get full tree structure
|
|
464
|
+
- `getChildren(parentId)` - Get direct children
|
|
465
|
+
- `getLabel(id)` - Get label for entry
|
|
466
|
+
- `branch(entryId)` - Move leaf to earlier entry
|
|
467
|
+
- `resetLeaf()` - Reset leaf to null (before any entries)
|
|
468
|
+
- `branchWithSummary(entryId, summary, details?, fromHook?, usage?)` - Branch with context summary; `entryId` may be `null` to branch from the root
|
|
469
|
+
|
|
470
|
+
### Instance Methods - Context & Info
|
|
471
|
+
- `buildContextEntries()` - Get active branch entries with compaction applied
|
|
472
|
+
- `buildSessionContext()` - Get messages, thinkingLevel, and model for LLM
|
|
473
|
+
- `getEntries()` - All entries (excluding header)
|
|
474
|
+
- `getHeader()` - Session header metadata
|
|
475
|
+
- `getSessionName()` - Get display name from latest session_info entry
|
|
476
|
+
- `getCwd()` - Working directory
|
|
477
|
+
- `getSessionDir()` - Session storage directory
|
|
478
|
+
- `getSessionId()` - Session UUID
|
|
479
|
+
- `getSessionFile()` - Session file path (undefined for in-memory)
|
|
480
|
+
- `isPersisted()` - Whether session is saved to disk
|