@zihanw/pi-forge 0.5.0 → 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 +38 -0
- package/README.md +2 -1
- package/README.zh-CN.md +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/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/lifecycle.d.ts +2 -0
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +2 -0
- package/dist/lifecycle.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 +2 -0
- 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 +3 -0
- package/dist/payload-state.d.ts.map +1 -1
- package/dist/payload-state.js +5 -0
- package/dist/payload-state.js.map +1 -1
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +17 -3
- package/dist/preview.js.map +1 -1
- package/dist/runtime/tool-policy-runtime.d.ts.map +1 -1
- package/dist/runtime/tool-policy-runtime.js +13 -3
- 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/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 +71 -6
- 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 +188 -21
- package/dist/web-editor/styles.js.map +1 -1
- package/dist/web-editor/types.d.ts +12 -0
- package/dist/web-editor/types.d.ts.map +1 -1
- package/dist/web-host.d.ts +2 -0
- package/dist/web-host.d.ts.map +1 -1
- package/dist/web-host.js +1 -0
- package/dist/web-host.js.map +1 -1
- package/docs/README.md +1 -0
- package/docs/concepts/agent-profiles.md +1 -1
- package/docs/design/0.5.1-plan.md +237 -0
- package/docs/design/architecture-0.5.md +12 -1
- package/docs/design/context-diff-plan.md +8 -2
- package/docs/development/release.md +7 -1
- package/docs/guides/delegation.md +3 -3
- package/docs/guides/web-editor.md +1 -1
- package/docs/reference/commands.md +1 -1
- package/docs/reference/configuration.md +2 -2
- package/docs/reference/public-api.md +14 -2
- package/docs/reference/stack-schema.md +1 -1
- package/docs/reference/ui-contribution-port.md +51 -0
- package/docs/zh-CN/concepts/agent-profiles.md +1 -1
- package/docs/zh-CN/concepts/prompt-stacks.md +1 -1
- package/docs/zh-CN/guides/delegation.md +2 -2
- package/docs/zh-CN/reference/commands.md +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# pi-forge 0.5.1 — Combined Release Plan
|
|
2
|
+
|
|
3
|
+
Status: active. Target release: 0.5.1 (first feature release after 0.5.0).
|
|
4
|
+
Owner of truth: this document. Supersedes/folds in:
|
|
5
|
+
- `docs/design/context-diff-plan.md` (context diff, now Lane 2)
|
|
6
|
+
- The subagent UI-contribution discussion from the 0.5.x review thread (now Lane 1)
|
|
7
|
+
|
|
8
|
+
Theme: **observability + subagent usability**. 0.5.0 was the architecture-split
|
|
9
|
+
release; 0.5.1 ships per-turn prompt observability and makes the optional
|
|
10
|
+
subagent package configurable without hand-editing JSON.
|
|
11
|
+
|
|
12
|
+
## Lane ordering (deliberate)
|
|
13
|
+
|
|
14
|
+
**Lane 1 ships first.** Its tab-registry refactor turns the web editor's tab
|
|
15
|
+
system data-driven, which Lane 2's Preview dock builds on. Both lanes touch the
|
|
16
|
+
client build pipeline and the tab area — do not run them in parallel in the
|
|
17
|
+
same working tree.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Lane 1 — UI contribution framework + subagent config UI
|
|
22
|
+
|
|
23
|
+
### Goal
|
|
24
|
+
|
|
25
|
+
Let the optional `@zihanw/pi-forge-subagents` package own its configuration UI
|
|
26
|
+
(schema, validation, defaults, file writes) while the rendered settings tab
|
|
27
|
+
appears inside the pi-forge web editor when — and only when — the subagent
|
|
28
|
+
package is installed.
|
|
29
|
+
|
|
30
|
+
Non-goal: arbitrary JS/component injection into the forge web UI. The event bus
|
|
31
|
+
carries JSON only; that rule does not bend for UI.
|
|
32
|
+
|
|
33
|
+
### Architecture (schema-driven contribution, "plan A")
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
┌─ pi-forge-subagents ─────────────┐ ┌─ pi-forge ─────────────────┐
|
|
37
|
+
│ UI contribution provider: │ bus │ web host discovers provider │
|
|
38
|
+
│ · getContribution() → { tabId, │ ◄────── │ at startup (capability │
|
|
39
|
+
│ title, icon, schema, values } │ JSON │ negotiation) │
|
|
40
|
+
│ · writeValues(patch) → validate │ ──────► │ generic schema-form tab │
|
|
41
|
+
│ + write subagents.json │ │ (self-contained Vue comp.) │
|
|
42
|
+
└──────────────────────────────────┘ │ PUT /api/contrib/<id> proxy │
|
|
43
|
+
└─────────────────────────────┘
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- **Contribution protocol**: new versioned port, separate version counter from
|
|
47
|
+
the v1 host port. All payloads are plain recursively-validated JSON (schema +
|
|
48
|
+
values), same discipline as `host-port.ts`.
|
|
49
|
+
- **Forge side** is fully generic: it knows nothing about subagents. No
|
|
50
|
+
provider discovered → no contributed tab, zero cost.
|
|
51
|
+
- **Config ownership stays put**: `subagents.json` (project/global + legacy
|
|
52
|
+
fallback) remains owned and written by the subagent package. Forge's web
|
|
53
|
+
server only proxies the bus call.
|
|
54
|
+
|
|
55
|
+
### Forge-side changes (~1.5–2d)
|
|
56
|
+
|
|
57
|
+
1. Tab registry: replace the hardcoded `"policy" | "regex" | "stack"` union in
|
|
58
|
+
`vue-tab-host.ts` with a data-driven registry (string tab ids, dynamic
|
|
59
|
+
buttons in `App.vue`).
|
|
60
|
+
2. Generic schema-form renderer: self-contained Vue component, bridged via the
|
|
61
|
+
vue-host mechanism. Restricted field types for v1: boolean, number, enum,
|
|
62
|
+
string, plus a record/table shape for per-profile entries. **Do NOT add
|
|
63
|
+
imperative code to `legacy-editor.ts`.**
|
|
64
|
+
3. Web server: `PUT /api/contrib/<tabId>` route proxying `writeValues` over the
|
|
65
|
+
bus; contribution descriptors fetched at page load through `/api/contrib`.
|
|
66
|
+
4. Contribution discovery: web host acts as client toward the provider port;
|
|
67
|
+
tolerate provider disappear/reappear across sessions.
|
|
68
|
+
|
|
69
|
+
### Subagents-side changes (~1d)
|
|
70
|
+
|
|
71
|
+
1. Provider endpoint implementing the contribution protocol.
|
|
72
|
+
2. `ForgeSubagentSettings` → schema mapping (backend, timeoutMs,
|
|
73
|
+
approval flag, summary-in-description flag, per-profile
|
|
74
|
+
enabled/backend/timeout table).
|
|
75
|
+
3. Server-side re-validation on write, reusing existing validators
|
|
76
|
+
(`isValidSubagentTimeoutMs` et al.). Never trust the web client.
|
|
77
|
+
4. TUI companion: `/forge-agent config` subcommand for the same settings
|
|
78
|
+
(internal to the package, no cross-repo coordination).
|
|
79
|
+
|
|
80
|
+
### Known v1 limitation
|
|
81
|
+
|
|
82
|
+
Pure schema cannot express "dropdown fed by live forge data" (e.g. a profileId
|
|
83
|
+
picker backed by `listProfiles`). v1: plain text input + validation errors.
|
|
84
|
+
v2 candidate: a "remote data source" field type. Do not gold-plate v1.
|
|
85
|
+
|
|
86
|
+
### Lane 1B — subagent call-time UX (subagents package only)
|
|
87
|
+
|
|
88
|
+
Two usability extras that live entirely in `@zihanw/pi-forge-subagents`; no
|
|
89
|
+
forge-side coupling, safe to build in parallel with the forge contribution
|
|
90
|
+
framework.
|
|
91
|
+
|
|
92
|
+
**1. Call-time model override** (~0.5d)
|
|
93
|
+
|
|
94
|
+
Main agent may pick the execution model per `forge_subagent` call; default
|
|
95
|
+
remains the profile's model. Feasibility already verified: the wire carries
|
|
96
|
+
model facts (`ForgeBackendFacts.model`, `ForgePrepareResponse.model`), and the
|
|
97
|
+
pi-subagent-runtime subprocess backend already spawns with `--model` — only
|
|
98
|
+
the tool surface lacks the knob.
|
|
99
|
+
|
|
100
|
+
- Add optional `model` parameter (`provider/id` string, parsed + validated) to
|
|
101
|
+
`ForgeSubagentParameters`.
|
|
102
|
+
- Resolution order: `model` param > profile default.
|
|
103
|
+
- Same policy as the `backend` param: override allowed for interactively
|
|
104
|
+
approved runs; unattended invocation is pinned to the profile/configured
|
|
105
|
+
model.
|
|
106
|
+
- Approval summary's existing `Model:` line shows the effective model for free.
|
|
107
|
+
- Update tool description accordingly.
|
|
108
|
+
|
|
109
|
+
**2. Restore rich TUI rendering for subagent runs** (~0.5–1d)
|
|
110
|
+
|
|
111
|
+
The 0.4 tool shipped `renderCall`/`renderResult` (pi-tui Container/Markdown,
|
|
112
|
+
collapsed/expanded states, live progress, usage stats); the 0.5 split dropped
|
|
113
|
+
them, falling back to the default tool display. Streaming infrastructure is
|
|
114
|
+
still intact (`onUpdate` progress pushes, `details.progress` ring buffer at
|
|
115
|
+
`MAX_PROGRESS_ITEMS`).
|
|
116
|
+
|
|
117
|
+
- Port the 0.4.1 renderers from git history (`v0.4.1:src/subagent-tool.ts`)
|
|
118
|
+
into `forge-subagent.ts`, adapted to the current details shape and including
|
|
119
|
+
the approval receipt.
|
|
120
|
+
- `@earendil-works/pi-tui` is already an optional peer dependency.
|
|
121
|
+
- Reference the historical render tests where recoverable.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Lane 2 — Context diff (folded from context-diff-plan.md)
|
|
126
|
+
|
|
127
|
+
### Goal
|
|
128
|
+
|
|
129
|
+
Per-turn observability for prompt changes so users can optimize KV-cache reuse:
|
|
130
|
+
|
|
131
|
+
- Mark which blocks of the prompt changed after each turn.
|
|
132
|
+
- Show token delta (added/removed/modified) vs the previous turn.
|
|
133
|
+
- Mark where the KV-cache prefix survives ("cache boundary").
|
|
134
|
+
|
|
135
|
+
Secondary goal: merge with live preview — while editing a stack,
|
|
136
|
+
debounce-compile and diff against the previous compile, so edits show their
|
|
137
|
+
prompt/token impact immediately.
|
|
138
|
+
|
|
139
|
+
### Existing building blocks
|
|
140
|
+
|
|
141
|
+
- `src/payload-capture.ts` — real provider request payload (secret-redacted),
|
|
142
|
+
with deliberately rough `approxTokens` (chars/4).
|
|
143
|
+
- Pi's authoritative assistant `message_end` usage — input, output, cache read,
|
|
144
|
+
and cache write token buckets correlated FIFO with captured provider requests.
|
|
145
|
+
- `src/preview.ts` — edit-time compile output split into sections (system +
|
|
146
|
+
per-message), each with chars/approxTokens.
|
|
147
|
+
- Legacy editor already polls payload state every 2s.
|
|
148
|
+
|
|
149
|
+
### Two data sources
|
|
150
|
+
|
|
151
|
+
| Scenario | Source | Question answered |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| Edit time (live preview merge point) | debounced compile vs previous compile | "what does this edit change, how many tokens" |
|
|
154
|
+
| Run time (request structure) | diff of consecutive real payloads | "where would the reusable serialized prefix end, and what changed" |
|
|
155
|
+
| Run time (provider truth) | correlated assistant usage | "how many prompt tokens and cache reads/writes did the provider report" |
|
|
156
|
+
|
|
157
|
+
### Core engine: `src/context-diff.ts` (host-neutral pure functions)
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
TurnSnapshot { turnId, capturedAt, stackId, blocks: Block[] }
|
|
161
|
+
Block { key, role, text, chars, approxTokens, hash }
|
|
162
|
+
TurnDiff { blocks: DiffBlock[], prefixTokens, prefixRatio, deltaTokens, summary }
|
|
163
|
+
DiffBlock { status: same|added|removed|modified, before?, after?, tokenDelta }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Cache-boundary algorithm: KV-cache hits depend on the longest common prefix of
|
|
167
|
+
the serialized request. Walk the block arrays in order while hashes match; at
|
|
168
|
+
the first mismatch, trim a char-level common prefix inside that block and
|
|
169
|
+
convert to tokens. Render a boundary marker: "cache valid up to ~18,204 tokens
|
|
170
|
+
(63% of prompt)". No Myers diff needed — prefix + block classification
|
|
171
|
+
suffices.
|
|
172
|
+
|
|
173
|
+
Honesty note: diff token figures remain chars/4 estimates and are always labeled
|
|
174
|
+
as such. Provider prompt/cache usage is displayed separately. Cache hit rate is
|
|
175
|
+
`cacheRead / (input + cacheRead + cacheWrite)` only after cache activity has
|
|
176
|
+
been observed for that provider/model; an all-zero normalized cache bucket is
|
|
177
|
+
otherwise reported as unavailable because it cannot distinguish a true miss
|
|
178
|
+
from a provider that did not report cache detail.
|
|
179
|
+
|
|
180
|
+
### UI
|
|
181
|
+
|
|
182
|
+
Promote the Preview modal into a dockable right-side panel with three tabs:
|
|
183
|
+
|
|
184
|
+
- **Compiled** — current preview content, auto-refresh with 500ms debounce
|
|
185
|
+
while editing (this is the live preview).
|
|
186
|
+
- **Draft diff** and **Run diff** — git-style unified/split line views with
|
|
187
|
+
old/new line numbers, inline changed spans, and selectable changes-only,
|
|
188
|
+
three-line, or full context. Run metadata keeps estimated reusable prefix
|
|
189
|
+
separate from actual provider usage and cache-hit rate.
|
|
190
|
+
|
|
191
|
+
Run-time mode: payload poll captures a new payload → rolling history (last 20
|
|
192
|
+
turns) → auto-compute diff.
|
|
193
|
+
Edit mode: diff current edited compile vs the active on-disk version.
|
|
194
|
+
|
|
195
|
+
Implementation constraint: self-contained Vue component bridged via the
|
|
196
|
+
vue-host mechanism, riding Lane 1's data-driven dock/tab registry. Do NOT add
|
|
197
|
+
more imperative code to `legacy-editor.ts`. Do NOT refactor the legacy editor
|
|
198
|
+
in the same lane.
|
|
199
|
+
|
|
200
|
+
### Phases / estimate
|
|
201
|
+
|
|
202
|
+
| Phase | Content | Effort |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| 0 | Design freeze + golden fixtures (turn payload sets) | 0.5d |
|
|
205
|
+
| 1 | `context-diff.ts` engine + unit tests (prefix/add/remove/modify/token rollups) | 1d |
|
|
206
|
+
| 2 | Server endpoint + rolling snapshot state on the web host | 0.5d |
|
|
207
|
+
| 3 | Web UI: preview dock + Diff view (self-contained Vue, bridged, on Lane 1's registry) | 1.5d |
|
|
208
|
+
| 4 | Browser tests + docs + changelog | 0.5–1d |
|
|
209
|
+
|
|
210
|
+
Lane 2 total ~4–5 working days. Descope option (~3d): run-time diff only,
|
|
211
|
+
live preview reduced to plain auto-refresh without edit-time diffing.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Combined estimate
|
|
216
|
+
|
|
217
|
+
| Lane | Content | Effort |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| 1 | UI contribution framework (forge) + provider & config UI (subagents) | ~2.5–3d |
|
|
220
|
+
| 1B | Call-time model override + rich TUI restore (subagents only) | ~1–1.5d |
|
|
221
|
+
| 2 | Context diff engine + dock UI | ~4–5d |
|
|
222
|
+
|
|
223
|
+
~8.5–9.5 working days total, ~2 calendar weeks with review. Both lanes require
|
|
224
|
+
coordinated releases: forge 0.5.1 must understand the contribution protocol
|
|
225
|
+
before (or simultaneously with) subagents 0.5.1 advertising it — the
|
|
226
|
+
capability negotiation makes order-independent rollout safe. Lane 1B lives
|
|
227
|
+
entirely in subagents 0.5.1 and ships with it; the promo should present both
|
|
228
|
+
packages together.
|
|
229
|
+
|
|
230
|
+
## Release narrative
|
|
231
|
+
|
|
232
|
+
0.5.1 headlines "observability + subagent UX". The promo video leads with the
|
|
233
|
+
context diff money shot (edit one system-prompt line, watch the cache-boundary
|
|
234
|
+
marker jump). Promo pipeline follows the AIGC/VIDEO_PRODUCTION ep02 reference:
|
|
235
|
+
`PLAN.md` → script draft → `narration.json` → roughcut → review; terminology
|
|
236
|
+
rule: plain words first, formal term named once ("KV cache" on first mention,
|
|
237
|
+
then "prefix cache / cache reuse region").
|
|
@@ -36,6 +36,15 @@ It is not a platformization release.
|
|
|
36
36
|
12. **Public surfaces are exactly three intentional entry points:** package root default factory, package root named extension API (`registerMacro`, `registerSlot`, and their contract types), and `@zihanw/pi-forge/subagent`. All other root re-exports and `src/*` aliases are removed. `check-package` enforces this allowlist.
|
|
37
37
|
13. **Migration is a small utility plus release notes, not a framework.** A v1-to-v2 script converts mechanical `variables`/macro fields with explicit diagnostics; removed behavior is never silently approximated.
|
|
38
38
|
|
|
39
|
+
## Accepted 0.5.1 amendment: generic settings contributions
|
|
40
|
+
|
|
41
|
+
Dogfooding invalidated decisions 10 and 12 as forward-looking constraints, while preserving their 0.5.0 historical outcome. The accepted 0.5.1 amendment is:
|
|
42
|
+
|
|
43
|
+
1. `@zihanw/pi-forge/ui-contribution` is a fourth intentional, experimental entry point. It is a generic, versioned, data-only event-bus port; main pi-forge owns the renderer and HTTP proxy but has no subagent-specific schema or persistence logic.
|
|
44
|
+
2. Optional packages may contribute restricted schema-driven Settings pages. Schemas and values are recursively validated JSON data; provider handlers may be asynchronous and receive generation-bound cancellation before side effects.
|
|
45
|
+
3. `pi-forge-subagents` remains the sole owner of both `subagents.json` files. It obtains profile choices only through `/subagent`, contributes plain settings descriptors through `/ui-contribution`, and performs all subagent validation and persistence itself.
|
|
46
|
+
4. This amendment does not authorize a general plugin UI/component runtime, arbitrary browser code, a second resource registry, or main-package reads/writes of optional-package configuration.
|
|
47
|
+
|
|
39
48
|
## Extension port contract (0.5.0)
|
|
40
49
|
|
|
41
50
|
The 0.5.0 extension contract is part of the breaking release. It is a trusted-extension port, not a security boundary.
|
|
@@ -77,6 +86,7 @@ flowchart LR
|
|
|
77
86
|
Workspace --> Compiler["forge-v1 compiler"]
|
|
78
87
|
Compiler --> Extensions["Trusted extension port"]
|
|
79
88
|
Workspace -. "event-bus host port v1" .-> Optional["pi-forge-subagents"]
|
|
89
|
+
WebEditor["Generic Settings renderer"] -. "UI contribution port v1" .-> Optional
|
|
80
90
|
Optional --> Runtime["pi-subagent-runtime"]
|
|
81
91
|
```
|
|
82
92
|
|
|
@@ -193,6 +203,7 @@ Lane 4e: release.
|
|
|
193
203
|
- Schema v2, extension contract, and migration notes are documented.
|
|
194
204
|
- Main package has no subagent runtime dependency and passes packed smoke tests alone.
|
|
195
205
|
- Optional package passes packed smoke tests through host port v1 and owns only its dedicated config files.
|
|
206
|
+
- UI contribution port passes schema validation, async generation cancellation, provider churn, and packed optional-consumer tests.
|
|
196
207
|
- No non-allowlisted root exports or `src/*` aliases remain.
|
|
197
208
|
- User-facing breaking changes are documented in English and Chinese.
|
|
198
209
|
|
|
@@ -205,7 +216,7 @@ These items come from the archived full plan and are intentionally not part of 0
|
|
|
205
216
|
- automatic dependency-direction checking;
|
|
206
217
|
- full `PromptStackService` / `AgentProfileService` application facades;
|
|
207
218
|
- complete host RPC operation catalogue, progress events, and richer lifecycle features beyond host port v1;
|
|
208
|
-
- optional-package standalone delegation UI
|
|
219
|
+
- optional-package standalone delegation UI and arbitrary contributed UI components;
|
|
209
220
|
- full public-surface classification register and consumer audit repeat;
|
|
210
221
|
- rolling Pi compatibility matrix and scheduled latest-Pi probe;
|
|
211
222
|
- sandbox, staged writes, new prompt features, richer imports, and orchestration.
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# Context Diff — design plan (post-0.5.0)
|
|
2
2
|
|
|
3
|
-
Status:
|
|
4
|
-
|
|
3
|
+
Status: folded into `docs/design/0.5.1-plan.md` as Lane 2 — that file is now the owner of truth. Kept for discussion history.
|
|
4
|
+
|
|
5
|
+
Implemented follow-up: the dock now provides git-style line diffs and correlates
|
|
6
|
+
captured requests with Pi's assistant usage. The structural cache-prefix figure
|
|
7
|
+
remains a chars/4 estimate; provider-reported cache hit rate is shown separately
|
|
8
|
+
and is unavailable until cache reporting is observed for that provider/model.
|
|
9
|
+
|
|
10
|
+
Original status: planned. Target release: 0.5.1 (first feature release after 0.5.0).
|
|
5
11
|
|
|
6
12
|
## Goal
|
|
7
13
|
|
|
@@ -6,12 +6,18 @@
|
|
|
6
6
|
|
|
7
7
|
1. Confirm the changelog and user documentation describe the intended version and experimental surfaces accurately.
|
|
8
8
|
2. Publish and smoke-test any required `@zihanw/pi-subagent-runtime` version first.
|
|
9
|
-
3. Install dependencies from the lockfile and run `npm run verify
|
|
9
|
+
3. Install dependencies from the lockfile and run `npm run verify`; require the
|
|
10
|
+
Ubuntu, macOS, and Windows GitHub Actions jobs to pass for the release commit.
|
|
10
11
|
4. Test a packed installation against the documented minimum and current Pi versions.
|
|
11
12
|
5. Exercise ordinary stack/profile use independently of delegation.
|
|
12
13
|
6. Exercise both configured foreground backends and confirm unsupported host capabilities fail closed before provider transport.
|
|
13
14
|
7. Inspect `npm pack --dry-run` for package size and unexpected or missing files.
|
|
14
15
|
|
|
16
|
+
The macOS and Windows jobs run the same complete verification surface as Linux,
|
|
17
|
+
including the real-browser editor suite against the hosted runner's system
|
|
18
|
+
Chrome. Compatibility-version and scheduled latest-Pi probes remain Linux-only;
|
|
19
|
+
they test dependency drift rather than operating-system behavior.
|
|
20
|
+
|
|
15
21
|
## Dependency policy
|
|
16
22
|
|
|
17
23
|
Published manifests use wildcard peer dependencies for Pi-host-provided SDK packages. Exact versions belong in development dependencies and the lockfile so tests are reproducible without restricting compatible host releases.
|
|
@@ -15,11 +15,11 @@ Profiles are not delegatable by default. Enable each eligible ID in the trusted
|
|
|
15
15
|
"backend": "pi-subprocess-readonly",
|
|
16
16
|
"timeoutMs": 60000,
|
|
17
17
|
"profiles": {
|
|
18
|
-
"reviewer": {
|
|
18
|
+
"project:reviewer": {
|
|
19
19
|
"enabled": true,
|
|
20
20
|
"timeoutMs": 300000
|
|
21
21
|
},
|
|
22
|
-
"rpc-reviewer": {
|
|
22
|
+
"project:rpc-reviewer": {
|
|
23
23
|
"enabled": true,
|
|
24
24
|
"backend": "pi-rpc-readonly",
|
|
25
25
|
"timeoutMs": 180000
|
|
@@ -28,7 +28,7 @@ Profiles are not delegatable by default. Enable each eligible ID in the trusted
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Legacy `.pi/forge/config.json.subagents` is accepted as read-only fallback with a warning.
|
|
31
|
+
Legacy `.pi/forge/config.json.subagents` is accepted as read-only fallback with a warning. Authorization keys should be canonical selectors: `project:<id>` or `global:<id>`. Bare keys remain a compatibility spelling for project profiles only, even inside `~/.pi/forge/subagents.json`; use an explicit key such as `global:reviewer` to authorize a global profile. Same-ID global and project profiles never inherit enablement, backend, or timeout policy from one another. Disabled or unlisted profiles are hidden from discovery and rejected even if guessed.
|
|
32
32
|
|
|
33
33
|
## Discover, plan, and run
|
|
34
34
|
|
|
@@ -43,7 +43,7 @@ The stack workspace provides:
|
|
|
43
43
|
- payload arming and redacted captured-payload inspection;
|
|
44
44
|
- light and dark themes.
|
|
45
45
|
|
|
46
|
-
Existing IDs are immutable during edit. Use **Fork** to create a different ID without breaking profile references or the active selection. The
|
|
46
|
+
Existing IDs are immutable during edit. Use **More → Fork** to create a different ID without breaking profile references or the active selection. The compact selector attached to **New stack** (default `Project`) chooses where new stacks, imports, and forks are written: `Global` targets the user-global `~/.pi/forge/prompt-stacks`, `Project` targets `.pi/forge/prompt-stacks`. Less-used capture, fork, import, export, and delete actions live under **More** so the stack and Preview/Diff panes keep the available viewport. Stack rows show a `global` badge, and save/delete routes use `global:<id>` for exact global mutations. Legacy stacks remain editable in place.
|
|
47
47
|
|
|
48
48
|
Saves, imports, forks, and deletes reload stack state into the current Pi session. When another surface changes a referenced stack, returning to profiles refreshes profile resolution.
|
|
49
49
|
|
|
@@ -49,7 +49,7 @@ The commands below are provided by the optional `@zihanw/pi-forge-subagents` pac
|
|
|
49
49
|
| `/forge-agent plan <profile> [--backend <id>] <task>` | Prepare, validate, display, and discard an exact plan without provider transport. |
|
|
50
50
|
| `/forge-agent run <profile> [--backend <id>] <task>` | Review and approve an exact foreground read-only run. |
|
|
51
51
|
|
|
52
|
-
Only
|
|
52
|
+
Only explicitly scoped profiles are accepted: use `project:<id>` or `global:<id>` keys in `subagents.json`. A bare authorization key always means `project:<id>`, even in the global file; `.pi/forge/config.json.subagents` remains a read-only legacy fallback. The model-callable equivalents are `forge_subagent_profiles` (local discovery) and `forge_subagent` (execution). See the [delegation safety guide](../guides/delegation.md).
|
|
53
53
|
|
|
54
54
|
## Payload inspection
|
|
55
55
|
|
|
@@ -38,7 +38,7 @@ Trusted project `subagents.json` may override defaults, authorize individual pro
|
|
|
38
38
|
"allowAgentInvocationWithoutApproval": false,
|
|
39
39
|
"summaryInToolDescription": false,
|
|
40
40
|
"profiles": {
|
|
41
|
-
"reviewer": {
|
|
41
|
+
"project:reviewer": {
|
|
42
42
|
"enabled": true,
|
|
43
43
|
"backend": "pi-rpc-readonly",
|
|
44
44
|
"timeoutMs": 180000
|
|
@@ -51,7 +51,7 @@ Valid timeouts are 1,000–3,600,000 ms. Invalid fields warn and fall back to th
|
|
|
51
51
|
|
|
52
52
|
`summaryInToolDescription` (default `false`) embeds a compact, bounded summary of enabled subagent profiles directly in the `forge_subagent` tool description so the parent model can pick a profile without a discovery call. Ready profiles appear first, and unavailable enabled profiles include their first resolution error. It may be set in user or trusted-project `subagents.json` and applies wherever it is enabled.
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Profile authorization keys should use canonical selectors: `project:<id>` or `global:<id>`. A bare key is a compatibility spelling for `project:<id>` regardless of which config file contains it; it never authorizes a global profile. Therefore a global profile must be written explicitly as `"global:reviewer": { "enabled": true }` in `~/.pi/forge/subagents.json`. Same-ID profiles never inherit enablement, backend, or timeout policy from each other. `allowAgentInvocationWithoutApproval` is project-only, requires trust, and fails closed when malformed. Deleting a profile does not modify `subagents.json`; remove any enabled entry for the deleted profile manually.
|
|
55
55
|
|
|
56
56
|
Treat project configuration as an authorization boundary. In particular, do not commit unattended delegation unless every permitted parent agent may transmit compiled prompt and readable project content without another human approval.
|
|
57
57
|
|
|
@@ -4,7 +4,7 @@
|
|
|
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
|
-
## The
|
|
7
|
+
## The four intentional entry points
|
|
8
8
|
|
|
9
9
|
`check-package` enforces this allowlist; nothing else is importable from the package.
|
|
10
10
|
|
|
@@ -60,10 +60,22 @@ The experimental host port over the Pi event bus: discovery, profile listing/sna
|
|
|
60
60
|
|
|
61
61
|
The optional `@zihanw/pi-forge-subagents` package consumes this port and owns subagent execution and configuration.
|
|
62
62
|
|
|
63
|
+
### 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
|
+
|
|
63
75
|
## Compatibility policy
|
|
64
76
|
|
|
65
77
|
- **Stable** surfaces (root factory, macro/slot registration) preserve source compatibility within the documented release range unless a changelog entry announces a breaking release.
|
|
66
|
-
- **Experimental** surfaces (the `/subagent`
|
|
78
|
+
- **Experimental** surfaces (the `/subagent` and `/ui-contribution` ports) are typed, tested, and documented, but may change deliberately as integration experience exposes missing semantics.
|
|
67
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`.
|
|
68
80
|
|
|
69
81
|
## Removed in 0.5.0
|
|
@@ -95,7 +95,7 @@ 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
|
|
|
@@ -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.
|
|
@@ -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 授权由可选包 `@zihanw/pi-forge-subagents`
|
|
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)。
|
|
@@ -27,7 +27,7 @@ Prompt stack 是一份有序、声明式的 prompt 与策略描述,由固定 *
|
|
|
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
|
|
|
@@ -15,7 +15,7 @@ Profile 默认不能委派。请在可信项目的 `.pi/forge/subagents.json`
|
|
|
15
15
|
"backend": "pi-subprocess-readonly",
|
|
16
16
|
"timeoutMs": 60000,
|
|
17
17
|
"profiles": {
|
|
18
|
-
"reviewer": {
|
|
18
|
+
"project:reviewer": {
|
|
19
19
|
"enabled": true,
|
|
20
20
|
"timeoutMs": 300000
|
|
21
21
|
}
|
|
@@ -23,7 +23,7 @@ Profile 默认不能委派。请在可信项目的 `.pi/forge/subagents.json`
|
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
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 也会被拒绝。
|
|
27
27
|
|
|
28
28
|
## Plan 与运行
|
|
29
29
|
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
| `/forge-agent plan <profile> [--backend <id>] <task>` | 准备、显示并丢弃计划,不联系 provider |
|
|
50
50
|
| `/forge-agent run <profile> [--backend <id>] <task>` | 审批并执行前台只读任务 |
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
只接受明确 scope 的授权:请在 `subagents.json` 中使用 `project:<id>` 或 `global:<id>` key。裸授权 key 始终表示 `project:<id>`,即使它位于全局配置中;`.pi/forge/config.json.subagents` 仅作为只读兼容来源。模型工具为 `forge_subagent_profiles` 和 `forge_subagent`。见[安全说明](../guides/delegation.md)。
|
|
53
53
|
|
|
54
54
|
## Payload
|
|
55
55
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zihanw/pi-forge",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Pi extension for prompt stacks, one-shot agent profiles, policy, import, and debugging.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"types": "./dist/subagent/index.d.ts",
|
|
18
18
|
"import": "./dist/subagent/index.js",
|
|
19
19
|
"default": "./dist/subagent/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./ui-contribution": {
|
|
22
|
+
"types": "./dist/ui-contribution/index.d.ts",
|
|
23
|
+
"import": "./dist/ui-contribution/index.js",
|
|
24
|
+
"default": "./dist/ui-contribution/index.js"
|
|
20
25
|
}
|
|
21
26
|
},
|
|
22
27
|
"keywords": [
|