@zihanw/pi-forge 0.5.3 → 0.5.5
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 +84 -0
- package/README.md +67 -103
- package/README.zh-CN.md +67 -95
- package/assets/pi-forge-header-concept-1.png +0 -0
- package/assets/readme/PROVENANCE.md +95 -0
- package/assets/readme/en/capability-tools.gif +0 -0
- package/assets/readme/en/context-composition.gif +0 -0
- package/assets/readme/en/context-toggle.gif +0 -0
- package/assets/readme/en/draft-diff.png +0 -0
- package/assets/readme/en/edit-draft-diff.gif +0 -0
- package/assets/readme/en/editor-overview-v3.png +0 -0
- package/assets/readme/en/editor-overview.png +0 -0
- package/assets/readme/en/mode-tools.gif +0 -0
- package/assets/readme/en/regex-transforms.gif +0 -0
- package/assets/readme/en/tool-selection.gif +0 -0
- package/assets/readme/tui-quickstart.gif +0 -0
- package/assets/readme/zh-CN/capability-tools.gif +0 -0
- package/assets/readme/zh-CN/context-composition.gif +0 -0
- package/assets/readme/zh-CN/context-toggle.gif +0 -0
- package/assets/readme/zh-CN/draft-diff.png +0 -0
- package/assets/readme/zh-CN/edit-draft-diff.gif +0 -0
- package/assets/readme/zh-CN/editor-overview-v3.png +0 -0
- package/assets/readme/zh-CN/editor-overview.png +0 -0
- package/assets/readme/zh-CN/mode-tools.gif +0 -0
- package/assets/readme/zh-CN/regex-transforms.gif +0 -0
- package/assets/readme/zh-CN/tool-selection.gif +0 -0
- package/dist/active-state.d.ts +148 -0
- package/dist/active-state.d.ts.map +1 -0
- package/dist/active-state.js +374 -0
- package/dist/active-state.js.map +1 -0
- package/dist/agent-profile.d.ts.map +1 -1
- package/dist/agent-profile.js +11 -0
- package/dist/agent-profile.js.map +1 -1
- package/dist/capabilities.d.ts +39 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +160 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/capability-anchors.d.ts +45 -0
- package/dist/capability-anchors.d.ts.map +1 -0
- package/dist/capability-anchors.js +263 -0
- package/dist/capability-anchors.js.map +1 -0
- package/dist/capability-command.d.ts +4 -0
- package/dist/capability-command.d.ts.map +1 -0
- package/dist/capability-command.js +164 -0
- package/dist/capability-command.js.map +1 -0
- package/dist/capability-events.d.ts +79 -0
- package/dist/capability-events.d.ts.map +1 -0
- package/dist/capability-events.js +478 -0
- package/dist/capability-events.js.map +1 -0
- package/dist/capability-projection.d.ts +22 -0
- package/dist/capability-projection.d.ts.map +1 -0
- package/dist/capability-projection.js +273 -0
- package/dist/capability-projection.js.map +1 -0
- package/dist/capability-protocol.d.ts +21 -0
- package/dist/capability-protocol.d.ts.map +1 -0
- package/dist/capability-protocol.js +15 -0
- package/dist/capability-protocol.js.map +1 -0
- package/dist/capability-state.d.ts +74 -0
- package/dist/capability-state.d.ts.map +1 -0
- package/dist/capability-state.js +43 -0
- package/dist/capability-state.js.map +1 -0
- package/dist/capability-tool.d.ts +11 -0
- package/dist/capability-tool.d.ts.map +1 -0
- package/dist/capability-tool.js +25 -0
- package/dist/capability-tool.js.map +1 -0
- package/dist/capability-web-host.d.ts +11 -0
- package/dist/capability-web-host.d.ts.map +1 -0
- package/dist/capability-web-host.js +105 -0
- package/dist/capability-web-host.js.map +1 -0
- package/dist/codecs/capability.d.ts +71 -0
- package/dist/codecs/capability.d.ts.map +1 -0
- package/dist/codecs/capability.js +363 -0
- package/dist/codecs/capability.js.map +1 -0
- package/dist/codecs/prompt-stack.d.ts +1 -1
- package/dist/codecs/prompt-stack.d.ts.map +1 -1
- package/dist/codecs/prompt-stack.js +140 -13
- package/dist/codecs/prompt-stack.js.map +1 -1
- package/dist/command-contribution/index.d.ts +21 -0
- package/dist/command-contribution/index.d.ts.map +1 -0
- package/dist/command-contribution/index.js +14 -0
- package/dist/command-contribution/index.js.map +1 -0
- package/dist/compile-cycle.d.ts +7 -1
- package/dist/compile-cycle.d.ts.map +1 -1
- package/dist/compile-cycle.js +2 -0
- package/dist/compile-cycle.js.map +1 -1
- package/dist/compiler.d.ts +7 -1
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +140 -19
- package/dist/compiler.js.map +1 -1
- package/dist/context-diff-history.d.ts +2 -0
- package/dist/context-diff-history.d.ts.map +1 -1
- package/dist/context-diff-history.js +9 -0
- package/dist/context-diff-history.js.map +1 -1
- package/dist/forge-command.d.ts +10 -0
- package/dist/forge-command.d.ts.map +1 -0
- package/dist/forge-command.js +106 -0
- package/dist/forge-command.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -7
- package/dist/index.js.map +1 -1
- package/dist/json-fingerprint.d.ts +11 -0
- package/dist/json-fingerprint.d.ts.map +1 -0
- package/dist/json-fingerprint.js +66 -0
- package/dist/json-fingerprint.js.map +1 -0
- package/dist/lifecycle.d.ts +14 -0
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +175 -66
- package/dist/lifecycle.js.map +1 -1
- package/dist/payload-command.d.ts +2 -2
- package/dist/payload-command.d.ts.map +1 -1
- package/dist/payload-command.js +80 -26
- package/dist/payload-command.js.map +1 -1
- package/dist/payload-state.d.ts +1 -0
- package/dist/payload-state.d.ts.map +1 -1
- package/dist/payload-state.js +1 -0
- package/dist/payload-state.js.map +1 -1
- package/dist/policy.d.ts +2 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +3 -0
- package/dist/policy.js.map +1 -1
- package/dist/preset-command.d.ts +2 -0
- package/dist/preset-command.d.ts.map +1 -1
- package/dist/preset-command.js +101 -36
- package/dist/preset-command.js.map +1 -1
- package/dist/preview-text.d.ts +5 -0
- package/dist/preview-text.d.ts.map +1 -0
- package/dist/preview-text.js +27 -0
- package/dist/preview-text.js.map +1 -0
- package/dist/preview.d.ts +18 -1
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +134 -99
- package/dist/preview.js.map +1 -1
- package/dist/profile-command.d.ts +4 -1
- package/dist/profile-command.d.ts.map +1 -1
- package/dist/profile-command.js +77 -14
- package/dist/profile-command.js.map +1 -1
- package/dist/prompt-cache-warning.d.ts +23 -0
- package/dist/prompt-cache-warning.d.ts.map +1 -0
- package/dist/prompt-cache-warning.js +74 -0
- package/dist/prompt-cache-warning.js.map +1 -0
- package/dist/regex.d.ts.map +1 -1
- package/dist/regex.js +5 -0
- package/dist/regex.js.map +1 -1
- package/dist/render-helpers.d.ts.map +1 -1
- package/dist/render-helpers.js +2 -0
- package/dist/render-helpers.js.map +1 -1
- package/dist/repositories/capability.d.ts +53 -0
- package/dist/repositories/capability.d.ts.map +1 -0
- package/dist/repositories/capability.js +294 -0
- package/dist/repositories/capability.js.map +1 -0
- package/dist/runtime/capability-runtime.d.ts +91 -0
- package/dist/runtime/capability-runtime.d.ts.map +1 -0
- package/dist/runtime/capability-runtime.js +967 -0
- package/dist/runtime/capability-runtime.js.map +1 -0
- package/dist/runtime/tool-policy-runtime.d.ts +8 -0
- package/dist/runtime/tool-policy-runtime.d.ts.map +1 -1
- package/dist/runtime/tool-policy-runtime.js +171 -30
- package/dist/runtime/tool-policy-runtime.js.map +1 -1
- package/dist/session-adapter.d.ts +13 -0
- package/dist/session-adapter.d.ts.map +1 -1
- package/dist/session-adapter.js +110 -0
- package/dist/session-adapter.js.map +1 -1
- package/dist/session-usage.d.ts +65 -0
- package/dist/session-usage.d.ts.map +1 -0
- package/dist/session-usage.js +134 -0
- package/dist/session-usage.js.map +1 -0
- package/dist/subagent/fingerprints.d.ts +3 -15
- package/dist/subagent/fingerprints.d.ts.map +1 -1
- package/dist/subagent/fingerprints.js +5 -69
- package/dist/subagent/fingerprints.js.map +1 -1
- package/dist/subagent/index.d.ts +2 -0
- package/dist/subagent/index.d.ts.map +1 -1
- package/dist/subagent/index.js +2 -0
- package/dist/subagent/index.js.map +1 -1
- package/dist/subagent-host.d.ts +2 -2
- package/dist/subagent-host.d.ts.map +1 -1
- package/dist/subagent-host.js +13 -1
- package/dist/subagent-host.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/web-editor/client-script.generated.d.ts.map +1 -1
- package/dist/web-editor/client-script.generated.js +1 -1
- package/dist/web-editor/client-script.generated.js.map +1 -1
- package/dist/web-editor/client-styles.generated.d.ts.map +1 -1
- package/dist/web-editor/client-styles.generated.js +1 -1
- package/dist/web-editor/client-styles.generated.js.map +1 -1
- package/dist/web-editor/server.d.ts.map +1 -1
- package/dist/web-editor/server.js +152 -4
- package/dist/web-editor/server.js.map +1 -1
- package/dist/web-editor/styles.d.ts.map +1 -1
- package/dist/web-editor/styles.js +521 -116
- package/dist/web-editor/styles.js.map +1 -1
- package/dist/web-editor/types.d.ts +81 -1
- package/dist/web-editor/types.d.ts.map +1 -1
- package/dist/web-host.d.ts +7 -0
- package/dist/web-host.d.ts.map +1 -1
- package/dist/web-host.js +168 -5
- package/dist/web-host.js.map +1 -1
- package/dist/workspace.d.ts +11 -0
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +63 -5
- package/dist/workspace.js.map +1 -1
- package/docs/README.md +4 -0
- package/docs/design/README.md +3 -1
- package/docs/design/architecture-0.5.md +22 -0
- package/docs/design/archive/2026-09-12-system-update-design.md +229 -0
- package/docs/design/pi-forge-system-update-design-notes.md +157 -0
- package/docs/development/release.md +20 -20
- package/docs/development/roadmap.md +17 -2
- package/docs/development/scoped-global-profiles-stacks.md +1 -1
- package/docs/development/setup.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/guides/delegation.md +22 -20
- package/docs/guides/migrating-to-0.5.md +29 -0
- package/docs/guides/use-cases.md +6 -2
- package/docs/guides/web-editor.md +73 -5
- package/docs/reference/active-state.md +77 -0
- package/docs/reference/capabilities.md +259 -0
- package/docs/reference/commands.md +52 -24
- package/docs/reference/configuration.md +4 -2
- package/docs/reference/features.md +70 -4
- package/docs/reference/provider-support.md +67 -0
- package/docs/reference/public-api.md +49 -3
- package/docs/reference/session-cache.md +112 -0
- package/docs/reference/stack-schema.md +18 -4
- package/docs/reference/subagent-host-port.md +8 -0
- package/docs/zh-CN/README.md +3 -0
- package/docs/zh-CN/getting-started.md +1 -1
- package/docs/zh-CN/guides/delegation.md +22 -10
- package/docs/zh-CN/guides/migrating-to-0.5.md +29 -0
- package/docs/zh-CN/guides/web-editor.md +74 -7
- package/docs/zh-CN/reference/capabilities.md +259 -0
- package/docs/zh-CN/reference/commands.md +61 -33
- package/docs/zh-CN/reference/provider-support.md +67 -0
- package/docs/zh-CN/reference/session-cache.md +112 -0
- package/examples/capabilities/review.json +12 -0
- package/examples/capabilities/write-tools.json +15 -0
- package/examples/read-first-worker-prompt-stack.json +49 -0
- package/package.json +16 -9
|
@@ -21,6 +21,8 @@ The port is preferred, not guaranteed. The editor binds only to `127.0.0.1` and
|
|
|
21
21
|
|
|
22
22
|
## Experimental subagents
|
|
23
23
|
|
|
24
|
+
The explicit non-boolean approval-flag handling described below remains an unreleased companion source fix; published `@zihanw/pi-forge-subagents` 0.5.3 does not contain it. It is optional-package work, not a Forge 0.5.5 main-package feature. Configuration parsing belongs to that optional package, not the Forge host.
|
|
25
|
+
|
|
24
26
|
Subagent configuration is owned by the optional `@zihanw/pi-forge-subagents` package. Dedicated files are `.pi/forge/subagents.json` for a trusted project and `~/.pi/forge/subagents.json` for user defaults. Legacy `.pi/forge/config.json` / `~/.pi/forge/config.json` `subagents` sections are read-only fallback material and emit a warning.
|
|
25
27
|
|
|
26
28
|
User defaults may set general settings:
|
|
@@ -50,11 +52,11 @@ Trusted project `subagents.json` may override defaults, authorize individual pro
|
|
|
50
52
|
}
|
|
51
53
|
```
|
|
52
54
|
|
|
53
|
-
Valid timeouts are 1,000–3,600,000 ms. Invalid fields warn and fall back to the preceding applicable default. General backend precedence is project then user then built-in;
|
|
55
|
+
Valid timeouts are 1,000–3,600,000 ms. Invalid timeout fields warn and fall back to the preceding applicable default. General backend precedence is project then user then built-in; a matching profile entry and an interactive per-run override can further override it as described in [delegation](../guides/delegation.md#backends-and-precedence).
|
|
54
56
|
|
|
55
57
|
`summaryInToolDescription` (default `false`) embeds a compact, bounded summary of enabled subagent profiles directly in the `forge_subagent` tool description so the parent model can pick a profile without a discovery call. Ready profiles appear first, and unavailable enabled profiles include their first resolution error. It may be set in user or trusted-project `subagents.json` and applies wherever it is enabled.
|
|
56
58
|
|
|
57
|
-
Profile authorization keys should use canonical selectors: `project:<id>` or `global:<id>`. A bare key is a compatibility spelling for `project:<id>` regardless of which config file contains it; it never authorizes a global profile. Therefore a global profile must be written explicitly as `"global:reviewer": { "enabled": true }` in `~/.pi/forge/subagents.json`. Same-ID profiles never inherit enablement, backend, or timeout policy from each other. `allowAgentInvocationWithoutApproval`
|
|
59
|
+
Profile authorization keys should use canonical selectors: `project:<id>` or `global:<id>`. A bare key is a compatibility spelling for `project:<id>` regardless of which config file contains it; it never authorizes a global profile. Therefore a global profile must be written explicitly as `"global:reviewer": { "enabled": true }` in `~/.pi/forge/subagents.json`. Same-ID profiles never inherit enablement, backend, or timeout policy from each other. `allowAgentInvocationWithoutApproval` may be supplied by global defaults or a trusted project file; the project value overrides the global value, and the execution trust gate still blocks delegation from an untrusted project. When that flag is absent at a layer it inherits; an explicitly non-boolean value sets that layer to `false` and emits a warning, while a valid boolean in a higher-priority layer still overrides normally. If an entire config file is unreadable, malformed, or not a JSON object, that file is ignored with a warning and any earlier valid layer remains effective. Deleting a profile does not modify `subagents.json`; remove any enabled entry for the deleted profile manually.
|
|
58
60
|
|
|
59
61
|
Treat project configuration as an authorization boundary. In particular, do not commit unattended delegation unless every permitted parent agent may transmit compiled prompt and readable project content without another human approval.
|
|
60
62
|
|
|
@@ -10,7 +10,7 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
10
10
|
- Tarball verification rejects physical `src/` entries and requires the root and subagent compiled entry points.
|
|
11
11
|
- The web editor's HTML page shell and static styles are maintained separately from its browser behavior modules.
|
|
12
12
|
- Strict typed web-editor client modules bundled into one self-contained browser script at build time, with generated-client consistency verification.
|
|
13
|
-
- Supported Node.js baseline is 22.19+.
|
|
13
|
+
- Supported Node.js baseline is 22.19+. The four Pi SDK packages are host-provided optional peers at `>=0.87.0 <0.88.0`; `typebox` is an optional wildcard peer. Exact repository versions are reproducible development/test fixtures rather than runtime constraints.
|
|
14
14
|
- Project trust check before loading prompt stacks.
|
|
15
15
|
- Footer status showing the active prompt stack.
|
|
16
16
|
|
|
@@ -55,7 +55,7 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
55
55
|
- `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]` copies legacy stacks into the forge storage location.
|
|
56
56
|
- `default.json` auto-activation unless `autoActivate` is `false`.
|
|
57
57
|
- Branch-aware persisted active stack restore from session entries.
|
|
58
|
-
- Persisted `/preset use none` / `
|
|
58
|
+
- Persisted `/preset use none` / `disable` opt-out.
|
|
59
59
|
- Invalid stacks with error diagnostics are skipped by automatic selection.
|
|
60
60
|
- Raw stack fields are shape-checked before recovery normalization, including behavior-changing booleans/enums, defaults, context, variables, and item fields.
|
|
61
61
|
- Stack validation for duplicate item IDs, duplicate stack IDs, unsupported slots, missing chat-history slots, and ignored items.
|
|
@@ -172,6 +172,15 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
172
172
|
- `/preset reload`
|
|
173
173
|
- `/preset ui [stop|restart]`
|
|
174
174
|
- `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]`
|
|
175
|
+
- `/capability add <text>`
|
|
176
|
+
- `/capability list`
|
|
177
|
+
- `/capability bindings`
|
|
178
|
+
- `/capability enable <[scope:]id>`
|
|
179
|
+
- `/capability enable-bound <id>`
|
|
180
|
+
- `/capability disable <activation-or-capability-id>`
|
|
181
|
+
- `/capability status`
|
|
182
|
+
- `/capability reset`
|
|
183
|
+
- `/capability help`
|
|
175
184
|
- `/intercept`
|
|
176
185
|
- `/payload next [save=<path>]`
|
|
177
186
|
|
|
@@ -199,7 +208,7 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
199
208
|
- Resource inventory and preview remain usable when a reclaimed editor host is refreshed from lifecycle contexts that do not expose command-only prompt APIs.
|
|
200
209
|
- Stack list with active/error/warning indicators.
|
|
201
210
|
- Collapsible prompt-stack sidebar.
|
|
202
|
-
-
|
|
211
|
+
- Preset properties from the resource header, with peer Stack, Regex, Policy, Bindings and Advanced editing tabs; the separate Preview/Draft diff/Run diff dock stays alongside the editor.
|
|
203
212
|
- Light/dark theme toggle, button icons, and tooltips for common actions.
|
|
204
213
|
- English/中文 interface switch (`webEditor.locale`: `"en"`, `"zh-CN"`, or `"auto"` following the browser language); contributed settings tabs remain provider-authored and are not translated.
|
|
205
214
|
- Unsaved-change badge in the top bar.
|
|
@@ -229,7 +238,7 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
229
238
|
- Export the current edited stack JSON from the browser, with clipboard fallback when download is unavailable.
|
|
230
239
|
- Fork the current stack into a new stack file, with optional activation.
|
|
231
240
|
- Delete stack files, disabling prompt-stack replacement if the deleted stack was active.
|
|
232
|
-
-
|
|
241
|
+
- Built-in Web writes cover Presets, Profiles, Capabilities, and trusted Forge configuration, with trust and path guardrails for save/import/fork/delete operations.
|
|
233
242
|
- Top-level navigation between prompt stacks and project agent profiles; stack drafts, selection, and active state survive surface switches.
|
|
234
243
|
- Profile list shows ID, name, model/thinking/stack targets, validation state, and `autoActivate` and last-applied badges.
|
|
235
244
|
- Profile create, edit, validate, save, one-shot apply, and delete reuse the shared resolver, transactional application service, and guarded repository; save rejects a second auto-activation profile and on-disk conflicts.
|
|
@@ -237,3 +246,60 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
237
246
|
- A runtime/provenance card distinguishes current runtime, last-applied provenance, source-definition state, and per-field runtime drift after external model, thinking-level, or stack changes.
|
|
238
247
|
- The main web editor no longer ships a delegation card; delegation configuration is owned by the optional `@zihanw/pi-forge-subagents` package through `.pi/forge/subagents.json`.
|
|
239
248
|
- Smoke tests cover editor server token checks, bundled page/script markers, save, payload arm/capture/clear, create/fork, native JSON import, collision handling, delete, and stop behavior.
|
|
249
|
+
|
|
250
|
+
## Capabilities and System Updates
|
|
251
|
+
|
|
252
|
+
- Upstream host requirement: Pi `>=0.87.0 <0.88.0` (repository dev SDK pinned to `0.87.0`, peer range `>=0.87.0 <0.88.0`; no dual 0.86 runtime support claim).
|
|
253
|
+
- File-backed capability definitions stored in `.pi/forge/capabilities/<id>.json` (project scope) and `~/.pi/forge/capabilities/<id>.json` (global scope) with schema `schemaVersion: 1`, `type: "pi-forge.capability"`.
|
|
254
|
+
- Literal text content (up to 100,000 characters) without macro, template, or script evaluation.
|
|
255
|
+
- Tool modification patches supporting `add` and `remove` arrays (tool IDs ≤ 128 characters, no whitespace/controls/wildcards, up to 256 tools per array). Capabilities support `add` and `remove` ONLY; candidate `only`/allowlist is not implemented.
|
|
256
|
+
- Fail-closed project-over-global shadowing for bare IDs; invalid local definitions fail closed with diagnostics and never fall back to global definitions.
|
|
257
|
+
- Scoped selectors (`project:<id>` and `global:<id>`) for targeting exact definitions.
|
|
258
|
+
- Local execution with zero inference cost: `/capability` commands and Web activity panel actions update internal session state and tool policy without invoking model inference or consuming API tokens.
|
|
259
|
+
- Unified `context_with_system` lifecycle: whole compiler, base prompt replacement, and capability projection pipeline moved to `context_with_system` without an internal two-phase split.
|
|
260
|
+
- Canonical session projection via `buildSessionProjection`: runtime, preview, and anchor locator helpers reflect turn-level `context_edit` omissions, replacements, and `sourceEntry` tracking without mutating raw session JSONL history on disk.
|
|
261
|
+
- Leading System prompt preservation: SDK incoming leading System message always remains first; Forge prefix plain metadata delivery anchors are inserted immediately after it.
|
|
262
|
+
- Settlement lifecycle and continuations: `agent_end` acts as an anchor commit boundary after tool batches or turns; compile cycle and busy fence reset only on `agent_settled` so `agent_before_settle` continuations preserve compiled Preset inputs.
|
|
263
|
+
- Immediate executable tool policy synchronization (`setActiveTools`) paired with next-model-request prompt text and section declaration delivery. Running tool batches are not killed mid-flight.
|
|
264
|
+
- Top-level Preset policy precedence: capability additions cannot enable tools denied by the active Preset (`tools.deny`); tool removals win globally across all active capabilities.
|
|
265
|
+
- Tool baseline recovery: restores session tools to a pristine baseline upon capability disable, adopting a conservative baseline when a session has no recorded baseline.
|
|
266
|
+
- Delivery via plain `custom` session entries carrying cursor-only metadata (`pi-forge-capability-delivery` with `{ schemaVersion: 1, throughEventId }`), replacing transcript `sendMessage` steering and `custom_message` carriers.
|
|
267
|
+
- Pre-compilation ordinal materialization into ephemeral in-memory markers at exact session positions matching canonical projection order.
|
|
268
|
+
- Request-only projection to native `SystemMessage.sections` (`forge-capability-<id>`) when supported by the provider, or fallback attributed user timeline updates (`[pi-forge capability update]`).
|
|
269
|
+
- Compaction input characterization: metadata delivery anchors and request-only rule text do not enter summarizer inputs while dialogue history is preserved.
|
|
270
|
+
- Breaking pre-release rename: no legacy aliases or readers are provided for the former instruction-mode schema, directories, or continuing capability state. Convert development configuration and start a new session; old JSONL and summaries are not rewritten.
|
|
271
|
+
- Provider-managed prompt cache warning: prompt caching and tool transport are downstream provider-managed; no guarantee of zero KV cache invalidation or exact cache hits.
|
|
272
|
+
|
|
273
|
+
## Preset Capability Bindings
|
|
274
|
+
|
|
275
|
+
- Declarative `capabilities` binding list in the Preset schema.
|
|
276
|
+
- Qualified capability references (`project:<id>`, `global:<id>`), unique binding IDs (≤ 128 characters), and opt-in `modelCallable: boolean` (defaults to `false`).
|
|
277
|
+
- Finite overrides: either content replacement (`content`) or paragraph append (`appendContent` with two newlines), and independent whole-array replacement for `tools.add` and/or `tools.remove`.
|
|
278
|
+
- Source-effective preview via the shared server resolver (`resolveCapabilityBindings`).
|
|
279
|
+
- Stale-save guard using `sourceRevision` checking against raw file bytes, rejecting concurrent or external edits (409 Conflict) whenever bindings are present or modified.
|
|
280
|
+
- Same-Preset reload preserves immutable active snapshots; switching Presets retires old bound activations while retaining manual/unbound rules.
|
|
281
|
+
- Revocation behavior: disabling `modelCallable` does not retroactively erase active snapshots; human CLI or Web deactivation is the recovery path.
|
|
282
|
+
|
|
283
|
+
## Agent Capability Controls
|
|
284
|
+
|
|
285
|
+
- Model-callable tool `forge_capability` registered when an active Preset includes bound capabilities.
|
|
286
|
+
- Fixed parameter schema: `{ action: "list" | "status" | "enable" | "disable", id?: string }` (ID ≤ 128 characters).
|
|
287
|
+
- Re-verifies project trust, active Preset existence, binding existence, `modelCallable: true`, and current tool policy on every call.
|
|
288
|
+
- Strict actor ownership: agent can only activate authorized bindings; agent `disable` can only stop its own agent-owned activations; agent cannot stop human rules, reset capabilities, add arbitrary prompt text, or remove `forge_capability`.
|
|
289
|
+
- Repeated use is idempotent and does not take over ownership from user to agent.
|
|
290
|
+
- Fences against disposed runtimes, restoring sessions, and cross-session re-entry.
|
|
291
|
+
|
|
292
|
+
## Web Editor Capabilities and Session Activity
|
|
293
|
+
|
|
294
|
+
- Top-level **Capabilities** surface for project and global capability CRUD with validation diagnostics.
|
|
295
|
+
- Capability writes and deletions require `sourceRevision` checking against raw file bytes; 409 Conflict on stale views preserves user drafts.
|
|
296
|
+
- Capability saves never activate definitions into the active session.
|
|
297
|
+
- Dedicated peer **Capability bindings** tab in the Preset editor with binding configuration, `modelCallable` toggle, finite overrides, and live source vs effective preview.
|
|
298
|
+
- Global **Session capabilities** summary opens the non-modal **Current session** workspace, pairing controls with the active saved Preset/session projection and showing active capabilities, actor attribution (`user`/`agent`), collapsible frozen snapshots, tool deltas, effective tools, delivery status (`none`/`pending`/`prepared`), and presentation mode.
|
|
299
|
+
- Human activation picker with available capabilities (`GET /api/capability-state/available`) categorized into Library capabilities (unbound) and Current preset (bound).
|
|
300
|
+
- Explicit pre-activation preview displaying label, ID, badge, fingerprint, tool diff, problem banner, and full literal content.
|
|
301
|
+
- Bodyguard activation (`POST /api/capability-state/enable`) requiring session guard (`sessionId`, `leafId`, `revision`) and source fingerprint validation, rejecting stale or modified sources (409 Conflict) without automatic retry or inference.
|
|
302
|
+
- Read-only resource discovery and Preview never mutate tool policies, commit session events, or mark pending capabilities as prepared.
|
|
303
|
+
- Quiet state polling (every 3 seconds while visible, and on focus) with zero inference; catalog discovery occurs on workspace entry, explicit refresh and mutation follow-up, not each status poll.
|
|
304
|
+
|
|
305
|
+
The [Read-first Worker example](capabilities.md#read-first-worker) demonstrates default reading tools plus a model-authorized `bash`/`edit` capability. It is a tool-selection pattern, not a sandbox.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Provider support for mid-conversation updates (Pi 0.87.1 snapshot)
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md) · [中文](../zh-CN/reference/provider-support.md)
|
|
4
|
+
|
|
5
|
+
This page records how Pi 0.87.1 sends mid-conversation system updates and tool changes for each API, and which models in the Pi model catalog were flagged for them. It explains why a [capability](capabilities.md#delivery-models-native-vs-fallback) may arrive as a native system update on one model and as a labeled user message on another.
|
|
6
|
+
|
|
7
|
+
> **Snapshot status:** Pi 0.87.1 (`@earendil-works/pi-ai` 0.87.1), local model catalog last checked 2026-09-21 to 2026-09-25, recorded 2026-09-26. Pi fetches the model catalog remotely and caches it in `~/.pi/agent/models-store.json`, so flags can change without a Pi upgrade. Run `/capability status` to see which path the current model uses before relying on this table.
|
|
8
|
+
|
|
9
|
+
## How the choice is made
|
|
10
|
+
|
|
11
|
+
Pi and Forge both read the current model's `compat` flags on every request:
|
|
12
|
+
|
|
13
|
+
| Flag | Effect when `true` | Effect when absent or `false` |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `supportsMidConvoSystemMessages` | Later system messages stay at their position in the conversation. Forge sends instruction text as native system sections. | Pi folds all system messages into the leading system prompt and sends the current tool list at request level. Forge sends instruction text as a labeled `[pi-forge capability update]` user message. |
|
|
16
|
+
| `supportsMidConvoToolChanges` (Anthropic Messages) | Tool additions and removals are sent as `tool_addition` / `tool_removal` blocks inside the system update. | The whole current tool list is sent at request level. |
|
|
17
|
+
| `supportsAdditionalTools` / `supportsToolSearch` (OpenAI Responses, Codex, Azure) | New tools are loaded in place (`additional_tools`, or a client-side tool search call and output). | The whole current tool list is sent at request level. |
|
|
18
|
+
| `supportsMidConvoToolAdditions` (OpenAI Completions) | New tools are loaded in place by a system message that carries `tools`. | The whole current tool list is sent at request level. |
|
|
19
|
+
|
|
20
|
+
Tool flags only apply when `supportsMidConvoSystemMessages` is also enabled. The provider name, the authentication method, and auth extensions do not decide the path. The same model can be flagged differently under different providers.
|
|
21
|
+
|
|
22
|
+
## Behavior by API
|
|
23
|
+
|
|
24
|
+
| API | Instruction text | Tool changes |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `anthropic-messages` | With the flag: a `role: "system"` message. Pi holds it until just before the next assistant message, so it never separates a `tool_use` from its `tool_result`; an update recorded before a user message is sent after it. | With `supportsMidConvoToolChanges`, at least one initial tool, and no same-name redefinition: initial tools stay first, later tools are appended with `defer_loading`, and changes are `tool_addition` / `tool_removal` blocks. The request-level list only grows. Otherwise: the current list at request level. |
|
|
27
|
+
| `openai-responses`, `openai-codex-responses`, `azure-openai-responses` | With the flag: a `developer` message (reasoning models that accept the developer role) or a `system` message, at its position. | Additions load in place while retained history contains only additions. Any removal or same-name redeclaration anywhere in retained history switches that request to the full current list at request level. |
|
|
28
|
+
| `openai-completions` | With the flag: a `developer` or `system` message at its position. | Additions load in place with `supportsMidConvoToolAdditions`; removals and redeclarations switch to the full current list. |
|
|
29
|
+
| `mistral-conversations` | With the flag: a `system` message at its position. | Always the full current list at request level. |
|
|
30
|
+
| Google Generative AI / Vertex | Always folded into `systemInstruction`; no mid-conversation path. | Full current list. |
|
|
31
|
+
| Bedrock Converse | Always folded into the request-level system prompt. | Full current tool configuration. |
|
|
32
|
+
| `pi-messages` | Passes the context to its backend unchanged; behavior depends on that backend. | Backend-defined. |
|
|
33
|
+
|
|
34
|
+
Updates are rendered as `Updated system prompt section "<name>": ...` or `Removed system prompt section "<name>".`. [Tool-only capabilities](capabilities.md#delivery-models-native-vs-fallback) send no text update.
|
|
35
|
+
|
|
36
|
+
## Flagged models in the 2026-09 catalog
|
|
37
|
+
|
|
38
|
+
Only models with `supportsMidConvoSystemMessages: true` are listed.
|
|
39
|
+
|
|
40
|
+
| Provider | Models | Tool changes |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `anthropic` | `claude-fable-5`, `claude-fable-5-1`, `claude-opus-4-8`, `claude-opus-5`, `claude-opus-5-5` | Native additions and removals |
|
|
43
|
+
| `openai-codex` | `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-6-astra`, `gpt-6-luna`, `gpt-6-sol` | Additions in place (`additional_tools`) |
|
|
44
|
+
| `openai-codex` | `gpt-5.5` | Additions in place via tool search |
|
|
45
|
+
| `opencode` | `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.4-pro`, `gpt-5.5`, `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-6-astra` | Additions in place (`additional_tools`) |
|
|
46
|
+
| `opencode` | `claude-fable-5`, `claude-fable-5-1`, `claude-opus-4-8`, `claude-opus-5` | Text only; any tool change sends the full list |
|
|
47
|
+
| `opencode`, `opencode-go` | `kimi-k3` | Additions in place |
|
|
48
|
+
| `opencode-go` | `gpt-5.6-luna` | Additions in place (`additional_tools`) |
|
|
49
|
+
| `deepseek` | `deepseek-v4-pro` | Text only; any tool change sends the full list |
|
|
50
|
+
|
|
51
|
+
Not flagged in the same catalog, among others: `anthropic/claude-sonnet-5`, `claude-sonnet-4-5`, `claude-sonnet-4-6`, `claude-opus-4-5` to `claude-opus-4-7`, `claude-haiku-4-5`; `openai-codex/gpt-5.3-codex-spark`; `deepseek/deepseek-flash`; every `google` and `kimi-coding` model.
|
|
52
|
+
|
|
53
|
+
## Observed cache behavior
|
|
54
|
+
|
|
55
|
+
These are single-session observations, not guarantees. Cache reuse is decided by the provider.
|
|
56
|
+
|
|
57
|
+
- **`anthropic/claude-opus-5-5`, native path (OAuth through an auth extension):** adding, removing, and re-adding tools, including a capability the model enabled itself, kept the full cached prefix on all 18 follow-up requests. Requests with lower hit rates were writing new content, such as new tool definitions or large file reads, not losing earlier cache.
|
|
58
|
+
- **`anthropic/claude-sonnet-5`, fallback path:** the request after a tool change read nothing from cache, because Pi rewrote the leading system prompt and tool list. The model also questioned the labeled user update before using the new tool.
|
|
59
|
+
- **OpenAI Responses / Codex:** in earlier tests, a removal switched to the full tool list and cache reads dropped to zero; requests with only additions kept the prefix.
|
|
60
|
+
|
|
61
|
+
To keep caches stable, prefer a flagged model with native tool changes. On Responses-family models, avoid removing tools in a session where cache reuse matters.
|
|
62
|
+
|
|
63
|
+
## Checking your own setup
|
|
64
|
+
|
|
65
|
+
1. Run `/capability status`. It reports `native system sections` or `attributed user updates` for the current model.
|
|
66
|
+
2. To see the flags directly, look up the model under its provider in `~/.pi/agent/models-store.json` and read its `compat` object.
|
|
67
|
+
3. Use `/forge payload next` to capture the actual next request if you need to confirm the wire format.
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[Documentation](../README.md)
|
|
4
4
|
|
|
5
|
-
pi-forge is pre-1.0. This document defines the intentional integration surfaces of the 0.5
|
|
5
|
+
pi-forge is pre-1.0. This document defines the intentional integration surfaces of the 0.5 development line.
|
|
6
6
|
|
|
7
|
-
## The
|
|
7
|
+
## The five intentional entry points
|
|
8
8
|
|
|
9
9
|
`check-package` enforces this allowlist; nothing else is importable from the package.
|
|
10
10
|
|
|
@@ -60,6 +60,24 @@ The experimental host port over the Pi event bus: discovery, profile listing/sna
|
|
|
60
60
|
|
|
61
61
|
The optional `@zihanw/pi-forge-subagents` package consumes this port and owns subagent execution and configuration.
|
|
62
62
|
|
|
63
|
+
#### Experimental nested-usage contract exports
|
|
64
|
+
|
|
65
|
+
The entry point also exports helper constants, validators, and types for tools and subagents reporting inner model usage under `toolResult.details[FORGE_NESTED_USAGE_KEY]`:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import {
|
|
69
|
+
FORGE_NESTED_USAGE_KEY,
|
|
70
|
+
parseForgeNestedUsage,
|
|
71
|
+
type ForgeNestedUsage,
|
|
72
|
+
} from "@zihanw/pi-forge/subagent";
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- `FORGE_NESTED_USAGE_KEY`: constant string key (`"forgeNestedUsage"`).
|
|
76
|
+
- `parseForgeNestedUsage(value: unknown): ForgeNestedUsage | undefined`: strict schema parser that returns typed usage or `undefined` for malformed objects.
|
|
77
|
+
- `type ForgeNestedUsage`: typed schemaVersion 1 contract (`schemaVersion`, `requests`, `input`, `output`, optional `cacheRead` and `cacheWrite`).
|
|
78
|
+
|
|
79
|
+
See the [session cache usage reference](session-cache.md) for full contract rules, ingestion boundaries, and hit-rate aggregation semantics.
|
|
80
|
+
|
|
63
81
|
### 4. `@zihanw/pi-forge/ui-contribution`: versioned settings port
|
|
64
82
|
|
|
65
83
|
```ts
|
|
@@ -72,10 +90,38 @@ import {
|
|
|
72
90
|
|
|
73
91
|
The experimental generic Settings integration surface. Optional packages contribute recursively validated, JSON-compatible schemas and values over the Pi event bus; pi-forge owns only the renderer and web proxy. Providers own validation and persistence, may resolve operations asynchronously, and receive an abort signal tied to provider generation so stale requests can stop before side effects. The full contract is documented in the [UI contribution port reference](ui-contribution-port.md).
|
|
74
92
|
|
|
93
|
+
### 5. `@zihanw/pi-forge/command-contribution`: Forge child-command contribution
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import {
|
|
97
|
+
FORGE_COMMAND_DISCOVERY_EVENT,
|
|
98
|
+
contributeForgeCommand,
|
|
99
|
+
} from "@zihanw/pi-forge/command-contribution";
|
|
100
|
+
import type {
|
|
101
|
+
ForgeCommandContribution,
|
|
102
|
+
ForgeCommandDiscovery,
|
|
103
|
+
ForgeCommandEvents,
|
|
104
|
+
} from "@zihanw/pi-forge/command-contribution";
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This is a local, synchronous discovery surface for contributing one child command below the main `/forge` root. A contribution supplies callback metadata (`name`, `description`, `handler`, and optional argument completions); `contributeForgeCommand` returns an explicit unsubscribe function. Discovery is an in-process callback exchange, not an RPC, authorization boundary, execution sandbox, singleton registry, or persistent format. The main package owns the sole `/forge` root. Reserved names are rejected and duplicate child contributors fail closed rather than being selected arbitrarily.
|
|
108
|
+
|
|
109
|
+
The optional subagent package can use this surface for `/forge subagent plan`, while its backend policy remains separate: `/forge-agent run` retains mandatory human approval and a selected backend may write; model-callable `forge_subagent` unattended authorization is a different path.
|
|
110
|
+
|
|
111
|
+
Forge 0.5.5 provides this main-package subpath. The optional package remains an independent unfinished release and must raise its Forge dependency floor to `^0.5.5` before consuming it as a paired release; this documentation does not claim optional-package publication or compatibility with an older main package.
|
|
112
|
+
|
|
113
|
+
## Event bus contracts (no import entry point)
|
|
114
|
+
|
|
115
|
+
Optional cosmetic consumers integrate over the Pi event bus instead of importing the package:
|
|
116
|
+
|
|
117
|
+
- Active-state snapshot/change uses `@zihanw/pi-forge/active-state/v1` and `@zihanw/pi-forge/active-state/request/v1`. See the [active-state bus contract](active-state.md).
|
|
118
|
+
|
|
119
|
+
These channels carry only plain JSON scalars. They are not `@zihanw/pi-forge` import surfaces and consumers must not depend on package internals.
|
|
120
|
+
|
|
75
121
|
## Compatibility policy
|
|
76
122
|
|
|
77
123
|
- **Stable** surfaces (root factory, macro/slot registration) preserve source compatibility within the documented release range unless a changelog entry announces a breaking release.
|
|
78
|
-
- **Experimental** surfaces (the `/subagent
|
|
124
|
+
- **Experimental** surfaces (the `/subagent`, `/ui-contribution`, and `/command-contribution` ports) are typed and documented, but may change deliberately as integration experience exposes missing semantics. Forge 0.5.5 provides the command-contribution surface; optional consumers remain pending their independent version/floor bump and release.
|
|
79
125
|
- Everything not listed above is internal and may change without notice. In particular: no `src/*` subpath aliases exist, `./examples/*` is not an import surface (examples ship as browsable files), and removed 0.4 surfaces (the execution contract re-exports, loader/profile/catalog helpers) now live either nowhere or in `@zihanw/pi-forge-subagents`.
|
|
80
126
|
|
|
81
127
|
## Removed in 0.5.0
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Session cache usage
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md) · [简体中文](../zh-CN/reference/session-cache.md)
|
|
4
|
+
|
|
5
|
+
Available in Forge 0.5.5. The nested-usage contract is experimental; producer integration is owned and released independently by optional tools. Forge tracks and summarizes read-only prompt-cache metrics for the active session branch. These metrics appear in the Web editor's **Current session** capabilities panel and are exposed in the capability runtime state.
|
|
6
|
+
|
|
7
|
+
## Read-only architecture
|
|
8
|
+
|
|
9
|
+
Cache usage metrics are computed on demand from provider-reported usage that Pi has already persisted in messages along the active branch:
|
|
10
|
+
|
|
11
|
+
- **Zero side effects:** Forge never initiates model inference, appends session entries, edits prompt text, inserts `cache_control` breakpoints, or triggers prompt warming for usage tracking.
|
|
12
|
+
- **Reused polling:** The Web client receives cache metrics through its existing visibility-based polling (`GET /api/capability-state`); no extra network requests or timers are introduced.
|
|
13
|
+
- **Root-to-leaf branch traversal:** Metrics reflect the active branch from root to leaf.
|
|
14
|
+
- **Main session requests:** Counted from `assistant` messages carrying non-zero persisted usage (`input + output + cacheRead + cacheWrite > 0`). Requests with zero reported usage (such as aborted turns or failed calls without provider usage) are excluded.
|
|
15
|
+
- **Latest reported request:** The latest assistant message with non-zero usage; a later aborted or unreported request does not replace it.
|
|
16
|
+
- **Current turn:** Aggregates assistant requests appearing after the latest `user` message on the branch. Tool loops within the turn aggregate together.
|
|
17
|
+
- **Session scope:** Aggregates all qualifying requests on the active branch, including pre-compaction conversation history that remains on the branch.
|
|
18
|
+
- **Exclusions and persistence boundaries:**
|
|
19
|
+
- Excludes standalone Pi `usage` events, compaction entries, and `branch_summary` records.
|
|
20
|
+
- Pi can persist warming usage separately; these metrics intentionally count conversational requests, not warming or summarization overhead.
|
|
21
|
+
- Not equivalent to Pi's overall session billing or total bill statistics.
|
|
22
|
+
|
|
23
|
+
## Hit rate formula and aggregation
|
|
24
|
+
|
|
25
|
+
### Hit rate formula
|
|
26
|
+
|
|
27
|
+
Prompt cache hit rate measures prompt prefix reuse:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
cacheHitRate = cacheRead / (input + cacheRead + cacheWrite)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- `input`: normalized uncached prompt tokens, following the `pi-ai` `Usage` convention.
|
|
34
|
+
- `cacheRead`: prompt tokens served from the provider prompt cache.
|
|
35
|
+
- `cacheWrite`: prompt tokens written to provider prompt cache checkpoints.
|
|
36
|
+
- `output`: model completion tokens are strictly excluded from the prompt cache hit rate denominator.
|
|
37
|
+
- **Undefined denominator:** When total prompt tokens (`input + cacheRead + cacheWrite`) equal zero, the hit rate is undefined and displayed as an em dash (`—`).
|
|
38
|
+
|
|
39
|
+
### Aggregation semantics
|
|
40
|
+
|
|
41
|
+
- **Mixed models:** When multiple models run on the same branch or turn, rates are aggregated by summing raw token counts across requests (sum of cache reads / sum of prompt tokens), never as an arithmetic mean of percentages.
|
|
42
|
+
- **Provider reporting caveats:** Zero reported cache counts (`cacheRead: 0`, `cacheWrite: 0`) can indicate that the provider does not report cache metrics. They do not prove that prompt caching is unsupported or that no caching occurred.
|
|
43
|
+
|
|
44
|
+
## Main session vs. nested tool separation
|
|
45
|
+
|
|
46
|
+
Usage is tracked in two distinct streams:
|
|
47
|
+
1. **Main (`main`):** Direct assistant turns initiated by the primary session model.
|
|
48
|
+
2. **Nested (`nested`):** Usage reported by tools that execute model requests internally (such as subagents). Nested usage is never merged into `main`.
|
|
49
|
+
|
|
50
|
+
In the Web UI:
|
|
51
|
+
- Main session and nested tools are displayed in separate visible rows (**Cache hit** and **Nested tools**).
|
|
52
|
+
- Tooltips display combined totals for **known** data only, with a permanent note that absent, invalid, or cache-unknown reports are excluded. The combined value is not a complete bill.
|
|
53
|
+
|
|
54
|
+
## Experimental nested-usage contract (`toolResult.details.forgeNestedUsage`)
|
|
55
|
+
|
|
56
|
+
Tools that make inner model calls can report aggregate token and cache metrics by attaching an object to `toolResult.details.forgeNestedUsage` (`FORGE_NESTED_USAGE_KEY`).
|
|
57
|
+
|
|
58
|
+
### Typed import
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import {
|
|
62
|
+
FORGE_NESTED_USAGE_KEY,
|
|
63
|
+
parseForgeNestedUsage,
|
|
64
|
+
type ForgeNestedUsage,
|
|
65
|
+
} from "@zihanw/pi-forge/subagent";
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### JSON payload example
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"role": "toolResult",
|
|
73
|
+
"toolCallId": "call_subagent_abc123",
|
|
74
|
+
"content": [{ "type": "text", "text": "Subagent task completed." }],
|
|
75
|
+
"details": {
|
|
76
|
+
"forgeNestedUsage": {
|
|
77
|
+
"schemaVersion": 1,
|
|
78
|
+
"requests": 2,
|
|
79
|
+
"input": 1500,
|
|
80
|
+
"output": 420,
|
|
81
|
+
"cacheRead": 3200,
|
|
82
|
+
"cacheWrite": 0
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Contract specification
|
|
89
|
+
|
|
90
|
+
| Field | Type | Required | Notes |
|
|
91
|
+
|---|---|---|---|
|
|
92
|
+
| `schemaVersion` | `1` | Yes | Contract version. Must be literal `1`. |
|
|
93
|
+
| `requests` | `number` | Yes | Non-negative safe integer. Total model requests executed during the tool invocation. `0` is allowed **only** when all supplied token counts are zero. |
|
|
94
|
+
| `input` | `number` | Yes | Non-negative safe integer. Normalized uncached input tokens. |
|
|
95
|
+
| `output` | `number` | Yes | Non-negative safe integer. Generated completion tokens. |
|
|
96
|
+
| `cacheRead` | `number` | Optional | Non-negative safe integer. Prompt tokens read from cache. Must be paired with `cacheWrite`. |
|
|
97
|
+
| `cacheWrite` | `number` | Optional | Non-negative safe integer. Prompt tokens written to cache. Must be paired with `cacheRead`. |
|
|
98
|
+
|
|
99
|
+
- **Strict schema:** No extra keys are permitted.
|
|
100
|
+
- **Cache pair rule:** `cacheRead` and `cacheWrite` must either both be present or both omitted. Omit both when the producer cannot provide cache numbers.
|
|
101
|
+
- **Invocation aggregation:** A final tool result must supply exactly **one** aggregate per tool invocation covering all its internal model requests. Intermediate progress snapshots or repeated lifetime totals across calls are prohibited.
|
|
102
|
+
- **Rollup ownership:** The tool producer owns deduplication and recursive rollup across child agents. Nested totals must not include main session tokens.
|
|
103
|
+
- **Ingestion and error handling:**
|
|
104
|
+
- **Unknown cache metrics:** Valid records omitting `cacheRead`/`cacheWrite` are excluded from all request and token totals; the call is counted in `cacheUnknownCalls` (`N calls reported no cache data`).
|
|
105
|
+
- **Malformed records:** Payloads failing schema validation are ignored; the call is counted in `invalidCalls` (`N malformed reports ignored`).
|
|
106
|
+
- **Absent key:** When `forgeNestedUsage` is absent, the tool call is treated as having no nested usage. Forge does not mine legacy output or parse logs.
|
|
107
|
+
|
|
108
|
+
### Attribution and Pi integration boundary
|
|
109
|
+
|
|
110
|
+
- **Forge attribution only:** `toolResult.details.forgeNestedUsage` is used solely for Forge UI attribution and cache tracking. It does **not** modify Pi's built-in session totals.
|
|
111
|
+
- **No duplicate counting:** Pi supports `toolResult.usage` natively. A future producer can emit the same underlying usage to `toolResult.usage` for Pi's session totals and to `toolResult.details.forgeNestedUsage` for Forge's cache display. Forge does not re-add top-level `toolResult.usage`, preventing duplication.
|
|
112
|
+
- **Ecosystem status:** Runtime and subagent producer integration is deferred. Existing subagent calls without this field display no data; no historical backfill is performed.
|
|
@@ -47,7 +47,7 @@ Item IDs must be unique. Unsupported slots and missing required custom registrat
|
|
|
47
47
|
|
|
48
48
|
Item position only matters within each channel: all `system` items join the system prompt in their relative order, and all non-system items become messages in their relative order. A `system` item placed after non-system items therefore has no effect on placement and produces a validation warning; roles are never silently converted. Use a `user` item for in-conversation injection.
|
|
49
49
|
|
|
50
|
-
##
|
|
50
|
+
## Capabilities
|
|
51
51
|
|
|
52
52
|
- `replace` replaces Pi's base system prompt; empty output falls back to the base.
|
|
53
53
|
- `append` places stack system text after Pi's base.
|
|
@@ -76,7 +76,7 @@ Item position only matters within each channel: all `system` items join the syst
|
|
|
76
76
|
"includeLastUserMessage": false,
|
|
77
77
|
"stripAssistantThinking": true,
|
|
78
78
|
"includeSummaries": true,
|
|
79
|
-
"
|
|
79
|
+
"toolCapability": "keep",
|
|
80
80
|
"roles": ["user", "assistant"],
|
|
81
81
|
"maxMessages": 40,
|
|
82
82
|
"maxChars": 20000
|
|
@@ -87,7 +87,7 @@ Item position only matters within each channel: all `system` items join the syst
|
|
|
87
87
|
- `stripAssistantThinking` removes prior thinking blocks but preserves visible assistant text, tool calls, and results. It does not change the live loop or stored transcript.
|
|
88
88
|
- `includeSummaries: false` excludes branch/compaction summaries.
|
|
89
89
|
- `roles` keeps only selected roles.
|
|
90
|
-
- `
|
|
90
|
+
- `toolCapability: "drop"` removes prior tool traffic.
|
|
91
91
|
- `maxMessages` and `maxChars` keep recent history within limits.
|
|
92
92
|
|
|
93
93
|
When filtering would separate a tool call from its result, pi-forge removes dangling entries rather than sending inconsistent provider history.
|
|
@@ -105,7 +105,8 @@ Patterns are exact by default and support `*` wildcards:
|
|
|
105
105
|
```json
|
|
106
106
|
{
|
|
107
107
|
"tools": {
|
|
108
|
-
"allow": ["read", "grep", "find", "ls"]
|
|
108
|
+
"allow": ["read", "grep", "find", "ls"],
|
|
109
|
+
"initial": ["read", "grep"]
|
|
109
110
|
},
|
|
110
111
|
"skills": {
|
|
111
112
|
"deny": ["browser-danger"]
|
|
@@ -115,6 +116,19 @@ Patterns are exact by default and support `*` wildcards:
|
|
|
115
116
|
|
|
116
117
|
Each resource may have a non-empty `allow` list or `deny` list, never both. A selective tool `allow` list chooses matching tools from Pi's complete registered tool catalog, so it can activate a registered tool that was inactive when the stack was selected. A tool `deny` list removes matching tools from the active baseline. `allow: ["*"]` remains unrestricted and does not activate every registered tool. Unmatched allow patterns are surfaced during validation/preflight.
|
|
117
118
|
|
|
119
|
+
### Initial active tools (`tools.initial`)
|
|
120
|
+
|
|
121
|
+
The `tools` policy optionally accepts an `initial` list:
|
|
122
|
+
|
|
123
|
+
- **Concrete names only:** `tools.initial` must be an array of valid, concrete tool name strings (up to 128 characters each). Wildcards (`*`, `?`) are rejected; duplicate names produce a warning and are deduplicated on parsing.
|
|
124
|
+
- **Omission vs. empty array:**
|
|
125
|
+
- When `initial` is omitted, pi-forge preserves legacy behavior: a selective allow chooses matching registered tools; unrestricted/deny policies retain or filter the restorable session baseline, not the entire catalog.
|
|
126
|
+
- When `initial: []` is set explicitly, zero tools are active initially.
|
|
127
|
+
- **Ceiling enforcement:** The `allow`/`deny` ceiling remains authoritative and exclusive. Initial tools must fall within permitted bounds: listing a tool that is blocked by allow/deny produces a validation error.
|
|
128
|
+
- **Extension and mod tools:** Dynamically registered extension tools are allowed by default if they satisfy the allow/deny policy, but when `initial` is specified, they remain registered and inactive until explicitly added by `initial`, by an active capability, or through runtime tooling.
|
|
129
|
+
- **Preset baseline behavior:** Configured initial tools serve as the active base for as long as the preset remains active—not a one-time reset per turn. Calling `/capability disable` or `/capability reset` returns the session to the preset defaults (plus any remaining active capabilities). Disabling restores the reconciled session baseline; switching recomputes under the new Preset and remaining unbound capabilities.
|
|
130
|
+
- **Compatibility:** Stacks declaring `tools.initial` require Forge 0.5.5 or newer. Older Forge versions may ignore `tools.initial` and revert to legacy selection behavior (selective allow selects catalog matches; unrestricted/deny retains or filters the session baseline), so the field is not downgrade-compatible. The host requirement remains Pi `>=0.87.0 <0.88.0`.
|
|
131
|
+
|
|
118
132
|
Tool policy changes Pi's active tool list, is reasserted before input/turns, and has a tool-call guard. It preserves external additions in the restorable baseline and restores that baseline when policy no longer applies or the extension shuts down.
|
|
119
133
|
|
|
120
134
|
Skill policy filters only pi-forge-rendered skill slots. It does not disable explicit invocation and is not a capability boundary. `append`/`prepend` may retain Pi's unfiltered base skill text, so validation warns.
|
|
@@ -40,6 +40,14 @@ Request: `{ profile: string }` — a scoped selector (`reviewer`, `project:revie
|
|
|
40
40
|
|
|
41
41
|
Request: `{ profile, task: { text }, access: ForgePromptAccessFacts, backend: ForgeBackendFacts }`. The workspace resolves the profile and stack from its snapshot, filters the client tool catalog through stack tool policy and the access facts, and compiles through the same compilation context as runtime and preview. Response: `{ profileId, model, thinkingLevel, systemPrompt, messages, effectiveToolIds, effectiveToolNames, diagnostics, profileSnapshot, preparedAt }`. `messages` ends with the protected delegated task (`protectedTask: true`, `source: "delegated-task"`); stack-compiled messages carry `source: "prompt-stack"`. The base system prompt is host-owned and intentionally empty for delegated subagents — the prompt stack composes the system prompt.
|
|
42
42
|
|
|
43
|
+
## Tool-selection compatibility
|
|
44
|
+
|
|
45
|
+
For Presets containing `tools.initial`, both the host and the optional package must understand the field. The host filters the registered backend catalog to those concrete names (including an explicitly empty set), applies the existing allow/deny ceiling, then applies request access. The optional package independently recomputes this selection when validating the execution plan; `plan.tool-negotiation` must continue to reject disagreement. Omitting `initial` preserves legacy selection.
|
|
46
|
+
|
|
47
|
+
Forge 0.5.5 provides the host-side `tools.initial` support. Published `pi-forge-subagents` 0.5.3 is not compatible with `tools.initial`: it ignores the field during its independent negotiation. Use matching local optional-package checkouts until the optional package raises its Forge dependency floor to `^0.5.5` and completes its own release; the existing broad package dependency range is not a feature-compatibility guarantee.
|
|
48
|
+
|
|
49
|
+
This is an optional-package release gate, not a gate on the main Forge 0.5.5 release. The optional package must update its own manifests, runtime sequencing, backend/continuation coverage, lockfiles, and cross-package packed tests through its separately authorized process. No optional package or runtime publication is claimed here.
|
|
50
|
+
|
|
43
51
|
## Fingerprints
|
|
44
52
|
|
|
45
53
|
`canonicalSubagentJson`, `subagentFingerprint`, `subagentSourceProfileFingerprint`, `subagentPromptStackFingerprint`, and `SUBAGENT_FINGERPRINT_PREFIX` are Forge-owned and vendored in the main package; golden vectors pin byte compatibility with the runtime's canonical serialization. Conversation and execution fingerprints are never host-computed — they are issued by `@zihanw/pi-subagent-runtime` during plan sealing in the optional package.
|
package/docs/zh-CN/README.md
CHANGED
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
## 参考
|
|
24
24
|
|
|
25
25
|
- [命令参考](reference/commands.md)
|
|
26
|
+
- [能力](reference/capabilities.md)
|
|
27
|
+
- [会话缓存用量](reference/session-cache.md):提示词缓存命中率与嵌套工具用量契约
|
|
28
|
+
- [各服务商对会话中更新的支持情况](reference/provider-support.md):Pi 0.87.1 快照
|
|
26
29
|
- [Stack schema 与策略(英文)](../reference/stack-schema.md)
|
|
27
30
|
- [Macros 与 slots(英文)](../reference/macros-and-slots.md)
|
|
28
31
|
- [配置(英文)](../reference/configuration.md)
|
|
@@ -21,7 +21,7 @@ mkdir -p .pi/forge/prompt-stacks
|
|
|
21
21
|
cp examples/default-prompt-stack.json .pi/forge/prompt-stacks/default.json
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
无需复制文件,也可以打开 `/forge ui` 新建预设;Forge 0.5.5 支持选择默认 Pi 提示词镜像、空白预设(Pi 仍保留基础提示词与历史)或极简工作者模板(仅限 `bash` 与 `edit`)。
|
|
25
25
|
|
|
26
26
|
```text
|
|
27
27
|
/preset reload
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
> **实验性:** 此 API 和 backend 可能独立于稳定的 prompt stack/profile 功能发生变化。
|
|
6
6
|
|
|
7
|
-
可选包 `@zihanw/pi-forge-subagents`
|
|
7
|
+
可选包 `@zihanw/pi-forge-subagents` 会通过选定的 backend 执行明确授权的 agent profile。默认只读 backend 使用独立、干净、一次性的 Pi 子进程;可写 backend 的边界见下文。本文档流程在前台运行,并向父对话返回有界报告。
|
|
8
|
+
|
|
9
|
+
> **默认工具兼容要求:** Forge 0.5.5 主包已提供 `tools.initial`;独立发布的可选 subagents 0.5.3 不兼容该字段。在可选包将 Forge floor 提升到 `^0.5.5` 并单独发布修复前,请使用匹配的本地源码;版本与发布门槛见[工具选择兼容说明(英文)](../../reference/subagent-host-port.md#tool-selection-compatibility)。这项可选包兼容工作不是主包 release gate。
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
## 启用 profile
|
|
10
13
|
|
|
@@ -33,11 +36,20 @@ Profile 默认不能委派。请在可信项目的 `.pi/forge/subagents.json`
|
|
|
33
36
|
/forge-agent run reviewer 检查这个 API 设计。
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
`plan` 会解析 profile/stack、编译并校验不可变的实际 provider-bound 计划,然后在不联系 provider 的情况下丢弃。Profile selector 在所有入口使用同一语法:`reviewer
|
|
39
|
+
`plan` 会解析 profile/stack、编译并校验不可变的实际 provider-bound 计划,然后在不联系 provider 的情况下丢弃。Profile selector 在所有入口使用同一语法:`reviewer`、`project:reviewer` 或 `global:reviewer`。在 delegation 中,裸 ID 选择 `project:<id>`;调用全局 profile 请使用明确的 `global:<id>`。同 ID 的 profile 仍彼此独立,不会互相继承 delegation policy。
|
|
37
40
|
|
|
38
41
|
父模型使用无数据外发的 `forge_subagent_profiles` 做 discovery,再用 `forge_subagent` 执行。限制严格的父 stack 必须允许这两个工具名。
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
匹配的可选 subagents 包与 runtime 开发版本提供四个 backend ID。以下说明基于尚未完成的可选包源码,不代表配套 release 已定稿;Forge 0.5.5 主包不依赖它们。请同时遵守上方 Forge 兼容要求:
|
|
44
|
+
|
|
45
|
+
- `pi-subprocess-readonly` 是默认 backend,使用 `pi --mode text --print`。它提供 `read`、`grep`、`find`、`ls` allowlist,属于 shared-user;allowlist 不是 OS 沙箱。
|
|
46
|
+
- `pi-rpc-readonly` 使用 `pi --mode rpc`,采用相同的 shared-user 只读策略,只改变进程协议。
|
|
47
|
+
- `pi-inprocess` 在 host model runtime 中运行,拥有启动用户的完整权限。它是 workspace-write backend;在 sealed access level 和 stack policy 允许时可提供 `read`/`grep`/`find`/`ls`/`edit`/`write`/`bash`,但没有 OS 沙箱。需要 extension-registered provider 时应使用它。
|
|
48
|
+
- `pi-bwrap-write` 是仅限 Linux 的可选 Bubblewrap backend。它为选定 workspace 提供隔离的 `workspace-write` 挂载,并可在允许时提供 `read`/`grep`/`find`/`ls`/`edit`/`write`/`bash`。写入会直接落到该 workspace,不是另行审批再 apply 的 staged patch;需要 Bubblewrap,默认还要求 git workspace。
|
|
49
|
+
|
|
50
|
+
所选 backend 不可用时会 fail closed,不会自动 fallback。Fresh-process backend 对 extension-registered provider 会报告不可移植;此时改用 `pi-inprocess`。不要把此开发矩阵或 `tools.initial` 修复理解为配套 companion release 已发布。
|
|
51
|
+
|
|
52
|
+
Human 运行的 backend 优先级是:显式 per-run `--backend`、匹配 profile override、可信项目默认值、全局默认值、内置 `pi-subprocess-readonly`。交互式模型调用也可以提供 per-call backend override;无人值守的模型调用会固定使用生效的 profile/config backend,并拒绝该 override。Timeout 依次采用匹配 profile override、可信项目默认值、全局默认值,再到内置 60 秒;有效范围为 1,000–3,600,000 ms,host timeout 仅为 best effort。
|
|
41
53
|
|
|
42
54
|
## 审批
|
|
43
55
|
|
|
@@ -47,18 +59,18 @@ Profile 默认不能委派。请在可信项目的 `.pi/forge/subagents.json`
|
|
|
47
59
|
|
|
48
60
|
```json
|
|
49
61
|
{
|
|
50
|
-
"
|
|
51
|
-
"allowAgentInvocationWithoutApproval": true
|
|
52
|
-
}
|
|
62
|
+
"allowAgentInvocationWithoutApproval": true
|
|
53
63
|
}
|
|
54
64
|
```
|
|
55
65
|
|
|
56
|
-
|
|
66
|
+
在专用 `subagents.json` 中该 flag 必须位于顶层;只有旧版 `config.json` 的嵌套 `subagents` 段落使用嵌套形式。
|
|
67
|
+
|
|
68
|
+
它只影响 `forge_subagent`;`/forge-agent run` 仍需要交互审批。该 flag 可以来自全局默认或可信项目文件,项目值优先。尚未发布的配套修复中,某一层省略时会继承;某一层明确写入非 boolean 时,该层设为 `false` 并发出 warning;更高优先级层的有效 boolean 仍会正常覆盖较低层。若整个配置文件不可读、格式错误或不是 JSON object,则该文件会带 warning 被忽略,之前有效的层仍可能继续生效。不可信项目的项目配置会被忽略,execution trust gate 也会阻止该项目运行 delegation。请把 `subagents.json` 当作授权文件:除非所有可调用父 agent 都可以无需再次询问就把编译 prompt 和可读文件发给 provider,否则不要启用或提交此设置。
|
|
57
69
|
|
|
58
70
|
## Child 边界
|
|
59
71
|
|
|
60
|
-
|
|
72
|
+
普通的新 child 从干净对话开始,不会自动继承父 history。显式保留 child 后续聊与后台运行属于独立的开发中特性,详见[配套包文档](https://github.com/MacroSony/pi-forge-subagents)。对 `pi-subprocess-readonly` 和 `pi-rpc-readonly`,候选工具只有 `read`、`grep`、`find`、`ls`,并继续受到 stack policy 限制;这些 child 不加载 write/edit/shell、skills、prompt templates、context files 或第三方 extensions。`pi-inprocess` 和 `pi-bwrap-write` 仅在 access level 与 stack policy 允许时提供上文所述可写工具。
|
|
61
73
|
|
|
62
|
-
>
|
|
74
|
+
> **边界取决于 backend:** subprocess/RPC 只读 backend 和 `pi-inprocess` 都是 shared-user,不是 OS 沙箱;后者在 host 进程中拥有启动用户完整权限。`pi-bwrap-write` 是 Linux 隔离例外:选定 workspace 是可写的项目挂载,另有只读运行时挂载与沙箱临时存储。它不是 staged patch/apply 流程,也不提供 network isolation。Shared-user backend 中,该用户可读的绝对路径可能被读取并发送给 provider;文本可能保留在父 tool-result 和 Pi session JSONL。Timeout/取消仅为 best effort。`/tree` 不能撤销 provider 请求、计费或外部影响,也不保证删除磁盘上的 abandoned entry。
|
|
63
75
|
|
|
64
|
-
|
|
76
|
+
选择只读 backend 时不要授予 mutation path;选择可写 backend 则应视为明确授权其修改选定 workspace。
|
|
@@ -86,6 +86,35 @@ Subagent 执行功能从主包移入可选包 `@zihanw/pi-forge-subagents`(要
|
|
|
86
86
|
| `@zihanw/pi-forge/src/*` 别名 | 已移除;无替代(内部实现) |
|
|
87
87
|
| 根部的 loader/profile/catalog/engine 再导出 | 已移除;无替代(内部实现) |
|
|
88
88
|
|
|
89
|
+
## 上游 Pi 0.87 迁移
|
|
90
|
+
|
|
91
|
+
Forge 0.5.5 要求上游 Pi 版本 `>=0.87.0 <0.88.0`。不提供对 0.86 的双重运行时支持(仓库开发 SDK 固定为 `0.87.0`,peer 范围为 `>=0.87.0 <0.88.0`)。主包和可选包独立发布。
|
|
92
|
+
|
|
93
|
+
**升级后重启 Pi 进程:** 更新全局安装不会替换已运行进程的核心。若当前会话在升级前启动,请退出并重新启动 Pi,再恢复会话;仅 `/reload` 扩展不足以切换 Pi 核心。重新打开 `/preset ui` 给出的新链接,旧服务器 token 不沿用。
|
|
94
|
+
|
|
95
|
+
### 上下文 Hook 迁移(`context_with_system`)
|
|
96
|
+
|
|
97
|
+
- **标准 `context` 排除 System 消息:** 在 Pi 0.87 中,标准 `context` 生命周期 hook 默认排除 System 消息。之前依赖或操作完整 System 上下文的第三方扩展必须迁移至完整的 `context_with_system` hook。
|
|
98
|
+
- **统一的 Forge 流水线:** Forge 将其整个编译器、基础提示词替换与能力投影流水线完整移至 `context_with_system`,在完整转录边界上统一运行,无需内部两阶段切分。
|
|
99
|
+
- **`before_agent_start` 注入时机:** 任何通过 `before_agent_start` 强制注入的 System 提示词在 Pi 执行流中仍然晚于 `context_with_system` 执行。
|
|
100
|
+
|
|
101
|
+
### 规范会话投影与转录隔离
|
|
102
|
+
|
|
103
|
+
- **集成 `buildSessionProjection`:** 运行时执行、Preview 预览与锚点定位器均采用 Pi 0.87 的 `buildSessionProjection`。轮次级的 `context_edit` 忽略(omission)、替换(replacement)以及 `sourceEntry` 引用均能正确反映在瞬态请求中,而磁盘上的原始 JSONL 会话历史完全保持不变。
|
|
104
|
+
- **首条 System 消息顺序:** SDK 传入的 leading System 提示词在请求转录中始终保持在第一位;Forge 自身的前缀纯元数据锚点紧随其后插入,绝不会置换请求头部或用户回退位置。
|
|
105
|
+
- **前置任意改写 Fail-Closed:** 若第三方扩展在 Forge 之前执行了破坏与规范投影唯一有序对齐的改写,Forge 依然 fail-closed 报错中止。
|
|
106
|
+
|
|
107
|
+
### 续跑与生命周期结算
|
|
108
|
+
|
|
109
|
+
- **`agent_end` 与 `agent_settled` 的职责划分:** `agent_end` 在低层运行结束后提供落锚机会,前提是没有 Forge 上下文失败或未完成的工具批次。但编译周期与 busy fence 仅在 `agent_settled` 时重置。这保证了由 `agent_before_settle` 发起的继续执行(continuation)不会丢失已编译的 Preset 输入与活跃能力。
|
|
110
|
+
|
|
111
|
+
### 防护机制与语义保持
|
|
112
|
+
|
|
113
|
+
- **项目信任:** 激活能力或执行 Agent 控制工具必须处于受信任项目(`isProjectTrusted()`);人类 CLI 的 disable/reset 恢复入口仍可用。
|
|
114
|
+
- **`sourceRevision` 防脏写:** 已有能力的更新/删除与带绑定的预设更新需要匹配原始字节的源版本;创建能力不得覆盖已有文件。并发冲突返回 `409 Conflict`。
|
|
115
|
+
- **Save ≠ Enable:** 保存能力库定义仅更新磁盘文件,绝不在当前会话中启用该能力;保存当前生效的预设会立即刷新其策略(更新实时工具与能力授权),但不会替换已冻结的活动能力快照。
|
|
116
|
+
- **上游缺陷状态:** 上游 Pi 元数据切分与语义截断缺陷未修复;压缩检查点位置保持不变;旧会话中的 carrier 保持原样不自动迁移;不支持也不承诺 OMP(Oh My Pi)。
|
|
117
|
+
|
|
89
118
|
## 兼容性说明
|
|
90
119
|
|
|
91
120
|
- Host port 的 wire 结构在 `FORGE_HOST_PORT_VERSION = 1` 内只做增量扩展;未知操作会以普通的 `{ ok: false, error }` 结果拒绝(`"Unknown Forge host operation: …"`),而不是抛出异常。可选包必须把任何操作失败视为该请求的终态。
|