@herbertgao/pi-extensions 2026.8.8 → 2026.8.10
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 +6 -3
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +24 -0
- package/node_modules/@czottmann/pi-automode/README.md +78 -112
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +18 -14
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +44 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +5 -0
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +198 -104
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +155 -0
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +55 -14
- package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +90 -0
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +61 -26
- package/node_modules/@czottmann/pi-automode/examples/automode.local.json +5 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +172 -18
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +127 -30
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +3 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +273 -31
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +60 -5
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +92 -8
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +203 -13
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +1 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +11 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +9 -1
- package/node_modules/@czottmann/pi-automode/package.json +9 -2
- package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +63 -0
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +3 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +8 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +56 -29
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +15 -13
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +29 -0
- package/node_modules/@herbertgao/pi-handoff/README.md +15 -18
- package/node_modules/@herbertgao/pi-handoff/package.json +11 -4
- package/node_modules/@herbertgao/pi-handoff/src/complete-text.ts +33 -0
- package/node_modules/@herbertgao/pi-handoff/src/index.ts +127 -232
- package/node_modules/@herbertgao/pi-handoff/src/session-query.ts +15 -30
- package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +14 -0
- package/node_modules/@herbertgao/pi-mermaid-open/README.md +21 -4
- package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +11 -0
- package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/viewer.mjs +305 -0
- package/node_modules/@herbertgao/pi-mermaid-open/package.json +15 -4
- package/node_modules/@herbertgao/pi-mermaid-open/src/index.ts +351 -101
- package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +12 -0
- package/node_modules/@herbertgao/pi-preferred-thinking/README.md +30 -14
- package/node_modules/@herbertgao/pi-preferred-thinking/package.json +7 -4
- package/node_modules/@herbertgao/pi-preferred-thinking/src/index.ts +140 -85
- package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +12 -0
- package/node_modules/@herbertgao/pi-recap/README.md +5 -3
- package/node_modules/@herbertgao/pi-recap/package.json +9 -3
- package/node_modules/@herbertgao/pi-recap/src/index.ts +3 -7
- package/node_modules/@herbertgao/pi-recap/src/model-picker.ts +6 -19
- package/node_modules/@herbertgao/pi-recap/src/models.ts +9 -21
- package/node_modules/@herbertgao/pi-recap/src/tui.ts +1 -1
- package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +49 -0
- package/node_modules/@herbertgao/pi-rename/README.md +13 -11
- package/node_modules/@herbertgao/pi-rename/package.json +13 -3
- package/node_modules/@herbertgao/pi-rename/src/index.ts +135 -59
- package/node_modules/@herbertgao/pi-rename/src/models.ts +5 -13
- package/node_modules/@herbertgao/pi-rename/src/naming.ts +2 -6
- package/node_modules/@herbertgao/pi-stash/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +16 -3
- package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
- package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +15 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +16 -0
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +5 -1
- package/node_modules/pi-web-access/CHANGELOG.md +13 -0
- package/node_modules/pi-web-access/README.md +2 -2
- package/node_modules/pi-web-access/chrome-cookies.ts +12 -7
- package/node_modules/pi-web-access/gemini-search.ts +28 -10
- package/node_modules/pi-web-access/index.ts +24 -10
- package/node_modules/pi-web-access/package.json +1 -1
- package/node_modules/resume-from/LICENSE +21 -0
- package/node_modules/resume-from/README.md +161 -0
- package/node_modules/resume-from/dist/adapters/claude-code/adapter.d.ts +25 -0
- package/node_modules/resume-from/dist/adapters/claude-code/adapter.js +60 -0
- package/node_modules/resume-from/dist/adapters/claude-code/contract.d.ts +8 -0
- package/node_modules/resume-from/dist/adapters/claude-code/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/claude-code/entries.d.ts +30 -0
- package/node_modules/resume-from/dist/adapters/claude-code/entries.js +107 -0
- package/node_modules/resume-from/dist/adapters/claude-code/index.d.ts +3 -0
- package/node_modules/resume-from/dist/adapters/claude-code/index.js +2 -0
- package/node_modules/resume-from/dist/adapters/claude-code/layout.d.ts +29 -0
- package/node_modules/resume-from/dist/adapters/claude-code/layout.js +80 -0
- package/node_modules/resume-from/dist/adapters/claude-code/readback.d.ts +9 -0
- package/node_modules/resume-from/dist/adapters/claude-code/readback.js +39 -0
- package/node_modules/resume-from/dist/adapters/claude-code/reader.d.ts +37 -0
- package/node_modules/resume-from/dist/adapters/claude-code/reader.js +415 -0
- package/node_modules/resume-from/dist/adapters/claude-code/redaction.d.ts +26 -0
- package/node_modules/resume-from/dist/adapters/claude-code/redaction.js +132 -0
- package/node_modules/resume-from/dist/adapters/claude-code/validation.d.ts +4 -0
- package/node_modules/resume-from/dist/adapters/claude-code/validation.js +39 -0
- package/node_modules/resume-from/dist/adapters/claude-code/writer.d.ts +23 -0
- package/node_modules/resume-from/dist/adapters/claude-code/writer.js +306 -0
- package/node_modules/resume-from/dist/adapters/codex/contract.d.ts +15 -0
- package/node_modules/resume-from/dist/adapters/codex/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/codex/index.d.ts +6 -0
- package/node_modules/resume-from/dist/adapters/codex/index.js +44 -0
- package/node_modules/resume-from/dist/adapters/codex/read.d.ts +28 -0
- package/node_modules/resume-from/dist/adapters/codex/read.js +270 -0
- package/node_modules/resume-from/dist/adapters/codex/readback.d.ts +9 -0
- package/node_modules/resume-from/dist/adapters/codex/readback.js +47 -0
- package/node_modules/resume-from/dist/adapters/codex/redaction.d.ts +26 -0
- package/node_modules/resume-from/dist/adapters/codex/redaction.js +132 -0
- package/node_modules/resume-from/dist/adapters/codex/rollout.d.ts +75 -0
- package/node_modules/resume-from/dist/adapters/codex/rollout.js +185 -0
- package/node_modules/resume-from/dist/adapters/codex/validation.d.ts +7 -0
- package/node_modules/resume-from/dist/adapters/codex/validation.js +78 -0
- package/node_modules/resume-from/dist/adapters/codex/write.d.ts +17 -0
- package/node_modules/resume-from/dist/adapters/codex/write.js +141 -0
- package/node_modules/resume-from/dist/adapters/contract.d.ts +74 -0
- package/node_modules/resume-from/dist/adapters/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/pi/adapter.d.ts +15 -0
- package/node_modules/resume-from/dist/adapters/pi/adapter.js +209 -0
- package/node_modules/resume-from/dist/adapters/pi/contract.d.ts +24 -0
- package/node_modules/resume-from/dist/adapters/pi/contract.js +4 -0
- package/node_modules/resume-from/dist/adapters/pi/format.d.ts +162 -0
- package/node_modules/resume-from/dist/adapters/pi/format.js +223 -0
- package/node_modules/resume-from/dist/adapters/pi/index.d.ts +7 -0
- package/node_modules/resume-from/dist/adapters/pi/index.js +10 -0
- package/node_modules/resume-from/dist/adapters/pi/parse.d.ts +41 -0
- package/node_modules/resume-from/dist/adapters/pi/parse.js +371 -0
- package/node_modules/resume-from/dist/adapters/pi/redaction.d.ts +26 -0
- package/node_modules/resume-from/dist/adapters/pi/redaction.js +132 -0
- package/node_modules/resume-from/dist/adapters/pi/serialize.d.ts +22 -0
- package/node_modules/resume-from/dist/adapters/pi/serialize.js +87 -0
- package/node_modules/resume-from/dist/adapters/pi/validate.d.ts +14 -0
- package/node_modules/resume-from/dist/adapters/pi/validate.js +134 -0
- package/node_modules/resume-from/dist/bin.d.ts +35 -0
- package/node_modules/resume-from/dist/bin.js +135 -0
- package/node_modules/resume-from/dist/contract.d.ts +10 -0
- package/node_modules/resume-from/dist/contract.js +4 -0
- package/node_modules/resume-from/dist/host/agents.d.ts +29 -0
- package/node_modules/resume-from/dist/host/agents.js +20 -0
- package/node_modules/resume-from/dist/host/cli/args.d.ts +21 -0
- package/node_modules/resume-from/dist/host/cli/args.js +187 -0
- package/node_modules/resume-from/dist/host/cli/contract.d.ts +27 -0
- package/node_modules/resume-from/dist/host/cli/contract.js +4 -0
- package/node_modules/resume-from/dist/host/cli/index.d.ts +2 -0
- package/node_modules/resume-from/dist/host/cli/index.js +1 -0
- package/node_modules/resume-from/dist/host/cli/presentation.d.ts +2 -0
- package/node_modules/resume-from/dist/host/cli/presentation.js +11 -0
- package/node_modules/resume-from/dist/host/cli/render.d.ts +3 -0
- package/node_modules/resume-from/dist/host/cli/render.js +70 -0
- package/node_modules/resume-from/dist/host/cli/runner.d.ts +8 -0
- package/node_modules/resume-from/dist/host/cli/runner.js +125 -0
- package/node_modules/resume-from/dist/host/contract.d.ts +42 -0
- package/node_modules/resume-from/dist/host/contract.js +4 -0
- package/node_modules/resume-from/dist/host/entry.d.ts +52 -0
- package/node_modules/resume-from/dist/host/entry.js +91 -0
- package/node_modules/resume-from/dist/host/index.d.ts +11 -0
- package/node_modules/resume-from/dist/host/index.js +10 -0
- package/node_modules/resume-from/dist/host/pi-extension/command.d.ts +18 -0
- package/node_modules/resume-from/dist/host/pi-extension/command.js +103 -0
- package/node_modules/resume-from/dist/host/pi-extension/contract.d.ts +34 -0
- package/node_modules/resume-from/dist/host/pi-extension/contract.js +4 -0
- package/node_modules/resume-from/dist/host/pi-extension/index.d.ts +6 -0
- package/node_modules/resume-from/dist/host/pi-extension/index.js +4 -0
- package/node_modules/resume-from/dist/host/pi-extension/picker.d.ts +16 -0
- package/node_modules/resume-from/dist/host/pi-extension/picker.js +35 -0
- package/node_modules/resume-from/dist/host/pi-extension/presentation.d.ts +2 -0
- package/node_modules/resume-from/dist/host/pi-extension/presentation.js +11 -0
- package/node_modules/resume-from/dist/host/pi-extension/register.d.ts +25 -0
- package/node_modules/resume-from/dist/host/pi-extension/register.js +11 -0
- package/node_modules/resume-from/dist/host/pi-extension/ui.d.ts +20 -0
- package/node_modules/resume-from/dist/host/pi-extension/ui.js +1 -0
- package/node_modules/resume-from/dist/host/profile.d.ts +8 -0
- package/node_modules/resume-from/dist/host/profile.js +31 -0
- package/node_modules/resume-from/dist/host/registry.d.ts +8 -0
- package/node_modules/resume-from/dist/host/registry.js +33 -0
- package/node_modules/resume-from/dist/host/wiring.d.ts +41 -0
- package/node_modules/resume-from/dist/host/wiring.js +67 -0
- package/node_modules/resume-from/dist/import/confirmation.d.ts +6 -0
- package/node_modules/resume-from/dist/import/confirmation.js +27 -0
- package/node_modules/resume-from/dist/import/contract.d.ts +41 -0
- package/node_modules/resume-from/dist/import/contract.js +4 -0
- package/node_modules/resume-from/dist/import/discovery/contract.d.ts +58 -0
- package/node_modules/resume-from/dist/import/discovery/contract.js +4 -0
- package/node_modules/resume-from/dist/import/discovery/errors.d.ts +9 -0
- package/node_modules/resume-from/dist/import/discovery/errors.js +12 -0
- package/node_modules/resume-from/dist/import/discovery/finder.d.ts +10 -0
- package/node_modules/resume-from/dist/import/discovery/finder.js +129 -0
- package/node_modules/resume-from/dist/import/discovery/homes.d.ts +23 -0
- package/node_modules/resume-from/dist/import/discovery/homes.js +83 -0
- package/node_modules/resume-from/dist/import/discovery/index.d.ts +2 -0
- package/node_modules/resume-from/dist/import/discovery/index.js +2 -0
- package/node_modules/resume-from/dist/import/discovery/ordering.d.ts +3 -0
- package/node_modules/resume-from/dist/import/discovery/ordering.js +21 -0
- package/node_modules/resume-from/dist/import/errors.d.ts +22 -0
- package/node_modules/resume-from/dist/import/errors.js +20 -0
- package/node_modules/resume-from/dist/import/index.d.ts +3 -0
- package/node_modules/resume-from/dist/import/index.js +5 -0
- package/node_modules/resume-from/dist/import/landing/contract.d.ts +44 -0
- package/node_modules/resume-from/dist/import/landing/contract.js +4 -0
- package/node_modules/resume-from/dist/import/landing/errors.d.ts +15 -0
- package/node_modules/resume-from/dist/import/landing/errors.js +15 -0
- package/node_modules/resume-from/dist/import/landing/handover.d.ts +5 -0
- package/node_modules/resume-from/dist/import/landing/handover.js +12 -0
- package/node_modules/resume-from/dist/import/landing/index.d.ts +4 -0
- package/node_modules/resume-from/dist/import/landing/index.js +4 -0
- package/node_modules/resume-from/dist/import/landing/lander.d.ts +7 -0
- package/node_modules/resume-from/dist/import/landing/lander.js +133 -0
- package/node_modules/resume-from/dist/import/landing/marker.d.ts +9 -0
- package/node_modules/resume-from/dist/import/landing/marker.js +46 -0
- package/node_modules/resume-from/dist/import/pipeline.d.ts +17 -0
- package/node_modules/resume-from/dist/import/pipeline.js +134 -0
- package/node_modules/resume-from/dist/import/preview/builder.d.ts +6 -0
- package/node_modules/resume-from/dist/import/preview/builder.js +76 -0
- package/node_modules/resume-from/dist/import/preview/contract.d.ts +39 -0
- package/node_modules/resume-from/dist/import/preview/contract.js +4 -0
- package/node_modules/resume-from/dist/import/preview/format.d.ts +19 -0
- package/node_modules/resume-from/dist/import/preview/format.js +45 -0
- package/node_modules/resume-from/dist/import/preview/index.d.ts +2 -0
- package/node_modules/resume-from/dist/import/preview/index.js +1 -0
- package/node_modules/resume-from/dist/import/preview/warnings.d.ts +11 -0
- package/node_modules/resume-from/dist/import/preview/warnings.js +80 -0
- package/node_modules/resume-from/dist/import/transfer/contract.d.ts +48 -0
- package/node_modules/resume-from/dist/import/transfer/contract.js +4 -0
- package/node_modules/resume-from/dist/import/transfer/index.d.ts +2 -0
- package/node_modules/resume-from/dist/import/transfer/index.js +1 -0
- package/node_modules/resume-from/dist/import/transfer/rules.d.ts +3 -0
- package/node_modules/resume-from/dist/import/transfer/rules.js +228 -0
- package/node_modules/resume-from/dist/import/wiring.d.ts +24 -0
- package/node_modules/resume-from/dist/import/wiring.js +27 -0
- package/node_modules/resume-from/dist/index.d.ts +36 -0
- package/node_modules/resume-from/dist/index.js +36 -0
- package/node_modules/resume-from/dist/platform/config/contract.d.ts +35 -0
- package/node_modules/resume-from/dist/platform/config/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/config/defaults.d.ts +16 -0
- package/node_modules/resume-from/dist/platform/config/defaults.js +22 -0
- package/node_modules/resume-from/dist/platform/config/errors.d.ts +9 -0
- package/node_modules/resume-from/dist/platform/config/errors.js +12 -0
- package/node_modules/resume-from/dist/platform/config/index.d.ts +5 -0
- package/node_modules/resume-from/dist/platform/config/index.js +6 -0
- package/node_modules/resume-from/dist/platform/config/loader.d.ts +10 -0
- package/node_modules/resume-from/dist/platform/config/loader.js +47 -0
- package/node_modules/resume-from/dist/platform/config/paths.d.ts +13 -0
- package/node_modules/resume-from/dist/platform/config/paths.js +37 -0
- package/node_modules/resume-from/dist/platform/config/validate.d.ts +9 -0
- package/node_modules/resume-from/dist/platform/config/validate.js +117 -0
- package/node_modules/resume-from/dist/platform/repo/contract.d.ts +30 -0
- package/node_modules/resume-from/dist/platform/repo/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/repo/git.d.ts +21 -0
- package/node_modules/resume-from/dist/platform/repo/git.js +74 -0
- package/node_modules/resume-from/dist/platform/repo/index.d.ts +2 -0
- package/node_modules/resume-from/dist/platform/repo/index.js +1 -0
- package/node_modules/resume-from/dist/platform/repo/reader.d.ts +8 -0
- package/node_modules/resume-from/dist/platform/repo/reader.js +130 -0
- package/node_modules/resume-from/dist/platform/store/contract.d.ts +31 -0
- package/node_modules/resume-from/dist/platform/store/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/store/file-committer.d.ts +3 -0
- package/node_modules/resume-from/dist/platform/store/file-committer.js +391 -0
- package/node_modules/resume-from/dist/platform/store/index.d.ts +2 -0
- package/node_modules/resume-from/dist/platform/store/index.js +2 -0
- package/node_modules/resume-from/dist/platform/tokens/contract.d.ts +12 -0
- package/node_modules/resume-from/dist/platform/tokens/contract.js +4 -0
- package/node_modules/resume-from/dist/platform/tokens/estimator.d.ts +12 -0
- package/node_modules/resume-from/dist/platform/tokens/estimator.js +111 -0
- package/node_modules/resume-from/dist/platform/tokens/index.d.ts +2 -0
- package/node_modules/resume-from/dist/platform/tokens/index.js +1 -0
- package/node_modules/resume-from/dist/session/contract.d.ts +109 -0
- package/node_modules/resume-from/dist/session/contract.js +4 -0
- package/node_modules/resume-from/package.json +80 -0
- package/node_modules/resume-from/shims/pi/extensions/resume-from.js +118 -0
- package/package.json +19 -14
|
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.24.2] - 2026-08-22
|
|
8
|
+
|
|
9
|
+
### Highlights
|
|
10
|
+
- `auto` search now uses Codex-backed OpenAI search when Pi is running a Codex model.
|
|
11
|
+
- Non-Codex sessions still prefer Exa first, so zero-config search keeps its fast keyless path.
|
|
12
|
+
- Gemini Web browser-cookie access is more reliable on Windows Chrome and Edge profiles.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Prefer Codex-backed OpenAI search in `auto` mode when the active Pi model is `openai-codex`; otherwise prefer Exa before OpenAI.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Fixed Windows Gemini Web browser-cookie extraction when Chromium cookie expiry values are too large for JavaScript numbers or PowerShell DPAPI key unprotect needs encoded command transport. Thanks to [@laixuanthoi](https://github.com/laixuanthoi) for issue #290.
|
|
19
|
+
|
|
7
20
|
## [0.24.1] - 2026-08-21
|
|
8
21
|
|
|
9
22
|
### Added
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
**Video Understanding** — Point it at a YouTube video or local screen recording and ask questions about what's on screen. Full transcripts, visual descriptions, and frame extraction at exact timestamps.
|
|
20
20
|
|
|
21
|
-
**Smart Fallbacks** — Every capability has a fallback chain. Search tries configured SearXNG first for local/private search
|
|
21
|
+
**Smart Fallbacks** — Every capability has a fallback chain. Search tries configured SearXNG first for local/private search. When the active Pi model is `openai-codex`, it then tries Codex-backed OpenAI search. Otherwise it tries Exa before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, and Gemini Web when browser cookies are enabled. YouTube tries Gemini Web when enabled, then API, then Perplexity. Blocked pages try configured self-hosted Firecrawl first. Third-party hosted page fetchers require explicit `fetchRouting.allowRemoteHostedProviders` opt-in for remote HTTP(S) targets.
|
|
22
22
|
|
|
23
23
|
**GitHub Cloning** — GitHub URLs are cloned locally instead of scraped. The agent gets real file contents and a local path to explore, not rendered HTML.
|
|
24
24
|
|
|
@@ -46,7 +46,7 @@ Works immediately with no API keys — Exa MCP provides zero-config search. If P
|
|
|
46
46
|
}
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
In `auto` mode (default), `web_search` tries a configured SearXNG endpoint first for local/private search
|
|
49
|
+
In `auto` mode (default), `web_search` tries a configured SearXNG endpoint first for local/private search. When the active Pi model is `openai-codex`, it then tries Codex-backed OpenAI search. Otherwise it tries Exa (direct API if keyed, MCP if not) before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Perplexity, Gemini API, and Gemini Web when browser-cookie access is enabled. Exa handles search; curator summary drafts are generated separately by the configured Pi summary model, defaulting to Claude Haiku, Codex Luna, Codex Terra, Gemini 3.6 Flash, GPT-5 mini, then DeepSeek V4 Flash when available. Slow summary drafts fall back to a deterministic result summary after a bounded deadline.
|
|
50
50
|
|
|
51
51
|
If your OpenAI key belongs to a third-party Responses-compatible gateway, set `openaiResponsesUrl` to that gateway's full Responses endpoint. The default remains `https://api.openai.com/v1/responses`.
|
|
52
52
|
|
|
@@ -375,8 +375,9 @@ async function readWindowsEncryptionKey(config: BrowserConfig, home: string): Pr
|
|
|
375
375
|
|
|
376
376
|
function unprotectWindowsData(protectedData: Buffer): Promise<Buffer | null> {
|
|
377
377
|
return new Promise((resolve) => {
|
|
378
|
-
const script = "
|
|
379
|
-
|
|
378
|
+
const script = "Add-Type -AssemblyName System.Security;$data=[Convert]::FromBase64String($env:PIWA_PROTECTED);$clear=[System.Security.Cryptography.ProtectedData]::Unprotect($data,$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser);[Console]::Write([Convert]::ToBase64String($clear))";
|
|
379
|
+
const encoded = Buffer.from(script, "utf16le").toString("base64");
|
|
380
|
+
execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", encoded], { timeout: 5000, maxBuffer: 1024 * 1024, env: { ...process.env, PIWA_PROTECTED: protectedData.toString("base64") } }, (err, stdout) => {
|
|
380
381
|
if (err) { resolve(null); return; }
|
|
381
382
|
try {
|
|
382
383
|
resolve(Buffer.from(stdout.trim(), "base64"));
|
|
@@ -509,10 +510,10 @@ async function queryCookieRows(dbPath: string, hosts: string[], names: Iterable<
|
|
|
509
510
|
const columns = await readCookieColumns(dbPath);
|
|
510
511
|
if (columns.status === "failure") return columns;
|
|
511
512
|
const pathExpr = columns.columns.has("path") ? "path" : "'/' AS path";
|
|
512
|
-
const expiresExpr = columns.columns.has("expires_utc") ?
|
|
513
|
-
const expiryFilter = filterExpired && columns.columns.has("expires_utc") ? ` AND (
|
|
513
|
+
const expiresExpr = columns.columns.has("expires_utc") ? chromeExpiryMillisExpr() : "0";
|
|
514
|
+
const expiryFilter = filterExpired && columns.columns.has("expires_utc") ? ` AND (${expiresExpr} = 0 OR ${expiresExpr} > ${chromeExpiryNowMillis()})` : "";
|
|
514
515
|
const partitionFilter = filterExpired ? unpartitionedCookieFilter(columns.columns) : "";
|
|
515
|
-
return runSqliteQuery(dbPath, `SELECT name, value, host_key, ${pathExpr}, ${expiresExpr}, hex(encrypted_value) AS encrypted_value_hex FROM cookies WHERE ${buildCookieWhere(hosts, names ?? undefined)}${expiryFilter}${partitionFilter} ORDER BY length(path) DESC,
|
|
516
|
+
return runSqliteQuery(dbPath, `SELECT name, value, host_key, ${pathExpr}, ${expiresExpr} AS expires_utc, hex(encrypted_value) AS encrypted_value_hex FROM cookies WHERE ${buildCookieWhere(hosts, names ?? undefined)}${expiryFilter}${partitionFilter} ORDER BY length(path) DESC, ${expiresExpr} ASC`);
|
|
516
517
|
}
|
|
517
518
|
|
|
518
519
|
async function readCookieColumns(dbPath: string): Promise<{ status: "success"; columns: Set<string> } | { status: "failure"; failure: SqliteFailure }> {
|
|
@@ -521,8 +522,12 @@ async function readCookieColumns(dbPath: string): Promise<{ status: "success"; c
|
|
|
521
522
|
return { status: "success", columns: new Set(result.rows.map(row => typeof row.name === "string" ? row.name : "")) };
|
|
522
523
|
}
|
|
523
524
|
|
|
524
|
-
function
|
|
525
|
-
return (
|
|
525
|
+
function chromeExpiryMillisExpr(): string {
|
|
526
|
+
return "CASE WHEN expires_utc = 0 THEN 0 ELSE CAST(expires_utc / 1000 AS INTEGER) + CASE WHEN expires_utc % 1000 = 0 THEN 0 ELSE 1 END END";
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function chromeExpiryNowMillis(): number {
|
|
530
|
+
return Date.now() + 11644473600000;
|
|
526
531
|
}
|
|
527
532
|
|
|
528
533
|
function unpartitionedCookieFilter(columns: Set<string>): string {
|
|
@@ -216,6 +216,24 @@ function shouldTryOpenAIInAuto(options: SearchOptions): boolean {
|
|
|
216
216
|
return true;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
function isOpenAICodexSelected(ctx?: ExtensionContext): boolean {
|
|
220
|
+
return ctx?.model?.provider === "openai-codex";
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function tryOpenAIInAuto(query: string, options: FullSearchOptions, fallbackErrors: string[]): Promise<AttributedSearchResponse | null> {
|
|
224
|
+
if (!shouldTryOpenAIInAuto(options)) return null;
|
|
225
|
+
try {
|
|
226
|
+
if (await isOpenAISearchAvailable(options.extensionContext)) {
|
|
227
|
+
const result = await searchWithOpenAI(query, options, options.extensionContext);
|
|
228
|
+
return { ...result, provider: "openai" };
|
|
229
|
+
}
|
|
230
|
+
} catch (err) {
|
|
231
|
+
if (isAbortError(err)) throw err;
|
|
232
|
+
fallbackErrors.push(`OpenAI: ${errorMessage(err)}`);
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
|
|
219
237
|
async function searchWithGemini(
|
|
220
238
|
query: string,
|
|
221
239
|
options: SearchOptions,
|
|
@@ -524,16 +542,11 @@ export async function search(query: string, options: FullSearchOptions = {}): Pr
|
|
|
524
542
|
}
|
|
525
543
|
}
|
|
526
544
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
}
|
|
533
|
-
} catch (err) {
|
|
534
|
-
if (isAbortError(err)) throw err;
|
|
535
|
-
fallbackErrors.push(`OpenAI: ${errorMessage(err)}`);
|
|
536
|
-
}
|
|
545
|
+
let triedOpenAI = false;
|
|
546
|
+
if (!options.extensionContext || isOpenAICodexSelected(options.extensionContext)) {
|
|
547
|
+
triedOpenAI = true;
|
|
548
|
+
const result = await tryOpenAIInAuto(query, options, fallbackErrors);
|
|
549
|
+
if (result) return result;
|
|
537
550
|
}
|
|
538
551
|
|
|
539
552
|
if (isExaAvailable()) {
|
|
@@ -546,6 +559,11 @@ export async function search(query: string, options: FullSearchOptions = {}): Pr
|
|
|
546
559
|
}
|
|
547
560
|
}
|
|
548
561
|
|
|
562
|
+
if (!triedOpenAI) {
|
|
563
|
+
const result = await tryOpenAIInAuto(query, options, fallbackErrors);
|
|
564
|
+
if (result) return result;
|
|
565
|
+
}
|
|
566
|
+
|
|
549
567
|
if (isBraveAvailable()) {
|
|
550
568
|
try {
|
|
551
569
|
const result = await searchWithBrave(query, options);
|
|
@@ -152,7 +152,7 @@ interface WebSearchConfig {
|
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
interface ProviderAvailability {
|
|
155
|
+
export interface ProviderAvailability {
|
|
156
156
|
all: boolean;
|
|
157
157
|
openai: boolean;
|
|
158
158
|
brave: boolean;
|
|
@@ -184,7 +184,7 @@ interface ProviderAvailability {
|
|
|
184
184
|
|
|
185
185
|
type WebSearchWorkflow = "none" | "summary-review" | "auto-summary";
|
|
186
186
|
type CuratorWorkflow = "summary-review";
|
|
187
|
-
type CuratorProvider = Exclude<SearchProvider, "auto">;
|
|
187
|
+
export type CuratorProvider = Exclude<SearchProvider, "auto">;
|
|
188
188
|
type SummaryWorkflow = "summary-review" | "auto-summary";
|
|
189
189
|
|
|
190
190
|
interface CuratorBootstrap {
|
|
@@ -420,13 +420,16 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
|
|
|
420
420
|
};
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
function
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
423
|
+
function shouldUseOpenAICodexDefault(ctx?: Pick<ExtensionContext, "model">): boolean {
|
|
424
|
+
return ctx?.model?.provider === "openai-codex";
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function shouldPreferOpenAI(options: Pick<PendingCurate, "numResults" | "recencyFilter"> | undefined, preferOpenAICodexDefault: boolean): boolean {
|
|
428
|
+
if (options?.recencyFilter) return false;
|
|
429
|
+
if (typeof options?.numResults === "number" && Number.isFinite(options.numResults) && Math.floor(options.numResults) !== 5) {
|
|
427
430
|
return false;
|
|
428
431
|
}
|
|
429
|
-
return
|
|
432
|
+
return preferOpenAICodexDefault;
|
|
430
433
|
}
|
|
431
434
|
|
|
432
435
|
async function loadCuratorBootstrap(
|
|
@@ -439,15 +442,25 @@ async function loadCuratorBootstrap(
|
|
|
439
442
|
if (Array.isArray(provider)) availableProviders.all = true;
|
|
440
443
|
return {
|
|
441
444
|
availableProviders,
|
|
442
|
-
defaultProvider:
|
|
445
|
+
defaultProvider: resolveCuratorDefaultProvider(provider, availableProviders, ctx, options),
|
|
443
446
|
timeoutSeconds: getCuratorTimeoutSeconds(),
|
|
444
447
|
};
|
|
445
448
|
}
|
|
446
449
|
|
|
450
|
+
export function resolveCuratorDefaultProvider(
|
|
451
|
+
provider: SearchProviderSelection,
|
|
452
|
+
available: ProviderAvailability,
|
|
453
|
+
ctx?: Pick<ExtensionContext, "model">,
|
|
454
|
+
options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
|
|
455
|
+
): CuratorProvider {
|
|
456
|
+
return resolveProvider(provider, available, options, shouldUseOpenAICodexDefault(ctx));
|
|
457
|
+
}
|
|
458
|
+
|
|
447
459
|
function firstAvailableProvider(available: ProviderAvailability, preferOpenAI: boolean, fallback: ResolvedSearchProvider): ResolvedSearchProvider {
|
|
448
460
|
if (available.searxng) return "searxng";
|
|
449
461
|
if (preferOpenAI && available.openai) return "openai";
|
|
450
462
|
if (available.exa) return "exa";
|
|
463
|
+
if (available.openai) return "openai";
|
|
451
464
|
if (available.brave) return "brave";
|
|
452
465
|
if (available.parallel) return "parallel";
|
|
453
466
|
if (available.tinyfish) return "tinyfish";
|
|
@@ -470,9 +483,10 @@ function resolveProvider(
|
|
|
470
483
|
provider: SearchProviderSelection,
|
|
471
484
|
available: ProviderAvailability,
|
|
472
485
|
options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
|
|
486
|
+
preferOpenAICodexDefault = false,
|
|
473
487
|
): CuratorProvider {
|
|
474
488
|
if (Array.isArray(provider)) return "all";
|
|
475
|
-
const preferOpenAI = shouldPreferOpenAI(options);
|
|
489
|
+
const preferOpenAI = shouldPreferOpenAI(options, preferOpenAICodexDefault);
|
|
476
490
|
|
|
477
491
|
if (provider === "auto") {
|
|
478
492
|
const routing = getConfiguredSearchRouting();
|
|
@@ -1660,7 +1674,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1660
1674
|
name: toolNames.webSearch,
|
|
1661
1675
|
label: "Web Search",
|
|
1662
1676
|
description:
|
|
1663
|
-
`Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider,
|
|
1677
|
+
`Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider, SearXNG is preferred first for local/private search. When the active Pi model is openai-codex, Codex-backed OpenAI search is preferred next. Otherwise Exa is preferred before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web.`,
|
|
1664
1678
|
promptSnippet:
|
|
1665
1679
|
"Use for web research questions. Prefer {queries:[...]} with 2-4 varied angles over a single query for broader coverage. Omit provider unless explicitly overriding the configured default.",
|
|
1666
1680
|
parameters: Type.Object({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-access",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.2",
|
|
4
4
|
"description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Exa, Perplexity, and Gemini.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alexei Led
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# resume-from
|
|
2
|
+
|
|
3
|
+
[](https://github.com/alexei-led/resume-from/actions/workflows/release.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/resume-from)
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
Continue an AI coding session in another terminal agent or another profile of the same agent.
|
|
9
|
+
|
|
10
|
+
`resume-from` converts saved sessions between **Pi**, **Claude Code**, and **Codex**. Use it when you want a different model, provider, tool harness, or account without rebuilding the task context by hand.
|
|
11
|
+
|
|
12
|
+
## Why this exists
|
|
13
|
+
|
|
14
|
+
Coding agents save conversations in different locations and vendor-specific formats. A Codex thread is not a Pi session. A Claude Code session cannot be opened directly by Codex.
|
|
15
|
+
|
|
16
|
+
You can ask the next agent to read another tool's raw session file, but then the model must understand that format and decide which internal data is safe or useful. `resume-from` performs that conversion before the target agent starts:
|
|
17
|
+
|
|
18
|
+
1. Find sessions for the current Git repository.
|
|
19
|
+
2. Parse the source agent's format into a common conversation model.
|
|
20
|
+
3. Remove tool-result bodies and vendor-only state.
|
|
21
|
+
4. Fit the useful history to the target context budget.
|
|
22
|
+
5. Show exactly what will be imported.
|
|
23
|
+
6. After confirmation, write a new session in the target agent's native format.
|
|
24
|
+
|
|
25
|
+
The source session is never changed.
|
|
26
|
+
|
|
27
|
+
## Use it when
|
|
28
|
+
|
|
29
|
+
- **You want another model or provider.** Start the target agent with the model you want, then import the session.
|
|
30
|
+
- **You want another harness.** Keep the task context while changing terminal UI, tools, permissions, extensions, or agent behavior.
|
|
31
|
+
- **You hit a rate or usage limit.** Continue through another installed agent or account instead of waiting or reconstructing the task.
|
|
32
|
+
- **You need another profile.** Move between work, personal, or team homes, including two profiles of the same agent.
|
|
33
|
+
- **The current context is too large.** Import a budgeted history into a fresh native session.
|
|
34
|
+
- **You want an independent handoff.** Create a target-side copy for continued work or review while preserving the original session.
|
|
35
|
+
|
|
36
|
+
`resume-from` moves conversation context. It does not copy the repository or migrate a running process. The target agent must have access to the same working tree.
|
|
37
|
+
|
|
38
|
+
## Supported transfers
|
|
39
|
+
|
|
40
|
+
Every source-to-target direction is supported, including transfers within the same agent:
|
|
41
|
+
|
|
42
|
+
| Source \ Target | Pi | Claude Code | Codex |
|
|
43
|
+
| --------------- | :-: | :---------: | :---: |
|
|
44
|
+
| **Pi** | ✓ | ✓ | ✓ |
|
|
45
|
+
| **Claude Code** | ✓ | ✓ | ✓ |
|
|
46
|
+
| **Codex** | ✓ | ✓ | ✓ |
|
|
47
|
+
|
|
48
|
+
The landing behavior depends on the target:
|
|
49
|
+
|
|
50
|
+
| Target | After confirmation |
|
|
51
|
+
| --------------- | ---------------------------------------------------------------- |
|
|
52
|
+
| **Pi** | Writes and opens the imported session in the current Pi process. |
|
|
53
|
+
| **Claude Code** | Writes the session and prints `claude --resume <session-id>`. |
|
|
54
|
+
| **Codex** | Writes the thread and prints `codex resume <thread-id>`. |
|
|
55
|
+
|
|
56
|
+
## What crosses the boundary
|
|
57
|
+
|
|
58
|
+
The importer keeps the parts needed to continue the task, subject to the target token budget:
|
|
59
|
+
|
|
60
|
+
- User prompts and agent replies.
|
|
61
|
+
- Compaction summaries.
|
|
62
|
+
- Tool activity as **non-replayable plain text**: tool name, recorded arguments, and a one-line outcome.
|
|
63
|
+
- Changed-file paths derived from mutating tool activity.
|
|
64
|
+
- Source provenance and a summary of anything dropped.
|
|
65
|
+
|
|
66
|
+
It excludes:
|
|
67
|
+
|
|
68
|
+
- Tool-result bodies, which may be large, stale, or sensitive.
|
|
69
|
+
- Replayable tool-call structures.
|
|
70
|
+
- Hidden reasoning, system prompts, environment blocks, API keys, telemetry, and vendor process state.
|
|
71
|
+
|
|
72
|
+
A dropped result is marked in the imported conversation. The target agent can reread the current file or rerun a command when it needs fresh state.
|
|
73
|
+
|
|
74
|
+
### Context budget
|
|
75
|
+
|
|
76
|
+
By default, the imported history may use up to 30% of the target context window. The first request, recent turns, summaries, and changed-file records are pinned. If older unpinned turns must be removed, the preview reports them. If the pinned content alone does not fit, the import stops before writing.
|
|
77
|
+
|
|
78
|
+
## Install in the destination agent
|
|
79
|
+
|
|
80
|
+
Install `resume-from` in the agent that will receive the new session.
|
|
81
|
+
|
|
82
|
+
### Pi
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
pi install npm:resume-from
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Restart Pi, then run `/resume-from`.
|
|
89
|
+
|
|
90
|
+
### Claude Code
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
claude plugin marketplace add alexei-led/resume-from
|
|
94
|
+
claude plugin install resume-from@alexei-led-resume-from
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Codex
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
codex plugin marketplace add alexei-led/resume-from
|
|
101
|
+
codex plugin add resume-from@alexei-led-resume-from
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The Codex prompt runs the matching published `resume-from` package through `npx`. Its first use needs npm registry access.
|
|
105
|
+
|
|
106
|
+
## Run the first transfer
|
|
107
|
+
|
|
108
|
+
Run the command from the Git repository that owns the source session.
|
|
109
|
+
|
|
110
|
+
### In Pi
|
|
111
|
+
|
|
112
|
+
1. Run `/resume-from`.
|
|
113
|
+
2. Select a source session in the native picker.
|
|
114
|
+
3. Read the preview.
|
|
115
|
+
4. Confirm.
|
|
116
|
+
|
|
117
|
+
Pi opens the imported session with an empty prompt. You decide when to continue.
|
|
118
|
+
|
|
119
|
+
### In Claude Code or Codex
|
|
120
|
+
|
|
121
|
+
1. Run `/resume-from` to list matching sessions.
|
|
122
|
+
2. Run `/resume-from <row>` to preview one.
|
|
123
|
+
3. Run the token-bearing `/resume-from <row> --confirm <token>` command printed by the preview.
|
|
124
|
+
4. Run the native resume command printed by the tool.
|
|
125
|
+
|
|
126
|
+
You can also select an exact session ID or file path. Selection by path does not bypass the current-repository check.
|
|
127
|
+
|
|
128
|
+
## Safety properties
|
|
129
|
+
|
|
130
|
+
- **Read-only source:** source homes and session files are not modified.
|
|
131
|
+
- **Explicit write:** cancellation or a blocked preview writes nothing.
|
|
132
|
+
- **Add-only target:** the importer creates target files; it does not replace or delete existing sessions.
|
|
133
|
+
- **Native validation:** the new file is validated and read back before it is reported as openable.
|
|
134
|
+
- **No model call during transfer:** conversion, filtering, budgeting, and writing are deterministic local operations.
|
|
135
|
+
- **Visible provenance:** the imported session identifies its source and states what was dropped without putting that marker in model context. Pi renders it as a transcript entry; Claude Code uses its native metadata entry; Codex prints it in the CLI because no safe durable out-of-context entry is verified.
|
|
136
|
+
|
|
137
|
+
## Documentation
|
|
138
|
+
|
|
139
|
+
The user and maintainer documentation is organized in [`docs/`](docs/README.md).
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
Development requires Node 24 LTS and pnpm 11.20.0.
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
pnpm install
|
|
147
|
+
pnpm build
|
|
148
|
+
pnpm test
|
|
149
|
+
pnpm typecheck
|
|
150
|
+
pnpm lint
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Run the command help after a build:
|
|
154
|
+
|
|
155
|
+
```sh
|
|
156
|
+
node dist/bin.js --help
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Claude Code adapter: the port of `src/adapters/`, filled in with what this module knows
|
|
3
|
+
* about Claude Code.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentAdapter, ClaudeCodeAdapterFactory } from "./contract.js";
|
|
6
|
+
/** Claude Code's context window, used when configuration overrides none (FR-18). */
|
|
7
|
+
export declare const DEFAULT_WINDOW_TOKENS = 200000;
|
|
8
|
+
/** The command the landing hands back, because Claude Code cannot move the user (C-2, FR-45). */
|
|
9
|
+
export declare const HANDOVER_COMMAND = "claude --resume";
|
|
10
|
+
export interface ClaudeCodeAdapterDeps {
|
|
11
|
+
/**
|
|
12
|
+
* The repository the import runs in. Claude Code keys a session to a repository, and no
|
|
13
|
+
* argument of the port names one, so the working directory is the signal.
|
|
14
|
+
*/
|
|
15
|
+
cwd: string;
|
|
16
|
+
env: Record<string, string | undefined>;
|
|
17
|
+
homeDir: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Build the adapter. `deps` exists for the tests of this module: the shipped factory below
|
|
21
|
+
* passes the real process values.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createClaudeCodeAdapter(deps?: Partial<ClaudeCodeAdapterDeps>): AgentAdapter;
|
|
24
|
+
/** The only export of this module (FR-57). */
|
|
25
|
+
export declare const claudeCodeAdapter: ClaudeCodeAdapterFactory;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Claude Code adapter: the port of `src/adapters/`, filled in with what this module knows
|
|
3
|
+
* about Claude Code.
|
|
4
|
+
*/
|
|
5
|
+
import { resolveDefaultHome } from "./layout.js";
|
|
6
|
+
import { readBack } from "./readback.js";
|
|
7
|
+
import { listSessions, loadSession } from "./reader.js";
|
|
8
|
+
import { serialize, validate } from "./writer.js";
|
|
9
|
+
/** Claude Code's context window, used when configuration overrides none (FR-18). */
|
|
10
|
+
export const DEFAULT_WINDOW_TOKENS = 200_000;
|
|
11
|
+
/** The command the landing hands back, because Claude Code cannot move the user (C-2, FR-45). */
|
|
12
|
+
export const HANDOVER_COMMAND = "claude --resume";
|
|
13
|
+
/**
|
|
14
|
+
* Build the adapter. `deps` exists for the tests of this module: the shipped factory below
|
|
15
|
+
* passes the real process values.
|
|
16
|
+
*/
|
|
17
|
+
export function createClaudeCodeAdapter(deps = {}) {
|
|
18
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
19
|
+
const env = deps.env ?? process.env;
|
|
20
|
+
// Resolved once: capabilities() is pure, synchronous, and equal on every call.
|
|
21
|
+
const capabilities = Object.freeze({
|
|
22
|
+
agent: "claude-code",
|
|
23
|
+
roles: ["source", "target"],
|
|
24
|
+
selection: "numbered-list",
|
|
25
|
+
landing: "create-only",
|
|
26
|
+
provenance: "out-of-context-entry",
|
|
27
|
+
defaultHome: deps.homeDir === undefined ? resolveDefaultHome(env) : resolveDefaultHome(env, deps.homeDir),
|
|
28
|
+
defaultWindowTokens: DEFAULT_WINDOW_TOKENS,
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
capabilities() {
|
|
32
|
+
return capabilities;
|
|
33
|
+
},
|
|
34
|
+
listSessions(home) {
|
|
35
|
+
return listSessions(home);
|
|
36
|
+
},
|
|
37
|
+
loadSession(descriptor) {
|
|
38
|
+
return loadSession(descriptor);
|
|
39
|
+
},
|
|
40
|
+
serialize(session, target, marker) {
|
|
41
|
+
return serialize(session, target, marker, { cwd });
|
|
42
|
+
},
|
|
43
|
+
validate(serialized) {
|
|
44
|
+
return validate(serialized);
|
|
45
|
+
},
|
|
46
|
+
readBack(home, sessionId) {
|
|
47
|
+
return readBack(home, sessionId);
|
|
48
|
+
},
|
|
49
|
+
switchTo(_home, sessionId, _runtime) {
|
|
50
|
+
return Promise.reject(new Error('Claude Code declares landing "create-only": it cannot move the user into a session ' +
|
|
51
|
+
`(C-2). Run: ${HANDOVER_COMMAND} ${sessionId}`));
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** The only export of this module (FR-57). */
|
|
56
|
+
export const claudeCodeAdapter = {
|
|
57
|
+
create() {
|
|
58
|
+
return createClaudeCodeAdapter();
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, Bytes, LandingLevel, PendingFile, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect } from "../contract.js";
|
|
2
|
+
export type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, Bytes, LandingLevel, PendingFile, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect, };
|
|
3
|
+
import type { AgentId, CanonicalSession, CanonicalTurn, HomePath, ProvenanceMarker, RepoSnapshot, SessionDescriptor, SessionId, SessionRef, SourceProvenance, TargetProfile, ToolCallRecord, ToolEffect, TurnKind, TurnRole } from "../../session/contract.js";
|
|
4
|
+
export type { AgentId, CanonicalSession, CanonicalTurn, HomePath, ProvenanceMarker, RepoSnapshot, SessionDescriptor, SessionId, SessionRef, SourceProvenance, TargetProfile, ToolCallRecord, ToolEffect, TurnKind, TurnRole, };
|
|
5
|
+
/** Builds the Claude Code adapter. The only export of this module (FR-57). */
|
|
6
|
+
export interface ClaudeCodeAdapterFactory {
|
|
7
|
+
create(): AgentAdapter;
|
|
8
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Claude Code session file: one JSON object per line.
|
|
3
|
+
*
|
|
4
|
+
* The store holds ten entry types (C-3). This module reads the few that carry turns and writes
|
|
5
|
+
* exactly two, `user` and `assistant` (C-9) — fewer types, fewer ways to corrupt the store.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ENTRY_TYPE_USER = "user";
|
|
8
|
+
export declare const ENTRY_TYPE_ASSISTANT = "assistant";
|
|
9
|
+
export declare const ENTRY_TYPE_SUMMARY = "summary";
|
|
10
|
+
/** The only entry types `serialize` writes (C-9). */
|
|
11
|
+
export declare const WRITTEN_ENTRY_TYPES: readonly string[];
|
|
12
|
+
export type RawEntry = Record<string, unknown>;
|
|
13
|
+
export interface JsonlParse {
|
|
14
|
+
entries: RawEntry[];
|
|
15
|
+
/** Set when a line is not a complete entry — the file is cut mid-entry. */
|
|
16
|
+
unreadable: string | null;
|
|
17
|
+
}
|
|
18
|
+
export interface ActiveEntryPath {
|
|
19
|
+
entries: RawEntry[];
|
|
20
|
+
unreadable: string | null;
|
|
21
|
+
}
|
|
22
|
+
/** Parse a session file. A line that is not a complete entry makes the whole file unreadable. */
|
|
23
|
+
export declare function parseJsonl(text: string): JsonlParse;
|
|
24
|
+
/** Follow the last non-sidechain UUID record to the root of Claude's active transcript. */
|
|
25
|
+
export declare function resolveActiveEntryPath(entries: RawEntry[]): ActiveEntryPath;
|
|
26
|
+
export declare function asString(value: unknown): string | null;
|
|
27
|
+
export declare function asObject(value: unknown): Record<string, unknown> | null;
|
|
28
|
+
export declare function asArray(value: unknown): unknown[] | null;
|
|
29
|
+
/** ISO-8601 UTC, the vocabulary every timestamp of the canonical model uses. */
|
|
30
|
+
export declare function toIsoUtc(value: unknown): string | null;
|