@zihanw/pi-forge 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -1
- package/README.md +11 -11
- package/README.zh-CN.md +3 -5
- package/SUBAGENT_ADAPTER_CONTRACT.md +3 -1
- package/dist/agent-profile.d.ts +18 -62
- package/dist/agent-profile.d.ts.map +1 -1
- package/dist/agent-profile.js +27 -249
- package/dist/agent-profile.js.map +1 -1
- package/dist/codecs/agent-profile.d.ts +53 -0
- package/dist/codecs/agent-profile.d.ts.map +1 -0
- package/dist/codecs/agent-profile.js +176 -0
- package/dist/codecs/agent-profile.js.map +1 -0
- package/dist/codecs/index.d.ts +5 -0
- package/dist/codecs/index.d.ts.map +1 -0
- package/dist/codecs/index.js +3 -0
- package/dist/codecs/index.js.map +1 -0
- package/dist/codecs/prompt-stack.d.ts +18 -0
- package/dist/codecs/prompt-stack.d.ts.map +1 -0
- package/dist/codecs/prompt-stack.js +479 -0
- package/dist/codecs/prompt-stack.js.map +1 -0
- package/dist/compile-cycle.d.ts +18 -0
- package/dist/compile-cycle.d.ts.map +1 -0
- package/dist/compile-cycle.js +13 -0
- package/dist/compile-cycle.js.map +1 -0
- package/dist/compiler.d.ts +10 -4
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +53 -19
- package/dist/compiler.js.map +1 -1
- package/dist/extension-registry.d.ts.map +1 -1
- package/dist/extension-registry.js +5 -2
- package/dist/extension-registry.js.map +1 -1
- package/dist/forge-config.d.ts +0 -105
- package/dist/forge-config.d.ts.map +1 -1
- package/dist/forge-config.js +1 -313
- package/dist/forge-config.js.map +1 -1
- package/dist/forge-v1/analyzer.d.ts +3 -0
- package/dist/forge-v1/analyzer.d.ts.map +1 -0
- package/dist/forge-v1/analyzer.js +50 -0
- package/dist/forge-v1/analyzer.js.map +1 -0
- package/dist/forge-v1/index.d.ts +6 -0
- package/dist/forge-v1/index.d.ts.map +1 -0
- package/dist/forge-v1/index.js +13 -0
- package/dist/forge-v1/index.js.map +1 -0
- package/dist/forge-v1/parser.d.ts +3 -0
- package/dist/forge-v1/parser.d.ts.map +1 -0
- package/dist/forge-v1/parser.js +186 -0
- package/dist/forge-v1/parser.js.map +1 -0
- package/dist/forge-v1/renderer.d.ts +9 -0
- package/dist/forge-v1/renderer.d.ts.map +1 -0
- package/dist/forge-v1/renderer.js +181 -0
- package/dist/forge-v1/renderer.js.map +1 -0
- package/dist/forge-v1/types.d.ts +87 -0
- package/dist/forge-v1/types.d.ts.map +1 -0
- package/dist/forge-v1/types.js +4 -0
- package/dist/forge-v1/types.js.map +1 -0
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -81
- package/dist/index.js.map +1 -1
- package/dist/lifecycle.d.ts +6 -5
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +43 -112
- package/dist/lifecycle.js.map +1 -1
- package/dist/loader.d.ts +5 -8
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +10 -467
- package/dist/loader.js.map +1 -1
- package/dist/macro-engine.d.ts +9 -14
- package/dist/macro-engine.d.ts.map +1 -1
- package/dist/macro-engine.js +5 -238
- package/dist/macro-engine.js.map +1 -1
- package/dist/payload-command.d.ts +6 -6
- package/dist/payload-command.d.ts.map +1 -1
- package/dist/payload-command.js.map +1 -1
- package/dist/payload-state.d.ts +16 -0
- package/dist/payload-state.d.ts.map +1 -0
- package/dist/payload-state.js +14 -0
- package/dist/payload-state.js.map +1 -0
- package/dist/preset-command.d.ts +4 -4
- package/dist/preset-command.d.ts.map +1 -1
- package/dist/preset-command.js +33 -104
- package/dist/preset-command.js.map +1 -1
- package/dist/preview.d.ts +4 -4
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +17 -8
- package/dist/preview.js.map +1 -1
- package/dist/profile-command.d.ts +2 -2
- package/dist/profile-command.d.ts.map +1 -1
- package/dist/profile-command.js +15 -14
- package/dist/profile-command.js.map +1 -1
- package/dist/profile-service.d.ts.map +1 -1
- package/dist/profile-service.js +23 -39
- package/dist/profile-service.js.map +1 -1
- package/dist/prompt-analysis.d.ts +24 -0
- package/dist/prompt-analysis.d.ts.map +1 -0
- package/dist/prompt-analysis.js +84 -0
- package/dist/prompt-analysis.js.map +1 -0
- package/dist/prompt-runtime.d.ts +19 -0
- package/dist/prompt-runtime.d.ts.map +1 -0
- package/dist/prompt-runtime.js +30 -0
- package/dist/prompt-runtime.js.map +1 -0
- package/dist/regex.js +6 -12
- package/dist/regex.js.map +1 -1
- package/dist/render-helpers.d.ts +2 -10
- package/dist/render-helpers.d.ts.map +1 -1
- package/dist/render-helpers.js +3 -53
- package/dist/render-helpers.js.map +1 -1
- package/dist/repositories/agent-profile.d.ts +36 -0
- package/dist/repositories/agent-profile.d.ts.map +1 -0
- package/dist/repositories/agent-profile.js +153 -0
- package/dist/repositories/agent-profile.js.map +1 -0
- package/dist/repositories/index.d.ts +3 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +3 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/prompt-stack.d.ts +57 -0
- package/dist/repositories/prompt-stack.d.ts.map +1 -0
- package/dist/repositories/prompt-stack.js +175 -0
- package/dist/repositories/prompt-stack.js.map +1 -0
- package/dist/runtime/profile-runtime.d.ts +2 -2
- package/dist/runtime/profile-runtime.d.ts.map +1 -1
- package/dist/runtime/profile-runtime.js +13 -10
- package/dist/runtime/profile-runtime.js.map +1 -1
- package/dist/runtime/prompt-stack-runtime.d.ts +4 -3
- package/dist/runtime/prompt-stack-runtime.d.ts.map +1 -1
- package/dist/runtime/prompt-stack-runtime.js +42 -57
- package/dist/runtime/prompt-stack-runtime.js.map +1 -1
- package/dist/runtime/tool-policy-runtime.d.ts +2 -2
- package/dist/runtime/tool-policy-runtime.d.ts.map +1 -1
- package/dist/runtime/tool-policy-runtime.js +3 -3
- package/dist/runtime/tool-policy-runtime.js.map +1 -1
- package/dist/session-adapter.d.ts +17 -0
- package/dist/session-adapter.d.ts.map +1 -0
- package/dist/session-adapter.js +57 -0
- package/dist/session-adapter.js.map +1 -0
- package/dist/slot-renderers.d.ts +16 -3
- package/dist/slot-renderers.d.ts.map +1 -1
- package/dist/slot-renderers.js +15 -63
- package/dist/slot-renderers.js.map +1 -1
- package/dist/stack-migration.d.ts +6 -0
- package/dist/stack-migration.d.ts.map +1 -1
- package/dist/stack-migration.js +49 -52
- package/dist/stack-migration.js.map +1 -1
- package/dist/subagent/fingerprints.d.ts +24 -0
- package/dist/subagent/fingerprints.d.ts.map +1 -0
- package/dist/subagent/fingerprints.js +81 -0
- package/dist/subagent/fingerprints.js.map +1 -0
- package/dist/subagent/host-port.d.ts +296 -0
- package/dist/subagent/host-port.d.ts.map +1 -0
- package/dist/subagent/host-port.js +560 -0
- package/dist/subagent/host-port.js.map +1 -0
- package/dist/subagent/index.d.ts +10 -10
- package/dist/subagent/index.d.ts.map +1 -1
- package/dist/subagent/index.js +9 -10
- package/dist/subagent/index.js.map +1 -1
- package/dist/subagent-host.d.ts +99 -18
- package/dist/subagent-host.d.ts.map +1 -1
- package/dist/subagent-host.js +143 -146
- package/dist/subagent-host.js.map +1 -1
- package/dist/template-render.d.ts +18 -0
- package/dist/template-render.d.ts.map +1 -0
- package/dist/template-render.js +232 -0
- package/dist/template-render.js.map +1 -0
- package/dist/types.d.ts +40 -27
- 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 +1 -68
- 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 +13 -0
- package/dist/web-editor/styles.js.map +1 -1
- package/dist/web-editor/types.d.ts +0 -35
- package/dist/web-editor/types.d.ts.map +1 -1
- package/dist/web-host.d.ts +4 -2
- package/dist/web-host.d.ts.map +1 -1
- package/dist/web-host.js +32 -103
- package/dist/web-host.js.map +1 -1
- package/dist/workspace.d.ts +74 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +351 -0
- package/dist/workspace.js.map +1 -0
- package/docs/README.md +6 -4
- package/docs/concepts/agent-profiles.md +1 -1
- package/docs/concepts/prompt-stacks.md +5 -5
- package/docs/design/README.md +21 -3
- package/docs/design/architecture-0.5.md +211 -0
- package/docs/design/archive/0.5-full-proposal/0.5-consumer-audit.md +62 -0
- package/docs/design/archive/0.5-full-proposal/0.5-inventory.md +208 -0
- package/docs/design/archive/0.5-full-proposal/0.5-phase0-decision-drafts.md +237 -0
- package/docs/design/archive/0.5-full-proposal/README.md +12 -0
- package/docs/design/archive/0.5-full-proposal/architecture-0.5.md +423 -0
- package/docs/design/archive/0.5-full-proposal/host-discovery-spike.md +103 -0
- package/docs/design/archive/0.5-full-proposal/template-language-spike.md +156 -0
- package/docs/design/context-diff-plan.md +72 -0
- package/docs/design/decision-template.md +33 -0
- package/docs/design/roadmap-0.4-archive.md +1 -1
- package/docs/design/subagents/interface-design.md +1 -1
- package/docs/development/architecture-rules.md +148 -0
- package/docs/development/roadmap.md +37 -5
- package/docs/development/scoped-global-profiles-stacks.md +1 -1
- package/docs/development/setup.md +6 -4
- package/docs/getting-started.md +5 -4
- package/docs/guides/custom-macros-and-slots.md +8 -7
- package/docs/guides/debugging.md +1 -1
- package/docs/guides/delegation.md +18 -22
- package/docs/guides/migrating-to-0.5.md +107 -0
- package/docs/guides/use-cases.md +7 -11
- package/docs/guides/web-editor.md +5 -9
- package/docs/reference/commands.md +4 -3
- package/docs/reference/configuration.md +17 -18
- package/docs/reference/features.md +34 -80
- package/docs/reference/macros-and-slots.md +70 -49
- package/docs/reference/public-api.md +64 -17
- package/docs/reference/stack-schema.md +14 -9
- package/docs/reference/subagent-host-port.md +49 -0
- package/docs/zh-CN/README.md +3 -3
- package/docs/zh-CN/concepts/agent-profiles.md +1 -1
- package/docs/zh-CN/concepts/prompt-stacks.md +4 -4
- package/docs/zh-CN/getting-started.md +3 -2
- package/docs/zh-CN/guides/delegation.md +10 -12
- package/docs/zh-CN/guides/migrating-to-0.5.md +92 -0
- package/docs/zh-CN/guides/web-editor.md +4 -4
- package/docs/zh-CN/reference/commands.md +3 -2
- package/examples/custom-system-status-extension/README.md +3 -3
- package/examples/custom-system-status-extension/index.ts +2 -1
- package/examples/custom-system-status-extension/prompt-stack.json +4 -3
- package/examples/default-prompt-stack.json +9 -4
- package/examples/image-reader-prompt-stack.json +16 -26
- package/examples/reviewer-prompt-stack.json +13 -24
- package/package.json +101 -120
- package/dist/runtime/subagent-runtime.d.ts +0 -45
- package/dist/runtime/subagent-runtime.d.ts.map +0 -1
- package/dist/runtime/subagent-runtime.js +0 -343
- package/dist/runtime/subagent-runtime.js.map +0 -1
- package/dist/runtime-state.d.ts +0 -30
- package/dist/runtime-state.d.ts.map +0 -1
- package/dist/runtime-state.js +0 -17
- package/dist/runtime-state.js.map +0 -1
- package/dist/sillytavern-importer/items.d.ts +0 -3
- package/dist/sillytavern-importer/items.d.ts.map +0 -1
- package/dist/sillytavern-importer/items.js +0 -88
- package/dist/sillytavern-importer/items.js.map +0 -1
- package/dist/sillytavern-importer/macros.d.ts +0 -15
- package/dist/sillytavern-importer/macros.d.ts.map +0 -1
- package/dist/sillytavern-importer/macros.js +0 -141
- package/dist/sillytavern-importer/macros.js.map +0 -1
- package/dist/sillytavern-importer/prompt-order.d.ts +0 -6
- package/dist/sillytavern-importer/prompt-order.d.ts.map +0 -1
- package/dist/sillytavern-importer/prompt-order.js +0 -38
- package/dist/sillytavern-importer/prompt-order.js.map +0 -1
- package/dist/sillytavern-importer/regex.d.ts +0 -3
- package/dist/sillytavern-importer/regex.d.ts.map +0 -1
- package/dist/sillytavern-importer/regex.js +0 -275
- package/dist/sillytavern-importer/regex.js.map +0 -1
- package/dist/sillytavern-importer/report.d.ts +0 -21
- package/dist/sillytavern-importer/report.d.ts.map +0 -1
- package/dist/sillytavern-importer/report.js +0 -166
- package/dist/sillytavern-importer/report.js.map +0 -1
- package/dist/sillytavern-importer/types.d.ts +0 -106
- package/dist/sillytavern-importer/types.d.ts.map +0 -1
- package/dist/sillytavern-importer/types.js +0 -2
- package/dist/sillytavern-importer/types.js.map +0 -1
- package/dist/sillytavern-importer.d.ts +0 -5
- package/dist/sillytavern-importer.d.ts.map +0 -1
- package/dist/sillytavern-importer.js +0 -117
- package/dist/sillytavern-importer.js.map +0 -1
- package/dist/subagent/canonical.d.ts +0 -22
- package/dist/subagent/canonical.d.ts.map +0 -1
- package/dist/subagent/canonical.js +0 -24
- package/dist/subagent/canonical.js.map +0 -1
- package/dist/subagent/context.d.ts +0 -8
- package/dist/subagent/context.d.ts.map +0 -1
- package/dist/subagent/context.js +0 -125
- package/dist/subagent/context.js.map +0 -1
- package/dist/subagent/contract.d.ts +0 -10
- package/dist/subagent/contract.d.ts.map +0 -1
- package/dist/subagent/contract.js +0 -10
- package/dist/subagent/contract.js.map +0 -1
- package/dist/subagent/plan.d.ts +0 -18
- package/dist/subagent/plan.d.ts.map +0 -1
- package/dist/subagent/plan.js +0 -157
- package/dist/subagent/plan.js.map +0 -1
- package/dist/subagent/preflight.d.ts +0 -4
- package/dist/subagent/preflight.d.ts.map +0 -1
- package/dist/subagent/preflight.js +0 -108
- package/dist/subagent/preflight.js.map +0 -1
- package/dist/subagent/request.d.ts +0 -4
- package/dist/subagent/request.d.ts.map +0 -1
- package/dist/subagent/request.js +0 -154
- package/dist/subagent/request.js.map +0 -1
- package/dist/subagent/response.d.ts +0 -8
- package/dist/subagent/response.d.ts.map +0 -1
- package/dist/subagent/response.js +0 -155
- package/dist/subagent/response.js.map +0 -1
- package/dist/subagent/tools.d.ts +0 -4
- package/dist/subagent/tools.d.ts.map +0 -1
- package/dist/subagent/tools.js +0 -42
- package/dist/subagent/tools.js.map +0 -1
- package/dist/subagent/types.d.ts +0 -272
- package/dist/subagent/types.d.ts.map +0 -1
- package/dist/subagent/types.js +0 -3
- package/dist/subagent/types.js.map +0 -1
- package/dist/subagent/validation.d.ts +0 -35
- package/dist/subagent/validation.d.ts.map +0 -1
- package/dist/subagent/validation.js +0 -314
- package/dist/subagent/validation.js.map +0 -1
- package/dist/subagent-command.d.ts +0 -5
- package/dist/subagent-command.d.ts.map +0 -1
- package/dist/subagent-command.js +0 -249
- package/dist/subagent-command.js.map +0 -1
- package/dist/subagent-profile-tool.d.ts +0 -49
- package/dist/subagent-profile-tool.d.ts.map +0 -1
- package/dist/subagent-profile-tool.js +0 -125
- package/dist/subagent-profile-tool.js.map +0 -1
- package/dist/subagent-tool.d.ts +0 -77
- package/dist/subagent-tool.d.ts.map +0 -1
- package/dist/subagent-tool.js +0 -559
- package/dist/subagent-tool.js.map +0 -1
- package/docs/guides/sillytavern-import.md +0 -47
- package/docs/reference/subagent-adapter.md +0 -204
- package/examples/sillytavern-dm-writer-prompt-stack.json +0 -190
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Implemented feature inventory
|
|
2
2
|
|
|
3
|
-
This file tracks the currently implemented feature surface for agent profiles, the prompt-stack runtime,
|
|
3
|
+
This file tracks the currently implemented feature surface for agent profiles, the prompt-stack runtime, static stack variables, web editor, storage migration, payload inspector, and regex MVP.
|
|
4
4
|
|
|
5
5
|
## Package and Runtime
|
|
6
6
|
|
|
@@ -33,31 +33,16 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
33
33
|
- Project trust gates profile loading, application, and writes.
|
|
34
34
|
- Shared typed profile services own capture, protected write/update/delete, application/rollback, immutable preview data, provenance changes, and runtime-drift calculation so command, web-editor, and adapter consumers do not duplicate behavior.
|
|
35
35
|
|
|
36
|
-
## Subagent
|
|
36
|
+
## Subagent Host Port
|
|
37
37
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
38
|
+
- Experimental versioned `@zihanw/pi-forge/subagent` entry point: the minimal Forge DTO host contract (wire messages, recursive exact-field validators, transport-neutral `ForgeHostTransport`, `ForgeHost`/`ForgeHostClient` lifecycle) plus Forge-owned canonical `sha256:v1` fingerprint helpers byte-compatible with the runtime's canonical JSON.
|
|
39
|
+
- Mandatory lifecycle semantics: bounded discovery timeouts, explicit duplicate-host failure, `hostId`+`generation`-bound request/reply with stale/foreign rejection, disposal with `unavailable` and full listener cleanup. The host starts only after the first workspace snapshot exists, so an advertised host implies a loaded workspace; reload honors project trust (untrusted workspaces expose global resources only).
|
|
40
|
+
- Three minimal operations: `listProfiles` (loaded profile summaries with diagnostics), `resolveProfile` (immutable host-owned profile snapshot artifact with content fingerprints), and `prepare` (host-owned prompt compilation).
|
|
41
|
+
- Host-owned preparation: the client sends only a profile selector, the task text, prompt-compilation access facts (`level`/`network`/`allowProcess`), and backend facts (model, thinking level, tool catalog). The workspace resolves the profile and stack from its snapshot, filters the tool catalog through stack policy and access facts, and compiles through the same compilation context as runtime and preview. Responses return the system prompt, messages ending with the protected delegated task, effective tool IDs/names, diagnostics, the profile snapshot, and `preparedAt`.
|
|
42
|
+
- The port never exposes live contexts, internal registries, or execution/runtime material (access workspace model, limits, `resultProjection`, `parent`, `remoteEgressConsent`, base system prompt). The delegated-task base system prompt is host-owned and intentionally empty; the prompt stack composes the system prompt.
|
|
41
43
|
- Backend-independent host profile resolution produces path-free declarative snapshots and does not consult the parent model registry or authentication state.
|
|
42
44
|
- Host dependency scanning detects custom macro and slot references, records registration source identities, and fails resolution when required registrations are missing.
|
|
43
|
-
-
|
|
44
|
-
- Optional empty-by-default backend registry validates registration and preflight identity, requires the backend to supply a complete fingerprinted prompt runtime, binds the exact host preparation to execution, routes dry-plan discard, rejects unbound or refingerprinted substitute plans, arbitrates cancellation and host timeouts, normalizes failures, and protects opaque trace routing behind authorization-scoped handles.
|
|
45
|
-
- Experimental `pi-subprocess-readonly` backend reuses the host Pi runtime for authenticated preparation, then runs a clean foreground Pi subprocess with the exact profile model, thinking level, and compiled prompt. Its candidate model tools are limited to `read`, `grep`, `find`, and `ls`, further filtered by prompt-stack policy; it loads no write/shell tools, skills, prompt templates, context files, or third-party extensions. Host-coupled capability mismatches fail closed during preflight.
|
|
46
|
-
- Delegation is an explicit per-profile opt-in under the trusted project's `subagents.profiles`; ordinary profile loading/application remains independent. Global profile entries warn and are ignored so project-local profile IDs cannot silently authorize unrelated projects. Disabled and unlisted profiles are omitted from `forge_subagent_profiles` and rejected before preparation by the command, model-callable tool, and concrete runtime.
|
|
47
|
-
- The no-egress `forge_subagent_profiles` tool gives the main agent a live catalog of enabled profile IDs, names, descriptions, model/thinking/stack metadata, effective backend/timeout and sources, and ready/unavailable resolution status. It also reports whether the parent tool policy currently permits `forge_subagent`.
|
|
48
|
-
- `subagents.summaryInToolDescription` (default `false`) embeds a compact, bounded summary of enabled profiles directly in the `forge_subagent` tool description, so the main agent can pick a frequently used profile without a discovery call. Ready profiles sort first, unavailable enabled profiles include their first resolution error, and the summary is capped at 8 profiles and 1,000 characters. It refreshes whenever profiles, stacks, or configuration change and keeps `forge_subagent_profiles` as the authoritative full-detail surface.
|
|
49
|
-
- The model-callable `forge_subagent` tool and `/forge-agent run` prepare an immutable plan before provider transport. `/forge-agent run` and the default tool path require explicit human approval; a trusted-project `subagents.allowAgentInvocationWithoutApproval` option may authorize only the model-callable tool without a per-run prompt. The default review shows the task, profile/stack, provider/model/thinking level, effective tools, working directory, shared-user boundary, payload size, and fingerprint; the complete provider-bound prompt can be opened on demand.
|
|
50
|
-
- Backend selection is layered configuration rather than profile schema: `subagents.backend` supplies global/project defaults, the trusted project's `subagents.profiles.<id>.backend` supplies a per-profile override, and `/forge-agent plan|run --backend <id>` or the interactive `forge_subagent` `backend` parameter overrides one run. Both the `pi-subprocess-readonly` and `pi-rpc-readonly` backends are registered; there is no fallback when the selected backend is unavailable, and unattended tool invocation is pinned to the effective configured profile backend.
|
|
51
|
-
- Foreground timeout is layered host configuration rather than profile schema: `subagents.timeoutMs` supplies a 60,000-millisecond default and `subagents.profiles.<id>.timeoutMs` can override it per profile; values must be from 1,000 through 3,600,000 milliseconds. Invalid values warn and preserve the preceding valid/default value; discovery, planning, and approval surfaces show the effective best-effort timeout and source.
|
|
52
|
-
- Foreground progress and the bounded final report enter the normal tool-call result. A dedicated child report channel retains the normalized response, complete text transcript, tool calls/results, diagnostics, usage, approval receipt, and execution report without persisting the full prompt or inline image data; omitted images retain MIME and encoded-size metadata.
|
|
53
|
-
- The subprocess backend is explicitly shared-user rather than OS-sandboxed: read-only is a tool policy, host timeout/cancellation are best effort, and `/tree` reverts conversation state rather than provider egress, billing, or external side effects.
|
|
54
|
-
- `/forge-agent backends` and `/forge-agent plan <profile> <task>` expose backend discovery and provider-free exact dry planning to a human.
|
|
55
|
-
- Deterministic fake-backend conformance coverage exercises accepted/rejected preflight, tool effects, access/limit refusal, exact preparation, success/failure, cancellation races, timeout, media, artifacts, and traces. An offline faux-provider test additionally executes the concrete SDK backend through a real Pi `AgentSession` without network traffic.
|
|
56
|
-
- Selected parent context uses explicit provenance and deterministic exact UTF-8 budgeting; required items survive, optional items are selected newest-first, and the complete delegated text/media task remains the protected final user message.
|
|
57
|
-
- Granular validators cover request access/depth/media/limits, backend capabilities and enforcement, prompt-runtime fidelity, plan correlation, all response terminal statuses, usage units, artifact namespaces/paths, and authorized trace handles.
|
|
58
|
-
- Portable profile, prompt-stack, and complete execution fingerprints use canonical `sha256:v1` serialization without changing legacy branch-provenance fingerprints.
|
|
59
|
-
- The opt-in internal Pi SDK spike remains available for broader live diagnostics, including media and trusted custom registrations beyond the shipped text-only walking skeleton.
|
|
60
|
-
- Adapter responsibilities and unsupported runner behavior are documented in the [subagent adapter contract](subagent-adapter.md).
|
|
45
|
+
- Execution ownership (delegation authorization in `subagents.json`, the 0.4 execution contract, backend preflight/plan sealing via `@zihanw/pi-subagent-runtime`, approval UX, `forge_subagent`/`forge_subagent_profiles`, and `/forge-agent`) lives in the optional `@zihanw/pi-forge-subagents` package, which consumes this port and never imports main-package internals. See the [subagent host port contract](subagent-host-port.md).
|
|
61
46
|
|
|
62
47
|
## Prompt Stack Loading and Storage
|
|
63
48
|
|
|
@@ -70,7 +55,6 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
70
55
|
- `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]` copies legacy stacks into the forge storage location.
|
|
71
56
|
- `default.json` auto-activation unless `autoActivate` is `false`.
|
|
72
57
|
- Branch-aware persisted active stack restore from session entries.
|
|
73
|
-
- Branch-aware macro session variable restore when navigating the session tree.
|
|
74
58
|
- Persisted `/preset use none` / `off` opt-out.
|
|
75
59
|
- Invalid stacks with error diagnostics are skipped by automatic selection.
|
|
76
60
|
- Raw stack fields are shape-checked before recovery normalization, including behavior-changing booleans/enums, defaults, context, variables, and item fields.
|
|
@@ -105,7 +89,7 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
105
89
|
- `effect: "outgoing"` is active for model-bound prompt text.
|
|
106
90
|
- `effect: "finalize"` is active for completed assistant messages at `stage: "compiled"` / `targets: ["messages"]`.
|
|
107
91
|
- `effect: "finalize"` is destructive: it replaces the finalized assistant message in Pi's stored transcript, so the original model output is not preserved.
|
|
108
|
-
- `effect: "
|
|
92
|
+
- `effect: "outgoing"` and `"finalize"` are the only valid effects; `"display"` and `"both"` are rejected during validation.
|
|
109
93
|
- Streaming display is not transformed; raw text may be visible until the final message replacement happens.
|
|
110
94
|
- Message transforms support role filters, `maxMessages`, `maxChars`, `minDepth`, `maxDepth`, and `trimStrings`. `$0` is supported as a full-match alias for `$&` in replacements.
|
|
111
95
|
- Compiled-stage transforms support `targets: ["system"]`, `["messages"]`, or both.
|
|
@@ -125,7 +109,6 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
125
109
|
- `date-cwd`
|
|
126
110
|
- `active-model`
|
|
127
111
|
- `pi-docs`
|
|
128
|
-
- `variables`
|
|
129
112
|
- `date` and `date-cwd` slots can include `Current time: HH:MM:SS` with `includeTime: true`.
|
|
130
113
|
- Runtime slots are registered through the same `registerSlot` definition interface used by trusted custom slots.
|
|
131
114
|
- Trusted `~/.pi/forge/extensions` / `.pi/forge/extensions` modules and reusable Pi packages can register additional runtime slots through `registerSlot`, with declarative option schemas and shared render helpers.
|
|
@@ -139,36 +122,29 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
139
122
|
- Tool policy is enforced with `pi.setActiveTools()` and restored when prompt stacks are disabled or switched to an unrestricted stack.
|
|
140
123
|
- Tool policy preserves later extension tool additions in the restorable baseline while keeping them filtered from an active restrictive stack.
|
|
141
124
|
- A `tool_call` guard blocks tools outside the active stack policy even if another extension later changes Pi's active tool list.
|
|
142
|
-
- Rendered `tools` slots,
|
|
125
|
+
- Rendered `tools` slots, template paths such as `{{ runtime.selectedToolsText }}`, and `tool-guidelines` respect stack tool policy.
|
|
143
126
|
- Rendered `skills` slots respect stack skill policy and continue to hide skills marked `disableModelInvocation`.
|
|
144
127
|
- Skill policy controls model-visible skill listings rendered by pi-forge; it does not disable explicit skill invocation and is not a security boundary.
|
|
145
128
|
- Validation warns when skill policy is used with `append` or `prepend` mode because Pi's base prompt may already include unfiltered skills.
|
|
146
129
|
|
|
147
|
-
## Macros
|
|
130
|
+
## Macros (forge-v1)
|
|
148
131
|
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
-
|
|
158
|
-
- Turn variable mutation through `{{setvar::name::value}}`, `{{setturnvar::name::value}}`, and `{{clearvar::name}}`.
|
|
159
|
-
- Session variable mutation through `{{setsessionvar::name::value}}`, `{{setvar::session::name::value}}`, and `{{clearsessionvar::name}}`.
|
|
160
|
-
- Unknown macro diagnostics with configurable keep/warn/error policy.
|
|
161
|
-
- Non-string variable values stringify as JSON during macro substitution.
|
|
132
|
+
- Prompt text is compiled with the closed `forge-v1` template engine (parse → analyze → render).
|
|
133
|
+
- Runtime facts resolve through `{{ runtime.* }}` (cwd, date, time, lastUserMessage, selectedToolsText, activeModel, tool/slot booleans).
|
|
134
|
+
- Static values resolve through `{{ parameters.* }}`; schema v2 stores them in `parameters` while v1 stacks read legacy `variables`.
|
|
135
|
+
- Custom macros resolve through `{{ extensions.<name> }}` and are registered via the pure `registerMacro` extension port with declared dependencies and bounded output.
|
|
136
|
+
- Filters: `trim`, `upper`, `lower`, `json`, `xml`, composed with `|` pipelines.
|
|
137
|
+
- Conditionals: `{% if path %}...{% else %}...{% endif %}` with `==` / `!=` string comparisons over template paths.
|
|
138
|
+
- Undefined paths, unknown filters, parse errors, cycles, and output-limit breaches are compile errors; a failing block is omitted rather than re-injected.
|
|
139
|
+
- Legacy v1 stacks keep a bare-name compatibility fallback (`{{name}}`, `{{lastUserMessage}}`, `{{date}}`, ...) that maps to the corresponding parameter/runtime path.
|
|
140
|
+
- `getRegisteredMacros()` and `getRegisteredSlots()` expose active definitions for inspection.
|
|
162
141
|
|
|
163
|
-
##
|
|
142
|
+
## Parameters
|
|
164
143
|
|
|
165
|
-
-
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
- XML variable entries rendered as `<var name="...">...</var>`.
|
|
170
|
-
- Optional `format: "plain"` variables slot rendering.
|
|
171
|
-
- Scope toggles with `includeStatic`, `includeSession`, and `includeTurn`.
|
|
144
|
+
- Schema v2 stacks store immutable JSON-compatible values in top-level `parameters`.
|
|
145
|
+
- Schema v1 / unversioned stacks read the legacy string-only `variables` field and support bare `{{name}}` fallback.
|
|
146
|
+
- Parameters resolve through `{{ parameters.<name> }}` and are available to trusted custom macros/slots through the frozen environment.
|
|
147
|
+
- Mutable turn/session stores, variable mutation macros, session variable entries, and the `variables` slot are removed in 0.5.0.
|
|
172
148
|
|
|
173
149
|
## Commands
|
|
174
150
|
|
|
@@ -180,9 +156,9 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
180
156
|
- `/profile validate [id]`
|
|
181
157
|
- `/profile reload`
|
|
182
158
|
- `/profile forget`
|
|
183
|
-
- `/forge-agent backends`
|
|
184
|
-
- `/forge-agent plan <profile> <task>`
|
|
185
|
-
- `/forge-agent run <profile> <task>`
|
|
159
|
+
- `/forge-agent backends` (optional `@zihanw/pi-forge-subagents` package)
|
|
160
|
+
- `/forge-agent plan <profile> <task>` (optional package)
|
|
161
|
+
- `/forge-agent run <profile> <task>` (optional package)
|
|
186
162
|
- `/preset list`
|
|
187
163
|
- `/preset status`
|
|
188
164
|
- `/preset use <id|none>`
|
|
@@ -192,29 +168,9 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
192
168
|
- `/preset reload`
|
|
193
169
|
- `/preset ui [stop|restart]`
|
|
194
170
|
- `/preset migrate-stacks [--dry-run] [--overwrite] [--delete-legacy]`
|
|
195
|
-
- `/preset import-silly <path> [character_id] [--dry-run] [--overwrite]`
|
|
196
171
|
- `/intercept`
|
|
197
172
|
- `/payload next [save=<path>]`
|
|
198
173
|
|
|
199
|
-
## SillyTavern Import
|
|
200
|
-
|
|
201
|
-
- Import SillyTavern preset JSON into `.pi/forge/prompt-stacks/<id>.json`.
|
|
202
|
-
- Generate import reports under `.pi/forge/import-reports/<id>.md`.
|
|
203
|
-
- Select a specific `character_id` when multiple prompt orders exist.
|
|
204
|
-
- Protect existing generated stack/report files from accidental overwrite, with confirmation or `--overwrite`.
|
|
205
|
-
- Preview generated output without writing files via `--dry-run`.
|
|
206
|
-
- Convert prompt order into prompt stack items.
|
|
207
|
-
- Preserve original SillyTavern identifiers in item source metadata.
|
|
208
|
-
- Convert `chatHistory` marker to a movable `chat-history` slot.
|
|
209
|
-
- Skip unsupported SillyTavern marker items and report omissions.
|
|
210
|
-
- Detect `{{lastUserMessage}}` and configure chat history accordingly.
|
|
211
|
-
- Strip SillyTavern comments and `{{trim}}` markers.
|
|
212
|
-
- Report macros that need manual migration, including normalized camelCase SillyTavern macro names.
|
|
213
|
-
- Report supported SillyTavern-style variable macros such as `setvar` and `getvar` as handled by pi-forge.
|
|
214
|
-
- Report SillyTavern `extensions.regex_scripts` counts, prompt/display classification, script names, and migration notes.
|
|
215
|
-
- Convert safe SillyTavern `promptOnly` regex scripts into pi-forge `regex.rules` with `stage: "history"`, `effect: "outgoing"`, JavaScript replacement syntax, trim strings, depth limits, clear placement role mappings, and preserved `source.sillytavern` metadata. History-stage depth is relative to the filtered chat history, matching SillyTavern's chat-relative depth.
|
|
216
|
-
- Leave SillyTavern display-only, mixed prompt/display, DOM/browser, CSS/HTML decoration, JavaScript, unsupported-placement, unsupported-flag, and invalid regex scripts as report-only migration notes.
|
|
217
|
-
|
|
218
174
|
## Debugging and Tests
|
|
219
175
|
|
|
220
176
|
- `/intercept` displays the next provider payload with redaction/truncation for secrets and large data.
|
|
@@ -223,10 +179,9 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
223
179
|
- The web editor can arm, poll, clear, and inspect the next redacted provider payload in a full-screen collapsible JSON inspector.
|
|
224
180
|
- Runtime compile diagnostics are visible through a footer status and `/preset diagnostics`.
|
|
225
181
|
- `/preset ui` starts a token-protected localhost web editor for stack management.
|
|
226
|
-
- Node built-in tests cover agent-profile resolution/application/provenance, compiler, loader,
|
|
227
|
-
- Tests cover variable rendering, XML escaping, macro persistence, and typed macro stringification.
|
|
182
|
+
- Node built-in tests cover agent-profile resolution/application/provenance, compiler, loader, regex, and the command/event harness.
|
|
228
183
|
- Tests cover regex validation, history-stage transforms, compiled-stage transforms, finalize transforms, replacement syntax, trim strings, depth limits, role/message/char limits, and preservation of non-text message parts.
|
|
229
|
-
- Tests cover subagent host resolution, custom dependency detection,
|
|
184
|
+
- Tests cover subagent host resolution, custom dependency detection, effect-aware tool negotiation, golden canonical fingerprint vectors, and malformed host-port wire values. Execution-contract matrices (access/required-limit/terminal-status, context budgeting, protected media tasks) moved to the optional package's contract tests.
|
|
230
185
|
- A real headless-Chrome smoke test covers editor load, dirty state, metadata editing, policy and regex editing, validation, save, disk persistence, export, import, and browser-console errors.
|
|
231
186
|
- TypeScript strict typecheck passes.
|
|
232
187
|
- Package dry-run verifies published tarball contents.
|
|
@@ -265,16 +220,15 @@ This file tracks the currently implemented feature surface for agent profiles, t
|
|
|
265
220
|
- Save existing stack JSON and immediately reload pi-forge stack data.
|
|
266
221
|
- Save rejects attempts to change an existing stack ID before writing or changing active selection.
|
|
267
222
|
- Keyboard shortcuts for new stack, save, validate, preview, and closing dialogs/inspectors.
|
|
268
|
-
- Import native stack JSON
|
|
269
|
-
- Show the SillyTavern import report in the web editor after import, with copy support.
|
|
223
|
+
- Import native pi-forge stack JSON into `.pi/forge/prompt-stacks`.
|
|
270
224
|
- Export the current edited stack JSON from the browser, with clipboard fallback when download is unavailable.
|
|
271
225
|
- Fork the current stack into a new stack file, with optional activation.
|
|
272
226
|
- Delete stack files, disabling prompt-stack replacement if the deleted stack was active.
|
|
273
227
|
- Trust and path guardrails for save/import/fork/delete writes.
|
|
274
228
|
- Top-level navigation between prompt stacks and project agent profiles; stack drafts, selection, and active state survive surface switches.
|
|
275
|
-
- Profile list shows ID, name, model/thinking/stack targets, validation state, `autoActivate` and last-applied badges
|
|
229
|
+
- Profile list shows ID, name, model/thinking/stack targets, validation state, and `autoActivate` and last-applied badges.
|
|
276
230
|
- 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.
|
|
277
231
|
- Profile form populates provider/model choices from the model registry and stack choices from the shared stack repository, and shows resolution diagnostics for missing models, authentication, unsupported thinking levels, invalid stacks, and unmatched tool policy.
|
|
278
232
|
- 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.
|
|
279
|
-
-
|
|
280
|
-
- Smoke tests cover editor server token checks, bundled page/script markers, save, payload arm/capture/clear, create/fork,
|
|
233
|
+
- 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`.
|
|
234
|
+
- 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.
|
|
@@ -1,56 +1,59 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Forge-v1 templates and runtime slots
|
|
2
2
|
|
|
3
3
|
[Documentation](../README.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Prompt text is compiled with the `forge-v1` engine: one closed grammar with no
|
|
6
|
+
includes, loops, function calls, or arbitrary expressions. Preview, runtime,
|
|
7
|
+
and subagent preparation use the same engine entry.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|---|---|
|
|
9
|
-
| `{{lastUserMessage}}` | Latest user message |
|
|
10
|
-
| `{{date}}` | Current date as `YYYY-MM-DD` |
|
|
11
|
-
| `{{time}}` | Current time as `HH:MM:SS` |
|
|
12
|
-
| `{{cwd}}` | Current working directory |
|
|
13
|
-
| `{{tools}}` | Comma-separated selected tool names |
|
|
14
|
-
| `{{selectedTools}}` | Alias of `{{tools}}` |
|
|
15
|
-
| `{{activeModel}}` | Current `provider/model` |
|
|
16
|
-
| `{{name}}` | Turn, session, then static variable lookup |
|
|
17
|
-
| `{{var::name}}` / `{{getvar::name}}` | Explicit scoped-fallback variable lookup |
|
|
18
|
-
| `{{getturnvar::name}}` | Turn-only lookup |
|
|
19
|
-
| `{{getsessionvar::name}}` | Session-only lookup |
|
|
20
|
-
|
|
21
|
-
## Variable mutation
|
|
9
|
+
## Template interpolation
|
|
22
10
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{{
|
|
26
|
-
{{
|
|
27
|
-
{{
|
|
28
|
-
{{
|
|
29
|
-
{{
|
|
30
|
-
{{
|
|
31
|
-
|
|
11
|
+
| Syntax | Value |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `{{ runtime.cwd }}` | Current working directory |
|
|
14
|
+
| `{{ runtime.date }}` | Current date as `YYYY-MM-DD` |
|
|
15
|
+
| `{{ runtime.time }}` | Current time as `HH:MM:SS` |
|
|
16
|
+
| `{{ runtime.lastUserMessage }}` | Latest user message |
|
|
17
|
+
| `{{ runtime.selectedToolsText }}` | Comma-separated effective tool names |
|
|
18
|
+
| `{{ runtime.activeModel }}` | Current `provider/model` |
|
|
19
|
+
| `{{ parameters.<name> }}` | Static stack parameter |
|
|
20
|
+
| `{{ extensions.<name> }}` | Registered custom macro value |
|
|
32
21
|
|
|
33
|
-
|
|
22
|
+
Legacy v1 stacks keep a compatibility fallback: bare `{{name}}` resolves to a
|
|
23
|
+
static parameter, `{{lastUserMessage}}`/`{{date}}`/`{{time}}`/`{{cwd}}` resolve
|
|
24
|
+
to the matching `runtime.*` value, and registered custom macros resolve by
|
|
25
|
+
name. New v2 stacks use the explicit `parameters.*` / `runtime.*` paths.
|
|
34
26
|
|
|
35
|
-
## Filters
|
|
27
|
+
## Filters
|
|
36
28
|
|
|
37
|
-
Nested
|
|
29
|
+
Nested pipelines are supported; filters are pure and versioned.
|
|
38
30
|
|
|
39
|
-
|
|
|
31
|
+
| Filter | Result |
|
|
40
32
|
|---|---|
|
|
41
|
-
| `{{trim
|
|
42
|
-
| `{{upper
|
|
43
|
-
| `{{lower
|
|
44
|
-
| `{{json
|
|
45
|
-
| `{{xml
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
33
|
+
| `{{ value \| trim }}` | Trim surrounding whitespace |
|
|
34
|
+
| `{{ value \| upper }}` | Uppercase |
|
|
35
|
+
| `{{ value \| lower }}` | Lowercase |
|
|
36
|
+
| `{{ value \| json }}` | JSON string literal |
|
|
37
|
+
| `{{ value \| xml }}` | XML-escaped |
|
|
38
|
+
|
|
39
|
+
## Conditionals
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
{% if runtime.tool.read %}read is available{% else %}read is unavailable{% endif %}
|
|
43
|
+
{% if parameters.mode == "image-reader" %}image reader{% endif %}
|
|
44
|
+
{% if runtime.tool.bash != null %}bash visible{% endif %}
|
|
45
|
+
```
|
|
50
46
|
|
|
51
|
-
|
|
47
|
+
- `{% if path %}` selects the branch when the path exists and is truthy.
|
|
48
|
+
- `==` / `!=` compare against a quoted string, including empty strings.
|
|
49
|
+
- Nested `{% if %}` blocks are supported.
|
|
50
|
+
- An undefined output path is a strict compile error (no raw fallback); the
|
|
51
|
+
legacy `defaults.unresolvedMacroPolicy` is ignored.
|
|
52
|
+
- `runtime.tool.<name>` and `runtime.slot.<name>` booleans power tool/slot
|
|
53
|
+
conditionals without function calls.
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
When a block fails to parse, analyze, or render, pi-forge emits an error
|
|
56
|
+
diagnostic and omits that block rather than re-injecting raw template text.
|
|
54
57
|
|
|
55
58
|
## Built-in slots
|
|
56
59
|
|
|
@@ -62,21 +65,39 @@ Unknown macro behavior is controlled by stack `defaults.unknownMacro`: keep, war
|
|
|
62
65
|
| `skills` | Model-visible loaded Pi skills |
|
|
63
66
|
| `project-context` | Trusted project instructions/context |
|
|
64
67
|
| `append-system-prompt` | Pi's appended system prompt text |
|
|
65
|
-
| `variables` | Static/session/turn values |
|
|
66
68
|
| `date` | Current date, optionally time |
|
|
67
69
|
| `cwd` | Working directory |
|
|
68
70
|
| `date-cwd` | Date and working directory, optionally time |
|
|
69
71
|
| `active-model` | Selected provider/model |
|
|
70
72
|
| `pi-docs` | Pi documentation guidance |
|
|
71
73
|
|
|
72
|
-
Structured slots (`tools`, `tool-guidelines`, `skills`, `project-context
|
|
73
|
-
|
|
74
|
-
Notable Pi-mirror options include `tools.onlyWithSnippets`, `tool-guidelines.heading`, `tool-guidelines.includePiDefaultGuidelines`, `tool-guidelines.piStyle`, and `skills.requireReadTool`. `date` and `date-cwd` support `includeTime: true`.
|
|
74
|
+
Structured slots (`tools`, `tool-guidelines`, `skills`, `project-context`)
|
|
75
|
+
default to XML-style wrappers and support `"format": "plain"`.
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
## Trusted custom definitions
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
Trusted global/project modules register macros (addressed as
|
|
80
|
+
`{{ extensions.<name> }}`) and slots through the pure extension port:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
api.registerMacro({
|
|
84
|
+
name: "ticketId",
|
|
85
|
+
description: "Current ticket id.",
|
|
86
|
+
dependencies: ["parameters.ticket.id"],
|
|
87
|
+
render: ({ env, helpers }) => String(env.parameters["ticket.id"]),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
api.registerSlot({
|
|
91
|
+
name: "ticket-context",
|
|
92
|
+
description: "Render ticket context.",
|
|
93
|
+
dependencies: ["parameters.ticket.id"],
|
|
94
|
+
options: { heading: { type: "string", default: "Ticket context" } },
|
|
95
|
+
render: ({ item, options, env, helpers }) => "...",
|
|
96
|
+
});
|
|
97
|
+
```
|
|
79
98
|
|
|
80
|
-
|
|
99
|
+
Custom slots receive the same pure `{ item, options, env, helpers }` context and
|
|
100
|
+
declared-dependency resolution as macros, and their output is held to the same
|
|
101
|
+
16,384-character extension limit.
|
|
81
102
|
|
|
82
|
-
|
|
103
|
+
See [custom macros and slots](../guides/custom-macros-and-slots.md).
|
|
@@ -1,28 +1,75 @@
|
|
|
1
1
|
# Public API policy
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[Documentation](../README.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
pi-forge is pre-1.0. This document defines the intentional integration surfaces of the 0.5.0 line.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- Package-root macro and slot registration APIs (`registerMacro`, `registerSlot`, their registry readers, render contexts, and declarative definition types) are supported for trusted reusable extensions.
|
|
9
|
-
- `ForgeExtensionApi` and related registration types are supported for trusted project-local forge extensions.
|
|
7
|
+
## The three intentional entry points
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
`check-package` enforces this allowlist; nothing else is importable from the package.
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
### 1. Package root: extension factory
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
```ts
|
|
14
|
+
import piForge from "@zihanw/pi-forge";
|
|
15
|
+
```
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
The default export is the Pi extension entry point declared by `pi.extensions`. Most users install the package and never import it directly.
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
### 2. Package root: trusted extension API
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
```ts
|
|
22
|
+
import { registerMacro, registerSlot } from "@zihanw/pi-forge";
|
|
23
|
+
import type {
|
|
24
|
+
ForgeExtensionApi,
|
|
25
|
+
ForgeExtensionRegister,
|
|
26
|
+
PromptEnvironment,
|
|
27
|
+
PromptEnvironmentValue,
|
|
28
|
+
PromptExtensionArgumentDefinition,
|
|
29
|
+
PromptExtensionOptionDefinition,
|
|
30
|
+
PromptExtensionOptionsSchema,
|
|
31
|
+
PromptExtensionOptionType,
|
|
32
|
+
PromptMacroDefinition,
|
|
33
|
+
PromptMacroRenderContext,
|
|
34
|
+
PromptMacroRenderer,
|
|
35
|
+
PromptRegistryEntry,
|
|
36
|
+
PromptRenderHelpers,
|
|
37
|
+
PromptSlotDefinition,
|
|
38
|
+
PromptSlotRenderContext,
|
|
39
|
+
PromptSlotRenderer,
|
|
40
|
+
} from "@zihanw/pi-forge";
|
|
41
|
+
```
|
|
27
42
|
|
|
28
|
-
|
|
43
|
+
Supported for trusted reusable and project-local extensions. The contract (pure renderers, declared dependencies, immutable `PromptEnvironment`, bounded output) is specified in the [0.5.0 architecture plan](../design/architecture-0.5.md#extension-port-contract-050) and the [custom macros and slots guide](../guides/custom-macros-and-slots.md).
|
|
44
|
+
|
|
45
|
+
### 3. `@zihanw/pi-forge/subagent`: versioned host port
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import {
|
|
49
|
+
ForgeHost, ForgeHostClient, ForgeHostPortError,
|
|
50
|
+
FORGE_HOST_CHANNEL, FORGE_HOST_PORT_VERSION, FORGE_HOST_PORT_OPERATIONS,
|
|
51
|
+
validateListProfilesRequest, validateListProfilesResponse,
|
|
52
|
+
validateResolveProfileRequest, validateResolveProfileResponse,
|
|
53
|
+
validatePrepareRequest, validatePrepareResponse,
|
|
54
|
+
canonicalSubagentJson, subagentFingerprint,
|
|
55
|
+
subagentSourceProfileFingerprint, subagentPromptStackFingerprint,
|
|
56
|
+
} from "@zihanw/pi-forge/subagent";
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The experimental host port over the Pi event bus: discovery, profile listing/snapshot, and host-owned prompt preparation with mandatory lifecycle semantics (correlation IDs, payload validation, bounded timeouts, host generation, duplicate-host failure, disposal/`unavailable`, listener cleanup). The wire DTOs and validators are self-contained Forge data contracts; the main package has no dependency on `@zihanw/pi-subagent-runtime`. The canonical `sha256:v1` fingerprint helpers are Forge-owned and byte-compatible with the runtime's canonical JSON.
|
|
60
|
+
|
|
61
|
+
The optional `@zihanw/pi-forge-subagents` package consumes this port and owns subagent execution and configuration.
|
|
62
|
+
|
|
63
|
+
## Compatibility policy
|
|
64
|
+
|
|
65
|
+
- **Stable** surfaces (root factory, macro/slot registration) preserve source compatibility within the documented release range unless a changelog entry announces a breaking release.
|
|
66
|
+
- **Experimental** surfaces (the `/subagent` host port) are typed, tested, and documented, but may change deliberately as integration experience exposes missing semantics.
|
|
67
|
+
- 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`.
|
|
68
|
+
|
|
69
|
+
## Removed in 0.5.0
|
|
70
|
+
|
|
71
|
+
- All `@zihanw/pi-forge/src/*` compatibility aliases and the `./examples/*` subpath export.
|
|
72
|
+
- Root re-exports of loader, agent-profile, profile-service, catalog, resource-identity, render-helper values, the `forge-v1` engine, and registry readers.
|
|
73
|
+
- Root and `/subagent` re-exports of the 0.4 execution contract (`AgentRequest`, `createAgentExecutionPlan`, `validateAgentRequest`, `negotiateSubagentTools`, `resolveSubagentHostProfile`, `prepareSubagentHostPlan`, and friends). The execution contract now belongs to `@zihanw/pi-forge-subagents`.
|
|
74
|
+
|
|
75
|
+
See the [0.5 migration guide](../guides/migrating-to-0.5.md) for the complete breaking-change list.
|
|
@@ -6,7 +6,7 @@ Use [the default Pi mirror](../../examples/default-prompt-stack.json) as the com
|
|
|
6
6
|
|
|
7
7
|
## Top-level shape
|
|
8
8
|
|
|
9
|
-
A stack has a unique `id`, schema/type identity, optional display metadata and auto-activation, a system `mode`, ordered `items`, and optional defaults, variables, context, resource policy, regex, and source metadata.
|
|
9
|
+
A stack has a unique `id`, schema/type identity, optional display metadata and auto-activation, a system `mode`, ordered `items`, and optional defaults, parameters (schema v2) or legacy variables, context, resource policy, regex, and source metadata.
|
|
10
10
|
|
|
11
11
|
Unknown/advanced metadata is preserved by raw editing, but behavior-changing fields are shape-checked and invalid values are not silently normalized into active behavior.
|
|
12
12
|
|
|
@@ -21,7 +21,7 @@ Block:
|
|
|
21
21
|
"name": "Readable label",
|
|
22
22
|
"enabled": true,
|
|
23
23
|
"role": "system",
|
|
24
|
-
"content": "Your text here. Use {{
|
|
24
|
+
"content": "Your text here. Use {{ parameters.role }} / {{ runtime.lastUserMessage }} for dynamic content."
|
|
25
25
|
}
|
|
26
26
|
```
|
|
27
27
|
|
|
@@ -65,7 +65,7 @@ Item IDs must be unique. Unsupported slots and missing required custom registrat
|
|
|
65
65
|
}
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
- Set `includeLastUserMessage: false` when a later block reinserts `{{lastUserMessage}}`.
|
|
68
|
+
- Set `includeLastUserMessage: false` when a later block reinserts `{{ runtime.lastUserMessage }}`.
|
|
69
69
|
- `stripAssistantThinking` removes prior thinking blocks but preserves visible assistant text, tool calls, and results. It does not change the live loop or stored transcript.
|
|
70
70
|
- `includeSummaries: false` excludes branch/compaction summaries.
|
|
71
71
|
- `roles` keeps only selected roles.
|
|
@@ -76,7 +76,7 @@ When filtering would separate a tool call from its result, pi-forge removes dang
|
|
|
76
76
|
|
|
77
77
|
## Structured slots
|
|
78
78
|
|
|
79
|
-
`tools`, `tool-guidelines`, `skills`, `project-context
|
|
79
|
+
`tools`, `tool-guidelines`, `skills`, and `project-context` support `"format": "plain"`; the default is XML-style structure. Date slots support `includeTime: true`.
|
|
80
80
|
|
|
81
81
|
See [macros and slots](macros-and-slots.md) for names and options.
|
|
82
82
|
|
|
@@ -101,13 +101,14 @@ Tool policy changes Pi's active tool list, is reasserted before input/turns, and
|
|
|
101
101
|
|
|
102
102
|
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.
|
|
103
103
|
|
|
104
|
-
##
|
|
104
|
+
## Parameters and schema v2
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
Schema v2 stacks store immutable static values in `parameters` (JSON-compatible):
|
|
107
107
|
|
|
108
108
|
```json
|
|
109
109
|
{
|
|
110
|
-
"
|
|
110
|
+
"schemaVersion": 2,
|
|
111
|
+
"parameters": {
|
|
111
112
|
"char": "Konata",
|
|
112
113
|
"user": "User",
|
|
113
114
|
"style": { "tone": "concise" }
|
|
@@ -115,7 +116,11 @@ Top-level static variables are JSON values:
|
|
|
115
116
|
}
|
|
116
117
|
```
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
Parameters resolve through `{{ parameters.<name> }}` templates and are available
|
|
120
|
+
to trusted custom macros/slots. Unversioned and v1 stacks continue to read the
|
|
121
|
+
legacy `variables` field (string values) and support bare `{{name}}` fallback.
|
|
122
|
+
A stack must not mix `parameters` and `variables` across schema versions. See
|
|
123
|
+
[macro reference](macros-and-slots.md).
|
|
119
124
|
|
|
120
125
|
## Regex transforms
|
|
121
126
|
|
|
@@ -164,4 +169,4 @@ Outgoing rules change future model input. To destructively change a completed as
|
|
|
164
169
|
|
|
165
170
|
> `finalize` runs at `message_end`, after raw output may have streamed. It replaces the stored assistant message, so the original output is not preserved.
|
|
166
171
|
|
|
167
|
-
`effect: "
|
|
172
|
+
`effect: "outgoing"` and `"finalize"` are the only valid effects; `"display"` and `"both"` are rejected during validation. Runtime diagnostics report match and changed-segment counts.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Subagent host port contract
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md)
|
|
4
|
+
|
|
5
|
+
Status: experimental, versioned (`FORGE_HOST_PORT_VERSION = 1`). The `/subagent` entry point is the main package's only subagent surface: a transport-neutral host port over data-only messages. Subagent execution, approval, and configuration live in the optional [`@zihanw/pi-forge-subagents`](https://github.com/MacroSony/pi-forge-subagents) package, which consumes this port and never imports main-package internals.
|
|
6
|
+
|
|
7
|
+
## Ownership boundary
|
|
8
|
+
|
|
9
|
+
- **Main package owns:** prompt-stack/agent-profile storage and validation (repositories + codecs), the immutable `ForgeWorkspace` snapshot, profile/stack resolution, host-owned prompt compilation, and tool filtering through stack policy.
|
|
10
|
+
- **Optional package owns:** delegation authorization (`subagents.json`), the execution contract (request, preflight, plan, response, validators), backend preflight and sealing via `@zihanw/pi-subagent-runtime`, approval UX, and execution.
|
|
11
|
+
- **Never crosses the port:** live contexts, internal registries, execution/runtime material (access workspace model, limits, `resultProjection`, `parent`, `remoteEgressConsent`, a base system prompt). The client sends only a profile selector, the task, prompt-compilation access facts (`level`/`network`/`allowProcess`), and backend facts (model, thinking level, tool catalog).
|
|
12
|
+
|
|
13
|
+
## Transport and lifecycle
|
|
14
|
+
|
|
15
|
+
`ForgeHostTransport` is a minimal `{ emit(channel, data), on(channel, handler) }` interface; the production wiring is `pi.events`. Wire messages are plain JSON-compatible data validated recursively (exact nested fields, typed enums, plain objects only, unknown fields rejected) at both boundaries.
|
|
16
|
+
|
|
17
|
+
Mandatory lifecycle rules:
|
|
18
|
+
|
|
19
|
+
1. Clients subscribe before announcing or discovering, and use bounded timeouts.
|
|
20
|
+
2. A duplicate live host fails explicitly (`host.duplicate`).
|
|
21
|
+
3. `request`/`reply` messages carry `hostId` + `generation`; stale-generation and wrong-host requests are rejected server-side, mismatched replies ignored client-side.
|
|
22
|
+
4. Disposal sends `unavailable` and invalidates connections; all transient and persistent listeners are cleaned up.
|
|
23
|
+
5. The host can only start after the first workspace snapshot exists, so an advertised host implies a loaded workspace. Reload honors project trust: untrusted workspaces expose global resources only.
|
|
24
|
+
|
|
25
|
+
## Operations
|
|
26
|
+
|
|
27
|
+
### Discovery
|
|
28
|
+
|
|
29
|
+
`ForgeHostClient.discover()` / `ForgeHostSession` in the optional package announce on `FORGE_HOST_CHANNEL` and wait for `available` with capabilities.
|
|
30
|
+
|
|
31
|
+
### `listProfiles`
|
|
32
|
+
|
|
33
|
+
Request: `{}`. Response: `{ profiles: ForgeProfileSummary[] }` — each with `profileId`, `scope`, optional `name`/`description`/`autoActivate`, `model`, `thinkingLevel`, `promptStack`, `usable`, and load diagnostics. Read-only; no resolution side effects.
|
|
34
|
+
|
|
35
|
+
### `resolveProfile`
|
|
36
|
+
|
|
37
|
+
Request: `{ profile: string }` — a scoped selector (`reviewer`, `project:reviewer`, `global:reviewer`). Response: `{ snapshot }` — the immutable host-owned profile snapshot artifact: resolved profile and prompt stack JSON, prompt dependency list, and `sha256:v1` content fingerprints (`profileFingerprint`, `promptStackFingerprint`) computed with Forge-owned canonical helpers byte-compatible with the runtime's canonical JSON. The optional package re-validates and re-fingerprints the snapshot before binding it into execution plans.
|
|
38
|
+
|
|
39
|
+
### `prepare`
|
|
40
|
+
|
|
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
|
+
|
|
43
|
+
## Fingerprints
|
|
44
|
+
|
|
45
|
+
`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.
|
|
46
|
+
|
|
47
|
+
## Errors
|
|
48
|
+
|
|
49
|
+
`ForgeHostPortError` carries `code: "timeout" | "duplicate" | "unavailable" | "protocol" | "invalid"`. Operation-level failures return `{ ok: false, error }` results rather than throwing across the bus.
|