@quandev104/pi-style 0.1.5 → 0.1.7
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 +12 -0
- package/README.md +5 -3
- package/dist/extensions/pi-style.js +8542 -8253
- package/dist/extensions/pi-style.js.map +1 -1
- package/extension-src/pi-style/app/command-service.ts +4 -0
- package/extension-src/pi-style/domain/config-authorization.ts +6 -3
- package/extension-src/pi-style/domain/config-normalization.ts +12 -1
- package/extension-src/pi-style/domain/config-presets.ts +2 -2
- package/extension-src/pi-style/domain/config-types.ts +18 -2
- package/extension-src/pi-style/features/messages/index.ts +58 -10
- package/extension-src/pi-style/features/tools/boxed/index.ts +41 -1
- package/extension-src/pi-style/features/tools/boxed/session-config.ts +3 -0
- package/extension-src/pi-style/features/tools/boxed/turn-summary.ts +368 -0
- package/extension-src/pi-style/features/tools/index.ts +15 -0
- package/extension-src/pi-style/pi/compatibility-coordinator.ts +17 -12
- package/extension-src/pi-style/pi/compatibility-probe.ts +304 -256
- package/extension-src/pi-style/pi/index.ts +40 -5
- package/extension-src/pi-style/pi/session-coordinator.ts +7 -0
- package/package.json +9 -9
|
@@ -25,142 +25,130 @@ import {
|
|
|
25
25
|
nextGeneration,
|
|
26
26
|
} from "./compatibility-registry.js";
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
export const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
28
|
+
/**
|
|
29
|
+
* Certification is identity-first, never version-pinned: a surface is certified
|
|
30
|
+
* when the runtime method (or class constructor, for additive installs) matches a
|
|
31
|
+
* recorded name/arity/source-fingerprint identity. Pi version strings are
|
|
32
|
+
* informational only (diagnostics, doctor output) and never gate installation — a
|
|
33
|
+
* version drift that preserves the native identity keeps working, and a drift that
|
|
34
|
+
* changes the identity degrades that single surface to its native fallback while
|
|
35
|
+
* every other surface continues.
|
|
36
|
+
*/
|
|
37
|
+
export const SUPPORTED_VERSION_RANGE = ">=0.83.0 <0.85.0";
|
|
38
|
+
export const SUPPORTED_PI_VERSIONS: readonly string[] = Object.freeze(["0.83.0", "0.84.0"]);
|
|
39
|
+
|
|
40
|
+
/** A recorded native identity for one certified surface. */
|
|
41
|
+
export interface KnownNativeIdentity {
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly arity: number;
|
|
44
|
+
readonly fingerprint: string;
|
|
45
|
+
/** Pi versions known to carry this exact identity (informational only). */
|
|
46
|
+
readonly versions: readonly string[];
|
|
47
|
+
}
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Registry of recorded native identities per surface. A surface matches when the
|
|
51
|
+
* runtime function has the same name, arity, and source fingerprint as one of its
|
|
52
|
+
* identities; the `versions` list only documents where that identity was observed.
|
|
53
|
+
* A matching name/arity/hash is evidence of the shipped native method, not a
|
|
54
|
+
* cryptographic proof: code loaded before this module could spoof the same
|
|
55
|
+
* function source. Unrecorded identities therefore fall back natively per surface.
|
|
56
|
+
*/
|
|
57
|
+
export const KNOWN_NATIVE_IDENTITIES: Readonly<Record<string, readonly KnownNativeIdentity[]>> = Object.freeze({
|
|
58
|
+
"native-assistant-message:render": Object.freeze([
|
|
59
|
+
Object.freeze({
|
|
59
60
|
name: "render",
|
|
60
61
|
arity: 1,
|
|
61
|
-
fingerprint:
|
|
62
|
-
|
|
63
|
-
status: "certified" as const,
|
|
62
|
+
fingerprint: "2a39243f",
|
|
63
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
64
64
|
}),
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
name: "getCallRenderer",
|
|
73
|
-
arity: 0,
|
|
74
|
-
fingerprint: TRUSTED_NATIVE_FINGERPRINTS["tool-call-renderer:getCallRenderer"],
|
|
75
|
-
adapterId: "tool-renderer-component-v1",
|
|
76
|
-
status: "certified" as const,
|
|
77
|
-
}),
|
|
78
|
-
"tool-result-renderer:getResultRenderer": Object.freeze({
|
|
79
|
-
feature: "tools",
|
|
80
|
-
subtype: "tool-result-renderer",
|
|
81
|
-
target: ToolExecutionComponent.prototype,
|
|
82
|
-
method: "getResultRenderer",
|
|
83
|
-
writable: true,
|
|
84
|
-
configurable: true,
|
|
85
|
-
name: "getResultRenderer",
|
|
86
|
-
arity: 0,
|
|
87
|
-
fingerprint: TRUSTED_NATIVE_FINGERPRINTS["tool-result-renderer:getResultRenderer"],
|
|
88
|
-
adapterId: "tool-renderer-component-v1",
|
|
89
|
-
status: "certified" as const,
|
|
65
|
+
]),
|
|
66
|
+
"native-assistant-message:updateContent": Object.freeze([
|
|
67
|
+
Object.freeze({
|
|
68
|
+
name: "updateContent",
|
|
69
|
+
arity: 1,
|
|
70
|
+
fingerprint: "4a2f15ff",
|
|
71
|
+
versions: Object.freeze(["0.83.0"]),
|
|
90
72
|
}),
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
method: "updateContent",
|
|
96
|
-
writable: true,
|
|
97
|
-
configurable: true,
|
|
73
|
+
// 0.84.0 adds an `isStreaming` default parameter and per-part markdown
|
|
74
|
+
// transforms; default parameters do not count toward Function.length, so
|
|
75
|
+
// the arity stays 1 while the source fingerprint changes.
|
|
76
|
+
Object.freeze({
|
|
98
77
|
name: "updateContent",
|
|
99
78
|
arity: 1,
|
|
100
|
-
fingerprint:
|
|
101
|
-
|
|
102
|
-
status: "certified" as const,
|
|
79
|
+
fingerprint: "d2114491",
|
|
80
|
+
versions: Object.freeze(["0.84.0"]),
|
|
103
81
|
}),
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
adapterId: "message-block-boxed-v1",
|
|
112
|
-
status: "certified" as const,
|
|
82
|
+
]),
|
|
83
|
+
"native-compaction-message:updateDisplay": Object.freeze([
|
|
84
|
+
Object.freeze({
|
|
85
|
+
name: "updateDisplay",
|
|
86
|
+
arity: 0,
|
|
87
|
+
fingerprint: "f8c44e78",
|
|
88
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
113
89
|
}),
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
adapterId: "message-block-boxed-v1",
|
|
122
|
-
status: "certified" as const,
|
|
90
|
+
]),
|
|
91
|
+
"native-branch-message:updateDisplay": Object.freeze([
|
|
92
|
+
Object.freeze({
|
|
93
|
+
name: "updateDisplay",
|
|
94
|
+
arity: 0,
|
|
95
|
+
fingerprint: "415d57b7",
|
|
96
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
123
97
|
}),
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
adapterId: "message-block-boxed-v1",
|
|
132
|
-
status: "certified" as const,
|
|
98
|
+
]),
|
|
99
|
+
"native-skill-message:updateDisplay": Object.freeze([
|
|
100
|
+
Object.freeze({
|
|
101
|
+
name: "updateDisplay",
|
|
102
|
+
arity: 0,
|
|
103
|
+
fingerprint: "48099ea6",
|
|
104
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
133
105
|
}),
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
106
|
+
]),
|
|
107
|
+
"native-custom-message:rebuild": Object.freeze([
|
|
108
|
+
Object.freeze({
|
|
109
|
+
name: "rebuild",
|
|
110
|
+
arity: 0,
|
|
111
|
+
fingerprint: "76ae2e3a",
|
|
112
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
113
|
+
}),
|
|
114
|
+
]),
|
|
115
|
+
"tool-call-renderer:getCallRenderer": Object.freeze([
|
|
116
|
+
Object.freeze({
|
|
117
|
+
name: "getCallRenderer",
|
|
118
|
+
arity: 0,
|
|
119
|
+
fingerprint: "951ea0e0",
|
|
120
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
143
121
|
}),
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
122
|
+
]),
|
|
123
|
+
"tool-result-renderer:getResultRenderer": Object.freeze([
|
|
124
|
+
Object.freeze({
|
|
125
|
+
name: "getResultRenderer",
|
|
126
|
+
arity: 0,
|
|
127
|
+
fingerprint: "8a25cd71",
|
|
128
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
129
|
+
}),
|
|
130
|
+
]),
|
|
131
|
+
"native-bash-execution:render": Object.freeze([
|
|
132
|
+
Object.freeze({
|
|
151
133
|
// The additive render patch is certified by the class constructor identity
|
|
152
134
|
// (name/arity/source fingerprint): the class defines no own `render`, so
|
|
153
135
|
// the installed own method is the only one and the inherited Container
|
|
154
136
|
// render is the native fallback.
|
|
155
137
|
name: "BashExecutionComponent",
|
|
156
138
|
arity: 2,
|
|
157
|
-
fingerprint:
|
|
158
|
-
|
|
159
|
-
status: "certified" as const,
|
|
139
|
+
fingerprint: "a5b5abca",
|
|
140
|
+
versions: Object.freeze(["0.83.0", "0.84.0"]),
|
|
160
141
|
}),
|
|
161
|
-
|
|
142
|
+
]),
|
|
162
143
|
});
|
|
163
144
|
|
|
145
|
+
/** Primary (first-recorded) fingerprint per surface, for diagnostics and back-compat. */
|
|
146
|
+
export const TRUSTED_NATIVE_FINGERPRINTS: Readonly<Record<string, string>> = Object.freeze(
|
|
147
|
+
Object.fromEntries(
|
|
148
|
+
Object.entries(KNOWN_NATIVE_IDENTITIES).map(([key, identities]) => [key, identities[0]!.fingerprint]),
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
|
|
164
152
|
export interface CompatibilityDescriptorSnapshot {
|
|
165
153
|
readonly kind: "data" | "accessor";
|
|
166
154
|
readonly value?: unknown;
|
|
@@ -185,7 +173,7 @@ export interface CompatibilityRecordSnapshot {
|
|
|
185
173
|
|
|
186
174
|
export interface CompatibilityProbeReport {
|
|
187
175
|
attemptedVersion: string;
|
|
188
|
-
|
|
176
|
+
supportedVersions: readonly string[];
|
|
189
177
|
certificationTable: typeof CERTIFICATION_TABLE;
|
|
190
178
|
piVersion: string;
|
|
191
179
|
versionRange: string;
|
|
@@ -196,9 +184,8 @@ export interface CompatibilityProbeReport {
|
|
|
196
184
|
certification: readonly {
|
|
197
185
|
readonly version: string;
|
|
198
186
|
readonly attemptedVersion: string;
|
|
199
|
-
readonly
|
|
200
|
-
readonly
|
|
201
|
-
readonly actualPreinstall: CompatibilityDescriptorSnapshot | undefined;
|
|
187
|
+
readonly matchedIdentity: KnownNativeIdentity | undefined;
|
|
188
|
+
readonly knownIdentities: readonly KnownNativeIdentity[];
|
|
202
189
|
readonly feature: CompatibilityRecord["feature"];
|
|
203
190
|
readonly subtype: CompatibilityRecord["subtype"];
|
|
204
191
|
readonly target: object;
|
|
@@ -210,6 +197,7 @@ export interface CompatibilityProbeReport {
|
|
|
210
197
|
readonly adapterId: string | undefined;
|
|
211
198
|
readonly status: "certified" | "native-fallback";
|
|
212
199
|
readonly fallbackReason?: string;
|
|
200
|
+
readonly actualPreinstall: CompatibilityDescriptorSnapshot | undefined;
|
|
213
201
|
}[];
|
|
214
202
|
getRuntimeDiagnostics: () => ReadonlyMap<string, number>;
|
|
215
203
|
getFinalDiagnostics: () => Readonly<import("../features/tools/index.js").ToolDiagnosticArchive> | undefined;
|
|
@@ -243,118 +231,38 @@ export function fingerprint(value: unknown): string | undefined {
|
|
|
243
231
|
return hash.toString(16).padStart(8, "0");
|
|
244
232
|
}
|
|
245
233
|
|
|
246
|
-
function
|
|
247
|
-
if (
|
|
234
|
+
function knownIdentityMatches(spec: TargetSpec, value: unknown): KnownNativeIdentity | undefined {
|
|
235
|
+
if (typeof value !== "function") return undefined;
|
|
236
|
+
const hash = fingerprint(value);
|
|
237
|
+
const key = `${spec.subtype}:${spec.method}`;
|
|
238
|
+
return (KNOWN_NATIVE_IDENTITIES[key] ?? []).find(
|
|
239
|
+
(identity) => value.name === identity.name && value.length === identity.arity && hash === identity.fingerprint,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function matchedNativeIdentity(spec: TargetSpec): KnownNativeIdentity | undefined {
|
|
248
244
|
if (spec.kind === "add-method") {
|
|
249
245
|
// Additive install: the prototype must not already own the method (it is
|
|
250
|
-
// inherited), the class constructor identity must match
|
|
246
|
+
// inherited), the class constructor identity must match a recorded build,
|
|
251
247
|
// and the inherited method becomes the native fallback for the delegate.
|
|
252
248
|
if (Object.getOwnPropertyDescriptor(spec.target, spec.method)) return undefined;
|
|
253
249
|
const ctor = Object.getOwnPropertyDescriptor(spec.target, "constructor")?.value;
|
|
254
|
-
|
|
255
|
-
if (
|
|
256
|
-
typeof ctor !== "function" ||
|
|
257
|
-
ctor.name !== (spec.identityName ?? spec.method) ||
|
|
258
|
-
ctor.length !== (spec.arity ?? 0) ||
|
|
259
|
-
fingerprint(ctor) !== TRUSTED_NATIVE_FINGERPRINTS[key]
|
|
260
|
-
)
|
|
261
|
-
return undefined;
|
|
262
|
-
const inherited = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(spec.target), spec.method)?.value;
|
|
263
|
-
return typeof inherited === "function" ? inherited : undefined;
|
|
250
|
+
return knownIdentityMatches(spec, ctor);
|
|
264
251
|
}
|
|
265
252
|
const descriptor = Object.getOwnPropertyDescriptor(spec.target, spec.method);
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const expectedArity = spec.arity ?? (spec.method === "render" || spec.method === "updateContent" ? 1 : 0);
|
|
269
|
-
if (
|
|
270
|
-
descriptor?.writable !== true ||
|
|
271
|
-
descriptor.configurable !== true ||
|
|
272
|
-
typeof value !== "function" ||
|
|
273
|
-
value.name !== (spec.identityName ?? spec.method) ||
|
|
274
|
-
value.length !== expectedArity ||
|
|
275
|
-
fingerprint(value) !== TRUSTED_NATIVE_FINGERPRINTS[key]
|
|
276
|
-
)
|
|
277
|
-
return undefined;
|
|
278
|
-
return value;
|
|
253
|
+
if (descriptor?.writable !== true || descriptor.configurable !== true) return undefined;
|
|
254
|
+
return knownIdentityMatches(spec, descriptor.value);
|
|
279
255
|
}
|
|
280
256
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
target
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{
|
|
291
|
-
feature: "messages",
|
|
292
|
-
subtype: "native-assistant-message",
|
|
293
|
-
target: AssistantMessageComponent.prototype,
|
|
294
|
-
method: "updateContent",
|
|
295
|
-
adapterId: "message-thinking-collapse-v1",
|
|
296
|
-
status: "certified",
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
feature: "messages",
|
|
300
|
-
subtype: "native-compaction-message",
|
|
301
|
-
target: CompactionSummaryMessageComponent.prototype,
|
|
302
|
-
method: "updateDisplay",
|
|
303
|
-
adapterId: "message-block-boxed-v1",
|
|
304
|
-
status: "certified",
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
feature: "messages",
|
|
308
|
-
subtype: "native-branch-message",
|
|
309
|
-
target: BranchSummaryMessageComponent.prototype,
|
|
310
|
-
method: "updateDisplay",
|
|
311
|
-
adapterId: "message-block-boxed-v1",
|
|
312
|
-
status: "certified",
|
|
313
|
-
},
|
|
314
|
-
{
|
|
315
|
-
feature: "messages",
|
|
316
|
-
subtype: "native-skill-message",
|
|
317
|
-
target: SkillInvocationMessageComponent.prototype,
|
|
318
|
-
method: "updateDisplay",
|
|
319
|
-
adapterId: "message-block-boxed-v1",
|
|
320
|
-
status: "certified",
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
feature: "messages",
|
|
324
|
-
subtype: "native-custom-message",
|
|
325
|
-
target: CustomMessageComponent.prototype,
|
|
326
|
-
method: "rebuild",
|
|
327
|
-
adapterId: "message-block-boxed-v1",
|
|
328
|
-
status: "certified",
|
|
329
|
-
},
|
|
330
|
-
{
|
|
331
|
-
feature: "tools",
|
|
332
|
-
subtype: "tool-call-renderer",
|
|
333
|
-
target: ToolExecutionComponent.prototype,
|
|
334
|
-
method: "getCallRenderer",
|
|
335
|
-
adapterId: "tool-renderer-component-v1",
|
|
336
|
-
status: "certified",
|
|
337
|
-
},
|
|
338
|
-
{
|
|
339
|
-
feature: "tools",
|
|
340
|
-
subtype: "tool-result-renderer",
|
|
341
|
-
target: ToolExecutionComponent.prototype,
|
|
342
|
-
method: "getResultRenderer",
|
|
343
|
-
adapterId: "tool-renderer-component-v1",
|
|
344
|
-
status: "certified",
|
|
345
|
-
},
|
|
346
|
-
{
|
|
347
|
-
feature: "tools",
|
|
348
|
-
subtype: "native-bash-execution",
|
|
349
|
-
target: BashExecutionComponent.prototype,
|
|
350
|
-
method: "render",
|
|
351
|
-
kind: "add-method",
|
|
352
|
-
identityName: "BashExecutionComponent",
|
|
353
|
-
arity: 2,
|
|
354
|
-
adapterId: "bash-execution-box-v1",
|
|
355
|
-
status: "certified",
|
|
356
|
-
},
|
|
357
|
-
];
|
|
257
|
+
function trustedNativeIdentity(spec: TargetSpec): unknown {
|
|
258
|
+
const identity = matchedNativeIdentity(spec);
|
|
259
|
+
if (!identity) return undefined;
|
|
260
|
+
if (spec.kind === "add-method") {
|
|
261
|
+
const inherited = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(spec.target), spec.method)?.value;
|
|
262
|
+
return typeof inherited === "function" ? inherited : undefined;
|
|
263
|
+
}
|
|
264
|
+
return Object.getOwnPropertyDescriptor(spec.target, spec.method)?.value;
|
|
265
|
+
}
|
|
358
266
|
|
|
359
267
|
export interface PiVersionResolution {
|
|
360
268
|
resolvePackageEntry?: (packageName: string) => string;
|
|
@@ -426,6 +334,7 @@ function descriptorSnapshot(descriptor: PropertyDescriptor | undefined): Compati
|
|
|
426
334
|
function certificationRecord(
|
|
427
335
|
spec: TargetSpec,
|
|
428
336
|
attemptedVersion: string | undefined,
|
|
337
|
+
matchedIdentity: KnownNativeIdentity | undefined,
|
|
429
338
|
evidence = Object.getOwnPropertyDescriptor(spec.target, spec.method),
|
|
430
339
|
) {
|
|
431
340
|
const descriptor = evidence;
|
|
@@ -433,9 +342,8 @@ function certificationRecord(
|
|
|
433
342
|
return {
|
|
434
343
|
version: attemptedVersion ?? "unknown",
|
|
435
344
|
attemptedVersion: attemptedVersion ?? "unknown",
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
actualPreinstall: descriptorSnapshot(descriptor),
|
|
345
|
+
matchedIdentity,
|
|
346
|
+
knownIdentities: KNOWN_NATIVE_IDENTITIES[`${spec.subtype}:${spec.method}`] ?? [],
|
|
439
347
|
feature: spec.feature,
|
|
440
348
|
subtype: spec.subtype,
|
|
441
349
|
target: spec.target,
|
|
@@ -450,10 +358,6 @@ function certificationRecord(
|
|
|
450
358
|
};
|
|
451
359
|
}
|
|
452
360
|
|
|
453
|
-
function versionInRange(version: string | undefined): boolean {
|
|
454
|
-
return version === TRUSTED_PI_VERSION;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
361
|
function shape(spec: TargetSpec): boolean {
|
|
458
362
|
const descriptor = Object.getOwnPropertyDescriptor(spec.target, spec.method);
|
|
459
363
|
// Additive installs need an unowned slot (the method is inherited); every
|
|
@@ -465,7 +369,13 @@ function shape(spec: TargetSpec): boolean {
|
|
|
465
369
|
export interface CompatibilityProbeOptions {
|
|
466
370
|
markers?: Set<string>;
|
|
467
371
|
config?: Readonly<{
|
|
468
|
-
messages: {
|
|
372
|
+
messages: {
|
|
373
|
+
enabled: boolean;
|
|
374
|
+
assistantPrefix: boolean;
|
|
375
|
+
specialBlocks: boolean;
|
|
376
|
+
hideThinkingLabel: boolean;
|
|
377
|
+
hideInterimText: boolean;
|
|
378
|
+
};
|
|
469
379
|
tools: { enabled: boolean; style: string; maxCollapsedLines: number; maxExpandedLines: number; dimOutput: boolean };
|
|
470
380
|
preset: string;
|
|
471
381
|
}>;
|
|
@@ -491,7 +401,7 @@ function createFallbackRecord(
|
|
|
491
401
|
method: spec.method,
|
|
492
402
|
originalIdentity: Reflect.get(spec.target, spec.method),
|
|
493
403
|
piVersion: piVersion ?? "unknown",
|
|
494
|
-
versionRange:
|
|
404
|
+
versionRange: SUPPORTED_VERSION_RANGE,
|
|
495
405
|
shape: "unsupported",
|
|
496
406
|
diagnostic: reason,
|
|
497
407
|
generation,
|
|
@@ -500,10 +410,10 @@ function createFallbackRecord(
|
|
|
500
410
|
};
|
|
501
411
|
}
|
|
502
412
|
|
|
503
|
-
function probeDiagnostic(spec: TargetSpec,
|
|
504
|
-
if (!versionInRange(piVersion)) return "Pi version is unknown or outside the recorded 0.83.0 support build";
|
|
413
|
+
function probeDiagnostic(spec: TargetSpec, identity: unknown): string {
|
|
505
414
|
if (!shape(spec)) return "target method shape is not an own writable/configurable function";
|
|
506
|
-
if (identity === undefined)
|
|
415
|
+
if (identity === undefined)
|
|
416
|
+
return "runtime native identity (name, arity, or source fingerprint) matched no recorded Pi surface";
|
|
507
417
|
return "exact native identity verified; certified guarded decoration enabled";
|
|
508
418
|
}
|
|
509
419
|
|
|
@@ -513,7 +423,7 @@ function surfaceDisabled(spec: TargetSpec, config: CompatibilityProbeOptions["co
|
|
|
513
423
|
if (!config.messages.enabled) return true;
|
|
514
424
|
if (spec.subtype === "native-assistant-message" && spec.method === "render") return !config.messages.assistantPrefix;
|
|
515
425
|
if (spec.subtype === "native-assistant-message" && spec.method === "updateContent")
|
|
516
|
-
return !config.messages.hideThinkingLabel;
|
|
426
|
+
return !config.messages.hideThinkingLabel && !config.messages.hideInterimText;
|
|
517
427
|
if (isSpecialBlock(spec)) return !config.messages.specialBlocks;
|
|
518
428
|
return true;
|
|
519
429
|
}
|
|
@@ -528,8 +438,8 @@ function probeSpec(options: {
|
|
|
528
438
|
toolOwner: ReturnType<typeof createToolDecorationOwner> | undefined;
|
|
529
439
|
}) {
|
|
530
440
|
const { spec, piVersion, generation, markers, config, toolOwner, messageSnapshot } = options;
|
|
531
|
-
const identity = trustedNativeIdentity(spec
|
|
532
|
-
const diagnostic = probeDiagnostic(spec,
|
|
441
|
+
const identity = trustedNativeIdentity(spec);
|
|
442
|
+
const diagnostic = probeDiagnostic(spec, identity);
|
|
533
443
|
const disabled = surfaceDisabled(spec, config);
|
|
534
444
|
if (disabled) {
|
|
535
445
|
const reason = "native fallback: surface disabled by normalized configuration";
|
|
@@ -541,8 +451,8 @@ function probeSpec(options: {
|
|
|
541
451
|
target: spec.target,
|
|
542
452
|
method: spec.method,
|
|
543
453
|
piVersion: piVersion ?? "unknown",
|
|
544
|
-
versionRange:
|
|
545
|
-
shape: identity !== undefined &&
|
|
454
|
+
versionRange: SUPPORTED_VERSION_RANGE,
|
|
455
|
+
shape: identity !== undefined && shape(spec),
|
|
546
456
|
generation,
|
|
547
457
|
expectedIdentity: identity,
|
|
548
458
|
hasExpectedIdentity: true,
|
|
@@ -578,6 +488,153 @@ function probeSpec(options: {
|
|
|
578
488
|
};
|
|
579
489
|
}
|
|
580
490
|
|
|
491
|
+
export const targetSpecs: readonly TargetSpec[] = [
|
|
492
|
+
{
|
|
493
|
+
feature: "messages",
|
|
494
|
+
subtype: "native-assistant-message",
|
|
495
|
+
target: AssistantMessageComponent.prototype,
|
|
496
|
+
method: "render",
|
|
497
|
+
adapterId: "message-prefix-osc133-v1",
|
|
498
|
+
status: "certified",
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
feature: "messages",
|
|
502
|
+
subtype: "native-assistant-message",
|
|
503
|
+
target: AssistantMessageComponent.prototype,
|
|
504
|
+
method: "updateContent",
|
|
505
|
+
adapterId: "message-thinking-collapse-v1",
|
|
506
|
+
status: "certified",
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
feature: "messages",
|
|
510
|
+
subtype: "native-compaction-message",
|
|
511
|
+
target: CompactionSummaryMessageComponent.prototype,
|
|
512
|
+
method: "updateDisplay",
|
|
513
|
+
adapterId: "message-block-boxed-v1",
|
|
514
|
+
status: "certified",
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
feature: "messages",
|
|
518
|
+
subtype: "native-branch-message",
|
|
519
|
+
target: BranchSummaryMessageComponent.prototype,
|
|
520
|
+
method: "updateDisplay",
|
|
521
|
+
adapterId: "message-block-boxed-v1",
|
|
522
|
+
status: "certified",
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
feature: "messages",
|
|
526
|
+
subtype: "native-skill-message",
|
|
527
|
+
target: SkillInvocationMessageComponent.prototype,
|
|
528
|
+
method: "updateDisplay",
|
|
529
|
+
adapterId: "message-block-boxed-v1",
|
|
530
|
+
status: "certified",
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
feature: "messages",
|
|
534
|
+
subtype: "native-custom-message",
|
|
535
|
+
target: CustomMessageComponent.prototype,
|
|
536
|
+
method: "rebuild",
|
|
537
|
+
adapterId: "message-block-boxed-v1",
|
|
538
|
+
status: "certified",
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
feature: "tools",
|
|
542
|
+
subtype: "tool-call-renderer",
|
|
543
|
+
target: ToolExecutionComponent.prototype,
|
|
544
|
+
method: "getCallRenderer",
|
|
545
|
+
adapterId: "tool-renderer-component-v1",
|
|
546
|
+
status: "certified",
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
feature: "tools",
|
|
550
|
+
subtype: "tool-result-renderer",
|
|
551
|
+
target: ToolExecutionComponent.prototype,
|
|
552
|
+
method: "getResultRenderer",
|
|
553
|
+
adapterId: "tool-renderer-component-v1",
|
|
554
|
+
status: "certified",
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
feature: "tools",
|
|
558
|
+
subtype: "native-bash-execution",
|
|
559
|
+
target: BashExecutionComponent.prototype,
|
|
560
|
+
method: "render",
|
|
561
|
+
kind: "add-method",
|
|
562
|
+
identityName: "BashExecutionComponent",
|
|
563
|
+
arity: 2,
|
|
564
|
+
adapterId: "bash-execution-box-v1",
|
|
565
|
+
status: "certified",
|
|
566
|
+
},
|
|
567
|
+
];
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Version → surface → recorded certified identity (informational). Certification
|
|
571
|
+
* itself is decided per-surface by the runtime identity; this table only documents
|
|
572
|
+
* which identity each supported Pi version is known to carry.
|
|
573
|
+
*/
|
|
574
|
+
export const CERTIFICATION_TABLE: Readonly<
|
|
575
|
+
Record<
|
|
576
|
+
string,
|
|
577
|
+
Readonly<
|
|
578
|
+
Record<
|
|
579
|
+
string,
|
|
580
|
+
Readonly<{
|
|
581
|
+
feature: CompatibilityRecord["feature"];
|
|
582
|
+
subtype: CompatibilityRecord["subtype"];
|
|
583
|
+
target: object;
|
|
584
|
+
method: string;
|
|
585
|
+
writable: boolean;
|
|
586
|
+
configurable: boolean;
|
|
587
|
+
name: string;
|
|
588
|
+
arity: number;
|
|
589
|
+
fingerprint: string;
|
|
590
|
+
adapterId: string | undefined;
|
|
591
|
+
status: "certified";
|
|
592
|
+
}>
|
|
593
|
+
>
|
|
594
|
+
>
|
|
595
|
+
>
|
|
596
|
+
> = Object.freeze(
|
|
597
|
+
Object.fromEntries(
|
|
598
|
+
SUPPORTED_PI_VERSIONS.map((version) => [
|
|
599
|
+
version,
|
|
600
|
+
Object.freeze(
|
|
601
|
+
Object.fromEntries(
|
|
602
|
+
targetSpecs.flatMap((spec) => {
|
|
603
|
+
const key = `${spec.subtype}:${spec.method}`;
|
|
604
|
+
const identity = (KNOWN_NATIVE_IDENTITIES[key] ?? []).find((candidate) =>
|
|
605
|
+
candidate.versions.includes(version),
|
|
606
|
+
);
|
|
607
|
+
if (!identity) return [];
|
|
608
|
+
return [
|
|
609
|
+
[
|
|
610
|
+
key,
|
|
611
|
+
Object.freeze({
|
|
612
|
+
feature: spec.feature,
|
|
613
|
+
subtype: spec.subtype,
|
|
614
|
+
target: spec.target,
|
|
615
|
+
method: spec.method,
|
|
616
|
+
writable: true,
|
|
617
|
+
configurable: true,
|
|
618
|
+
name: identity.name,
|
|
619
|
+
arity: identity.arity,
|
|
620
|
+
fingerprint: identity.fingerprint,
|
|
621
|
+
adapterId: spec.adapterId,
|
|
622
|
+
status: "certified" as const,
|
|
623
|
+
}),
|
|
624
|
+
],
|
|
625
|
+
];
|
|
626
|
+
}),
|
|
627
|
+
),
|
|
628
|
+
),
|
|
629
|
+
]),
|
|
630
|
+
),
|
|
631
|
+
);
|
|
632
|
+
|
|
633
|
+
const reportStates = new WeakMap<
|
|
634
|
+
object,
|
|
635
|
+
{ records: CompatibilityRecord[]; toolOwner: ReturnType<typeof createToolDecorationOwner> | undefined }
|
|
636
|
+
>();
|
|
637
|
+
|
|
581
638
|
export function probePiCompatibility(
|
|
582
639
|
piVersion: string | undefined,
|
|
583
640
|
options: Set<string> | CompatibilityProbeOptions = new Set(),
|
|
@@ -587,7 +644,7 @@ export function probePiCompatibility(
|
|
|
587
644
|
const toolSpecs = targetSpecs.filter((spec) => spec.feature === "tools");
|
|
588
645
|
let toolOwner: ReturnType<typeof createToolDecorationOwner> | undefined;
|
|
589
646
|
if (
|
|
590
|
-
toolSpecs.some((spec) => trustedNativeIdentity(spec
|
|
647
|
+
toolSpecs.some((spec) => trustedNativeIdentity(spec) !== undefined) &&
|
|
591
648
|
(options instanceof Set || options.config?.tools.enabled !== false)
|
|
592
649
|
) {
|
|
593
650
|
toolOwner = createToolDecorationOwner(options instanceof Set ? {} : options.toolSnapshot);
|
|
@@ -610,6 +667,9 @@ export function probePiCompatibility(
|
|
|
610
667
|
for (const spec of targetSpecs) {
|
|
611
668
|
const captured = evidenceByKey.get(`${spec.subtype}:${String(spec.method)}`);
|
|
612
669
|
const preinstallDescriptor = captured?.descriptor;
|
|
670
|
+
// Captured before install: the runtime identity is still the pristine native
|
|
671
|
+
// method (or class constructor for additive installs) at this point.
|
|
672
|
+
const matchedIdentity = matchedNativeIdentity(spec);
|
|
613
673
|
const result = probeSpec({
|
|
614
674
|
messageSnapshot: options instanceof Set ? undefined : options.messageSnapshot,
|
|
615
675
|
spec,
|
|
@@ -620,15 +680,10 @@ export function probePiCompatibility(
|
|
|
620
680
|
toolOwner,
|
|
621
681
|
});
|
|
622
682
|
records.push(result.record);
|
|
623
|
-
const certificate = certificationRecord(spec, piVersion, preinstallDescriptor);
|
|
683
|
+
const certificate = certificationRecord(spec, piVersion, matchedIdentity, preinstallDescriptor);
|
|
624
684
|
certification.push({
|
|
625
685
|
...certificate,
|
|
626
686
|
attemptedVersion: piVersion ?? "unknown",
|
|
627
|
-
matchedCertifiedVersion: piVersion === TRUSTED_PI_VERSION ? TRUSTED_PI_VERSION : undefined,
|
|
628
|
-
expected:
|
|
629
|
-
CERTIFICATION_TABLE[TRUSTED_PI_VERSION][
|
|
630
|
-
`${spec.subtype}:${spec.method}` as keyof (typeof CERTIFICATION_TABLE)["0.83.0"]
|
|
631
|
-
],
|
|
632
687
|
actualPreinstall: descriptorSnapshot(preinstallDescriptor),
|
|
633
688
|
status: result.fallback ? "native-fallback" : "certified",
|
|
634
689
|
...(result.fallback ? { fallbackReason: result.reason } : {}),
|
|
@@ -637,10 +692,10 @@ export function probePiCompatibility(
|
|
|
637
692
|
}
|
|
638
693
|
const report: CompatibilityProbeReport = {
|
|
639
694
|
attemptedVersion: piVersion ?? "unknown",
|
|
640
|
-
|
|
695
|
+
supportedVersions: SUPPORTED_PI_VERSIONS,
|
|
641
696
|
certificationTable: CERTIFICATION_TABLE,
|
|
642
697
|
piVersion: piVersion ?? "unknown",
|
|
643
|
-
versionRange:
|
|
698
|
+
versionRange: SUPPORTED_VERSION_RANGE,
|
|
644
699
|
generation: currentGeneration(),
|
|
645
700
|
recordSnapshots: Object.freeze(
|
|
646
701
|
records.map((record) =>
|
|
@@ -659,14 +714,7 @@ export function probePiCompatibility(
|
|
|
659
714
|
),
|
|
660
715
|
unsupported: Object.freeze(unsupported.map((item) => Object.freeze({ ...item }))),
|
|
661
716
|
delegationMarkers: Object.freeze([...markers]),
|
|
662
|
-
certification: Object.freeze(
|
|
663
|
-
certification.map((item) =>
|
|
664
|
-
Object.freeze({
|
|
665
|
-
...item,
|
|
666
|
-
actualPreinstall: item.actualPreinstall,
|
|
667
|
-
}),
|
|
668
|
-
),
|
|
669
|
-
),
|
|
717
|
+
certification: Object.freeze(certification.map((item) => Object.freeze({ ...item }))),
|
|
670
718
|
getRuntimeDiagnostics: () => toolOwner?.getDiagnostics() ?? new Map(),
|
|
671
719
|
getFinalDiagnostics: () => toolOwner?.getFinalArchive(),
|
|
672
720
|
getActiveToolRecordCount: () => toolOwner?.getActiveRecordCount() ?? 0,
|