@zihanw/pi-forge 0.4.1 → 0.5.1
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 +79 -1
- package/README.md +12 -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/context-diff-history.d.ts +61 -0
- package/dist/context-diff-history.d.ts.map +1 -0
- package/dist/context-diff-history.js +84 -0
- package/dist/context-diff-history.js.map +1 -0
- package/dist/context-diff-snapshot.d.ts +19 -0
- package/dist/context-diff-snapshot.d.ts.map +1 -0
- package/dist/context-diff-snapshot.js +146 -0
- package/dist/context-diff-snapshot.js.map +1 -0
- package/dist/context-diff.d.ts +70 -0
- package/dist/context-diff.d.ts.map +1 -0
- package/dist/context-diff.js +259 -0
- package/dist/context-diff.js.map +1 -0
- 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 +54 -83
- package/dist/index.js.map +1 -1
- package/dist/lifecycle.d.ts +8 -5
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +45 -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-capture.d.ts +10 -0
- package/dist/payload-capture.d.ts.map +1 -1
- package/dist/payload-capture.js +39 -9
- package/dist/payload-capture.js.map +1 -1
- package/dist/payload-command.d.ts +8 -6
- package/dist/payload-command.d.ts.map +1 -1
- package/dist/payload-command.js +36 -6
- package/dist/payload-command.js.map +1 -1
- package/dist/payload-state.d.ts +19 -0
- package/dist/payload-state.d.ts.map +1 -0
- package/dist/payload-state.js +19 -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 +34 -11
- 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 +16 -6
- package/dist/runtime/tool-policy-runtime.js.map +1 -1
- package/dist/runtime/web-editor-runtime.d.ts +2 -1
- package/dist/runtime/web-editor-runtime.d.ts.map +1 -1
- package/dist/runtime/web-editor-runtime.js +8 -3
- package/dist/runtime/web-editor-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/ui-contribution/contrib-port.d.ts +170 -0
- package/dist/ui-contribution/contrib-port.d.ts.map +1 -0
- package/dist/ui-contribution/contrib-port.js +640 -0
- package/dist/ui-contribution/contrib-port.js.map +1 -0
- package/dist/ui-contribution/index.d.ts +3 -0
- package/dist/ui-contribution/index.d.ts.map +1 -0
- package/dist/ui-contribution/index.js +2 -0
- package/dist/ui-contribution/index.js.map +1 -0
- 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/contrib-service.d.ts +41 -0
- package/dist/web-editor/contrib-service.d.ts.map +1 -0
- package/dist/web-editor/contrib-service.js +174 -0
- package/dist/web-editor/contrib-service.js.map +1 -0
- package/dist/web-editor/line-diff.d.ts +28 -0
- package/dist/web-editor/line-diff.d.ts.map +1 -0
- package/dist/web-editor/line-diff.js +216 -0
- package/dist/web-editor/line-diff.js.map +1 -0
- package/dist/web-editor/schema-form.d.ts +63 -0
- package/dist/web-editor/schema-form.d.ts.map +1 -0
- package/dist/web-editor/schema-form.js +213 -0
- package/dist/web-editor/schema-form.js.map +1 -0
- package/dist/web-editor/server.d.ts.map +1 -1
- package/dist/web-editor/server.js +72 -74
- 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 +201 -21
- package/dist/web-editor/styles.js.map +1 -1
- package/dist/web-editor/types.d.ts +12 -35
- package/dist/web-editor/types.d.ts.map +1 -1
- package/dist/web-host.d.ts +6 -2
- package/dist/web-host.d.ts.map +1 -1
- package/dist/web-host.js +33 -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 +7 -4
- package/docs/concepts/agent-profiles.md +1 -1
- package/docs/concepts/prompt-stacks.md +5 -5
- package/docs/design/0.5.1-plan.md +237 -0
- package/docs/design/README.md +21 -3
- package/docs/design/architecture-0.5.md +222 -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 +78 -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/release.md +7 -1
- 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 +6 -10
- 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 +76 -17
- package/docs/reference/stack-schema.md +15 -10
- package/docs/reference/subagent-host-port.md +49 -0
- package/docs/reference/ui-contribution-port.md +51 -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 +5 -5
- 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 +106 -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,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,87 @@
|
|
|
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 four 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
|
+
### 4. `@zihanw/pi-forge/ui-contribution`: versioned settings port
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import {
|
|
67
|
+
UiContributionProvider,
|
|
68
|
+
UiContributionClient,
|
|
69
|
+
UI_CONTRIBUTION_PORT_VERSION,
|
|
70
|
+
} from "@zihanw/pi-forge/ui-contribution";
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
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
|
+
|
|
75
|
+
## Compatibility policy
|
|
76
|
+
|
|
77
|
+
- **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` and `/ui-contribution` ports) are typed, tested, and documented, but may change deliberately as integration experience exposes missing semantics.
|
|
79
|
+
- 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
|
+
|
|
81
|
+
## Removed in 0.5.0
|
|
82
|
+
|
|
83
|
+
- All `@zihanw/pi-forge/src/*` compatibility aliases and the `./examples/*` subpath export.
|
|
84
|
+
- Root re-exports of loader, agent-profile, profile-service, catalog, resource-identity, render-helper values, the `forge-v1` engine, and registry readers.
|
|
85
|
+
- 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`.
|
|
86
|
+
|
|
87
|
+
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
|
|
|
@@ -95,19 +95,20 @@ Patterns are exact by default and support `*` wildcards:
|
|
|
95
95
|
}
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
Each resource may have a non-empty `allow` list or `deny` list, never both.
|
|
98
|
+
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.
|
|
99
99
|
|
|
100
100
|
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.
|
|
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.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# UI contribution port contract
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md)
|
|
4
|
+
|
|
5
|
+
Status: experimental, versioned (`UI_CONTRIBUTION_PORT_VERSION = 1`). The `@zihanw/pi-forge/ui-contribution` entry point is the generic cross-extension port that lets optional packages contribute schema-driven pages to the pi-forge web editor's top-level **Settings** surface. The forge side knows nothing about specific providers; the first consumer is [`@zihanw/pi-forge-subagents`](https://github.com/MacroSony/pi-forge-subagents), which contributes its Subagent Settings page when installed.
|
|
6
|
+
|
|
7
|
+
## Ownership boundary
|
|
8
|
+
|
|
9
|
+
- **The contributing package owns** its tab's form schema, current values, server-side validation on write, and persistence (for example, the subagent package owns `subagents.json`). It implements the provider side of the port.
|
|
10
|
+
- **pi-forge owns** provider discovery over the bus, rendering contributed pages through the generic schema-form renderer, and proxying browser writes back over the bus through the web server routes. It never interprets or stores contributed configuration itself. Contributed pages are not stack tabs and never mount in the stack Preview dock.
|
|
11
|
+
- **Never crosses the port:** functions, components, live contexts, internal registries, or any non-JSON-compatible value. All payloads are plain recursively validated JSON. The port is not a trust boundary — providers must re-validate everything they receive and never trust the web client.
|
|
12
|
+
|
|
13
|
+
## Transport and lifecycle
|
|
14
|
+
|
|
15
|
+
`UiContributionTransport` is a minimal `{ emit(channel, data), on(channel, handler) }` interface; the production wiring is `pi.events`. Messages travel on the dedicated `@zihanw/pi-forge/ui-contribution/v1` channel namespace with its own version counter, separate from the `/subagent` host port. Wire messages are plain JSON-compatible data validated recursively at both boundaries (exact field sets, typed enums, plain objects only, unknown fields rejected).
|
|
16
|
+
|
|
17
|
+
Channels: `discover`, `available`, `request`, `reply`, `unavailable`.
|
|
18
|
+
|
|
19
|
+
Lifecycle rules:
|
|
20
|
+
|
|
21
|
+
1. Version negotiation: `discover` carries `protocolVersion` plus a supported `minVersion`/`maxVersion` range; a compatible provider answers `available` with its own `protocolVersion`, range, `capabilities`, `hostId`, and `generation`.
|
|
22
|
+
2. A second compatible provider fails discovery explicitly (`duplicate`).
|
|
23
|
+
3. `request`/`reply` messages carry `requestId` + `hostId` + `generation`; stale-generation and wrong-host requests are rejected server-side, mismatched replies ignored client-side.
|
|
24
|
+
4. Provider disposal sends `unavailable`. The web editor clears that provider's contributed Settings pages and re-discovers when a provider reappears across sessions; late-surfacing providers are picked up without a page reload path change. The local HTTP listing also carries a forge-owned monotonic, opaque provider-session key so a fast restart refreshes a still-visible form even when browser polling never observes the empty interval. Browser PUT handling binds each response to the session that received it; a delayed success from an older session cannot mark or overwrite the newer session and the preserved draft is retried instead.
|
|
25
|
+
5. Operation handlers may return a result or a promise of one and must never throw across the bus; rejected promises and thrown failures are converted to `{ ok: false, error }` results. Each invocation receives `{ signal, generation }`; stopping the provider aborts the signal. Handlers that await before persistence must check it before side effects. Replies from a stopped generation are discarded as a final transport guard.
|
|
26
|
+
|
|
27
|
+
The Settings host keeps the first descriptor for each `tabId`; later duplicates are ignored. Browser button IDs use a Settings-specific prefix and cannot collide with built-in stack tabs. Providers should still emit unique stable `tabId` values because `writeValues` routes by that identifier. In-progress drafts and save status are tracked per tab, so switching between contributed pages does not discard a pending edit or leak its status into another page.
|
|
28
|
+
|
|
29
|
+
## Operations
|
|
30
|
+
|
|
31
|
+
### Discovery
|
|
32
|
+
|
|
33
|
+
The web host acts as the client: `UiContributionClient.discover()` announces on the channel namespace and waits (bounded timeout) for an `available` announcement. Discovered tab descriptors are fetched at page load through `GET /api/contrib`.
|
|
34
|
+
|
|
35
|
+
### `listContributions`
|
|
36
|
+
|
|
37
|
+
Request: `{}`. Response: `{ tabs: UiContributionTabDescriptor[] }` — each descriptor carries `tabId`, `title`, `icon`, a `FormSchema`, and the current `values`. Read-only; listing a tab contributes it to the editor but performs no other side effect. Every HTTP `GET /api/contrib` refreshes this operation, so providers may update plain-data option catalogs without restarting their session.
|
|
38
|
+
|
|
39
|
+
### `writeValues`
|
|
40
|
+
|
|
41
|
+
Request: `{ tabId, patch }` — a partial values patch for one contributed tab. Omitted top-level fields preserve their stored values. A supplied `record` field is the complete keyed table produced by the form, so omitted rows represent deletion. The provider merges those semantics over its current values, re-validates server-side, and persists the result to its own storage. Response: `{ ok: true, values? }` with the canonical stored values, or `{ ok: false, errors }` with per-field error strings keyed by field key (dotted paths for record rows). The web server exposes this as `PUT /api/contrib/<tabId>` and rejects malformed or oversized request bodies with 400/413 before any bus call.
|
|
42
|
+
|
|
43
|
+
The browser serializes autosave requests. If the form changes while a PUT is in flight, the latest complete normalized snapshot is queued and written only after the current request settles. This ordering prevents older provider writes from landing after newer ones.
|
|
44
|
+
|
|
45
|
+
## Form schema
|
|
46
|
+
|
|
47
|
+
v1 field types are deliberately restricted: `boolean`, `number`, `enum`, `string`, and `record` (a keyed table of entries — for example per-profile settings). Fields carry `key`, `label`, optional `description`/`required`/`default`, enum `options` (plain strings or `{ value, label }`), numeric `min`/`max`, string `maxLength`/`pattern`/`placeholder`, and record sub-fields (`recordFields`, `keyLabel`, `keyPlaceholder`). A record may also provide `keyOptions` (the same string-or-labelled-option shape as enum options); the generic renderer then uses a selector for row identity and prevents choosing a key already used by another row. Providers remain responsible for refreshing those plain-data options and validating them again on write.
|
|
48
|
+
|
|
49
|
+
## Errors
|
|
50
|
+
|
|
51
|
+
`UiContributionPortError` carries `code: "timeout" | "duplicate" | "unavailable" | "protocol" | "invalid"`. Operation-level failures return `{ ok: false, error }` results rather than throwing across the bus.
|
package/docs/zh-CN/README.md
CHANGED
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
## 指南
|
|
12
12
|
|
|
13
13
|
- [Web 编辑器](guides/web-editor.md)
|
|
14
|
+
- [迁移到 0.5](guides/migrating-to-0.5.md)
|
|
14
15
|
- [实验性前台 delegation](guides/delegation.md):启用前请先阅读安全边界。
|
|
15
16
|
- [Prompt stack 使用场景(英文)](../guides/use-cases.md)
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
自定义 macros/slots 和调试的完整说明目前以英文版为准:
|
|
18
19
|
|
|
19
|
-
- [SillyTavern import](../guides/sillytavern-import.md)
|
|
20
20
|
- [Custom macros and slots](../guides/custom-macros-and-slots.md)
|
|
21
21
|
- [Prompt and payload debugging](../guides/debugging.md)
|
|
22
22
|
|
|
@@ -27,7 +27,7 @@ SillyTavern 导入、自定义 macros/slots 和调试的完整说明目前以英
|
|
|
27
27
|
- [Macros 与 slots(英文)](../reference/macros-and-slots.md)
|
|
28
28
|
- [配置(英文)](../reference/configuration.md)
|
|
29
29
|
- [Public API(英文)](../reference/public-api.md)
|
|
30
|
-
- [实验性 subagent
|
|
30
|
+
- [实验性 subagent host port(英文)](../reference/subagent-host-port.md)
|
|
31
31
|
|
|
32
32
|
## 开发与设计
|
|
33
33
|
|
|
@@ -43,4 +43,4 @@ Agent profile 是项目级或用户全局、带 schema version 的预设,只
|
|
|
43
43
|
|
|
44
44
|
`/profile status` 会把 profile 源定义变化和当前模型/思考等级/stack drift 分开显示。Provenance 只用于 branch 状态报告;reload、resume、tree navigation 和 compaction 不会重新应用 profile。
|
|
45
45
|
|
|
46
|
-
普通 profile 默认不能委派。Delegation
|
|
46
|
+
普通 profile 默认不能委派。Delegation 授权由可选包 `@zihanw/pi-forge-subagents` 通过专用文件持有,使用 `project:<id>` 或 `global:<id>` 完整 key,并可按 profile 覆盖 backend/timeout。裸授权 key 无论位于哪个文件都只是项目 profile 的兼容别名;同 ID 的全局和项目 profile 永不互相继承授权。主包不读取任何 subagent 配置,删除 profile 也不会改动 `subagents.json`。启用前见[前台 delegation](../guides/delegation.md)。
|
|
@@ -11,7 +11,7 @@ Prompt stack 是一份有序、声明式的 prompt 与策略描述,由固定 *
|
|
|
11
11
|
1. 按 JSON 顺序排列启用的 block/slot。
|
|
12
12
|
2. 构建 system 内容,并使用 `replace`、`append` 或 `prepend` 模式。
|
|
13
13
|
3. 在可移动 `chat-history` 周围插入 user/assistant 消息。
|
|
14
|
-
4.
|
|
14
|
+
4. 用 forge-v1 编译 `runtime.*` / `parameters.*` / `extensions.*` 模板。
|
|
15
15
|
5. 对 Pi 执行工具策略,并过滤 pi-forge 渲染的 skills。
|
|
16
16
|
6. 应用 history/compiled outgoing regex。
|
|
17
17
|
7. 可选地在消息完成后应用破坏性的 finalize regex。
|
|
@@ -21,13 +21,13 @@ Prompt stack 是一份有序、声明式的 prompt 与策略描述,由固定 *
|
|
|
21
21
|
1. 长期 system 规则。
|
|
22
22
|
2. 工具和项目上下文。
|
|
23
23
|
3. `includeLastUserMessage: false` 的 `chat-history`。
|
|
24
|
-
4. 包含 `{{lastUserMessage}}` 的最终 user block。
|
|
24
|
+
4. 包含 `{{ runtime.lastUserMessage }}` 的最终 user block。
|
|
25
25
|
|
|
26
26
|
这样既保留旧上下文,又只在最后明确出现一次当前请求。History 还可以过滤 summary/role、去掉旧工具消息、移除 assistant thinking,并限制消息数或字符数。
|
|
27
27
|
|
|
28
28
|
## 策略边界
|
|
29
29
|
|
|
30
|
-
工具 `allow`/`deny` 会修改 Pi active tools,并在 tool call
|
|
30
|
+
工具 `allow`/`deny` 会修改 Pi active tools,并在 tool call 时再次检查。具体的 `allow` 列表会从 Pi 的完整已注册工具目录中选择,因此可以启用 stack 激活前处于 inactive 状态的工具;`deny` 只从原 active baseline 中移除工具,`allow: ["*"]` 仍表示不限制且不会启用全部工具。Skill policy 只过滤 pi-forge 渲染给模型的列表;它不能阻止明确调用,也不是安全边界。若必须控制模型可见 skill 列表,请使用 `replace`,因为 Pi 的基础 prompt 可能已经在 `append`/`prepend` 内容之前列出 skills。
|
|
31
31
|
|
|
32
32
|
## Scope 与自动启用
|
|
33
33
|
|
|
@@ -35,8 +35,8 @@ Prompt stack 是一份有序、声明式的 prompt 与策略描述,由固定 *
|
|
|
35
35
|
- 项目 stack 优先于全局 stack;项目 scope 存在候选时,即使项目候选无效或冲突也会 fail closed,不会回退到全局 stack。
|
|
36
36
|
- 同 ID 项目 stack 会遮蔽全局 stack,包括无效 shadow 或显式 opt-out。
|
|
37
37
|
- `/preset use none` 会记录 session branch 的 opt-out。
|
|
38
|
-
- Active stack
|
|
38
|
+
- Active stack 选择会跟随 Pi session tree branch。
|
|
39
39
|
- 恢复的 branch 状态优先于新 session 自动启用。
|
|
40
40
|
- 自动启用的 agent profile 优先于独立 stack autoload。
|
|
41
41
|
|
|
42
|
-
完整字段见英文 [stack schema](../../reference/stack-schema.md)
|
|
42
|
+
完整字段见英文 [stack schema](../../reference/stack-schema.md)(schema v2 使用 `parameters`),模板语法见[参考](../../reference/macros-and-slots.md)。
|
|
@@ -64,11 +64,12 @@ Profile 默认保存在 `.pi/forge/agent-profiles/*.json`。`/profile save globa
|
|
|
64
64
|
|---|---|
|
|
65
65
|
| `.pi/forge/prompt-stacks/` | 项目 prompt stacks |
|
|
66
66
|
| `.pi/forge/agent-profiles/` | 项目 agent profiles |
|
|
67
|
-
| `.pi/forge/config.json` |
|
|
67
|
+
| `.pi/forge/config.json` | 项目配置(`webEditor.*`) |
|
|
68
68
|
| `.pi/forge/extensions/` | 可信项目 macro/slot 代码 |
|
|
69
69
|
| `~/.pi/forge/prompt-stacks/` | 用户全局 prompt stacks |
|
|
70
70
|
| `~/.pi/forge/agent-profiles/` | 用户全局 agent profiles |
|
|
71
|
-
| `~/.pi/forge/config.json` |
|
|
71
|
+
| `~/.pi/forge/config.json` | 用户默认配置(`webEditor.*`) |
|
|
72
|
+
| `.pi/forge/subagents.json` / `~/.pi/forge/subagents.json` | 由可选包 `@zihanw/pi-forge-subagents` 持有的 delegation 授权配置 |
|
|
72
73
|
| `~/.pi/forge/extensions/` | 可信用户 macro/slot 代码 |
|
|
73
74
|
|
|
74
75
|
旧的 `.pi/prompt-stacks/*.json` 仍可读取;命令创建的 stack 会写到 `.pi/forge/prompt-stacks`,使用 Web 编辑器的 `global` scope 下拉可创建到用户全局 `~/.pi/forge/prompt-stacks`。安全迁移方式:
|
|
@@ -4,28 +4,26 @@
|
|
|
4
4
|
|
|
5
5
|
> **实验性:** 此 API 和 backend 可能独立于稳定的 prompt stack/profile 功能发生变化。
|
|
6
6
|
|
|
7
|
-
pi-forge 可以把明确授权的 agent profile 作为独立、干净、一次性的 Pi 进程执行。它在前台运行,并向父对话返回有界报告。
|
|
7
|
+
可选包 `@zihanw/pi-forge-subagents` 可以把明确授权的 agent profile 作为独立、干净、一次性的 Pi 进程执行。它在前台运行,并向父对话返回有界报告。
|
|
8
8
|
|
|
9
9
|
## 启用 profile
|
|
10
10
|
|
|
11
|
-
Profile 默认不能委派。请在可信项目的 `.pi/forge/
|
|
11
|
+
Profile 默认不能委派。请在可信项目的 `.pi/forge/subagents.json` 中逐个启用项目 profile,在用户全局 `~/.pi/forge/subagents.json` 中逐个启用全局 profile;`.pi/forge/config.json.subagents` 仅作为只读兼容来源:
|
|
12
12
|
|
|
13
13
|
```json
|
|
14
14
|
{
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
"timeoutMs": 300000
|
|
22
|
-
}
|
|
15
|
+
"backend": "pi-subprocess-readonly",
|
|
16
|
+
"timeoutMs": 60000,
|
|
17
|
+
"profiles": {
|
|
18
|
+
"project:reviewer": {
|
|
19
|
+
"enabled": true,
|
|
20
|
+
"timeoutMs": 300000
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
```
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
授权 key 应使用完整 selector:`project:<id>` 或 `global:<id>`。裸 key 仅为项目 profile 的兼容写法,即使写在 `~/.pi/forge/subagents.json` 中也只授权 `project:<id>`;授权全局 profile 必须显式写成 `"global:reviewer": { "enabled": true }`。同 ID 的全局和项目 profile 不会互相继承 enable/backend/timeout。未启用或未列出的 ID 不会被 discovery 返回,即使猜中 ID 也会被拒绝。
|
|
29
27
|
|
|
30
28
|
## Plan 与运行
|
|
31
29
|
|
|
@@ -55,7 +53,7 @@ Profile 默认不能委派。请在可信项目的 `.pi/forge/config.json` 中
|
|
|
55
53
|
}
|
|
56
54
|
```
|
|
57
55
|
|
|
58
|
-
它只影响 `forge_subagent`;`/forge-agent run` 仍需要交互审批。格式错误或不可信项目会 fail closed。请把此
|
|
56
|
+
它只影响 `forge_subagent`;`/forge-agent run` 仍需要交互审批。格式错误或不可信项目会 fail closed。请把此 `subagents.json` 当作授权文件:除非所有可调用父 agent 都可以无需再次询问就把编译 prompt 和可读文件发给 provider,否则不要启用或提交此设置。
|
|
59
57
|
|
|
60
58
|
## Child 边界
|
|
61
59
|
|