@oh-my-pi/pi-wire 18.17.0 → 18.18.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 +6 -0
- package/dist/types/shell-trace.d.ts +18 -11
- package/package.json +1 -1
- package/src/shell-trace.ts +47 -29
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.18.0] - 2026-11-07
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- `ShellTrace` fields that carry values from the run (argv, assignments, redirect targets, unlocated unit sources, diagnostics) are `ShellTraceBytes`: a string when the bytes are UTF-8, otherwise the raw byte values. `isShellTrace` accepts both forms
|
|
10
|
+
|
|
5
11
|
## [18.17.0] - 2026-11-06
|
|
6
12
|
|
|
7
13
|
### Added
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
* node's props. Every offset is a BYTE offset; UIs convert bytes to characters
|
|
6
6
|
* when the script is not ASCII. Fields at their default are omitted.
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* Bytes a run produced (expansions, assignments, eval bodies, diagnostics):
|
|
10
|
+
* a string when they are UTF-8, else the raw byte values. Nothing is replaced,
|
|
11
|
+
* so values and byte offsets stay exactly what the engine recorded.
|
|
12
|
+
*/
|
|
13
|
+
export type ShellTraceBytes = string | number[];
|
|
8
14
|
/** NodeKind of the engine's AST, snake_case. `assign` and `word` are not statements. */
|
|
9
15
|
export type ShellTraceNodeKind = "and_or" | "pipeline" | "simple" | "brace" | "subshell" | "if" | "while" | "until" | "for" | "arith_for" | "select" | "case" | "arith" | "cond" | "func_def" | "coproc" | "assign" | "word";
|
|
10
16
|
/** How the engine resolved a simple command's name. */
|
|
@@ -14,11 +20,11 @@ export type ShellTraceState = "pending" | "running" | "ok" | "fail" | "skipped";
|
|
|
14
20
|
export interface ShellTraceRedir {
|
|
15
21
|
fd: number;
|
|
16
22
|
op: string;
|
|
17
|
-
target:
|
|
23
|
+
target: ShellTraceBytes;
|
|
18
24
|
}
|
|
19
25
|
export interface ShellTraceDiag {
|
|
20
26
|
code: string;
|
|
21
|
-
message:
|
|
27
|
+
message: ShellTraceBytes;
|
|
22
28
|
}
|
|
23
29
|
/** One AST node of a unit; the unit's `nodes` index is the AstNodeId. */
|
|
24
30
|
export interface ShellTraceNode {
|
|
@@ -42,11 +48,11 @@ export interface ShellTraceNode {
|
|
|
42
48
|
/** `t_ns` of the last CmdStart, relative to RunStart. */
|
|
43
49
|
at?: number;
|
|
44
50
|
/** Last CmdExpanded argv (each arg ≤ 256 bytes, ≤ 64 args). */
|
|
45
|
-
argv?:
|
|
51
|
+
argv?: ShellTraceBytes[];
|
|
46
52
|
/** The full argv length when `argv` was cut. */
|
|
47
53
|
argc?: number;
|
|
48
54
|
/** Last CmdExpanded assigns. */
|
|
49
|
-
env?: [
|
|
55
|
+
env?: [ShellTraceBytes, ShellTraceBytes][];
|
|
50
56
|
res?: ShellTraceResolved;
|
|
51
57
|
redirs?: ShellTraceRedir[];
|
|
52
58
|
/** Pipestatus of the last CmdEnd. */
|
|
@@ -73,8 +79,8 @@ export interface ShellTraceUnit {
|
|
|
73
79
|
line: number;
|
|
74
80
|
/** Exact UTF-8 source byte length, including heredocs; absent in older traces. */
|
|
75
81
|
bytes?: number;
|
|
76
|
-
/** The unit's source; present only for unlocated units. */
|
|
77
|
-
source?:
|
|
82
|
+
/** The unit's source; present only for unlocated units (an eval or function body). */
|
|
83
|
+
source?: ShellTraceBytes;
|
|
78
84
|
/** Opaque canonical native syntax archive. Only pi-shell may interpret it. */
|
|
79
85
|
syntax?: unknown;
|
|
80
86
|
/** Compiler-known wrapper bytes removed from this unit's displayed source. */
|
|
@@ -126,19 +132,20 @@ export interface ShellTraceHistoryEvent {
|
|
|
126
132
|
status?: number;
|
|
127
133
|
dur_ns?: number;
|
|
128
134
|
pipestatus?: number[];
|
|
129
|
-
argv?:
|
|
130
|
-
assigns?: [
|
|
135
|
+
argv?: ShellTraceBytes[];
|
|
136
|
+
assigns?: [ShellTraceBytes, ShellTraceBytes][];
|
|
131
137
|
resolved?: ShellTraceResolved;
|
|
132
138
|
redirs?: ShellTraceRedir[];
|
|
133
|
-
name?:
|
|
134
|
-
value?:
|
|
139
|
+
name?: ShellTraceBytes;
|
|
140
|
+
value?: ShellTraceBytes;
|
|
135
141
|
full_len?: number;
|
|
136
142
|
scope?: string;
|
|
137
143
|
iteration?: number;
|
|
138
144
|
iterations?: number;
|
|
139
145
|
taken?: boolean;
|
|
140
146
|
construct?: string;
|
|
141
|
-
text
|
|
147
|
+
/** `Output` text is always a string (undecodable bytes arrive as U+FFFD); `Diag` text is run bytes. */
|
|
148
|
+
text?: ShellTraceBytes;
|
|
142
149
|
contributors?: ShellTraceOutputContributor[];
|
|
143
150
|
/** Final visible capture descriptor; merged stderr uses stdout's descriptor. */
|
|
144
151
|
fd?: number;
|
package/package.json
CHANGED
package/src/shell-trace.ts
CHANGED
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
* when the script is not ASCII. Fields at their default are omitted.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Bytes a run produced (expansions, assignments, eval bodies, diagnostics):
|
|
11
|
+
* a string when they are UTF-8, else the raw byte values. Nothing is replaced,
|
|
12
|
+
* so values and byte offsets stay exactly what the engine recorded.
|
|
13
|
+
*/
|
|
14
|
+
export type ShellTraceBytes = string | number[];
|
|
15
|
+
|
|
9
16
|
/** NodeKind of the engine's AST, snake_case. `assign` and `word` are not statements. */
|
|
10
17
|
export type ShellTraceNodeKind =
|
|
11
18
|
| "and_or"
|
|
@@ -45,12 +52,12 @@ export type ShellTraceState = "pending" | "running" | "ok" | "fail" | "skipped";
|
|
|
45
52
|
export interface ShellTraceRedir {
|
|
46
53
|
fd: number;
|
|
47
54
|
op: string;
|
|
48
|
-
target:
|
|
55
|
+
target: ShellTraceBytes;
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
export interface ShellTraceDiag {
|
|
52
59
|
code: string;
|
|
53
|
-
message:
|
|
60
|
+
message: ShellTraceBytes;
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
/** One AST node of a unit; the unit's `nodes` index is the AstNodeId. */
|
|
@@ -75,11 +82,11 @@ export interface ShellTraceNode {
|
|
|
75
82
|
/** `t_ns` of the last CmdStart, relative to RunStart. */
|
|
76
83
|
at?: number;
|
|
77
84
|
/** Last CmdExpanded argv (each arg ≤ 256 bytes, ≤ 64 args). */
|
|
78
|
-
argv?:
|
|
85
|
+
argv?: ShellTraceBytes[];
|
|
79
86
|
/** The full argv length when `argv` was cut. */
|
|
80
87
|
argc?: number;
|
|
81
88
|
/** Last CmdExpanded assigns. */
|
|
82
|
-
env?: [
|
|
89
|
+
env?: [ShellTraceBytes, ShellTraceBytes][];
|
|
83
90
|
res?: ShellTraceResolved;
|
|
84
91
|
redirs?: ShellTraceRedir[];
|
|
85
92
|
/** Pipestatus of the last CmdEnd. */
|
|
@@ -107,8 +114,8 @@ export interface ShellTraceUnit {
|
|
|
107
114
|
line: number;
|
|
108
115
|
/** Exact UTF-8 source byte length, including heredocs; absent in older traces. */
|
|
109
116
|
bytes?: number;
|
|
110
|
-
/** The unit's source; present only for unlocated units. */
|
|
111
|
-
source?:
|
|
117
|
+
/** The unit's source; present only for unlocated units (an eval or function body). */
|
|
118
|
+
source?: ShellTraceBytes;
|
|
112
119
|
/** Opaque canonical native syntax archive. Only pi-shell may interpret it. */
|
|
113
120
|
syntax?: unknown;
|
|
114
121
|
/** Compiler-known wrapper bytes removed from this unit's displayed source. */
|
|
@@ -181,19 +188,20 @@ export interface ShellTraceHistoryEvent {
|
|
|
181
188
|
status?: number;
|
|
182
189
|
dur_ns?: number;
|
|
183
190
|
pipestatus?: number[];
|
|
184
|
-
argv?:
|
|
185
|
-
assigns?: [
|
|
191
|
+
argv?: ShellTraceBytes[];
|
|
192
|
+
assigns?: [ShellTraceBytes, ShellTraceBytes][];
|
|
186
193
|
resolved?: ShellTraceResolved;
|
|
187
194
|
redirs?: ShellTraceRedir[];
|
|
188
|
-
name?:
|
|
189
|
-
value?:
|
|
195
|
+
name?: ShellTraceBytes;
|
|
196
|
+
value?: ShellTraceBytes;
|
|
190
197
|
full_len?: number;
|
|
191
198
|
scope?: string;
|
|
192
199
|
iteration?: number;
|
|
193
200
|
iterations?: number;
|
|
194
201
|
taken?: boolean;
|
|
195
202
|
construct?: string;
|
|
196
|
-
text
|
|
203
|
+
/** `Output` text is always a string (undecodable bytes arrive as U+FFFD); `Diag` text is run bytes. */
|
|
204
|
+
text?: ShellTraceBytes;
|
|
197
205
|
contributors?: ShellTraceOutputContributor[];
|
|
198
206
|
/** Final visible capture descriptor; merged stderr uses stdout's descriptor. */
|
|
199
207
|
fd?: number;
|
|
@@ -232,21 +240,29 @@ function finite(value: unknown): value is number {
|
|
|
232
240
|
return typeof value === "number" && Number.isFinite(value);
|
|
233
241
|
}
|
|
234
242
|
|
|
235
|
-
function
|
|
236
|
-
return
|
|
243
|
+
function byteValues(value: unknown): value is number[] {
|
|
244
|
+
return (
|
|
245
|
+
Array.isArray(value) &&
|
|
246
|
+
value.every((byte: unknown) => finite(byte) && Number.isInteger(byte) && byte >= 0 && byte <= 255)
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function bytes(value: unknown): value is ShellTraceBytes {
|
|
251
|
+
return typeof value === "string" || byteValues(value);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function byteList(value: unknown): value is ShellTraceBytes[] {
|
|
255
|
+
return Array.isArray(value) && value.every(bytes);
|
|
237
256
|
}
|
|
238
257
|
|
|
239
258
|
function numbers(value: unknown): value is number[] {
|
|
240
259
|
return Array.isArray(value) && value.every(finite);
|
|
241
260
|
}
|
|
242
261
|
|
|
243
|
-
function
|
|
262
|
+
function bytePairs(value: unknown): value is [ShellTraceBytes, ShellTraceBytes][] {
|
|
244
263
|
return (
|
|
245
264
|
Array.isArray(value) &&
|
|
246
|
-
value.every(
|
|
247
|
-
(item: unknown) =>
|
|
248
|
-
Array.isArray(item) && item.length === 2 && typeof item[0] === "string" && typeof item[1] === "string",
|
|
249
|
-
)
|
|
265
|
+
value.every((item: unknown) => Array.isArray(item) && item.length === 2 && bytes(item[0]) && bytes(item[1]))
|
|
250
266
|
);
|
|
251
267
|
}
|
|
252
268
|
|
|
@@ -277,7 +293,7 @@ function resolved(value: unknown): value is ShellTraceResolved {
|
|
|
277
293
|
}
|
|
278
294
|
|
|
279
295
|
function redirection(value: unknown): value is ShellTraceRedir {
|
|
280
|
-
return record(value) && finite(value.fd) && string(value.op) &&
|
|
296
|
+
return record(value) && finite(value.fd) && string(value.op) && bytes(value.target);
|
|
281
297
|
}
|
|
282
298
|
|
|
283
299
|
function redirections(value: unknown): value is ShellTraceRedir[] {
|
|
@@ -322,8 +338,8 @@ function traceNode(value: unknown): value is ShellTraceNode {
|
|
|
322
338
|
if (!optional(value, key, finite)) return false;
|
|
323
339
|
}
|
|
324
340
|
return (
|
|
325
|
-
optional(value, "argv",
|
|
326
|
-
optional(value, "env",
|
|
341
|
+
optional(value, "argv", byteList) &&
|
|
342
|
+
optional(value, "env", bytePairs) &&
|
|
327
343
|
optional(value, "res", resolved) &&
|
|
328
344
|
optional(value, "redirs", redirections) &&
|
|
329
345
|
optional(value, "pipe", numbers) &&
|
|
@@ -338,7 +354,7 @@ function traceUnit(value: unknown): value is ShellTraceUnit {
|
|
|
338
354
|
finite(value.line) &&
|
|
339
355
|
optional(value, "at", finite) &&
|
|
340
356
|
optional(value, "bytes", finite) &&
|
|
341
|
-
optional(value, "source",
|
|
357
|
+
optional(value, "source", bytes) &&
|
|
342
358
|
optional(value, "callout", boolean) &&
|
|
343
359
|
Array.isArray(value.nodes) &&
|
|
344
360
|
value.nodes.every(traceNode)
|
|
@@ -353,8 +369,7 @@ function outputContributor(value: unknown): value is ShellTraceOutputContributor
|
|
|
353
369
|
return (
|
|
354
370
|
record(value) &&
|
|
355
371
|
finite(value.t_ns) &&
|
|
356
|
-
|
|
357
|
-
value.bytes.every((byte: unknown) => finite(byte) && Number.isInteger(byte) && byte >= 0 && byte <= 255) &&
|
|
372
|
+
byteValues(value.bytes) &&
|
|
358
373
|
optional(value, "u", finite) &&
|
|
359
374
|
optional(value, "n", finite) &&
|
|
360
375
|
optional(value, "vpid", finite) &&
|
|
@@ -405,12 +420,15 @@ function historyEntry(value: unknown): value is ShellTraceHistoryEvent {
|
|
|
405
420
|
]) {
|
|
406
421
|
if (!optional(value, key, finite)) return false;
|
|
407
422
|
}
|
|
408
|
-
for (const key of ["name", "value", "
|
|
423
|
+
for (const key of ["name", "value", "text"]) {
|
|
424
|
+
if (!optional(value, key, bytes)) return false;
|
|
425
|
+
}
|
|
426
|
+
for (const key of ["scope", "construct"]) {
|
|
409
427
|
if (!optional(value, key, string)) return false;
|
|
410
428
|
}
|
|
411
429
|
return (
|
|
412
|
-
optional(value, "argv",
|
|
413
|
-
optional(value, "assigns",
|
|
430
|
+
optional(value, "argv", byteList) &&
|
|
431
|
+
optional(value, "assigns", bytePairs) &&
|
|
414
432
|
optional(value, "redirs", redirections) &&
|
|
415
433
|
optional(value, "resolved", resolved) &&
|
|
416
434
|
optional(value, "pipestatus", numbers) &&
|
|
@@ -420,7 +438,7 @@ function historyEntry(value: unknown): value is ShellTraceHistoryEvent {
|
|
|
420
438
|
optional(value, "contributors", items => Array.isArray(items) && items.every(outputContributor)) &&
|
|
421
439
|
(value.kind !== "Output" || (string(value.text) && finite(value.fd))) &&
|
|
422
440
|
(value.kind !== "Assign" ||
|
|
423
|
-
(
|
|
441
|
+
(bytes(value.name) && bytes(value.value) && finite(value.full_len) && string(value.scope)))
|
|
424
442
|
);
|
|
425
443
|
}
|
|
426
444
|
|
|
@@ -440,7 +458,7 @@ export function isShellTrace(value: unknown): value is ShellTrace {
|
|
|
440
458
|
"diags",
|
|
441
459
|
items =>
|
|
442
460
|
Array.isArray(items) &&
|
|
443
|
-
items.every((item: unknown) => record(item) && string(item.code) &&
|
|
461
|
+
items.every((item: unknown) => record(item) && string(item.code) && bytes(item.message)),
|
|
444
462
|
) &&
|
|
445
463
|
optional(value, "history", items => Array.isArray(items) && items.every(historyEntry)) &&
|
|
446
464
|
optional(value, "historyTruncated", boolean)
|