@davidorex/pi-context 0.29.0 → 0.30.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 +19 -0
- package/README.md +28 -16
- package/dist/block-api.d.ts +12 -3
- package/dist/block-api.d.ts.map +1 -1
- package/dist/block-api.js +16 -5
- package/dist/block-api.js.map +1 -1
- package/dist/context-sdk.d.ts +99 -4
- package/dist/context-sdk.d.ts.map +1 -1
- package/dist/context-sdk.js +183 -13
- package/dist/context-sdk.js.map +1 -1
- package/dist/context.d.ts +43 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +41 -0
- package/dist/context.js.map +1 -1
- package/dist/ops-registry.d.ts +180 -4
- package/dist/ops-registry.d.ts.map +1 -1
- package/dist/ops-registry.js +529 -106
- package/dist/ops-registry.js.map +1 -1
- package/dist/read-element.d.ts +48 -0
- package/dist/read-element.d.ts.map +1 -1
- package/dist/read-element.js +88 -30
- package/dist/read-element.js.map +1 -1
- package/dist/write-schema-migration-tool.d.ts +2 -1
- package/dist/write-schema-migration-tool.d.ts.map +1 -1
- package/dist/write-schema-migration-tool.js +13 -10
- package/dist/write-schema-migration-tool.js.map +1 -1
- package/package.json +1 -1
- package/skills/pi-context/SKILL.md +56 -1
package/dist/ops-registry.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { type TSchema } from "typebox";
|
|
3
|
+
import type { DispatchContext } from "./dispatch-context.js";
|
|
4
|
+
import { type ReadStructured } from "./read-element.js";
|
|
3
5
|
/**
|
|
4
6
|
* One substrate operation. `run(cwd, params)` returns the text payload that
|
|
5
7
|
* registerAll places at `content[0].text`; everything else (param coercion,
|
|
@@ -12,13 +14,51 @@ import { type TSchema } from "typebox";
|
|
|
12
14
|
* for that consumer and is not the enforcement point (the pi-agent-dispatch
|
|
13
15
|
* auth-gate remains canonical).
|
|
14
16
|
*/
|
|
17
|
+
/**
|
|
18
|
+
* The discriminated result of an op's `run` (TASK-012 / FGAP-013). An op returns
|
|
19
|
+
* one of three shapes, each carrying its OWN text-rendering rule so the CLI
|
|
20
|
+
* `--json` envelope can emit a real JSON value (no double-encode) while the
|
|
21
|
+
* default text surface + the in-pi Pi-tool surface stay byte-identical:
|
|
22
|
+
* - `string` — a prose op's human message; rendered as itself.
|
|
23
|
+
* - `{ json: … }` — a data op that previously returned `JSON.stringify(x, null, 2)`;
|
|
24
|
+
* rendered via JSON.stringify, structured value is `json`.
|
|
25
|
+
* - `{ read: … }` — a read op that previously returned `serializeForRead(x).content`;
|
|
26
|
+
* rendered via renderReadText, structured value is the
|
|
27
|
+
* {@link ReadStructured} (data + paging/cap metadata).
|
|
28
|
+
* {@link renderOpResultText} collapses all three back to the text both boundaries
|
|
29
|
+
* emit; the CLI `--json` branch unwraps the structured value instead.
|
|
30
|
+
*/
|
|
31
|
+
export type OpResult = string | {
|
|
32
|
+
json: unknown;
|
|
33
|
+
} | {
|
|
34
|
+
read: ReadStructured;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Collapse an {@link OpResult} to the text the default CLI surface + the in-pi
|
|
38
|
+
* Pi-tool surface emit, NOW BOUNDED at the 50KB read cap (TASK-013 / FGAP-015).
|
|
39
|
+
* `{read}` → renderReadText (already capped); prose `string` → itself when under
|
|
40
|
+
* cap, else the REFUSAL prose; `{json}` → `JSON.stringify(x, null, 2)` when under
|
|
41
|
+
* cap, else the REFUSAL prose (no partial body).
|
|
42
|
+
*/
|
|
43
|
+
export declare function renderOpResultText(r: OpResult): string;
|
|
44
|
+
/**
|
|
45
|
+
* The JSON VALUE for the CLI `--json` envelope `output` field, NOW BOUNDED at the
|
|
46
|
+
* 50KB read cap (TASK-013 / FGAP-015). Prose `string` → itself when under cap,
|
|
47
|
+
* else the REFUSAL string; `{read}` → its ReadStructured (already fail-closed —
|
|
48
|
+
* serializes tiny on over-cap); `{json}` → the raw value when under cap, else a
|
|
49
|
+
* fail-closed envelope that MIRRORS {@link ReadStructured}'s over-cap shape
|
|
50
|
+
* (`{ data: null, truncated: true, totalBytes, complete: false }`) so `--json`
|
|
51
|
+
* consumers see one uniform fail-closed envelope across `{read}` and bounded
|
|
52
|
+
* `{json}`. No partial payload is ever emitted past the cap.
|
|
53
|
+
*/
|
|
54
|
+
export declare function boundedJsonOutput(r: OpResult): unknown;
|
|
15
55
|
export interface OpDefinition<P = any> {
|
|
16
56
|
name: string;
|
|
17
57
|
label: string;
|
|
18
58
|
description: string;
|
|
19
59
|
promptSnippet?: string;
|
|
20
60
|
parameters: TSchema;
|
|
21
|
-
run(cwd: string, params: P):
|
|
61
|
+
run(cwd: string, params: P, ctx?: DispatchContext): OpResult | Promise<OpResult>;
|
|
22
62
|
authGated?: boolean;
|
|
23
63
|
surface: "use" | "process";
|
|
24
64
|
}
|
|
@@ -34,11 +74,147 @@ export declare const ops: OpDefinition[];
|
|
|
34
74
|
* point; this list is the source of pi-context's contribution to it.
|
|
35
75
|
*/
|
|
36
76
|
export declare const gatedTools: string[];
|
|
77
|
+
/**
|
|
78
|
+
* One entry on the {@link INTENTIONALLY_UNEXPOSED_WRITERS} allowlist. `libraryFn`
|
|
79
|
+
* names a library write function deliberately NOT given its own op; exactly one
|
|
80
|
+
* of `safeOp` / `reason` carries the justification (`safeOp` when a safe op
|
|
81
|
+
* supersedes the raw writer; `reason` for internal/foreign-only writers with no
|
|
82
|
+
* op surface at all).
|
|
83
|
+
*/
|
|
84
|
+
export interface UnexposedWriter {
|
|
85
|
+
libraryFn: string;
|
|
86
|
+
reason?: string;
|
|
87
|
+
safeOp?: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The FGAP-009 non-exposure allowlist: every library write function that is
|
|
91
|
+
* deliberately NOT op-backed, with the reason it is withheld. This is the
|
|
92
|
+
* closure contract γ (TASK-008) WILL consume: γ's parity test — not yet written
|
|
93
|
+
* (no executable parity test exists in β; β defines the contract, γ implements
|
|
94
|
+
* the test against it) — WILL assert that EVERY library writer is either op-backed
|
|
95
|
+
* (appears in {@link ops}, directly or transitively) OR named here, so a
|
|
96
|
+
* newly-added library writer with neither an op nor an allowlist entry will fail
|
|
97
|
+
* that test, keeping the op surface and the library write surface in lockstep.
|
|
98
|
+
*
|
|
99
|
+
* The `*ForDir` twins of op-backed writers (e.g. `appendRelationForDir`,
|
|
100
|
+
* `writeRelationsForDir`, `upsertItemInBlockForDir`, `appendToBlockForDir`, …)
|
|
101
|
+
* are NOT enumerated individually: each is the dir-targeted internal twin of a
|
|
102
|
+
* cwd-form writer that IS op-backed, and is covered by that cwd-form op (the op
|
|
103
|
+
* resolves the active substrate dir then delegates to the same shared
|
|
104
|
+
* typed-file primitive the `*ForDir` twin calls). The contract is that γ's
|
|
105
|
+
* parity test (TASK-008, not yet written) WILL treat a `*ForDir` writer as
|
|
106
|
+
* covered when its cwd-form sibling is covered.
|
|
107
|
+
*/
|
|
108
|
+
export declare const INTENTIONALLY_UNEXPOSED_WRITERS: UnexposedWriter[];
|
|
109
|
+
/**
|
|
110
|
+
* The five mutually-exhaustive ways a library write function is COVERED by the
|
|
111
|
+
* FGAP-009 op-surface ↔ library-write-surface parity contract. A writer that
|
|
112
|
+
* matches NONE of these is a silent gap that γ's (TASK-008) parity test — once
|
|
113
|
+
* written — MUST fail on. Coverage is the DISJUNCTION over these classes — a
|
|
114
|
+
* writer needs ANY one, not all.
|
|
115
|
+
*/
|
|
116
|
+
export declare enum CoverageClass {
|
|
117
|
+
/** An op's `run` calls the writer directly (e.g. `append-block-item` → `appendToBlock`). */
|
|
118
|
+
OpBackedDirect = "op-backed-direct",
|
|
119
|
+
/**
|
|
120
|
+
* An op's `run` reaches the writer TRANSITIVELY — through any helper / wrapper
|
|
121
|
+
* chain, not just a direct call. Two sub-shapes both land here:
|
|
122
|
+
* - `*ByRef` / SDK relation porcelain: the `remove-relation` / `replace-relation`
|
|
123
|
+
* / `append-relations` ops call `removeRelationByRef` / `replaceRelationByRef`
|
|
124
|
+
* / `appendRelationsByRef`, which call `writeRelations`.
|
|
125
|
+
* - init / switch → internal-helper chains: `context-init` → `initProject` →
|
|
126
|
+
* `writeSkeletonConfig`; `context-switch` → `switchToExisting` /
|
|
127
|
+
* `switchAndCreate` → `reconcileActiveSubstrateRegistration`. The writer is
|
|
128
|
+
* not a `*ByRef` porcelain and is not allowlisted, but it IS reachable from an
|
|
129
|
+
* op's `run` via a helper the op calls.
|
|
130
|
+
* Coverage condition: reachable from some op's `run` via any helper/wrapper chain.
|
|
131
|
+
*/
|
|
132
|
+
OpBackedTransitive = "op-backed-transitive",
|
|
133
|
+
/**
|
|
134
|
+
* A `*ForDir` dir-targeted twin of a covered cwd-form writer (e.g.
|
|
135
|
+
* `appendToBlockForDir` is the twin of the op-backed `appendToBlock`). Covered
|
|
136
|
+
* by its cwd-form sibling — both delegate to the same shared typed-file
|
|
137
|
+
* primitive; the cwd-form op resolves the active dir then calls it.
|
|
138
|
+
*/
|
|
139
|
+
ForDirTwin = "for-dir-twin",
|
|
140
|
+
/**
|
|
141
|
+
* On {@link INTENTIONALLY_UNEXPOSED_WRITERS}: a raw write deliberately given NO
|
|
142
|
+
* direct op (a scoped op supersedes it, or it is internal/foreign-only).
|
|
143
|
+
*/
|
|
144
|
+
IntentionallyUnexposed = "intentionally-unexposed",
|
|
145
|
+
/**
|
|
146
|
+
* A block-api internal primitive below the op layer — the `*TypedFile` read/
|
|
147
|
+
* write layer (`readTypedFile` / `writeTypedFile`), `prepareItemIdentityForWrite`,
|
|
148
|
+
* and the identity / content-hash helpers. Never op-backed by design; the ops
|
|
149
|
+
* compose over these.
|
|
150
|
+
*/
|
|
151
|
+
InternalPrimitive = "internal-primitive"
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* One clause of {@link OP_COVERAGE_RULE}: a coverage class plus the human-readable
|
|
155
|
+
* test γ applies to decide whether a writer falls in it.
|
|
156
|
+
*/
|
|
157
|
+
export interface CoverageClause {
|
|
158
|
+
coverageClass: CoverageClass;
|
|
159
|
+
test: string;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The FGAP-009 coverage RULE, made explicit so γ (TASK-008) will import the
|
|
163
|
+
* contract rather than re-derive it. A library write function is COVERED iff it
|
|
164
|
+
* matches ANY clause below (the disjunction); a writer matching none is a silent
|
|
165
|
+
* gap that γ's parity test — when written — MUST fail on. β fixes the contract
|
|
166
|
+
* here; no executable parity test exists yet (that is γ).
|
|
167
|
+
*
|
|
168
|
+
* Why `writeConfig` is allowlisted but `writeRelations` is NOT — the distinction
|
|
169
|
+
* a strict name-parity reading mis-saw as inconsistent:
|
|
170
|
+
* - `writeConfig` has NO direct wholesale-config op. The scoped surface is
|
|
171
|
+
* `amend-config` (one-entry-in-one-registry add/replace/remove, AJV-validated),
|
|
172
|
+
* which deliberately does NOT expose a raw whole-config overwrite. So
|
|
173
|
+
* `writeConfig` is `intentionally-unexposed` (the scoped op supersedes the raw
|
|
174
|
+
* writer; a raw wholesale overwrite is withheld by design).
|
|
175
|
+
* - `writeRelations` IS reached — transitively — by the relation ops:
|
|
176
|
+
* `remove-relation` / `replace-relation` / `append-relations` call
|
|
177
|
+
* `removeRelationByRef` / `replaceRelationByRef` / `appendRelationsByRef`, each
|
|
178
|
+
* of which calls `writeRelations`. It is therefore `op-backed-transitive`
|
|
179
|
+
* and needs NO allowlist entry. The asymmetry is real and correct: one writer
|
|
180
|
+
* has an op path (via a helper/wrapper chain), the other does not.
|
|
181
|
+
*
|
|
182
|
+
* The `op-backed-transitive` clause covers BOTH the `*ByRef` relation porcelain
|
|
183
|
+
* AND the init/switch → internal-helper chains: `writeSkeletonConfig` (reached
|
|
184
|
+
* via `context-init` → `initProject`) and `reconcileActiveSubstrateRegistration`
|
|
185
|
+
* (reached via `context-switch` → `switchToExisting` / `switchAndCreate`) are
|
|
186
|
+
* neither `*ByRef` porcelain nor allowlisted, yet each is reachable from an op's
|
|
187
|
+
* `run` through a helper that op calls — so each classifies cleanly as
|
|
188
|
+
* `op-backed-transitive`, not as a gap.
|
|
189
|
+
*/
|
|
190
|
+
export declare const OP_COVERAGE_RULE: CoverageClause[];
|
|
191
|
+
/**
|
|
192
|
+
* Build the DispatchContext threaded into an op's `run` from the in-pi tool
|
|
193
|
+
* execute boundary (registerAll). Two derivation branches:
|
|
194
|
+
*
|
|
195
|
+
* - When `params.writer.user` is a non-empty string — the shape the
|
|
196
|
+
* pi-agent-dispatch auth-gate stamps onto authGated op params on operator
|
|
197
|
+
* confirm — the writer is a human identity. (The smuggle-ops promote-item /
|
|
198
|
+
* write-schema-migration / context-switch carry a `writer` schema field
|
|
199
|
+
* precisely so the gate has somewhere to stamp; this converts that field
|
|
200
|
+
* into the contract ctx the op now consumes via its 3rd `run` arg.)
|
|
201
|
+
* - Otherwise the writer is the running agent, identified by the active
|
|
202
|
+
* model's id (`ExtensionContext.model.id`); falls back to "pi-agent" when
|
|
203
|
+
* no model (or no id) is resolvable.
|
|
204
|
+
*
|
|
205
|
+
* Exported for unit testing — the two branches are asserted directly against
|
|
206
|
+
* synthetic params + a minimal ExtensionContext-shaped object.
|
|
207
|
+
*/
|
|
208
|
+
export declare function buildDispatchContextFromExecute(params: unknown, extCtx: {
|
|
209
|
+
model?: {
|
|
210
|
+
id?: string;
|
|
211
|
+
} | undefined;
|
|
212
|
+
}): DispatchContext;
|
|
37
213
|
/**
|
|
38
214
|
* Register every op in `ops` as a pi tool. Each tool's execute body is the
|
|
39
|
-
* uniform wrapper around the op's run(): coerce params,
|
|
40
|
-
*
|
|
41
|
-
*
|
|
215
|
+
* uniform wrapper around the op's run(): coerce params, build the attestation
|
|
216
|
+
* DispatchContext from the auth-gate-stamped writer (human) or the running
|
|
217
|
+
* model (agent), await run, place the returned string at content[0].text.
|
|
42
218
|
*/
|
|
43
219
|
export declare function registerAll(pi: ExtensionAPI): void;
|
|
44
220
|
//# sourceMappingURL=ops-registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops-registry.d.ts","sourceRoot":"","sources":["../src/ops-registry.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAGX,YAAY,EAEZ,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,OAAO,EAAQ,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ops-registry.d.ts","sourceRoot":"","sources":["../src/ops-registry.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAGX,YAAY,EAEZ,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,OAAO,EAAQ,MAAM,SAAS,CAAC;AAkC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAwB7D,OAAO,EAAe,KAAK,cAAc,EAAoC,MAAM,mBAAmB,CAAC;AAQvG;;;;;;;;;;;GAWG;AACH;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC;AA4C7E;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAStD;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,CAStD;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,eAAe,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,KAAK,GAAG,SAAS,CAAC;CAC3B;AA6BD,eAAO,MAAM,GAAG,EAAE,YAAY,EAmjD7B,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,EAAsD,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,+BAA+B,EAAE,eAAe,EAgB5D,CAAC;AAEF;;;;;;GAMG;AACH,oBAAY,aAAa;IACxB,4FAA4F;IAC5F,cAAc,qBAAqB;IACnC;;;;;;;;;;;;OAYG;IACH,kBAAkB,yBAAyB;IAC3C;;;;;OAKG;IACH,UAAU,iBAAiB;IAC3B;;;OAGG;IACH,sBAAsB,4BAA4B;IAClD;;;;;OAKG;IACH,iBAAiB,uBAAuB;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAqB5C,CAAC;AAYF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,+BAA+B,CAC9C,MAAM,EAAE,OAAO,EACf,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;CAAE,GAC7C,eAAe,CAOjB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAwBlD"}
|