@caupulican/pi-adaptative 0.84.1 → 0.85.3
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 +53 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +14 -8
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +14 -8
- package/dist/bundled-resources/runtimes/pi-shell-engine/arithmetic.py +364 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +2 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +16 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +137 -14
- package/dist/bundled-resources/runtimes/pi-shell-engine/nodes.py +23 -2
- package/dist/bundled-resources/runtimes/pi-shell-engine/parser.py +134 -6
- package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +25 -2
- package/dist/bundled-resources/skills/deduplicate-by-evidence/SKILL.md +7 -5
- package/dist/bundled-resources/skills/worker-profile-writer/SKILL.md +63 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +8 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +4 -2
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +3 -0
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +6 -0
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/compaction-controller.d.ts +2 -0
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +35 -13
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +1 -0
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts +7 -0
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +28 -0
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.d.ts +2 -0
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.js +46 -11
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
- package/dist/core/doctor.d.ts +1 -1
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +5 -4
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/failure-corpus.d.ts +26 -1
- package/dist/core/failure-corpus.d.ts.map +1 -1
- package/dist/core/failure-corpus.js +17 -0
- package/dist/core/failure-corpus.js.map +1 -1
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +1 -0
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-tool-protocol.d.ts +3 -2
- package/dist/core/model-tool-protocol.d.ts.map +1 -1
- package/dist/core/model-tool-protocol.js +5 -1
- package/dist/core/model-tool-protocol.js.map +1 -1
- package/dist/core/models/runtime-process.d.ts +7 -1
- package/dist/core/models/runtime-process.d.ts.map +1 -1
- package/dist/core/models/runtime-process.js +4 -2
- package/dist/core/models/runtime-process.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js +6 -1
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/orchestration/session-task-profile-store.d.ts +31 -0
- package/dist/core/orchestration/session-task-profile-store.d.ts.map +1 -0
- package/dist/core/orchestration/session-task-profile-store.js +138 -0
- package/dist/core/orchestration/session-task-profile-store.js.map +1 -0
- package/dist/core/orchestration/task-profile-writer.d.ts +58 -0
- package/dist/core/orchestration/task-profile-writer.d.ts.map +1 -0
- package/dist/core/orchestration/task-profile-writer.js +165 -0
- package/dist/core/orchestration/task-profile-writer.js.map +1 -0
- package/dist/core/process-matrix/runtime.js +43 -11
- package/dist/core/process-matrix/runtime.js.map +1 -1
- package/dist/core/resource-loader.d.ts +2 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +18 -6
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +3 -1
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +14 -0
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/security/untrusted-boundary.d.ts.map +1 -1
- package/dist/core/security/untrusted-boundary.js +4 -6
- package/dist/core/security/untrusted-boundary.js.map +1 -1
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +1 -0
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +21 -23
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tool-capability-policy.js +1 -1
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tool-recovery-log-records.d.ts +33 -1
- package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
- package/dist/core/tool-recovery-log-records.js +59 -12
- package/dist/core/tool-recovery-log-records.js.map +1 -1
- package/dist/core/tool-recovery-logger.d.ts +12 -1
- package/dist/core/tool-recovery-logger.d.ts.map +1 -1
- package/dist/core/tool-recovery-logger.js +24 -1
- package/dist/core/tool-recovery-logger.js.map +1 -1
- package/dist/core/tool-repair-health.d.ts.map +1 -1
- package/dist/core/tool-repair-health.js +6 -0
- package/dist/core/tool-repair-health.js.map +1 -1
- package/dist/core/tools/bash.d.ts +3 -8
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +4 -28
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate.js +4 -4
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +32 -5
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +137 -69
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +22 -7
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +128 -55
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-intent.d.ts +70 -0
- package/dist/core/tools/file-mutation-intent.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-intent.js +325 -0
- package/dist/core/tools/file-mutation-intent.js.map +1 -0
- package/dist/core/tools/find.d.ts +2 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +2 -6
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +41 -18
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/grep.d.ts +2 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +2 -6
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +3 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +31 -8
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/managed-search-tool.d.ts +8 -0
- package/dist/core/tools/managed-search-tool.d.ts.map +1 -0
- package/dist/core/tools/managed-search-tool.js +10 -0
- package/dist/core/tools/managed-search-tool.js.map +1 -0
- package/dist/core/tools/profile-writer.d.ts +33 -0
- package/dist/core/tools/profile-writer.d.ts.map +1 -0
- package/dist/core/tools/profile-writer.js +67 -0
- package/dist/core/tools/profile-writer.js.map +1 -0
- package/dist/core/tools/shell-command-parser.d.ts +4 -3
- package/dist/core/tools/shell-command-parser.d.ts.map +1 -1
- package/dist/core/tools/shell-command-parser.js +32 -7
- package/dist/core/tools/shell-command-parser.js.map +1 -1
- package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
- package/dist/core/tools/shell-contract-router.js +23 -1
- package/dist/core/tools/shell-contract-router.js.map +1 -1
- package/dist/core/tools/task-steps.d.ts.map +1 -1
- package/dist/core/tools/task-steps.js +6 -11
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts +2 -0
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
- package/dist/core/tools/tmux-dispatch.js +16 -2
- package/dist/core/tools/tmux-dispatch.js.map +1 -1
- package/dist/core/tools/windows-shell-engine.js +1 -1
- package/dist/core/tools/windows-shell-engine.js.map +1 -1
- package/dist/core/tools/write.d.ts +24 -7
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +182 -107
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/jscpd-cli.d.ts +3 -0
- package/dist/jscpd-cli.d.ts.map +1 -0
- package/dist/jscpd-cli.js +22 -0
- package/dist/jscpd-cli.js.map +1 -0
- package/dist/modes/interactive/components/profile-resource-editor.js +2 -2
- package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +85 -3
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/bundled-jscpd.d.ts +20 -0
- package/dist/utils/bundled-jscpd.d.ts.map +1 -0
- package/dist/utils/bundled-jscpd.js +154 -0
- package/dist/utils/bundled-jscpd.js.map +1 -0
- package/dist/utils/paths.js +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +11 -0
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +19 -2
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +92 -40
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/index.md +3 -0
- package/docs/managed-data-tools.md +15 -0
- package/docs/models.md +1 -1
- package/docs/quickstart.md +2 -2
- package/docs/settings.md +1 -1
- package/docs/tool-boundary-performance-roadmap-2026-08-02.md +166 -0
- package/docs/tool-repair.md +4 -4
- package/docs/windows.md +7 -5
- package/docs/worker-profiles.md +16 -0
- package/examples/extensions/built-in-tool-renderer.ts +12 -5
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/minimal-mode.ts +8 -7
- package/examples/extensions/prompt-customizer.ts +4 -2
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/ssh.ts +113 -24
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +112 -12
- package/package.json +7 -5
package/docs/index.md
CHANGED
|
@@ -49,11 +49,13 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
49
49
|
- [Tool repair](tool-repair.md) - repaired tool-call arguments, health diagnostics, kill switches, and replay workflow.
|
|
50
50
|
- [Task steps](task-steps.md) - native session checklist, slash commands, persistence, and delegation migration.
|
|
51
51
|
- [Native Python](python.md) - uv-managed bounded Python execution, provisioning, output limits, and cross-platform file guidance.
|
|
52
|
+
- [Managed data tools](managed-data-tools.md) - pinned rg, jq, and Rust jscpd provisioning without project files.
|
|
52
53
|
|
|
53
54
|
## Customization
|
|
54
55
|
|
|
55
56
|
- [Extensions](extensions.md) - TypeScript modules for tools, commands, events, and custom UI.
|
|
56
57
|
- [tmux agent manager](tmux-agent-manager.md) - bundled event-driven external-provider teams with parent wake handoffs.
|
|
58
|
+
- [Task worker profiles](worker-profiles.md) - immutable session-scoped worker profiles with bounded model and tool authority.
|
|
57
59
|
- [Skills](skills.md) - Agent Skills for reusable on-demand capabilities.
|
|
58
60
|
- [Resource profiles & library](resources.md) - curate extensions, skills, and agents per project or situation; share a catalog; install and back up.
|
|
59
61
|
- [Self-adaptation](self-adaptation.md) - draft live skills/extensions and run evidence-backed Pi harness improvement loops.
|
|
@@ -86,3 +88,4 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
86
88
|
## Development
|
|
87
89
|
|
|
88
90
|
- [Development](development.md) - local setup, project structure, and debugging.
|
|
91
|
+
- [Tool boundary performance roadmap](tool-boundary-performance-roadmap-2026-08-02.md) - evidence ledger for preflight, payload ownership, Python coordination, and remaining latency/memory work.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Managed data tools
|
|
2
|
+
|
|
3
|
+
Pi keeps source filtering and structured-data projection outside the JavaScript heap with managed native tools:
|
|
4
|
+
|
|
5
|
+
- `rg` for bounded text and file candidate searches.
|
|
6
|
+
- `jq` for selecting only the JSON records and fields needed by the agent.
|
|
7
|
+
- Rust `jscpd` 5.0.14 for production clone evidence.
|
|
8
|
+
|
|
9
|
+
Pi provisions these binaries under its managed agent `bin` directory and places that directory first on the tool environment `PATH`. Provisioning never runs a project package manager and never writes dependencies, configuration, reports, or caches into the current repository.
|
|
10
|
+
|
|
11
|
+
The npm package includes the exact jscpd v5 platform package. Standalone releases carry the native binary beside Pi. The first Pi startup, `pi doctor`, or direct `jscpd` wrapper invocation installs the verified binary into managed storage. Concurrent sessions converge on the same exact version; different agent directories remain isolated.
|
|
12
|
+
|
|
13
|
+
Use `pi doctor` to verify availability. If a managed binary cannot be verified, treat the scan as incomplete and change approach; do not install a fallback into the project.
|
|
14
|
+
|
|
15
|
+
Ad hoc scanner reports and configuration belong in the OS or Pi transient work directory. A green clone report is evidence only when its production coverage and detection thresholds are also verified.
|
package/docs/models.md
CHANGED
|
@@ -237,7 +237,7 @@ If your command is slow, expensive, rate-limited, or should keep using a previou
|
|
|
237
237
|
| `compat` | No | provider `compat` | Provider compatibility overrides. Merged with provider-level `compat` when both are set. |
|
|
238
238
|
| `textToolCallProtocol` | No | omitted | Set `true` to enable pi's text tool-call protocol fallback for a pure-text model that cannot emit native provider tool calls. |
|
|
239
239
|
|
|
240
|
-
`textToolCallProtocol` is a per-model opt-in.
|
|
240
|
+
`textToolCallProtocol` is a per-model fallback opt-in. The `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1` kill switch always disables it. A persisted `/toolprobe` native verdict also keeps that exact model on native calls even if the emergency global setting or model metadata enables the text protocol. Without native proof, `toolRepair.textProtocol` overrides the per-model setting. Failed calibration is remembered for the host/model until `/toolprotocol-reset <provider/model>` clears it.
|
|
241
241
|
|
|
242
242
|
Current behavior:
|
|
243
243
|
- `/model` and `--list-models` list entries by model `id`.
|
package/docs/quickstart.md
CHANGED
|
@@ -77,8 +77,8 @@ Summarize this repository and tell me how to run its checks.
|
|
|
77
77
|
By default, pi gives the model four tools:
|
|
78
78
|
|
|
79
79
|
- `read` - read files
|
|
80
|
-
- `write` - create
|
|
81
|
-
- `edit` - patch files
|
|
80
|
+
- `write` - preflight and create new files without overwriting existing paths
|
|
81
|
+
- `edit` - preflight and patch existing files with stale-target checks
|
|
82
82
|
- `bash` - run shell commands
|
|
83
83
|
|
|
84
84
|
Additional built-in read-only tools (`grep`, `find`, `ls`) are available through tool options. Pi runs in your current working directory and can modify files there. Use git or another checkpointing workflow if you want easy rollback.
|
package/docs/settings.md
CHANGED
|
@@ -278,7 +278,7 @@ Worker writes use **review-after-apply** semantics: a grant-authorized direct `w
|
|
|
278
278
|
|
|
279
279
|
Deterministic argument repair is built in and has no settings toggle; schema-valid calls still return unchanged without entering the repair layer. `PI_TOOL_REPAIR_DISABLED=1` remains only an emergency diagnostic kill switch.
|
|
280
280
|
|
|
281
|
-
Text protocol precedence is: `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1` kills it
|
|
281
|
+
Text protocol precedence is: `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1` kills it; a persisted `/toolprobe` native verdict then keeps that exact model on native calls; otherwise `toolRepair.textProtocol` force-enables or disables globally, per-model `textToolCallProtocol` applies, and finally a persisted calibrated text-protocol verdict applies. The phone/text protocol is therefore a fallback lane for models without proven native calls, never a replacement for a proven native path. Failed calibration is stored per host/model and can be cleared with `/toolprotocol-reset <provider/model>`.
|
|
282
282
|
|
|
283
283
|
Environment kill switches override their diagnostic layers: `PI_TOOL_REPAIR_DISABLED=1`, `PI_TOOL_REPAIR_TEACH_DISABLED=1`, and `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1`. See [Tool repair](tool-repair.md) for diagnostics, reset controls, and replay.
|
|
284
284
|
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Tool Boundary Performance Roadmap — 2026-08-02
|
|
2
|
+
|
|
3
|
+
This is the evidence ledger for avoiding wasted model output, repeated large-string work, foreground stalls,
|
|
4
|
+
and cross-session contention at tool boundaries. Findings are classified as fixed, open, rejected, or
|
|
5
|
+
incomplete. A green process exit is not evidence when a relevant payload, race, platform, or memory probe was
|
|
6
|
+
not exercised.
|
|
7
|
+
|
|
8
|
+
## Required invariants
|
|
9
|
+
|
|
10
|
+
1. Validate cheap authority, path, identity, availability, and collision facts before asking the model for a
|
|
11
|
+
large payload.
|
|
12
|
+
2. Keep coordinators, payload handles, mutable queues, and retry state session-owned unless cross-session
|
|
13
|
+
coordination is the explicit invariant.
|
|
14
|
+
3. Store large bytes once, outside the JavaScript heap where practical. Context and telemetry retain bounded
|
|
15
|
+
metadata and opaque handles, not duplicate payloads.
|
|
16
|
+
4. Never flatten accumulated text repeatedly. Rendering, loop detection, failure handling, and telemetry use
|
|
17
|
+
incremental processing or constant-size fingerprints.
|
|
18
|
+
5. A failure that requires a different approach discards its operation arguments. It may expose one bounded
|
|
19
|
+
reason/directive for the next model turn, then expires.
|
|
20
|
+
6. Every visible tool operation reports elapsed time through the shared TUI timing owner.
|
|
21
|
+
|
|
22
|
+
## Confirmed and fixed in this cycle
|
|
23
|
+
|
|
24
|
+
| Boundary | Root cause | Fix | Evidence gate |
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
|
+
| Write collision | `write` accepted the full content before discovering an occupied destination and could overwrite it. | Two-phase `prepare`/`commit`, path-only collision and parent checks, single-use session intent, and final `wx` no-clobber create. | `test/file-mutation-preflight.test.ts`; `test/file-encoding-policy.test.ts` |
|
|
27
|
+
| Missing/stale edit | `edit` accepted replacement payloads before existence checks and could apply a plan prepared against older bytes. | Path-only preparation records file identity; commit consumes the intent and rejects a missing or changed target. | `test/file-mutation-preflight.test.ts`; `test/file-mutation-queue.test.ts` |
|
|
28
|
+
| Repeated exact content | Copying identical generated content to another destination required retransmitting it. | Successful writes/edits return a session-local `contentRef`; the bounded controller hashes the source and performs exclusive verified copies without retaining bytes on the JS heap. | `test/file-mutation-preflight.test.ts` |
|
|
29
|
+
| Encoding corruption | An unsafe text edit could be remembered as a retryable operation and teach repair/re-read loops. | The central execution-error catalogue classifies `PI_FILE_ENCODING_CORRUPTION` as change-approach, consumes the edit intent, retains no operation arguments, exposes one bounded directive, and expires it after the next assistant response. | `packages/ai/test/tool-execution-error-catalogue.test.ts`; `packages/agent/test/tool-failure-memory.test.ts` |
|
|
30
|
+
| Edit preview flattening | Preview rendering used `JSON.stringify({ path, edits })` during render and result settlement, copying the complete edit payload. | Constant-size request generations fence asynchronous previews; partial renders do not scan accumulated edits. | `test/edit-tool-no-full-redraw.test.ts` |
|
|
31
|
+
| Write preview flattening | Collapsed streamed previews compared the complete prior content prefix, split and highlighted complete snapshots, and retained duplicate full line arrays. | Collapsed rendering inspects at most 8,192 characters, caches by argument-generation identity, and performs one allocation-free final line count; complete text is materialized only on explicit expansion. | `test/tool-execution-component.test.ts` |
|
|
32
|
+
| Loop/failure payload retention | Stall and failure signatures serialized complete tool arguments and stored the normalized string in the loop window. | A streaming structural fingerprint returns 32 hex characters; failure display keeps a bounded structural preview and never serializes the original payload. | `packages/agent/test/tool-failure-memory.test.ts` |
|
|
33
|
+
| Tool timing gaps | Only selected tool implementations exposed duration, so reads and Python appeared to have no timing. | One monotonic component displays live `Elapsed` and terminal `Took` timing for every tool surface, including failures, replayed panels, built-ins, and extensions. | `test/tool-execution-component.test.ts` |
|
|
34
|
+
|
|
35
|
+
All fixed paths must retain the zero-clone production gate and the focused regression named above.
|
|
36
|
+
|
|
37
|
+
## P0 — confirmed open work
|
|
38
|
+
|
|
39
|
+
### P0.1 Persistent Python coordinator per session
|
|
40
|
+
|
|
41
|
+
Evidence:
|
|
42
|
+
|
|
43
|
+
- `src/core/tools/python.ts` creates `createLocalPythonOperations()` per tool definition and calls
|
|
44
|
+
`spawnProcess()` for every execution.
|
|
45
|
+
- `src/core/python-runtime.ts` caches interpreter discovery process-wide, but it is not a command coordinator.
|
|
46
|
+
- `src/core/tools/python.ts` wraps every job in `withExclusiveMutationBarrier()`.
|
|
47
|
+
- `src/core/tools/file-mutation-queue.ts` owns one module-global writer queue, so a long Python job can block
|
|
48
|
+
unrelated sessions and workspaces.
|
|
49
|
+
|
|
50
|
+
Required design:
|
|
51
|
+
|
|
52
|
+
- RuntimeBuilder owns one `PythonCommandCoordinator` per agent session. Never share the command process across
|
|
53
|
+
sessions or tenants.
|
|
54
|
+
- Start the interpreter/worker once on first use, use framed requests and terminal acknowledgements, and reset
|
|
55
|
+
the owned process after protocol corruption, timeout, abort, or crash.
|
|
56
|
+
- Completion is event-driven and emits the normal terminal tool signal. Jobs handed to the existing background
|
|
57
|
+
lane after 15 seconds keep the same session coordinator and notify their owning session only.
|
|
58
|
+
- Replace the process-global exclusive writer with an explicit session/workspace mutation port. Same-file
|
|
59
|
+
operations remain serialized; unrelated sessions are not globally stopped.
|
|
60
|
+
|
|
61
|
+
Acceptance evidence:
|
|
62
|
+
|
|
63
|
+
- Cold start and first dispatch measured separately from warm dispatch on Linux and Windows.
|
|
64
|
+
- Warm no-op harness overhead target: p95 <= 25 ms, excluding Python code runtime.
|
|
65
|
+
- Two concurrent sessions prove distinct worker PIDs/state and no cross-session variables.
|
|
66
|
+
- A 20-second Python job does not delay a read-only call or a mutation in another isolated workspace.
|
|
67
|
+
- Timeout, abort, malformed frame, worker exit, and session disposal each produce one terminal event and bounded
|
|
68
|
+
handoff.
|
|
69
|
+
|
|
70
|
+
### P0.2 Python path/runtime preflight before inline code
|
|
71
|
+
|
|
72
|
+
Evidence: `python` receives up to 200,000 characters of inline code before it checks `cwd`, `scriptPath`, uv, or
|
|
73
|
+
the interpreter. An invalid working directory can therefore waste the entire generated program.
|
|
74
|
+
|
|
75
|
+
Required design:
|
|
76
|
+
|
|
77
|
+
- Add a path-only/runtime-only prepare action for inline-code mode and a path/runtime prepare action for script
|
|
78
|
+
mode.
|
|
79
|
+
- Commit consumes a single-use session intent. Runtime failure or coordinator reset invalidates the intent; the
|
|
80
|
+
code is not stored as retry memory.
|
|
81
|
+
- Do not add a legacy one-phase fallback.
|
|
82
|
+
|
|
83
|
+
Acceptance evidence: invalid cwd/runtime tests prove that no `code` field was accepted; stale and cross-session
|
|
84
|
+
intents fail; successful warm preparation meets the same p95 budget as P0.1.
|
|
85
|
+
|
|
86
|
+
### P0.3 Process-isolate extension smoke tests
|
|
87
|
+
|
|
88
|
+
Evidence: `src/core/tools/extensionify.ts` writes the complete draft and calls `loadExtension()` in the live Pi
|
|
89
|
+
process. The “isolated runtime” isolates registration state, not CPU, environment, memory, filesystem, or process
|
|
90
|
+
lifetime. A draft can block the event loop or inspect live process state.
|
|
91
|
+
|
|
92
|
+
Required design:
|
|
93
|
+
|
|
94
|
+
- Validate name, proposed destination, package JSON shape, size bounds, and policy before accepting factory code.
|
|
95
|
+
- Run the draft in a disposable child process with a bounded environment, output, time, memory, and capability
|
|
96
|
+
surface. Send back registration metadata only.
|
|
97
|
+
- The child emits one terminal result; cleanup is lease-owned and event-driven.
|
|
98
|
+
- Do not repeat `code`/`packageJson` in tool result details.
|
|
99
|
+
|
|
100
|
+
Acceptance evidence: infinite loop, allocation bomb, environment read, process exit, malformed package JSON,
|
|
101
|
+
path traversal, and cleanup-failure probes; parent session remains responsive and bounded.
|
|
102
|
+
|
|
103
|
+
### P0.4 Close edit's external-writer race
|
|
104
|
+
|
|
105
|
+
Evidence: edit commit verifies identity before `readFile()` and later overwrites by path. A non-Pi writer can
|
|
106
|
+
replace the file after the identity check but before the final write.
|
|
107
|
+
|
|
108
|
+
Required design: bind read/compare/commit to a file handle or an adapter-owned compare-and-replace primitive;
|
|
109
|
+
fail closed when identity changes. Define Windows replace/share semantics explicitly and preserve BOM/newlines.
|
|
110
|
+
|
|
111
|
+
Acceptance evidence: deterministic interleavings at every stat/read/write boundary, symlink swaps, same-size
|
|
112
|
+
same-timestamp replacement, Windows sharing violations, abort, and cleanup failure.
|
|
113
|
+
|
|
114
|
+
## P1 — confirmed, bounded, or dependent work
|
|
115
|
+
|
|
116
|
+
1. **General payload leases for `skillify`/`extensionify`.** Both tools repeat full draft bodies in result
|
|
117
|
+
details, while their name/description checks happen only after the payload exists. Introduce a session-owned,
|
|
118
|
+
disk-backed, byte/count/age-bounded payload store and return opaque handles. Keep security-sensitive payload
|
|
119
|
+
classes separate even if they share a storage port.
|
|
120
|
+
2. **Streaming skill audit.** `skill-audit.ts` lowercases, regex-replaces, splits, and de-duplicates the complete
|
|
121
|
+
draft body, then performs pairwise Jaccard comparisons. Add bounded streaming tokenization and an inverted
|
|
122
|
+
candidate index before exact scoring. Preserve evidence that distinct trust/workflow semantics are not merged.
|
|
123
|
+
3. **Verify custom write adapters before issuing reusable content handles.** Local `wx` writes are authoritative;
|
|
124
|
+
remote/custom adapters need an adapter-owned verified-create contract so a handle is not returned for altered
|
|
125
|
+
bytes.
|
|
126
|
+
4. **Reduce bounded toolkit-output copies.** Script capture is capped at 512 KiB per stream, but result assembly
|
|
127
|
+
trims and joins both strings before artifact packing. Stream directly into the existing output/artifact owner.
|
|
128
|
+
This is not an OOM path under the present cap, so it follows the unbounded P0 items.
|
|
129
|
+
5. **Bound metadata schemas.** Add evidence-derived character/item limits to `extensionify`, `skillify`, and
|
|
130
|
+
toolkit identifiers/arguments. Limits must be measured and must not truncate source or reduce correctness.
|
|
131
|
+
6. **Bound renderer-less tool arguments.** `ToolExecutionComponent.formatToolExecution()` currently
|
|
132
|
+
`JSON.stringify()`s complete arguments for tools without a renderer, and the scrollback component retains
|
|
133
|
+
that argument object after settlement. Use the shared bounded structural projection for display and release
|
|
134
|
+
the UI-owned payload after the session transcript has accepted the authoritative call. Preserve explicit
|
|
135
|
+
expansion through a disk-backed/session-owned handle instead of another heap copy.
|
|
136
|
+
|
|
137
|
+
## Rejected or low-benefit candidates
|
|
138
|
+
|
|
139
|
+
- **Ropes/piece tables for provider payloads:** rejected at the network boundary. Providers still require a
|
|
140
|
+
contiguous JSON/body representation; chunked message ownership, pruning before formatting, and one terminal
|
|
141
|
+
serialization are the useful controls.
|
|
142
|
+
- **Two-phase preflight for `read`, `grep`, `find`, `ls`, and artifact retrieval:** rejected unless new evidence
|
|
143
|
+
shows large arguments. Their requests are small, outputs are bounded or artifact-backed, and an extra model
|
|
144
|
+
round trip would cost more than the local validation.
|
|
145
|
+
- **Replacing native JSON globally:** rejected without per-boundary benchmarks. Several provider transports
|
|
146
|
+
require JSON text; changing parsers cannot remove serialization and may add copies. Optimize duplicate
|
|
147
|
+
serialization and retained ownership first.
|
|
148
|
+
- **Raising output/context limits:** rejected as a performance fix. It moves the failure boundary and increases
|
|
149
|
+
heap exposure without removing repeated work.
|
|
150
|
+
|
|
151
|
+
## Incomplete probes
|
|
152
|
+
|
|
153
|
+
- Windows timing distributions for local and SSH-backed prepare/commit.
|
|
154
|
+
- Heap/GC profiles for multi-megabyte skill drafts and extension smoke tests.
|
|
155
|
+
- External-writer race reproduction on NTFS with antivirus/indexer sharing behavior.
|
|
156
|
+
- Provider-specific cost of the extra prepare turn versus rejected-payload tokens across native and text tool
|
|
157
|
+
protocols.
|
|
158
|
+
- Persistent Python protocol throughput and reset cost; no implementation exists yet, so prior process-spawn
|
|
159
|
+
timings are not acceptance evidence.
|
|
160
|
+
|
|
161
|
+
## Release gate for roadmap items
|
|
162
|
+
|
|
163
|
+
For each item: Detect -> deterministic failing regression and negative control -> fix at the named owner -> run
|
|
164
|
+
the smallest package test -> run adjacent package tests -> `npm run check` -> production clone audit. Run the full
|
|
165
|
+
non-e2e suite only at the pre-release gate. Report fixed findings, rejected candidates, incomplete probes, and
|
|
166
|
+
remaining platform risks separately.
|
package/docs/tool-repair.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Pi validates every model-emitted tool call against its TypeBox schema before execution. Valid calls run unchanged. Invalid calls either pass through a named deterministic repair and then execute with the repaired arguments, or they bounce with schema feedback when no safe repair applies.
|
|
4
4
|
|
|
5
|
-
Execution failures are not argument repairs. Pi removes their potentially large failed protocol turns from provider context and retains one bounded failure record:
|
|
5
|
+
Execution failures are not argument repairs. Pi removes their potentially large failed protocol turns from provider context and normally retains one bounded failure record: constant-size operation fingerprint, bounded operation preview, occurrence count, failure code, a cause-bearing diagnostic when available, and `next_action`. A matching successful retry clears the record. Change-approach classes such as non-UTF-8 text edits are different: Pi discards the complete attempted operation, exposes one bounded reason/directive for the next assistant response, then expires it. Pi uses `repair` only for argument/protocol rejections with a concrete call correction; policy, preflight, abort, and execution failures use `next_action`. It never invents a deterministic repair from an unknown nonzero exit.
|
|
6
6
|
|
|
7
7
|
## Runtime behavior
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ Execution failures are not argument repairs. Pi removes their potentially large
|
|
|
11
11
|
- Repair is built-in and has no settings toggle. `PI_TOOL_REPAIR_DISABLED=1` is only an emergency diagnostic kill switch; normal configuration should leave repair on.
|
|
12
12
|
- Teaching can be disabled independently with `toolRepair.teach: false` or `PI_TOOL_REPAIR_TEACH_DISABLED=1`. Repairs can still execute; the in-band "Tool argument repair note" is suppressed.
|
|
13
13
|
- Tool-recovery logging can be disabled with `toolRepair.logging: false`. Repairs still run, but Pi does not enqueue recovery records or spawn the background recovery-log worker.
|
|
14
|
-
- Text tool-call protocol calibration can be enabled per model with `textToolCallProtocol: true` in `models.json`. `/toolprobe [provider/model]` can
|
|
14
|
+
- Text tool-call protocol calibration can be enabled per model with `textToolCallProtocol: true` in `models.json`. `/toolprobe [provider/model]` probes native calls first and can persist a host-local text-protocol verdict only when native calls are absent. A persisted native verdict always keeps that model off the text protocol, including when global or model settings enable it. Use `toolRepair.textProtocol` only as a global emergency force/kill switch for models without native proof; `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1` always disables it.
|
|
15
15
|
|
|
16
16
|
Example project settings:
|
|
17
17
|
|
|
@@ -29,7 +29,7 @@ Example project settings:
|
|
|
29
29
|
|
|
30
30
|
- Interactive tool panels show `[repaired arguments]` when execution used repaired arguments.
|
|
31
31
|
- RPC `tool_execution_start`, `tool_execution_update`, and `tool_execution_end` events include a `repair` object when arguments were repaired.
|
|
32
|
-
- `/toolhealth` prints model adaptation records for this host: tool-probe verdicts, calibrated or failed text protocol, learned standing rules, teach statistics,
|
|
32
|
+
- `/toolhealth` prints model adaptation records for this host: tool-probe verdicts, calibrated or failed text protocol, learned standing rules, teach statistics, recovery-log worker counters, and execution-failure counts by phase.
|
|
33
33
|
- `/toolrule-remove <provider/model> <mode>` removes one learned standing rule from the host-local adaptation store.
|
|
34
34
|
- `/toolprotocol-reset <provider/model>` removes a stored text protocol calibration or failed-calibration record so the next turn can calibrate again.
|
|
35
35
|
- `/toolprobe [provider/model]` probes the current fleet or one explicit model for native tool calls first, then text-protocol fallback, persists the verdict in the host-local adaptation store, and prints a report table.
|
|
@@ -45,7 +45,7 @@ node scripts/tool-repair-replay.mjs ~/.pi/agent/state/failure-corpus.jsonl --jso
|
|
|
45
45
|
node scripts/tool-repair-replay.mjs ~/.pi/agent/sessions/<session>.jsonl --fixtures /tmp/tool-repair-fixtures.json
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
The replay helper reads `tool_validation` corpus records and legacy bounced `tool_argument_validation` session entries. Current recovery telemetry is written by a dedicated `node:worker_threads` worker to `state/tool-recovery-events.jsonl`; bounced
|
|
48
|
+
The replay helper reads `tool_validation` corpus records and legacy bounced `tool_argument_validation` session entries. Current recovery telemetry is written by a dedicated `node:worker_threads` worker to `state/tool-recovery-events.jsonl`; bounced calls append sanitized `tool_validation` corpus rows, while rejected or failed executions append bounded `tool_execution` rows with phase, failure code, optional redacted diagnostic, and next action. Records do not store full tool arguments.
|
|
49
49
|
|
|
50
50
|
## Repair modes
|
|
51
51
|
|
package/docs/windows.md
CHANGED
|
@@ -13,7 +13,7 @@ Pi supports native Windows on x64 and ARM64. The Node.js package runs under Wind
|
|
|
13
13
|
The model always sees one stable `bash` tool contract. On Windows, a deterministic router classifies every command into one of three tiers instead of parsing the full Bash grammar in one place:
|
|
14
14
|
|
|
15
15
|
1. **PowerShell floor** (always available): one simple command — a bounded set of builtin translations or a quoted external argv — converted deterministically to PowerShell, exactly as before this tier existed.
|
|
16
|
-
2. **Bundled Python engine** (uv-provisioned Python 3.13, on by default): pipelines, redirection, chaining, quoting, expansion, globs, and the coreutils vocabulary below, plus every state-mutating command (`cd`, `export`, `unset`), which the engine always owns so there is a single mutator.
|
|
16
|
+
2. **Bundled Python engine** (uv-provisioned Python 3.13, on by default): pipelines, redirection, chaining, word-list and arithmetic `for` loops, loop control, quoting, expansion, globs, and the coreutils vocabulary below, plus every state-mutating command (`cd`, `export`, `unset`), which the engine always owns so there is a single mutator.
|
|
17
17
|
|
|
18
18
|
External programs are not reimplemented. A simple `rg` call runs the installed native `rg.exe` through the persistent PowerShell floor; when a pipeline or chain requires the Python coordinator, it spawns that same `rg.exe` directly without resolving or starting PowerShell. A `.ps1` target in an engine-owned command is adapted through the same selected PowerShell executable as the floor, without starting a nested model-authored shell.
|
|
19
19
|
3. **Named fail-closed refusal**: constructs outside the supported grammar (see below) return an actionable error naming the construct instead of guessing or downgrading silently.
|
|
@@ -36,7 +36,9 @@ The PowerShell tier runs with `-NoLogo -NoProfile -NonInteractive -Command` and
|
|
|
36
36
|
| Sequencing | `a ; b`, newline-separated, `a && b`, `a \|\| b`, `! pipeline` | Left-to-right / short-circuit / negation, bash-standard. |
|
|
37
37
|
| Subshell | `( … )` | Isolated cwd/env copy — inner `cd`/`export` do not leak out. |
|
|
38
38
|
| Brace group | `{ …; }` | Shares state — inner `cd`/`export` persist. |
|
|
39
|
-
|
|
|
39
|
+
| For loop | `for name in words; do …; done`, `for name; do …; done`, `for ((init; condition; update)); do …; done` | Word lists expand once before iteration; the final value remains in the session environment. The omitted-list form iterates shell positional arguments, which Pi does not supply. Arithmetic clauses support integer variables, updates, assignments, comparisons, logical/bitwise operators, and signed 64-bit wrapping. |
|
|
40
|
+
| Loop control | `break [N]`, `continue [N]` | Works across nested word-list and arithmetic loops. An omitted count means one; invalid counts report status 1 without crashing the coordinator. |
|
|
41
|
+
| Redirection | `>`, `>>`, `1>`, `1>>`, `<`, `2>`, `2>>`, `2>&1`, `&>`, `>&` | `/dev/null` maps to `os.devnull`. Unredirected stderr shares Pi's session output; explicit stderr redirection is honored for builtins, state commands, and external programs. |
|
|
40
42
|
| Quoting | `'…'`, `"…"`, `\x`, `$'…'` | Standard single/double/backslash/ANSI-C semantics. |
|
|
41
43
|
| Tilde | `~`, `~/x` | Word-start, unquoted, expands to `$HOME`. `~user` is unsupported (refusal). |
|
|
42
44
|
| Parameter expansion | `$VAR`, `$?`, `${VAR}`, `${V:-w}`, `${V:=w}`, `${V:+w}`, `${V:?w}`, `${#VAR}` | `$?` is the latest foreground pipeline status. POSIX `:`-prefixed (empty-or-unset) semantics only; other `${…}` operators refuse. |
|
|
@@ -53,13 +55,13 @@ Builtins: `cd`, `pwd`, `echo [-n -e -E]`, `printf`, `export`, `unset`, `exit [N]
|
|
|
53
55
|
- `wc`/`uniq -c` column widths reproduce GNU's dynamic field width only for the single-count stdin case; multi-count/file-arg forms use fixed deterministic padding.
|
|
54
56
|
- No shell-variable vs. exported-environment distinction: every `NAME=value` sets engine env.
|
|
55
57
|
- Sorting is always ordinal (`LC_ALL=C`): globs, `ls`, `find`, and default `sort`.
|
|
56
|
-
-
|
|
58
|
+
- Arithmetic loop variables use deterministic signed 64-bit wrapping; invalid shifts, division by zero, negative exponents, and malformed expressions return status 1 with a bounded diagnostic.
|
|
57
59
|
- Globs expand only the final path segment (`dir/*.py` works; `*/x.py` matches the directory part literally).
|
|
58
60
|
- `wc -m` counts UTF-8 characters (bash under `LC_ALL=C` counts bytes).
|
|
59
61
|
|
|
60
62
|
### Named unsupported constructs
|
|
61
63
|
|
|
62
|
-
Each of these fails closed with a named, actionable error instead of an approximation: `job-control` (trailing `&`, `fg`/`bg`/`jobs`/`wait`/`disown`), `process-substitution` (`<(…)`/`>(…)`), `arithmetic-expansion` (`$((…))`, `((…))`, `let`), `brace-expansion` (`{a,b,c}`), `nested-shell` (`bash`/`sh`/`cmd`/`powershell`/`pwsh`/`wsl`/… as a command word), `exec-builtin`, `heredoc`/`here-string` (`<<`, `<<-`, `<<<`), `function-definition`, `control-flow` (`if`/`
|
|
64
|
+
Each of these fails closed with a named, actionable error instead of an approximation: `job-control` (trailing `&`, `fg`/`bg`/`jobs`/`wait`/`disown`), `process-substitution` (`<(…)`/`>(…)`), `arithmetic-expansion` (`$((…))`, standalone `((…))`, and `let`; arithmetic `for` headers are supported), `brace-expansion` (`{a,b,c}`), `nested-shell` (`bash`/`sh`/`cmd`/`powershell`/`pwsh`/`wsl`/… as a command word), `exec-builtin`, `heredoc`/`here-string` (`<<`, `<<-`, `<<<`), `function-definition`, `control-flow` (`if`/`while`/`until`/`case`/`select`), `extended-glob` (`@(…)`, `!(…)`, etc.), `unsupported-builtin` (`eval`, `source`/`.`, `alias`, `trap`, `set`, `shopt`, `read`, `declare`, `local`), `unsupported-flag`, `posix-script` (`*.sh`, `/bin/…`), `cwd-missing`, `tilde-user`, `malformed-syntax` (unbalanced quote/paren/brace, empty pipeline element, missing redirect target, malformed `for` loop), `parameter-expansion` (a `${…}` form outside the supported op set).
|
|
63
65
|
|
|
64
66
|
### State and session semantics
|
|
65
67
|
|
|
@@ -73,7 +75,7 @@ The Python interpreter and engine imports stay warm in one coordinator process p
|
|
|
73
75
|
|
|
74
76
|
`windowsShell.pythonEngine` (default `true`) is the kill switch. Set it to `false` to restore the PowerShell-only contract verbatim: only the simple-command floor is used, and every pipeline/redirection/expansion/chaining form that would have routed to the engine instead returns the same fail-closed error it did before the engine existed.
|
|
75
77
|
|
|
76
|
-
When the setting is left on but the bundled Python runtime cannot be resolved (uv missing, network failure provisioning Python 3.13, or similar), the engine tier is simply unavailable: simple commands still run on the PowerShell floor exactly as always, and any command that needs the engine returns a named error stating the Python runtime is unavailable, that the simple-command floor still works, and to fix `uv`/network to restore pipelines, redirection, expansion, and chaining. There is no silent approximation — a complex command is never downgraded to a plausible-but-wrong simple execution.
|
|
78
|
+
When the setting is left on but the bundled Python runtime cannot be resolved (uv missing, network failure provisioning Python 3.13, or similar), the engine tier is simply unavailable: simple commands still run on the PowerShell floor exactly as always, and any command that needs the engine returns a named error stating the Python runtime is unavailable, that the simple-command floor still works, and to fix `uv`/network to restore loops, pipelines, redirection, expansion, and chaining. There is no silent approximation — a complex command is never downgraded to a plausible-but-wrong simple execution.
|
|
77
79
|
|
|
78
80
|
The native `python` tool uses the same contract on Windows and Unix-like systems. Pi provisions a pinned uv executable, resolves or installs Python 3.13 through uv, then spawns the interpreter directly with UTF-8 and bytecode-cache suppression. Python calls default to 30 seconds. See [Native Python](python.md).
|
|
79
81
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Task worker profiles
|
|
2
|
+
|
|
3
|
+
`profile_writer` lets the foreground orchestrator create the smallest worker profile needed for one bounded task. It does not edit user or project profile files.
|
|
4
|
+
|
|
5
|
+
Task profiles are:
|
|
6
|
+
|
|
7
|
+
- Derived only from an owner-authorized base profile.
|
|
8
|
+
- Immutable and assigned a `task-...` ID by Pi.
|
|
9
|
+
- Stored on the owning session branch, never shared across independent sessions.
|
|
10
|
+
- Limited to 32 profiles per session.
|
|
11
|
+
- Unable to add tools, resources, or budget beyond the base profile.
|
|
12
|
+
- Limited to configured, authenticated, non-exhausted models and a thinking level that model supports.
|
|
13
|
+
|
|
14
|
+
Use `profile_writer { action: "inspect" }` when the authorized bases or model combinations are unknown. Then call `create` with a concise task and only the fields that need narrowing. Pass the returned profile ID unchanged to `delegate`; never invent one.
|
|
15
|
+
|
|
16
|
+
Workers cannot invoke `profile_writer`, recursively delegate, or expand their admitted contract. A resumed worker retains the exact profile, model, resources, and transcript admitted for that task.
|
|
@@ -26,7 +26,13 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import type { BashToolDetails, EditToolDetails, ExtensionAPI, ReadToolDetails } from "@caupulican/pi-adaptative";
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
createBashTool,
|
|
31
|
+
createEditTool,
|
|
32
|
+
createReadTool,
|
|
33
|
+
createWriteTool,
|
|
34
|
+
FileMutationIntentController,
|
|
35
|
+
} from "@caupulican/pi-adaptative";
|
|
30
36
|
import { Text } from "@caupulican/pi-tui";
|
|
31
37
|
|
|
32
38
|
export default function (pi: ExtensionAPI) {
|
|
@@ -151,7 +157,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
151
157
|
});
|
|
152
158
|
|
|
153
159
|
// --- Edit tool: show path and diff stats ---
|
|
154
|
-
const
|
|
160
|
+
const fileMutationIntents = new FileMutationIntentController();
|
|
161
|
+
const originalEdit = createEditTool(cwd, { intentController: fileMutationIntents });
|
|
155
162
|
pi.registerTool({
|
|
156
163
|
name: "edit",
|
|
157
164
|
label: "edit",
|
|
@@ -216,7 +223,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
216
223
|
});
|
|
217
224
|
|
|
218
225
|
// --- Write tool: show path and size ---
|
|
219
|
-
const originalWrite = createWriteTool(cwd);
|
|
226
|
+
const originalWrite = createWriteTool(cwd, { intentController: fileMutationIntents });
|
|
220
227
|
pi.registerTool({
|
|
221
228
|
name: "write",
|
|
222
229
|
label: "write",
|
|
@@ -230,8 +237,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
230
237
|
renderCall(args, theme, _context) {
|
|
231
238
|
let text = theme.fg("toolTitle", theme.bold("write "));
|
|
232
239
|
text += theme.fg("accent", args.path);
|
|
233
|
-
const
|
|
234
|
-
text += theme.fg("dim", ` (${
|
|
240
|
+
const writeContent = args.action === "commit" && "content" in args ? args.content : undefined;
|
|
241
|
+
if (writeContent) text += theme.fg("dim", ` (${writeContent.length} characters)`);
|
|
235
242
|
return new Text(text, 0, 0);
|
|
236
243
|
},
|
|
237
244
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.85.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.85.3",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
createLsTool,
|
|
26
26
|
createReadTool,
|
|
27
27
|
createWriteTool,
|
|
28
|
+
FileMutationIntentController,
|
|
28
29
|
} from "@caupulican/pi-adaptative";
|
|
29
30
|
import { Text } from "@caupulican/pi-tui";
|
|
30
31
|
import { homedir } from "os";
|
|
@@ -44,11 +45,12 @@ function shortenPath(path: string): string {
|
|
|
44
45
|
const toolCache = new Map<string, ReturnType<typeof createBuiltInTools>>();
|
|
45
46
|
|
|
46
47
|
function createBuiltInTools(cwd: string) {
|
|
48
|
+
const fileMutationIntents = new FileMutationIntentController();
|
|
47
49
|
return {
|
|
48
50
|
read: createReadTool(cwd),
|
|
49
51
|
bash: createBashTool(cwd),
|
|
50
|
-
edit: createEditTool(cwd),
|
|
51
|
-
write: createWriteTool(cwd),
|
|
52
|
+
edit: createEditTool(cwd, { intentController: fileMutationIntents }),
|
|
53
|
+
write: createWriteTool(cwd, { intentController: fileMutationIntents }),
|
|
52
54
|
find: createFindTool(cwd),
|
|
53
55
|
grep: createGrepTool(cwd),
|
|
54
56
|
ls: createLsTool(cwd),
|
|
@@ -167,8 +169,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
167
169
|
pi.registerTool({
|
|
168
170
|
name: "write",
|
|
169
171
|
label: "write",
|
|
170
|
-
description:
|
|
171
|
-
"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
|
|
172
|
+
description: "Create a new file through path-only preflight. Existing paths are never overwritten.",
|
|
172
173
|
parameters: getBuiltInTools(process.cwd()).write.parameters,
|
|
173
174
|
|
|
174
175
|
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
@@ -179,10 +180,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
179
180
|
renderCall(args, theme, _context) {
|
|
180
181
|
const path = shortenPath(args.path || "");
|
|
181
182
|
const pathDisplay = path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
|
|
182
|
-
const
|
|
183
|
-
const
|
|
183
|
+
const writeContent = args.action === "commit" && "content" in args ? args.content : undefined;
|
|
184
|
+
const sizeInfo = writeContent ? theme.fg("muted", ` (${writeContent.length} characters)`) : "";
|
|
184
185
|
|
|
185
|
-
return new Text(`${theme.fg("toolTitle", theme.bold("write"))} ${pathDisplay}${
|
|
186
|
+
return new Text(`${theme.fg("toolTitle", theme.bold("write"))} ${pathDisplay}${sizeInfo}`, 0, 0);
|
|
186
187
|
},
|
|
187
188
|
|
|
188
189
|
renderResult(result, { expanded }, theme, _context) {
|
|
@@ -37,12 +37,14 @@ function addToolGuidance(options: BuildSystemPromptOptions, basePrompt: string):
|
|
|
37
37
|
|
|
38
38
|
if (hasTool("edit")) {
|
|
39
39
|
parts.push(
|
|
40
|
-
"• Use
|
|
40
|
+
"• Use `edit` action=prepare before generating precise replacements, then commit with the returned intent. Match exact content including whitespace.",
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
if (hasTool("write")) {
|
|
45
|
-
parts.push(
|
|
45
|
+
parts.push(
|
|
46
|
+
"• Use `write` action=prepare before generating content; commit creates a new file and never overwrites.",
|
|
47
|
+
);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
if (options.skills && options.skills.length > 0) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-sandbox",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.85.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-sandbox",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.85.3",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sandbox-runtime": "^0.0.26"
|
|
12
12
|
}
|