@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
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,47 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
In 0.x development, breaking changes may occur in minor releases and will be explicitly noted.
|
|
8
8
|
|
|
9
|
-
## [
|
|
9
|
+
## [0.5.0] - 2026-08-21
|
|
10
|
+
|
|
11
|
+
### Planning
|
|
12
|
+
|
|
13
|
+
- Replaced the proposed six-phase 0.5.0 plan with the accepted [lean 0.5.0 architecture plan](docs/design/architecture-0.5.md). The original full proposal and Phase-0 evidence are archived under [docs/design/archive/0.5-full-proposal/](docs/design/archive/0.5-full-proposal/README.md) and remain the long-term target.
|
|
14
|
+
- Accepted lean 0.5.0 decisions: complete SillyTavern removal; mutable-variable removal; `forge-v1` with a redesigned pure trusted-extension port; regex `display`/`both` removal while `finalize` is retained under lifecycle-adapter ownership; minimal repositories/codecs with fingerprint and atomic writes deferred; minimal `ForgeWorkspace`; versioned `/subagent` host port with mandatory lifecycle semantics; optional `pi-forge-subagents` package without main-package delegation UI and with dedicated `subagents.json` files; explicit root default, root named extension API, and `/subagent` surfaces.
|
|
15
|
+
|
|
16
|
+
### Removed
|
|
17
|
+
|
|
18
|
+
- SillyTavern importer, `/preset import-silly`, its reports, guide, example, and tests are removed. 0.4 is the last supported conversion path.
|
|
19
|
+
- Mutable turn/session variable stores, `pi-forge-variable-state` session entries, set/get/clear variable macros, and the `variables` slot are removed. Static reusable values now live on stack `parameters` in schema v2 or legacy `variables` in v1.
|
|
20
|
+
- Regex `display` and `both` effects are removed and rejected as validation errors; only `outgoing` and `finalize` remain.
|
|
21
|
+
- **Breaking (Lane 4b): legacy package surfaces.** All `@zihanw/pi-forge/src/*` compatibility aliases and the `./examples/*` subpath export are removed. The package root now exports exactly the default Pi extension factory plus `registerMacro`/`registerSlot` and their contract types (`PromptEnvironment`, `PromptRenderHelpers`, macro/slot definition and renderer types, option-schema types, and the trusted project extension API types). `@zihanw/pi-forge/subagent` is the only other entry point. `check-package` enforces the allowlist and forbids legacy aliases.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Prompt compilation uses the `forge-v1` parse/analyze/render engine with a frozen `PromptEnvironment` (`runtime.*`, `parameters.*`, `extensions.*`). Preview, runtime, and subagent preparation share the same compiler entry.
|
|
26
|
+
- `registerMacro` and `registerSlot` move to a pure-contract extension port with immutable `env`, declared dependencies, bounded output, and strict undefined-path errors.
|
|
27
|
+
- Prompt-stack schema v2 introduces immutable `parameters`; unversioned/v1 stacks continue to read through the legacy `variables` field.
|
|
28
|
+
- `finalize` regex remains lifecycle-owned and is excluded from preview, which now reports an informational diagnostic.
|
|
29
|
+
- Legacy 0.4 nested macro syntax (for example `{{upper::x}}`, `{{json::...}}`, `{{iftools::...}}`) is no longer executed by the compiler and must migrate to forge-v1 syntax.
|
|
30
|
+
- Compiler/extension conformance (Lane 1d): custom slots share the pure `{ item, options, env, helpers }` contract with declared `dependencies` and the 16,384-character output limit; `env.extensions` is resolved for slots; a shared dependency analysis and one compilation context keep preview/runtime/subagent consistent; extension values resolve lazily per active branch; nested `{% if %}` and empty-string comparisons are supported.
|
|
31
|
+
- Subagent extraction (Lane 3): the `forge_subagent`/`/forge-agent` execution surface, the web-editor delegation UI, and all subagent configuration reads/writes are removed from the main package and move to the optional `@zihanw/pi-forge-subagents` package, which discovers the active host through the versioned `/subagent` port and owns its own `subagents.json`. Packed-install smoke tests cover main-only and main-plus-optional installs (`check:packed`).
|
|
32
|
+
- Host-neutralization (Lane 3.5): the prompt compiler's rendering and preflight contract is fully host-neutral (capability-driven, no subagent-specific branches), `ForgeWorkspace` is the single owner of resource state and compilation contexts (no second loader/registry path), and subagent documentation/configuration alignment was completed for the optional package split. The packed-install smoke was made portable across checkouts.
|
|
33
|
+
- Forge-native host contract (Lane 4a): the main package no longer depends on `@zihanw/pi-subagent-runtime` at all. `@zihanw/pi-forge/subagent` is now exactly the minimal Forge DTO host contract — host-port wire messages, recursive validators, transport, client/host lifecycle, and Forge-owned canonical fingerprint helpers (byte-compatible with the runtime's `sha256:v1` canonical JSON, pinned by golden vectors). The 0.4 execution contract (request, preflight, plan, response, context budgeting, tool negotiation, and validators) moves to `@zihanw/pi-forge-subagents` with names unchanged, importing portable leaves from the runtime directly. Host-owned preparation no longer synthesizes runtime request/preflight/prompt-runtime artifacts: the workspace resolves the profile and stack from its snapshot, filters the client tool catalog through stack policy, and compiles through the shared compilation context directly. **Breaking:** the package root no longer re-exports subagent contract or host-resolution names (the `/subagent` entry point is the only subagent surface); client-side snapshot validation keeps structural and fingerprint checks while deep profile schema validation remains host-owned.
|
|
34
|
+
- Minimum repositories and codecs (Lane 2a): prompt-stack and agent-profile parse/normalize/validate/serialize are centralized in `src/codecs/`, and reads, writes, and deletes all go through scoped repositories (`src/repositories/`) with containment and symlink checks; the loaders and profile service delegate to the repositories, so domain resources are never read or written directly at the adapter layer. Replacement semantics are unchanged and characterized by tests (no fingerprint conflict or atomic replace yet). Legacy stack migration is a documented byte-preserving exception whose raw IO lives inside the repository.
|
|
35
|
+
- ForgeWorkspace and host port v1 (Lane 2b): a minimal `ForgeWorkspace` snapshot owner (genuinely immutable, deep-frozen snapshots) over the repositories/codecs, plus a versioned `@zihanw/pi-forge/subagent` host-port protocol over the Pi event bus with the three minimal operations (discovery, profile listing, prepare). Mandatory lifecycle semantics are enforced and covered by tests: bounded timeouts, explicit duplicate-host failure, `hostId`+`generation`-bound request/reply so stale/foreign requests are rejected, disposal/`unavailable`, listener cleanup, host-owned prompt preparation (client sends only profile selector + task + backend facts), and recursive JSON-compatible operation validators. The host is wired into the real extension lifecycle via `pi.events` (host can only start after the first snapshot exists, so availability implies a loaded workspace; `reload` honors project trust; disposal runs before subagent teardown; the base system prompt is host-owned and empty for delegated subagents), with integration tests that discover, list, prepare, and observe disposal through the published `/subagent` surface — including that the host is not advertised before any session start. Operation validators are strict and recursive: exact nested field sets, typed enums, plain-object-only JSON compatibility, and unknown-field rejection — so `allowProcess` is the only process fact and no runtime access/limit/execution material crosses.
|
|
36
|
+
|
|
37
|
+
- Documentation and migration notes (Lane 4d): the [public API policy](docs/reference/public-api.md) was rewritten for the three intentional entry points; the 0.4 subagent adapter contract reference was replaced by the [subagent host port contract](docs/reference/subagent-host-port.md); the [0.5 migration guide](docs/guides/migrating-to-0.5.md) now covers Lanes 1–4 with a [zh-CN translation](docs/zh-CN/guides/migrating-to-0.5.md); README, setup, getting-started, web-editor, features, and configuration docs were aligned with the optional-package split (EN + zh-CN).
|
|
38
|
+
|
|
39
|
+
- Strengthened the `/subagent` host-port DTO types (code-review follow-up, no wire-behavior change): `ForgeResolveProfileResponse.snapshot`, `ForgePrepareResponse.messages`/`diagnostics`/`profileSnapshot` are no longer `unknown`. New exported types: `ForgeProfileSnapshot`, `ForgeWireAgentProfile`, `ForgeWirePromptStack`, `ForgeDelegationMessage`, `ForgeDelegationDiagnostic`, `ForgePromptDependency`/`ForgePromptDependencyKind`, `ForgeListProfilesResponse`, `ForgeHostWireMessage`, and a generic `ValidationResult<T>`; the recursive validators now return typed data. Runtime validation is byte-compatible with 0.5.0.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- Profile auto-activation now honors project-over-global shadowing: a global `autoActivate` profile whose ID exists in project scope no longer activates, matching `chooseAutoActivateStack` semantics (0.5.x review A1). Regression test covers explicit opt-out and implicit shadowing.
|
|
44
|
+
- The fresh-session startup branch now evaluates auto-activation requests with the same shadow-aware candidacy (A1 follow-up, found by dogfooding): a global `autoActivate` profile shadowed by a same-ID project profile no longer triggers the spurious "multiple agent profiles request auto-activation" error, and the auto-activate stack fallback is no longer skipped in that state.
|
|
45
|
+
- Extension macro/slot names may no longer contain `.` — forge-v1 uses dots as path separators, so dotted names were registerable but unreachable (0.5.x review A2). Regression test pins the rejection.
|
|
46
|
+
- Static prompt analysis now reports macro dependency cycles as `recursion` diagnostics instead of silently stopping traversal (0.5.x review A5). Regression test pins a single deduplicated diagnostic per cycle.
|
|
47
|
+
- Dev/test Pi SDK pins aligned across both repositories at `0.84.2` (0.5.x review A4); the optional package no longer mixes `0.83.0`/`0.84.2` instances in its tree.
|
|
48
|
+
|
|
49
|
+
- Web editor polish (code-review follow-up): the theme toggle moved from the legacy stacks topbar into the shared surface navigation, so it stays visible and functional on the Agent profiles surface; theme state now lives in a shared `theme.ts` module consumed by both the Vue shell and the legacy bridge. Policy editor rows no longer repeat the column labels on wide layouts (labels return when the grid stacks on narrow screens). Item/main action buttons no longer wrap their own text mid-label, and the item toolbar wraps whole buttons instead of clipping.
|
|
10
50
|
|
|
11
51
|
## [0.4.1] - 2026-08-17
|
|
12
52
|
|
package/README.md
CHANGED
|
@@ -14,9 +14,8 @@ Think of it as a character sheet and workbench for your AI agent.
|
|
|
14
14
|
- Switch between coding, reviewing, writing, roleplay, and translation modes with one command.
|
|
15
15
|
- Save and apply complete model/thinking/stack profiles.
|
|
16
16
|
- Enforce per-stack tool policy and filter model-visible skills.
|
|
17
|
-
- Use
|
|
17
|
+
- Use immutable stack `parameters` with the deterministic forge-v1 template engine.
|
|
18
18
|
- Apply deterministic regex transforms to outgoing prompts or finalized assistant messages.
|
|
19
|
-
- Import SillyTavern presets and inspect the migration report.
|
|
20
19
|
- Edit stacks and profiles in a local browser UI and inspect the exact provider payload.
|
|
21
20
|
- Run an explicitly enabled profile as an experimental, approval-gated foreground subagent.
|
|
22
21
|
|
|
@@ -58,7 +57,7 @@ Restart Pi or run:
|
|
|
58
57
|
/preset ui
|
|
59
58
|
```
|
|
60
59
|
|
|
61
|
-
The local editor can create, fork, validate, preview, import, export, and delete prompt stacks. Its **Agent profiles** view manages one-shot model/thinking/stack presets
|
|
60
|
+
The local editor can create, fork, validate, preview, import, export, and delete prompt stacks. Its **Agent profiles** view manages one-shot model/thinking/stack presets. Writes require a trusted project. Delegation settings live in the optional `@zihanw/pi-forge-subagents` package's `subagents.json` files, not in the editor.
|
|
62
61
|
|
|
63
62
|
### 3. Save a profile
|
|
64
63
|
|
|
@@ -78,9 +77,9 @@ A prompt stack is an ordered JSON document containing:
|
|
|
78
77
|
| Item | Purpose |
|
|
79
78
|
|---|---|
|
|
80
79
|
| **Block** | Static `system`, `user`, `assistant`, or hidden `custom` text |
|
|
81
|
-
| **Slot** | Runtime content such as tools, skills, project context,
|
|
80
|
+
| **Slot** | Runtime content such as tools, skills, project context, date/cwd, or chat history |
|
|
82
81
|
|
|
83
|
-
Stacks can `replace`, `append`, or `prepend` Pi's base system prompt. During compilation, pi-forge
|
|
82
|
+
Stacks can `replace`, `append`, or `prepend` Pi's base system prompt. During compilation, pi-forge compiles forge-v1 templates over `runtime.*` / `parameters.*` / `extensions.*`, inserts conversation content, enforces tool policy, filters its skill listing, and applies enabled regex rules.
|
|
84
83
|
|
|
85
84
|
Agent profiles are project-local references to an exact provider/model, thinking level, and prompt stack. They intentionally do not duplicate tool or skill policy—the referenced stack remains the source of truth.
|
|
86
85
|
|
|
@@ -88,7 +87,6 @@ Start with these examples:
|
|
|
88
87
|
|
|
89
88
|
- [Default Pi mirror](examples/default-prompt-stack.json) keeps normal Pi behavior while making its sections movable.
|
|
90
89
|
- [Focused reviewer](examples/reviewer-prompt-stack.json) creates a read-only review layout with an explicit latest-user target.
|
|
91
|
-
- [SillyTavern DM writer](examples/sillytavern-dm-writer-prompt-stack.json) demonstrates characters, variables, history placement, and regex cleanup.
|
|
92
90
|
- [Custom system-status extension](examples/custom-system-status-extension/README.md) registers a trusted macro and slot.
|
|
93
91
|
|
|
94
92
|
## Common commands
|
|
@@ -111,9 +109,9 @@ See the [complete command reference](docs/reference/commands.md).
|
|
|
111
109
|
|
|
112
110
|
## Experimental foreground delegation
|
|
113
111
|
|
|
114
|
-
pi-forge
|
|
112
|
+
The optional `@zihanw/pi-forge-subagents` package provides foreground delegation on top of pi-forge's `/subagent` host port. The model can discover eligible profiles with `forge_subagent_profiles` and invoke one with `forge_subagent`; humans use `/forge-agent plan` and `/forge-agent run`.
|
|
115
113
|
|
|
116
|
-
This feature is **experimental** and profiles are not delegatable by default. Enable each profile in the trusted project's `.pi/forge/
|
|
114
|
+
This feature is **experimental** and profiles are not delegatable by default. Enable each profile in the trusted project's `.pi/forge/subagents.json` (or the optional package's read-only legacy fallback in `.pi/forge/config.json.subagents`). Interactive execution presents an immutable plan for approval unless the project explicitly authorizes unattended model invocation.
|
|
117
115
|
|
|
118
116
|
> **Security boundary:** The current backends are shared-user processes, not operating-system sandboxes. “Read-only” describes the model-visible tool policy. The child retains the invoking user's OS read permissions, and readable content may be sent to the selected provider and retained in Pi's session data. Timeout and cancellation are best effort, and `/tree` cannot undo provider requests, billing, or external effects.
|
|
119
117
|
|
|
@@ -124,11 +122,11 @@ Read [foreground delegation and its safety model](docs/guides/delegation.md) bef
|
|
|
124
122
|
### Learn
|
|
125
123
|
|
|
126
124
|
- [Getting started](docs/getting-started.md)
|
|
125
|
+
- [Migrating to 0.5](docs/guides/migrating-to-0.5.md)
|
|
127
126
|
- [Prompt-stack concepts](docs/concepts/prompt-stacks.md)
|
|
128
127
|
- [Agent-profile concepts](docs/concepts/agent-profiles.md)
|
|
129
128
|
- [Web editor](docs/guides/web-editor.md)
|
|
130
129
|
- [Prompt-stack patterns and examples](docs/guides/use-cases.md)
|
|
131
|
-
- [SillyTavern import](docs/guides/sillytavern-import.md)
|
|
132
130
|
- [Custom macros and slots](docs/guides/custom-macros-and-slots.md)
|
|
133
131
|
- [Prompt and payload debugging](docs/guides/debugging.md)
|
|
134
132
|
|
|
@@ -139,14 +137,16 @@ Read [foreground delegation and its safety model](docs/guides/delegation.md) bef
|
|
|
139
137
|
- [Macros and slots](docs/reference/macros-and-slots.md)
|
|
140
138
|
- [Configuration](docs/reference/configuration.md)
|
|
141
139
|
- [Public API policy](docs/reference/public-api.md)
|
|
142
|
-
- [Experimental subagent
|
|
140
|
+
- [Experimental subagent host port](docs/reference/subagent-host-port.md)
|
|
143
141
|
|
|
144
142
|
### Develop and design
|
|
145
143
|
|
|
146
144
|
- [Development setup](docs/development/setup.md)
|
|
145
|
+
- [Architecture and development rules](docs/development/architecture-rules.md)
|
|
146
|
+
- [0.5 architecture plan](docs/design/architecture-0.5.md)
|
|
147
147
|
- [Release process](docs/development/release.md)
|
|
148
148
|
- [Roadmap](docs/development/roadmap.md)
|
|
149
|
-
- [
|
|
149
|
+
- [Architecture and design index](docs/design/README.md)
|
|
150
150
|
|
|
151
151
|
Chinese user documentation starts at [docs/zh-CN/README.md](docs/zh-CN/README.md).
|
|
152
152
|
|
package/README.zh-CN.md
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
- 按栈严格限制工具,并过滤模型可见的 skills。
|
|
17
17
|
- 使用静态、轮次和会话变量,以及支持嵌套的模板宏。
|
|
18
18
|
- 对发给模型的 prompt 或最终 assistant 消息执行确定性 regex 转换。
|
|
19
|
-
- 导入 SillyTavern 预设并检查迁移报告。
|
|
20
19
|
- 在本地 Web 编辑器中管理 stack/profile,并检查实际 provider payload。
|
|
21
20
|
- 用明确启用的 profile 运行实验性、需要审批的前台 subagent。
|
|
22
21
|
|
|
@@ -58,7 +57,7 @@ cp examples/default-prompt-stack.json .pi/forge/prompt-stacks/default.json
|
|
|
58
57
|
/preset ui
|
|
59
58
|
```
|
|
60
59
|
|
|
61
|
-
本地编辑器可以新建、fork、校验、预览、导入、导出和删除 prompt stack,并可在新建/fork/导入时明确选择写入项目或用户全局存储。切换到 **Agent profiles** 可以浏览项目与全局 profile、编辑和删除全局 profile(通过显式 `global:<id>`
|
|
60
|
+
本地编辑器可以新建、fork、校验、预览、导入、导出和删除 prompt stack,并可在新建/fork/导入时明确选择写入项目或用户全局存储。切换到 **Agent profiles** 可以浏览项目与全局 profile、编辑和删除全局 profile(通过显式 `global:<id>` 路由)。写入操作要求项目已被信任。Delegation 配置由可选包 `@zihanw/pi-forge-subagents` 的 `subagents.json` 文件管理,不在编辑器中。
|
|
62
61
|
|
|
63
62
|
### 3. 保存 profile
|
|
64
63
|
|
|
@@ -88,7 +87,6 @@ Agent profile 是项目级或用户全局预设,引用精确 provider/model、
|
|
|
88
87
|
|
|
89
88
|
- [默认 Pi mirror](examples/default-prompt-stack.json):保留 Pi 默认行为,同时让所有区域都可移动。
|
|
90
89
|
- [专注代码审查](examples/reviewer-prompt-stack.json):只读工具策略、背景历史和明确的最新用户目标。
|
|
91
|
-
- [SillyTavern DM writer](examples/sillytavern-dm-writer-prompt-stack.json):角色、变量、历史布局和 regex 清理。
|
|
92
90
|
- [自定义 system-status extension](examples/custom-system-status-extension/README.md):注册可信 macro 和 slot。
|
|
93
91
|
|
|
94
92
|
## 常用命令
|
|
@@ -111,9 +109,9 @@ Agent profile 是项目级或用户全局预设,引用精确 provider/model、
|
|
|
111
109
|
|
|
112
110
|
## 实验性前台 delegation
|
|
113
111
|
|
|
114
|
-
pi-forge
|
|
112
|
+
可选包 `@zihanw/pi-forge-subagents` 在 pi-forge 的 `/subagent` host port 之上提供前台 delegation。模型通过 `forge_subagent_profiles` 发现可用 profile,再用 `forge_subagent` 调用;用户可以使用 `/forge-agent plan` 和 `/forge-agent run`。
|
|
115
113
|
|
|
116
|
-
此功能仍是**实验性功能**,profile 默认不能委派。请在可信项目的 `.pi/forge/
|
|
114
|
+
此功能仍是**实验性功能**,profile 默认不能委派。请在可信项目的 `.pi/forge/subagents.json`(或可选包只读兼容的 `.pi/forge/config.json.subagents`)中逐个启用。除非项目明确授权无人值守的模型调用,否则执行前会显示与不可变计划绑定的审批界面。
|
|
117
115
|
|
|
118
116
|
> **安全边界:** 当前 backend 是 shared-user 进程,不是操作系统沙箱。“只读”只描述模型可见工具策略。Child 仍有启动用户的 OS 读取权限;可读内容可能发送给所选 provider,并保留在 Pi session 数据中。Timeout 和取消仅为 best effort,`/tree` 不能撤销 provider 请求、计费或外部影响。
|
|
119
117
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Subagent adapter contract
|
|
2
2
|
|
|
3
|
-
The authoritative experimental contract moved to [`docs/reference/subagent-
|
|
3
|
+
The authoritative experimental contract moved to [`docs/reference/subagent-host-port.md`](docs/reference/subagent-host-port.md).
|
|
4
|
+
|
|
5
|
+
The 0.4 execution contract (request, preflight, plan, response, validators) moved to the optional `@zihanw/pi-forge-subagents` package in 0.5.0; the main package keeps only the versioned host port.
|
|
4
6
|
|
|
5
7
|
This compatibility pointer remains at the published root path so existing links continue to work.
|
package/dist/agent-profile.d.ts
CHANGED
|
@@ -2,39 +2,24 @@ import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
|
2
2
|
import { type Model } from "@earendil-works/pi-ai";
|
|
3
3
|
import { type ResourceScope } from "./resource-identity.ts";
|
|
4
4
|
import type { LoadedPromptStack } from "./types.ts";
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export
|
|
23
|
-
export interface AgentProfileDiagnostic {
|
|
24
|
-
level: AgentProfileDiagnosticLevel;
|
|
25
|
-
message: string;
|
|
26
|
-
field?: string;
|
|
27
|
-
}
|
|
28
|
-
export interface LoadedAgentProfile {
|
|
29
|
-
profile: AgentProfile;
|
|
30
|
-
filePath: string;
|
|
31
|
-
scope: "global" | "project";
|
|
32
|
-
key: {
|
|
33
|
-
scope: "global" | "project";
|
|
34
|
-
id: string;
|
|
35
|
-
};
|
|
36
|
-
diagnostics: AgentProfileDiagnostic[];
|
|
37
|
-
}
|
|
5
|
+
import { type AgentProfile, type AgentProfileDiagnostic, type AgentProfileModelReference, type LoadedAgentProfile } from "./codecs/agent-profile.ts";
|
|
6
|
+
export { AGENT_PROFILE_TYPE, AGENT_PROFILE_THINKING_LEVELS, validateAgentProfile, validateAgentProfilePromptStackScope } from "./codecs/agent-profile.ts";
|
|
7
|
+
export type { AgentProfile, AgentProfileDiagnostic, AgentProfileDiagnosticLevel, AgentProfileModelReference, LoadedAgentProfile } from "./codecs/agent-profile.ts";
|
|
8
|
+
export declare function loadAgentProfileFile(filePath: string, scope?: "global" | "project"): LoadedAgentProfile;
|
|
9
|
+
export { agentProfilePath, agentProfilesDir } from "./storage.ts";
|
|
10
|
+
export declare function isValidAgentProfileId(id: string): boolean;
|
|
11
|
+
export declare function loadAgentProfiles(cwd: string): LoadedAgentProfile[];
|
|
12
|
+
export declare function loadAgentProfilesScoped(cwd: string, globalDir?: string): LoadedAgentProfile[];
|
|
13
|
+
export declare function loadGlobalAgentProfiles(globalDir?: string): LoadedAgentProfile[];
|
|
14
|
+
export declare function chooseAutoActivateAgentProfile(profiles: readonly LoadedAgentProfile[]): LoadedAgentProfile | undefined;
|
|
15
|
+
export declare function hasAutoActivateAgentProfile(profiles: readonly LoadedAgentProfile[]): boolean;
|
|
16
|
+
export declare function resolveAgentProfile(loaded: LoadedAgentProfile, resources: AgentProfileResolutionResources): ResolvedAgentProfile;
|
|
17
|
+
export declare function isUsableAgentProfile(loaded: LoadedAgentProfile): boolean;
|
|
18
|
+
export declare function isResolvedAgentProfileUsable(resolved: ResolvedAgentProfile): boolean;
|
|
19
|
+
export declare function hasAgentProfileErrors(diagnostics: readonly AgentProfileDiagnostic[]): boolean;
|
|
20
|
+
export declare function renderAgentProfileDiagnostics(diagnostics: readonly AgentProfileDiagnostic[]): string;
|
|
21
|
+
export declare function agentProfileFingerprint(profile: AgentProfile): string;
|
|
22
|
+
export declare function isAgentProfileProvenance(value: unknown): value is AgentProfileProvenance;
|
|
38
23
|
export interface AgentProfileResolutionResources {
|
|
39
24
|
models: readonly Model<any>[];
|
|
40
25
|
availableModels?: readonly Model<any>[];
|
|
@@ -62,33 +47,4 @@ export interface AgentProfileProvenance {
|
|
|
62
47
|
appliedAt: string;
|
|
63
48
|
snapshot: AgentProfileRuntimeSnapshot;
|
|
64
49
|
}
|
|
65
|
-
export { agentProfilePath, agentProfilesDir } from "./storage.ts";
|
|
66
|
-
export declare function isValidAgentProfileId(id: string): boolean;
|
|
67
|
-
export declare function loadAgentProfiles(cwd: string): LoadedAgentProfile[];
|
|
68
|
-
/**
|
|
69
|
-
* Load both global and project profiles. Global definitions are user-owned
|
|
70
|
-
* and always load; project definitions load from the trusted project dirs.
|
|
71
|
-
* The caller decides whether project trust applies before calling.
|
|
72
|
-
*/
|
|
73
|
-
export declare function loadAgentProfilesScoped(cwd: string, globalDir?: string): LoadedAgentProfile[];
|
|
74
|
-
/** Load only the user-owned global profiles, used by untrusted projects. */
|
|
75
|
-
export declare function loadGlobalAgentProfiles(globalDir?: string): LoadedAgentProfile[];
|
|
76
|
-
export declare function chooseAutoActivateAgentProfile(profiles: readonly LoadedAgentProfile[]): LoadedAgentProfile | undefined;
|
|
77
|
-
export declare function hasAutoActivateAgentProfile(profiles: readonly LoadedAgentProfile[]): boolean;
|
|
78
|
-
export declare function loadAgentProfileFile(filePath: string, scope?: "global" | "project"): LoadedAgentProfile;
|
|
79
|
-
export declare function validateAgentProfile(profile: AgentProfile): AgentProfileDiagnostic[];
|
|
80
|
-
/**
|
|
81
|
-
* Validate the profile's stored `promptStack` selector against the profile's
|
|
82
|
-
* own scope. Bare references stay scope-relative; only global profiles are
|
|
83
|
-
* prohibited from referencing project stacks explicitly. Used by write paths
|
|
84
|
-
* so edited JSON cannot persist a scope-unsafe dependency.
|
|
85
|
-
*/
|
|
86
|
-
export declare function validateAgentProfilePromptStackScope(profile: AgentProfile, scope: ResourceScope): AgentProfileDiagnostic[];
|
|
87
|
-
export declare function resolveAgentProfile(loaded: LoadedAgentProfile, resources: AgentProfileResolutionResources): ResolvedAgentProfile;
|
|
88
|
-
export declare function isUsableAgentProfile(loaded: LoadedAgentProfile): boolean;
|
|
89
|
-
export declare function isResolvedAgentProfileUsable(resolved: ResolvedAgentProfile): boolean;
|
|
90
|
-
export declare function hasAgentProfileErrors(diagnostics: readonly AgentProfileDiagnostic[]): boolean;
|
|
91
|
-
export declare function renderAgentProfileDiagnostics(diagnostics: readonly AgentProfileDiagnostic[]): string;
|
|
92
|
-
export declare function agentProfileFingerprint(profile: AgentProfile): string;
|
|
93
|
-
export declare function isAgentProfileProvenance(value: unknown): value is AgentProfileProvenance;
|
|
94
50
|
//# sourceMappingURL=agent-profile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-profile.d.ts","sourceRoot":"","sources":["../src/agent-profile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-profile.d.ts","sourceRoot":"","sources":["../src/agent-profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAsB,KAAK,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EAAgF,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1I,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAQpD,OAAO,EAKN,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAE3B,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,oBAAoB,EAAE,oCAAoC,EAAE,MAAM,2BAA2B,CAAC;AAC1J,YAAY,EAAE,YAAY,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAYnK,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,QAAQ,GAAG,SAAqB,GAAG,kBAAkB,CAElH;AAED,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAEnE;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,GAAE,MAAiC,GAAG,kBAAkB,EAAE,CAEvH;AAED,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAiC,GAAG,kBAAkB,EAAE,CAE1G;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GAAG,kBAAkB,GAAG,SAAS,CAoBtH;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GAAG,OAAO,CAW5F;AAED,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,+BAA+B,GACxC,oBAAoB,CA2DtB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAExE;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAEpF;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,GAAG,OAAO,CAE7F;AAED,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,GAAG,MAAM,CAKpG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAErE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAaxF;AAoDD,MAAM,WAAW,+BAA+B;IAC/C,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACxC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC3C,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,sBAAsB,EAAE,aAAa,CAAC;IACtC,WAAW,EAAE,sBAAsB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,2BAA2B;IAC3C,KAAK,EAAE,0BAA0B,CAAC;IAClC,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,2BAA2B,CAAC;CACtC"}
|
package/dist/agent-profile.js
CHANGED
|
@@ -1,56 +1,32 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
-
import { basename, join } from "node:path";
|
|
3
1
|
import { clampThinkingLevel } from "@earendil-works/pi-ai";
|
|
4
2
|
import { resourcePatternMatches } from "./policy.js";
|
|
5
3
|
import { formatResourceKey, isResourceScope, isValidResourceId, parseResourceSelector } from "./resource-identity.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import { globalAgentProfilesDir } from "./storage.js";
|
|
5
|
+
import { readAgentProfiles as readProjects, readAgentProfilesScoped as readScoped, readGlobalAgentProfiles as readGlobals, readSingleAgentProfileFile, } from "./repositories/agent-profile.js";
|
|
6
|
+
import { AGENT_PROFILE_THINKING_LEVELS, } from "./codecs/agent-profile.js";
|
|
7
|
+
export { AGENT_PROFILE_TYPE, AGENT_PROFILE_THINKING_LEVELS, validateAgentProfile, validateAgentProfilePromptStackScope } from "./codecs/agent-profile.js";
|
|
9
8
|
const VALID_THINKING_LEVELS = new Set(AGENT_PROFILE_THINKING_LEVELS);
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
function isPlainObject(value) {
|
|
10
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
function nonEmptyString(value) {
|
|
13
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
14
|
+
}
|
|
15
|
+
export function loadAgentProfileFile(filePath, scope = "project") {
|
|
16
|
+
return readSingleAgentProfileFile(filePath, scope);
|
|
17
|
+
}
|
|
12
18
|
export { agentProfilePath, agentProfilesDir } from "./storage.js";
|
|
13
19
|
export function isValidAgentProfileId(id) {
|
|
14
20
|
return isValidResourceId(id);
|
|
15
21
|
}
|
|
16
22
|
export function loadAgentProfiles(cwd) {
|
|
17
|
-
|
|
18
|
-
annotateDuplicateProfileIds(profiles);
|
|
19
|
-
annotateAutoActivateConflicts(profiles);
|
|
20
|
-
return profiles;
|
|
23
|
+
return readProjects(cwd);
|
|
21
24
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Load both global and project profiles. Global definitions are user-owned
|
|
24
|
-
* and always load; project definitions load from the trusted project dirs.
|
|
25
|
-
* The caller decides whether project trust applies before calling.
|
|
26
|
-
*/
|
|
27
25
|
export function loadAgentProfilesScoped(cwd, globalDir = globalAgentProfilesDir()) {
|
|
28
|
-
|
|
29
|
-
...loadAgentProfilesFromDir(globalDir, "global"),
|
|
30
|
-
...loadAgentProfilesFromDir(agentProfilesDir(cwd), "project"),
|
|
31
|
-
];
|
|
32
|
-
annotateDuplicateProfileIds(profiles);
|
|
33
|
-
annotateAutoActivateConflicts(profiles);
|
|
34
|
-
return profiles;
|
|
26
|
+
return readScoped(cwd, globalDir);
|
|
35
27
|
}
|
|
36
|
-
/** Load only the user-owned global profiles, used by untrusted projects. */
|
|
37
28
|
export function loadGlobalAgentProfiles(globalDir = globalAgentProfilesDir()) {
|
|
38
|
-
|
|
39
|
-
annotateDuplicateProfileIds(profiles);
|
|
40
|
-
annotateAutoActivateConflicts(profiles);
|
|
41
|
-
return profiles;
|
|
42
|
-
}
|
|
43
|
-
function loadAgentProfilesFromDir(dir, scope) {
|
|
44
|
-
if (!existsSync(dir))
|
|
45
|
-
return [];
|
|
46
|
-
let entries;
|
|
47
|
-
try {
|
|
48
|
-
entries = readdirSync(dir).filter((name) => name.endsWith(".json")).sort();
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
return [];
|
|
52
|
-
}
|
|
53
|
-
return entries.map((name) => loadAgentProfileFile(join(dir, name), scope));
|
|
29
|
+
return readGlobals(globalDir);
|
|
54
30
|
}
|
|
55
31
|
export function chooseAutoActivateAgentProfile(profiles) {
|
|
56
32
|
// Project auto-activation has explicit precedence. An invalid or ambiguous
|
|
@@ -61,82 +37,22 @@ export function chooseAutoActivateAgentProfile(profiles) {
|
|
|
61
37
|
? projectCandidates[0]
|
|
62
38
|
: undefined;
|
|
63
39
|
}
|
|
64
|
-
const
|
|
40
|
+
const projectIds = new Set(profiles.filter((loaded) => loaded.scope === "project").map((loaded) => loaded.profile.id));
|
|
41
|
+
// Global candidates shadowed by a same-ID project profile must not activate:
|
|
42
|
+
// normal resolution would never see them either.
|
|
43
|
+
const globalCandidates = profiles.filter((loaded) => loaded.scope === "global" && loaded.profile.autoActivate === true && !projectIds.has(loaded.profile.id));
|
|
65
44
|
return globalCandidates.length === 1 && !hasAgentProfileErrors(globalCandidates[0].diagnostics)
|
|
66
45
|
? globalCandidates[0]
|
|
67
46
|
: undefined;
|
|
68
47
|
}
|
|
69
48
|
export function hasAutoActivateAgentProfile(profiles) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
return {
|
|
80
|
-
filePath,
|
|
81
|
-
scope,
|
|
82
|
-
key: { scope, id: basename(filePath, ".json") },
|
|
83
|
-
profile: fallbackProfile(filePath),
|
|
84
|
-
diagnostics: [{
|
|
85
|
-
level: "error",
|
|
86
|
-
message: `Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
87
|
-
}],
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
const profile = normalizeAgentProfile(raw, filePath, diagnostics);
|
|
91
|
-
diagnostics.push(...validateAgentProfile(profile));
|
|
92
|
-
return { filePath, scope, key: { scope, id: profile.id }, profile, diagnostics };
|
|
93
|
-
}
|
|
94
|
-
export function validateAgentProfile(profile) {
|
|
95
|
-
const diagnostics = [];
|
|
96
|
-
if (profile.schemaVersion !== 1)
|
|
97
|
-
diagnostics.push({ level: "error", field: "schemaVersion", message: "schemaVersion must be 1." });
|
|
98
|
-
if (profile.type !== AGENT_PROFILE_TYPE)
|
|
99
|
-
diagnostics.push({ level: "error", field: "type", message: `type must be "${AGENT_PROFILE_TYPE}".` });
|
|
100
|
-
if (!isValidAgentProfileId(profile.id)) {
|
|
101
|
-
diagnostics.push({
|
|
102
|
-
level: "error",
|
|
103
|
-
field: "id",
|
|
104
|
-
message: "Profile id must start with a letter or number and contain only letters, numbers, dots, underscores, and hyphens.",
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
if (!profile.model.provider.trim())
|
|
108
|
-
diagnostics.push({ level: "error", field: "model.provider", message: "model.provider must not be empty." });
|
|
109
|
-
if (!profile.model.id.trim())
|
|
110
|
-
diagnostics.push({ level: "error", field: "model.id", message: "model.id must not be empty." });
|
|
111
|
-
if (!VALID_THINKING_LEVELS.has(profile.thinkingLevel)) {
|
|
112
|
-
diagnostics.push({ level: "error", field: "thinkingLevel", message: `Unsupported thinkingLevel: ${String(profile.thinkingLevel)}` });
|
|
113
|
-
}
|
|
114
|
-
if (profile.promptStack !== null && !profile.promptStack.trim()) {
|
|
115
|
-
diagnostics.push({ level: "error", field: "promptStack", message: "promptStack must be a non-empty stack id or null." });
|
|
116
|
-
}
|
|
117
|
-
return diagnostics;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Validate the profile's stored `promptStack` selector against the profile's
|
|
121
|
-
* own scope. Bare references stay scope-relative; only global profiles are
|
|
122
|
-
* prohibited from referencing project stacks explicitly. Used by write paths
|
|
123
|
-
* so edited JSON cannot persist a scope-unsafe dependency.
|
|
124
|
-
*/
|
|
125
|
-
export function validateAgentProfilePromptStackScope(profile, scope) {
|
|
126
|
-
if (profile.promptStack === null)
|
|
127
|
-
return [];
|
|
128
|
-
const parsed = parseResourceSelector(profile.promptStack);
|
|
129
|
-
if (!parsed.ok) {
|
|
130
|
-
return [{ level: "error", field: "promptStack", message: parsed.error }];
|
|
131
|
-
}
|
|
132
|
-
if (scope === "global" && parsed.selector.scope === "project") {
|
|
133
|
-
return [{
|
|
134
|
-
level: "error",
|
|
135
|
-
field: "promptStack",
|
|
136
|
-
message: `Global profile ${profile.id} cannot reference project prompt stack ${parsed.selector.id}.`,
|
|
137
|
-
}];
|
|
138
|
-
}
|
|
139
|
-
return [];
|
|
49
|
+
// Shadow-aware: a global auto-activate profile whose ID exists in project
|
|
50
|
+
// scope is not a candidate (see chooseAutoActivateAgentProfile), so it must
|
|
51
|
+
// not count as requesting activation either.
|
|
52
|
+
if (profiles.some((loaded) => loaded.scope === "project" && loaded.profile.autoActivate === true))
|
|
53
|
+
return true;
|
|
54
|
+
const projectIds = new Set(profiles.filter((loaded) => loaded.scope === "project").map((loaded) => loaded.profile.id));
|
|
55
|
+
return profiles.some((loaded) => loaded.scope === "global" && loaded.profile.autoActivate === true && !projectIds.has(loaded.profile.id));
|
|
140
56
|
}
|
|
141
57
|
export function resolveAgentProfile(loaded, resources) {
|
|
142
58
|
const diagnostics = [...loaded.diagnostics];
|
|
@@ -230,11 +146,6 @@ export function isAgentProfileProvenance(value) {
|
|
|
230
146
|
&& VALID_THINKING_LEVELS.has(value.snapshot.thinkingLevel)
|
|
231
147
|
&& (value.snapshot.promptStack === null || !!nonEmptyString(value.snapshot.promptStack));
|
|
232
148
|
}
|
|
233
|
-
/**
|
|
234
|
-
* Resolve a profile's stored `promptStack` reference relative to the profile's
|
|
235
|
-
* own scope. Bare IDs resolve to the profile scope; explicit qualification
|
|
236
|
-
* overrides that scope. A global profile can never reference a project stack.
|
|
237
|
-
*/
|
|
238
149
|
function resolveProfilePromptStack(loaded, promptStacks) {
|
|
239
150
|
const diagnostics = [];
|
|
240
151
|
const reference = loaded.profile.promptStack;
|
|
@@ -277,137 +188,4 @@ function resolveProfilePromptStack(loaded, promptStacks) {
|
|
|
277
188
|
function findModel(models, reference) {
|
|
278
189
|
return models.find((model) => model.provider === reference.provider && model.id === reference.id);
|
|
279
190
|
}
|
|
280
|
-
function annotateDuplicateProfileIds(profiles) {
|
|
281
|
-
const byScopeId = new Map();
|
|
282
|
-
for (const loaded of profiles) {
|
|
283
|
-
const key = `${loaded.scope}\0${loaded.profile.id}`;
|
|
284
|
-
const matches = byScopeId.get(key) ?? [];
|
|
285
|
-
matches.push(loaded);
|
|
286
|
-
byScopeId.set(key, matches);
|
|
287
|
-
}
|
|
288
|
-
for (const matches of byScopeId.values()) {
|
|
289
|
-
if (matches.length <= 1)
|
|
290
|
-
continue;
|
|
291
|
-
const files = matches.map((loaded) => basename(loaded.filePath)).join(", ");
|
|
292
|
-
for (const loaded of matches) {
|
|
293
|
-
loaded.diagnostics.push({
|
|
294
|
-
level: "error",
|
|
295
|
-
message: `Duplicate ${loaded.scope} profile id: ${loaded.profile.id} appears in multiple files (${files}).`,
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
function annotateAutoActivateConflicts(profiles) {
|
|
301
|
-
const byScope = new Map();
|
|
302
|
-
for (const loaded of profiles) {
|
|
303
|
-
if (loaded.profile.autoActivate !== true)
|
|
304
|
-
continue;
|
|
305
|
-
const matches = byScope.get(loaded.scope) ?? [];
|
|
306
|
-
matches.push(loaded);
|
|
307
|
-
byScope.set(loaded.scope, matches);
|
|
308
|
-
}
|
|
309
|
-
for (const [scope, candidates] of byScope) {
|
|
310
|
-
if (candidates.length <= 1)
|
|
311
|
-
continue;
|
|
312
|
-
const files = candidates.map((loaded) => basename(loaded.filePath)).join(", ");
|
|
313
|
-
for (const loaded of candidates) {
|
|
314
|
-
loaded.diagnostics.push({
|
|
315
|
-
level: "error",
|
|
316
|
-
field: "autoActivate",
|
|
317
|
-
message: `Multiple ${scope} profiles request auto-activation (${files}); exactly one is allowed.`,
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
function normalizeAgentProfile(raw, filePath, diagnostics) {
|
|
323
|
-
if (!isPlainObject(raw)) {
|
|
324
|
-
diagnostics.push({ level: "error", message: "Agent profile root must be a JSON object." });
|
|
325
|
-
return fallbackProfile(filePath);
|
|
326
|
-
}
|
|
327
|
-
for (const field of Object.keys(raw)) {
|
|
328
|
-
if (!PROFILE_FIELDS.has(field))
|
|
329
|
-
diagnostics.push({ level: "error", field, message: `Unsupported profile field: ${field}` });
|
|
330
|
-
}
|
|
331
|
-
if (raw.schemaVersion !== 1)
|
|
332
|
-
diagnostics.push({ level: "error", field: "schemaVersion", message: "schemaVersion must be 1." });
|
|
333
|
-
if (raw.type !== AGENT_PROFILE_TYPE)
|
|
334
|
-
diagnostics.push({ level: "error", field: "type", message: `type must be "${AGENT_PROFILE_TYPE}".` });
|
|
335
|
-
const id = nonEmptyString(raw.id);
|
|
336
|
-
if (!id)
|
|
337
|
-
diagnostics.push({ level: "error", field: "id", message: "Profile id must be a non-empty string." });
|
|
338
|
-
const model = normalizeModelReference(raw.model, diagnostics);
|
|
339
|
-
const thinkingLevel = normalizeThinkingLevel(raw.thinkingLevel, diagnostics);
|
|
340
|
-
const promptStack = normalizePromptStackReference(raw, diagnostics);
|
|
341
|
-
if (raw.name !== undefined && typeof raw.name !== "string")
|
|
342
|
-
diagnostics.push({ level: "error", field: "name", message: "name must be a string when provided." });
|
|
343
|
-
if (raw.description !== undefined && typeof raw.description !== "string") {
|
|
344
|
-
diagnostics.push({ level: "error", field: "description", message: "description must be a string when provided." });
|
|
345
|
-
}
|
|
346
|
-
if (raw.autoActivate !== undefined && typeof raw.autoActivate !== "boolean") {
|
|
347
|
-
diagnostics.push({ level: "error", field: "autoActivate", message: "autoActivate must be a boolean when provided." });
|
|
348
|
-
}
|
|
349
|
-
return {
|
|
350
|
-
schemaVersion: 1,
|
|
351
|
-
type: AGENT_PROFILE_TYPE,
|
|
352
|
-
id: id ?? basename(filePath, ".json"),
|
|
353
|
-
name: typeof raw.name === "string" ? raw.name : undefined,
|
|
354
|
-
description: typeof raw.description === "string" ? raw.description : undefined,
|
|
355
|
-
autoActivate: typeof raw.autoActivate === "boolean" ? raw.autoActivate : undefined,
|
|
356
|
-
model,
|
|
357
|
-
thinkingLevel,
|
|
358
|
-
promptStack,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
function normalizeModelReference(raw, diagnostics) {
|
|
362
|
-
if (!isPlainObject(raw)) {
|
|
363
|
-
diagnostics.push({ level: "error", field: "model", message: "model must be an object containing provider and id." });
|
|
364
|
-
return { provider: "", id: "" };
|
|
365
|
-
}
|
|
366
|
-
for (const field of Object.keys(raw)) {
|
|
367
|
-
if (!MODEL_FIELDS.has(field))
|
|
368
|
-
diagnostics.push({ level: "error", field: `model.${field}`, message: `Unsupported model field: ${field}` });
|
|
369
|
-
}
|
|
370
|
-
const provider = nonEmptyString(raw.provider);
|
|
371
|
-
const id = nonEmptyString(raw.id);
|
|
372
|
-
return { provider: provider ?? "", id: id ?? "" };
|
|
373
|
-
}
|
|
374
|
-
function normalizeThinkingLevel(raw, diagnostics) {
|
|
375
|
-
if (typeof raw === "string" && VALID_THINKING_LEVELS.has(raw))
|
|
376
|
-
return raw;
|
|
377
|
-
diagnostics.push({
|
|
378
|
-
level: "error",
|
|
379
|
-
field: "thinkingLevel",
|
|
380
|
-
message: `thinkingLevel must be one of: ${AGENT_PROFILE_THINKING_LEVELS.join(", ")}.`,
|
|
381
|
-
});
|
|
382
|
-
return "off";
|
|
383
|
-
}
|
|
384
|
-
function normalizePromptStackReference(raw, diagnostics) {
|
|
385
|
-
if (!Object.prototype.hasOwnProperty.call(raw, "promptStack")) {
|
|
386
|
-
diagnostics.push({ level: "error", field: "promptStack", message: "promptStack is required and must be a stack id or null." });
|
|
387
|
-
return null;
|
|
388
|
-
}
|
|
389
|
-
if (raw.promptStack === null)
|
|
390
|
-
return null;
|
|
391
|
-
const id = nonEmptyString(raw.promptStack);
|
|
392
|
-
if (id)
|
|
393
|
-
return id;
|
|
394
|
-
diagnostics.push({ level: "error", field: "promptStack", message: "promptStack must be a non-empty stack id or null." });
|
|
395
|
-
return null;
|
|
396
|
-
}
|
|
397
|
-
function fallbackProfile(filePath) {
|
|
398
|
-
return {
|
|
399
|
-
schemaVersion: 1,
|
|
400
|
-
type: AGENT_PROFILE_TYPE,
|
|
401
|
-
id: basename(filePath, ".json"),
|
|
402
|
-
model: { provider: "", id: "" },
|
|
403
|
-
thinkingLevel: "off",
|
|
404
|
-
promptStack: null,
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
function nonEmptyString(value) {
|
|
408
|
-
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
409
|
-
}
|
|
410
|
-
function isPlainObject(value) {
|
|
411
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
412
|
-
}
|
|
413
191
|
//# sourceMappingURL=agent-profile.js.map
|