@clowder-ai/plugin-contract 0.1.0-beta.1 → 0.1.0-beta.10

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.
Files changed (157) hide show
  1. package/dist/codegen/generate-contract.d.ts +5 -0
  2. package/dist/codegen/generate-contract.d.ts.map +1 -1
  3. package/dist/codegen/generate-contract.js +45 -4
  4. package/dist/codegen/generate-contract.js.map +1 -1
  5. package/dist/conformance/behavior-executor.d.ts +18 -0
  6. package/dist/conformance/behavior-executor.d.ts.map +1 -0
  7. package/dist/conformance/behavior-executor.js +52 -0
  8. package/dist/conformance/behavior-executor.js.map +1 -0
  9. package/dist/conformance/fixtures.d.ts +9 -0
  10. package/dist/conformance/fixtures.d.ts.map +1 -0
  11. package/dist/conformance/fixtures.js +8 -0
  12. package/dist/conformance/fixtures.js.map +1 -0
  13. package/dist/conformance/index.d.ts +5 -0
  14. package/dist/conformance/index.d.ts.map +1 -1
  15. package/dist/conformance/index.js +4 -0
  16. package/dist/conformance/index.js.map +1 -1
  17. package/dist/conformance/messaging-loopback-adapter.d.ts +23 -0
  18. package/dist/conformance/messaging-loopback-adapter.d.ts.map +1 -0
  19. package/dist/conformance/messaging-loopback-adapter.js +389 -0
  20. package/dist/conformance/messaging-loopback-adapter.js.map +1 -0
  21. package/dist/conformance/messaging-loopback-state.d.ts +22 -0
  22. package/dist/conformance/messaging-loopback-state.d.ts.map +1 -0
  23. package/dist/conformance/messaging-loopback-state.js +101 -0
  24. package/dist/conformance/messaging-loopback-state.js.map +1 -0
  25. package/dist/conformance/runner.d.ts +18 -1
  26. package/dist/conformance/runner.d.ts.map +1 -1
  27. package/dist/conformance/runner.js +153 -66
  28. package/dist/conformance/runner.js.map +1 -1
  29. package/dist/conformance/stdio-harness/child-process-harness.d.ts +65 -0
  30. package/dist/conformance/stdio-harness/child-process-harness.d.ts.map +1 -0
  31. package/dist/conformance/stdio-harness/child-process-harness.js +296 -0
  32. package/dist/conformance/stdio-harness/child-process-harness.js.map +1 -0
  33. package/dist/conformance/stdio-harness/dual-transport-oracle.d.ts +26 -0
  34. package/dist/conformance/stdio-harness/dual-transport-oracle.d.ts.map +1 -0
  35. package/dist/conformance/stdio-harness/dual-transport-oracle.js +32 -0
  36. package/dist/conformance/stdio-harness/dual-transport-oracle.js.map +1 -0
  37. package/dist/conformance/stdio-harness/harness-process-spawn.d.ts +27 -0
  38. package/dist/conformance/stdio-harness/harness-process-spawn.d.ts.map +1 -0
  39. package/dist/conformance/stdio-harness/harness-process-spawn.js +43 -0
  40. package/dist/conformance/stdio-harness/harness-process-spawn.js.map +1 -0
  41. package/dist/conformance/stdio-harness/index.d.ts +5 -0
  42. package/dist/conformance/stdio-harness/index.d.ts.map +1 -0
  43. package/dist/conformance/stdio-harness/index.js +4 -0
  44. package/dist/conformance/stdio-harness/index.js.map +1 -0
  45. package/dist/conformance/stdio-harness/ndjson-frame.d.ts +31 -0
  46. package/dist/conformance/stdio-harness/ndjson-frame.d.ts.map +1 -0
  47. package/dist/conformance/stdio-harness/ndjson-frame.js +125 -0
  48. package/dist/conformance/stdio-harness/ndjson-frame.js.map +1 -0
  49. package/dist/conformance/stdio-harness/node-process-tree-runtime.d.ts +15 -0
  50. package/dist/conformance/stdio-harness/node-process-tree-runtime.d.ts.map +1 -0
  51. package/dist/conformance/stdio-harness/node-process-tree-runtime.js +78 -0
  52. package/dist/conformance/stdio-harness/node-process-tree-runtime.js.map +1 -0
  53. package/dist/conformance/stdio-harness/process-tree-controller.d.ts +51 -0
  54. package/dist/conformance/stdio-harness/process-tree-controller.d.ts.map +1 -0
  55. package/dist/conformance/stdio-harness/process-tree-controller.js +162 -0
  56. package/dist/conformance/stdio-harness/process-tree-controller.js.map +1 -0
  57. package/dist/conformance/stdio-harness/windows-sentinel.d.ts +15 -0
  58. package/dist/conformance/stdio-harness/windows-sentinel.d.ts.map +1 -0
  59. package/dist/conformance/stdio-harness/windows-sentinel.js +160 -0
  60. package/dist/conformance/stdio-harness/windows-sentinel.js.map +1 -0
  61. package/dist/conformance/stdio-harness/wire-shape.d.ts +18 -0
  62. package/dist/conformance/stdio-harness/wire-shape.d.ts.map +1 -0
  63. package/dist/conformance/stdio-harness/wire-shape.js +2 -0
  64. package/dist/conformance/stdio-harness/wire-shape.js.map +1 -0
  65. package/dist/generated/contract.generated.d.ts +305 -1
  66. package/dist/generated/contract.generated.d.ts.map +1 -1
  67. package/dist/generated/contract.generated.js +1 -1
  68. package/dist/generated/contract.generated.js.map +1 -1
  69. package/dist/index.d.ts +3 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +5 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/validation/index.d.ts +2 -0
  74. package/dist/validation/index.d.ts.map +1 -1
  75. package/dist/validation/index.js +2 -0
  76. package/dist/validation/index.js.map +1 -1
  77. package/dist/validation/manifest.d.ts +23 -0
  78. package/dist/validation/manifest.d.ts.map +1 -0
  79. package/dist/validation/manifest.js +53 -0
  80. package/dist/validation/manifest.js.map +1 -0
  81. package/dist/validation/signals.d.ts +26 -0
  82. package/dist/validation/signals.d.ts.map +1 -0
  83. package/dist/validation/signals.js +206 -0
  84. package/dist/validation/signals.js.map +1 -0
  85. package/dist/wire/constants.d.ts +36 -0
  86. package/dist/wire/constants.d.ts.map +1 -0
  87. package/dist/wire/constants.js +36 -0
  88. package/dist/wire/constants.js.map +1 -0
  89. package/dist/wire/disposition-fixtures.d.ts +110 -0
  90. package/dist/wire/disposition-fixtures.d.ts.map +1 -0
  91. package/dist/wire/disposition-fixtures.js +1462 -0
  92. package/dist/wire/disposition-fixtures.js.map +1 -0
  93. package/dist/wire/disposition.d.ts +102 -0
  94. package/dist/wire/disposition.d.ts.map +1 -0
  95. package/dist/wire/disposition.js +217 -0
  96. package/dist/wire/disposition.js.map +1 -0
  97. package/dist/wire/envelope.d.ts +253 -0
  98. package/dist/wire/envelope.d.ts.map +1 -0
  99. package/dist/wire/envelope.js +19 -0
  100. package/dist/wire/envelope.js.map +1 -0
  101. package/dist/wire/errors.d.ts +222 -0
  102. package/dist/wire/errors.d.ts.map +1 -0
  103. package/dist/wire/errors.js +153 -0
  104. package/dist/wire/errors.js.map +1 -0
  105. package/dist/wire/grants.d.ts +57 -0
  106. package/dist/wire/grants.d.ts.map +1 -0
  107. package/dist/wire/grants.js +59 -0
  108. package/dist/wire/grants.js.map +1 -0
  109. package/dist/wire/handshake-byte-bounds.d.ts +69 -0
  110. package/dist/wire/handshake-byte-bounds.d.ts.map +1 -0
  111. package/dist/wire/handshake-byte-bounds.js +173 -0
  112. package/dist/wire/handshake-byte-bounds.js.map +1 -0
  113. package/dist/wire/handshake.d.ts +146 -0
  114. package/dist/wire/handshake.d.ts.map +1 -0
  115. package/dist/wire/handshake.js +189 -0
  116. package/dist/wire/handshake.js.map +1 -0
  117. package/dist/wire/index.d.ts +35 -0
  118. package/dist/wire/index.d.ts.map +1 -0
  119. package/dist/wire/index.js +53 -0
  120. package/dist/wire/index.js.map +1 -0
  121. package/dist/wire/lifecycle-byte-bounds.d.ts +55 -0
  122. package/dist/wire/lifecycle-byte-bounds.d.ts.map +1 -0
  123. package/dist/wire/lifecycle-byte-bounds.js +209 -0
  124. package/dist/wire/lifecycle-byte-bounds.js.map +1 -0
  125. package/dist/wire/registry.d.ts +283 -0
  126. package/dist/wire/registry.d.ts.map +1 -0
  127. package/dist/wire/registry.js +258 -0
  128. package/dist/wire/registry.js.map +1 -0
  129. package/dist/wire/request-id.d.ts +34 -0
  130. package/dist/wire/request-id.d.ts.map +1 -0
  131. package/dist/wire/request-id.js +40 -0
  132. package/dist/wire/request-id.js.map +1 -0
  133. package/dist/wire/row-shapes.d.ts +212 -0
  134. package/dist/wire/row-shapes.d.ts.map +1 -0
  135. package/dist/wire/row-shapes.js +59 -0
  136. package/dist/wire/row-shapes.js.map +1 -0
  137. package/dist/wire/signal-byte-bounds.d.ts +97 -0
  138. package/dist/wire/signal-byte-bounds.d.ts.map +1 -0
  139. package/dist/wire/signal-byte-bounds.js +229 -0
  140. package/dist/wire/signal-byte-bounds.js.map +1 -0
  141. package/dist/wire/wire-uint53.d.ts +26 -0
  142. package/dist/wire/wire-uint53.d.ts.map +1 -0
  143. package/dist/wire/wire-uint53.js +32 -0
  144. package/dist/wire/wire-uint53.js.map +1 -0
  145. package/fixtures/behavior/messaging/adversarial-invariants.json +56 -5
  146. package/fixtures/manifest/invalid/duplicate-signal-type.json +33 -0
  147. package/fixtures/signals/invalid/destination-injection.json +15 -0
  148. package/fixtures/signals/invalid/dynamic-schema-url.json +10 -0
  149. package/fixtures/signals/invalid/forbidden-raw-privacy.json +10 -0
  150. package/fixtures/signals/invalid/non-utc-occurred-at.json +12 -0
  151. package/fixtures/signals/valid/feishu-meeting-artifact.json +18 -0
  152. package/fixtures/signals/valid/remote-service-declaration.json +10 -0
  153. package/package.json +13 -5
  154. package/src/schemas/manifest.schema.json +5 -2
  155. package/src/schemas/messaging.schema.json +1 -0
  156. package/src/schemas/physical-limb.schema.json +319 -0
  157. package/src/schemas/signal.schema.json +129 -0
@@ -0,0 +1,296 @@
1
+ import {} from 'node:child_process';
2
+ import { createDirectTargetLifecycle, spawnHarnessProcess, spawnHarnessProcessWithAdapter, } from './harness-process-spawn.js';
3
+ import { NdjsonFrameDecoder, encodeNdjsonFrame, } from './ndjson-frame.js';
4
+ import { createNodeProcessTreeRuntime } from './node-process-tree-runtime.js';
5
+ import { HarnessCleanupError, ProcessTreeController, } from './process-tree-controller.js';
6
+ export { HarnessCleanupError } from './process-tree-controller.js';
7
+ export const MAX_HARNESS_QUEUED_FRAMES = 16;
8
+ /**
9
+ * Node.js setTimeout uses a 32-bit signed integer internally.
10
+ * Values above 2^31-1 (2_147_483_647) are silently clamped to 1ms,
11
+ * making the timer fire immediately — a correctness hazard.
12
+ */
13
+ export const MAX_TIMER_MS = 2_147_483_647;
14
+ function assertTimerMs(value, name) {
15
+ if (!Number.isSafeInteger(value) || value <= 0) {
16
+ throw new RangeError(`${name} must be a positive safe integer`);
17
+ }
18
+ if (value > MAX_TIMER_MS) {
19
+ throw new RangeError(`${name} must not exceed ${MAX_TIMER_MS}ms (Node timer overflow ceiling)`);
20
+ }
21
+ }
22
+ function assertTimerMsNonNegative(value, name) {
23
+ if (!Number.isSafeInteger(value) || value < 0) {
24
+ throw new RangeError(`${name} must be a non-negative safe integer`);
25
+ }
26
+ if (value > MAX_TIMER_MS) {
27
+ throw new RangeError(`${name} must not exceed ${MAX_TIMER_MS}ms (Node timer overflow ceiling)`);
28
+ }
29
+ }
30
+ const HARNESS_CLEANUP_TIMEOUT_MS = 1_000;
31
+ const HARNESS_CLEANUP_PROBE_INTERVAL_MS = 5;
32
+ const TASKKILL_TIMEOUT_MS = 500;
33
+ const TARGET_EXIT_GRACE_MS = 500;
34
+ export class HarnessTimeoutError extends Error {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = 'HarnessTimeoutError';
38
+ }
39
+ }
40
+ export class HarnessChildExitedError extends Error {
41
+ exit;
42
+ constructor(exit) {
43
+ super(`harness child exited before another frame was available (code=${String(exit.code)}, signal=${String(exit.signal)})`);
44
+ this.exit = exit;
45
+ this.name = 'HarnessChildExitedError';
46
+ }
47
+ }
48
+ export class HarnessFrameBacklogError extends Error {
49
+ maxQueuedFrames;
50
+ constructor(maxQueuedFrames = MAX_HARNESS_QUEUED_FRAMES) {
51
+ super(`decoded child frame backlog exceeded ${maxQueuedFrames} queued frames`);
52
+ this.maxQueuedFrames = maxQueuedFrames;
53
+ this.name = 'HarnessFrameBacklogError';
54
+ }
55
+ }
56
+ export class HarnessChild {
57
+ child;
58
+ pid;
59
+ decoder = new NdjsonFrameDecoder();
60
+ frames = [];
61
+ waiters = [];
62
+ exitPromise;
63
+ processTree;
64
+ resolveExit;
65
+ exit;
66
+ streamsClosed = false;
67
+ stopPromise;
68
+ constructor(child, target = createDirectTargetLifecycle(child), runtime = createNodeProcessTreeRuntime(process.platform, target.signalTarget)) {
69
+ this.child = child;
70
+ this.pid = child.pid;
71
+ this.processTree = new ProcessTreeController(this.pid, runtime);
72
+ this.exitPromise = new Promise((resolve) => {
73
+ this.resolveExit = resolve;
74
+ });
75
+ child.stdout.on('data', (chunk) => {
76
+ try {
77
+ for (const frame of this.decoder.push(chunk)) {
78
+ this.enqueue(frame);
79
+ }
80
+ }
81
+ catch (error) {
82
+ this.failAndKill(error);
83
+ }
84
+ });
85
+ child.stdout.on('end', () => {
86
+ if (harnessFatalErrors.has(this)) {
87
+ return;
88
+ }
89
+ try {
90
+ for (const frame of this.decoder.end()) {
91
+ this.enqueue(frame);
92
+ }
93
+ }
94
+ catch (error) {
95
+ this.failAndKill(error);
96
+ }
97
+ });
98
+ child.stdin.on('error', (error) => this.failAndKill(error));
99
+ child.stdout.on('error', (error) => this.failAndKill(error));
100
+ child.stderr.on('error', (error) => this.failAndKill(error));
101
+ target.onTargetError((error) => this.failAndKill(error));
102
+ child.stderr.resume();
103
+ const recordExit = (code, signal) => {
104
+ if (this.exit === undefined) {
105
+ this.exit = { code, signal };
106
+ this.processTree.markTargetExited();
107
+ this.resolveExit(this.exit);
108
+ }
109
+ return this.exit;
110
+ };
111
+ target.onTargetExit(recordExit);
112
+ child.once('close', (code, signal) => {
113
+ const exit = recordExit(code, signal);
114
+ this.streamsClosed = true;
115
+ this.processTree.markStreamsClosed();
116
+ if (!harnessFatalErrors.has(this)) {
117
+ this.rejectWaiters(new HarnessChildExitedError(exit));
118
+ }
119
+ });
120
+ this.processTree.markRunning();
121
+ }
122
+ async send(frame) {
123
+ this.assertRunning();
124
+ const encoded = encodeNdjsonFrame(frame);
125
+ await new Promise((resolve, reject) => {
126
+ this.child.stdin.write(encoded, (error) => {
127
+ if (error === null || error === undefined) {
128
+ resolve();
129
+ }
130
+ else {
131
+ reject(error);
132
+ }
133
+ });
134
+ });
135
+ }
136
+ async receive(options) {
137
+ assertTimerMs(options.timeoutMs, 'receive timeoutMs');
138
+ const frame = this.frames.shift();
139
+ if (frame !== undefined) {
140
+ return frame;
141
+ }
142
+ const fatalError = harnessFatalErrors.get(this);
143
+ if (fatalError !== undefined) {
144
+ throw fatalError;
145
+ }
146
+ if (this.streamsClosed && this.exit !== undefined) {
147
+ throw new HarnessChildExitedError(this.exit);
148
+ }
149
+ return new Promise((resolve, reject) => {
150
+ const waiter = {
151
+ resolve,
152
+ reject,
153
+ timer: setTimeout(() => {
154
+ const index = this.waiters.indexOf(waiter);
155
+ if (index !== -1) {
156
+ this.waiters.splice(index, 1);
157
+ }
158
+ reject(new HarnessTimeoutError(`timed out after ${options.timeoutMs}ms waiting for child frame`));
159
+ }, options.timeoutMs),
160
+ };
161
+ this.waiters.push(waiter);
162
+ });
163
+ }
164
+ kill(signal = 'SIGKILL') {
165
+ this.processTree.requestTermination(signal);
166
+ if (signal === 'SIGKILL') {
167
+ void this.startReap();
168
+ }
169
+ }
170
+ waitForExit() {
171
+ return this.exitPromise;
172
+ }
173
+ async stop(terminateGraceMs = 100) {
174
+ assertTimerMsNonNegative(terminateGraceMs, 'terminateGraceMs');
175
+ this.stopPromise ??= this.stopOnce(terminateGraceMs);
176
+ return await this.stopPromise;
177
+ }
178
+ async stopOnce(terminateGraceMs) {
179
+ this.child.stdin.end();
180
+ this.processTree.requestTermination('SIGTERM');
181
+ await new Promise((resolve) => {
182
+ const timer = setTimeout(resolve, terminateGraceMs);
183
+ this.exitPromise.then(() => {
184
+ clearTimeout(timer);
185
+ resolve();
186
+ });
187
+ });
188
+ this.processTree.requestTermination('SIGKILL');
189
+ await this.startReap();
190
+ return await this.exitPromise;
191
+ }
192
+ assertRunning() {
193
+ const fatalError = harnessFatalErrors.get(this);
194
+ if (fatalError !== undefined) {
195
+ throw fatalError;
196
+ }
197
+ if (this.exit !== undefined) {
198
+ throw new HarnessChildExitedError(this.exit);
199
+ }
200
+ }
201
+ enqueue(frame) {
202
+ const waiter = this.waiters.shift();
203
+ if (waiter === undefined) {
204
+ if (this.frames.length >= MAX_HARNESS_QUEUED_FRAMES) {
205
+ throw new HarnessFrameBacklogError();
206
+ }
207
+ this.frames.push(frame);
208
+ return;
209
+ }
210
+ clearTimeout(waiter.timer);
211
+ waiter.resolve(frame);
212
+ }
213
+ fail(error, discardQueuedFrames = false) {
214
+ if (harnessFatalErrors.has(this)) {
215
+ if (discardQueuedFrames) {
216
+ this.frames.splice(0);
217
+ }
218
+ return;
219
+ }
220
+ harnessFatalErrors.set(this, error);
221
+ if (discardQueuedFrames) {
222
+ this.frames.splice(0);
223
+ }
224
+ this.rejectWaiters(error);
225
+ }
226
+ rejectWaiters(error) {
227
+ for (const waiter of this.waiters.splice(0)) {
228
+ clearTimeout(waiter.timer);
229
+ waiter.reject(error);
230
+ }
231
+ }
232
+ failAndKill(error) {
233
+ this.fail(error instanceof Error ? error : new Error(String(error)), true);
234
+ this.kill('SIGKILL');
235
+ }
236
+ startReap() {
237
+ const cleanup = this.processTree.reap({
238
+ timeoutMs: HARNESS_CLEANUP_TIMEOUT_MS,
239
+ probeIntervalMs: HARNESS_CLEANUP_PROBE_INTERVAL_MS,
240
+ taskkillTimeoutMs: TASKKILL_TIMEOUT_MS,
241
+ targetExitGraceMs: TARGET_EXIT_GRACE_MS,
242
+ });
243
+ void cleanup.catch((error) => {
244
+ this.fail(error instanceof Error ? error : new Error(String(error)), true);
245
+ });
246
+ return cleanup;
247
+ }
248
+ }
249
+ const harnessFatalErrors = new WeakMap();
250
+ export function spawnHarnessChild(options) {
251
+ const spawned = spawnHarnessProcess(options);
252
+ return new HarnessChild(spawned.root, spawned.target, spawned.runtime);
253
+ }
254
+ export function spawnHarnessChildWithAdapter(options, adapter) {
255
+ const spawned = spawnHarnessProcessWithAdapter(options, adapter);
256
+ return new HarnessChild(spawned.root, spawned.target, spawned.runtime);
257
+ }
258
+ export async function runHarnessCase(options, execute) {
259
+ assertTimerMs(options.timeoutMs, 'case timeoutMs');
260
+ assertTimerMsNonNegative(options.terminateGraceMs ?? 100, 'case terminateGraceMs');
261
+ const child = spawnHarnessChild(options);
262
+ let timer;
263
+ let completed = false;
264
+ let result;
265
+ let executionError;
266
+ try {
267
+ result = await Promise.race([
268
+ execute(child),
269
+ new Promise((_, reject) => {
270
+ timer = setTimeout(() => {
271
+ child.kill('SIGKILL');
272
+ reject(new HarnessTimeoutError(`harness case timed out after ${options.timeoutMs}ms`));
273
+ }, options.timeoutMs);
274
+ }),
275
+ ]);
276
+ completed = true;
277
+ }
278
+ catch (error) {
279
+ executionError = error;
280
+ }
281
+ finally {
282
+ if (timer !== undefined) {
283
+ clearTimeout(timer);
284
+ }
285
+ await child.stop(options.terminateGraceMs);
286
+ }
287
+ const fatalError = harnessFatalErrors.get(child);
288
+ if (fatalError !== undefined) {
289
+ throw fatalError;
290
+ }
291
+ if (!completed) {
292
+ throw executionError;
293
+ }
294
+ return result;
295
+ }
296
+ //# sourceMappingURL=child-process-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-process-harness.js","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/child-process-harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface OracleTransport<Input, Result, Observation> {
2
+ /** Harness-local control-plane setup; never sent over the plugin wire. */
3
+ setup(): Promise<void>;
4
+ /** The sole semantic operation path being compared across transports. */
5
+ execute(input: Input): Promise<Result>;
6
+ /** Harness-local observation; never exposed as a production wire method. */
7
+ observe(): Promise<Observation>;
8
+ }
9
+ export interface DualTransportOracleCase<Input> {
10
+ readonly id: string;
11
+ readonly input: Input;
12
+ }
13
+ export interface TransportTranscript<Result, Observation> {
14
+ readonly before: Observation;
15
+ readonly result: Result;
16
+ readonly after: Observation;
17
+ }
18
+ export interface DualTransportOracleReport<Result, Observation> {
19
+ readonly id: string;
20
+ readonly passed: boolean;
21
+ readonly failures: readonly string[];
22
+ readonly inProcess: TransportTranscript<Result, Observation>;
23
+ readonly wire: TransportTranscript<Result, Observation>;
24
+ }
25
+ export declare function runDualTransportOracle<Input, Result, Observation>(oracleCase: DualTransportOracleCase<Input>, inProcessTransport: OracleTransport<Input, Result, Observation>, wireTransport: OracleTransport<Input, Result, Observation>): Promise<DualTransportOracleReport<Result, Observation>>;
26
+ //# sourceMappingURL=dual-transport-oracle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dual-transport-oracle.d.ts","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/dual-transport-oracle.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW;IACzD,0EAA0E;IAC1E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,yEAAyE;IACzE,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,4EAA4E;IAC5E,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB,CAAC,KAAK;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB,CAAC,MAAM,EAAE,WAAW;IACtD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB,CAAC,MAAM,EAAE,WAAW;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7D,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACzD;AAaD,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EACrE,UAAU,EAAE,uBAAuB,CAAC,KAAK,CAAC,EAC1C,kBAAkB,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAC/D,aAAa,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,GACzD,OAAO,CAAC,yBAAyB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAwBzD"}
@@ -0,0 +1,32 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ async function captureTranscript(input, transport) {
3
+ await transport.setup();
4
+ const before = structuredClone(await transport.observe());
5
+ const result = structuredClone(await transport.execute(structuredClone(input)));
6
+ const after = structuredClone(await transport.observe());
7
+ return { before, result, after };
8
+ }
9
+ export async function runDualTransportOracle(oracleCase, inProcessTransport, wireTransport) {
10
+ const [inProcess, wire] = await Promise.all([
11
+ captureTranscript(oracleCase.input, inProcessTransport),
12
+ captureTranscript(oracleCase.input, wireTransport),
13
+ ]);
14
+ const failures = [];
15
+ if (!isDeepStrictEqual(inProcess.before, wire.before)) {
16
+ failures.push('before observation mismatch');
17
+ }
18
+ if (!isDeepStrictEqual(inProcess.result, wire.result)) {
19
+ failures.push('result mismatch');
20
+ }
21
+ if (!isDeepStrictEqual(inProcess.after, wire.after)) {
22
+ failures.push('after observation mismatch');
23
+ }
24
+ return {
25
+ id: oracleCase.id,
26
+ passed: failures.length === 0,
27
+ failures,
28
+ inProcess,
29
+ wire,
30
+ };
31
+ }
32
+ //# sourceMappingURL=dual-transport-oracle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dual-transport-oracle.js","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/dual-transport-oracle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AA8B9C,KAAK,UAAU,iBAAiB,CAC9B,KAAY,EACZ,SAAsD;IAEtD,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChF,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IACzD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAA0C,EAC1C,kBAA+D,EAC/D,aAA0D;IAE1D,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1C,iBAAiB,CAAC,UAAU,CAAC,KAAK,EAAE,kBAAkB,CAAC;QACvD,iBAAiB,CAAC,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC;KACnD,CAAC,CAAC;IACH,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,MAAM,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC7B,QAAQ;QACR,SAAS;QACT,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { type ChildProcessWithoutNullStreams } from 'node:child_process';
2
+ import { type ProcessTreeRuntime } from './process-tree-controller.js';
3
+ export interface SpawnHarnessChildOptions {
4
+ readonly command: string;
5
+ readonly args?: readonly string[];
6
+ readonly cwd?: string;
7
+ readonly env?: NodeJS.ProcessEnv;
8
+ }
9
+ export interface HarnessTargetLifecycle {
10
+ readonly onTargetError: (listener: (error: Error) => void) => void;
11
+ readonly onTargetExit: (listener: (code: number | null, signal: NodeJS.Signals | null) => void) => void;
12
+ readonly signalTarget: (signal: NodeJS.Signals) => void;
13
+ }
14
+ /** @internal Injectable platform boundary for cross-platform conformance tests. */
15
+ export interface HarnessPlatformAdapter {
16
+ readonly platform: NodeJS.Platform;
17
+ readonly createProcessTreeRuntime: (signalTarget: (signal: NodeJS.Signals) => void) => ProcessTreeRuntime;
18
+ }
19
+ export interface SpawnedHarnessProcess {
20
+ readonly root: ChildProcessWithoutNullStreams;
21
+ readonly target: HarnessTargetLifecycle;
22
+ readonly runtime: ProcessTreeRuntime;
23
+ }
24
+ export declare function spawnHarnessProcess(options: SpawnHarnessChildOptions): SpawnedHarnessProcess;
25
+ export declare function spawnHarnessProcessWithAdapter(options: SpawnHarnessChildOptions, adapter: HarnessPlatformAdapter): SpawnedHarnessProcess;
26
+ export declare function createDirectTargetLifecycle(child: ChildProcessWithoutNullStreams): HarnessTargetLifecycle;
27
+ //# sourceMappingURL=harness-process-spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-process-spawn.d.ts","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/harness-process-spawn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAGhF,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;IACnE,QAAQ,CAAC,YAAY,EAAE,CACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,KACnE,IAAI,CAAC;IACV,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;CACzD;AAED,mFAAmF;AACnF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IACnC,QAAQ,CAAC,wBAAwB,EAAE,CACjC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,KAC3C,kBAAkB,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;CACtC;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,wBAAwB,GAChC,qBAAqB,CAMvB;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,sBAAsB,GAC9B,qBAAqB,CAsBvB;AACD,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,8BAA8B,GACpC,sBAAsB,CAQxB"}
@@ -0,0 +1,43 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { createNodeProcessTreeRuntime } from './node-process-tree-runtime.js';
3
+ import {} from './process-tree-controller.js';
4
+ import { spawnWindowsSentinel } from './windows-sentinel.js';
5
+ export function spawnHarnessProcess(options) {
6
+ return spawnHarnessProcessWithAdapter(options, {
7
+ platform: process.platform,
8
+ createProcessTreeRuntime: (signalTarget) => createNodeProcessTreeRuntime(process.platform, signalTarget),
9
+ });
10
+ }
11
+ export function spawnHarnessProcessWithAdapter(options, adapter) {
12
+ const args = [...(options.args ?? [])];
13
+ if (adapter.platform === 'win32') {
14
+ const target = spawnWindowsSentinel({ ...options, args });
15
+ return {
16
+ root: target.root,
17
+ target,
18
+ runtime: adapter.createProcessTreeRuntime(target.signalTarget),
19
+ };
20
+ }
21
+ const root = spawn(options.command, args, {
22
+ cwd: options.cwd,
23
+ detached: true,
24
+ env: options.env,
25
+ stdio: ['pipe', 'pipe', 'pipe'],
26
+ });
27
+ const target = createDirectTargetLifecycle(root);
28
+ return {
29
+ root,
30
+ target,
31
+ runtime: adapter.createProcessTreeRuntime(target.signalTarget),
32
+ };
33
+ }
34
+ export function createDirectTargetLifecycle(child) {
35
+ return {
36
+ onTargetError: (listener) => child.once('error', listener),
37
+ onTargetExit: (listener) => child.once('exit', listener),
38
+ signalTarget: (signal) => {
39
+ child.kill(signal);
40
+ },
41
+ };
42
+ }
43
+ //# sourceMappingURL=harness-process-spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-process-spawn.js","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/harness-process-spawn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAuC,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAA2B,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AA+B7D,MAAM,UAAU,mBAAmB,CACjC,OAAiC;IAEjC,OAAO,8BAA8B,CAAC,OAAO,EAAE;QAC7C,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,wBAAwB,EAAE,CAAC,YAAY,EAAE,EAAE,CACzC,4BAA4B,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC;KAC/D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,OAAiC,EACjC,OAA+B;IAE/B,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,oBAAoB,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM;YACN,OAAO,EAAE,OAAO,CAAC,wBAAwB,CAAC,MAAM,CAAC,YAAY,CAAC;SAC/D,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE;QACxC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,IAAI;QACd,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,2BAA2B,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO;QACL,IAAI;QACJ,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,wBAAwB,CAAC,MAAM,CAAC,YAAY,CAAC;KAC/D,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,2BAA2B,CACzC,KAAqC;IAErC,OAAO;QACL,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;QAC1D,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;QACxD,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;YACvB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { HarnessChild, HarnessChildExitedError, HarnessCleanupError, HarnessFrameBacklogError, HarnessTimeoutError, MAX_HARNESS_QUEUED_FRAMES, MAX_TIMER_MS, runHarnessCase, spawnHarnessChild, type HarnessChildExit, type HarnessReceiveOptions, type RunHarnessCaseOptions, type SpawnHarnessChildOptions, } from './child-process-harness.js';
2
+ export { runDualTransportOracle, type DualTransportOracleCase, type DualTransportOracleReport, type OracleTransport, type TransportTranscript, } from './dual-transport-oracle.js';
3
+ export { MAX_NDJSON_FRAME_BYTES, NdjsonFrameDecoder, NdjsonFrameError, encodeNdjsonFrame, type DecodedNdjsonFrame, type JsonObject, type NdjsonFrameErrorCode, } from './ndjson-frame.js';
4
+ export type { HarnessWireShape } from './wire-shape.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,yBAAyB,EACzB,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,GAC9B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACpB,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { HarnessChild, HarnessChildExitedError, HarnessCleanupError, HarnessFrameBacklogError, HarnessTimeoutError, MAX_HARNESS_QUEUED_FRAMES, MAX_TIMER_MS, runHarnessCase, spawnHarnessChild, } from './child-process-harness.js';
2
+ export { runDualTransportOracle, } from './dual-transport-oracle.js';
3
+ export { MAX_NDJSON_FRAME_BYTES, NdjsonFrameDecoder, NdjsonFrameError, encodeNdjsonFrame, } from './ndjson-frame.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACnB,yBAAyB,EACzB,YAAY,EACZ,cAAc,EACd,iBAAiB,GAKlB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,GAKvB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAIlB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * NDJSON frame ceiling — derived from the canonical wire constant.
3
+ * P-1b consumes P-1a's truth; this alias exists for harness-local naming.
4
+ * Widened to `number` so callers can pass stricter sub-limits.
5
+ */
6
+ export declare const MAX_NDJSON_FRAME_BYTES: number;
7
+ export type JsonObject = Readonly<Record<string, unknown>>;
8
+ export interface DecodedNdjsonFrame {
9
+ /** Exact bytes before LF; retained for pre-parse contract validation. */
10
+ readonly raw: Uint8Array;
11
+ /** Convenience parse only; contract validation must still inspect raw. */
12
+ readonly value: JsonObject;
13
+ }
14
+ export type NdjsonFrameErrorCode = 'FRAME_TOO_LARGE' | 'INVALID_UTF8' | 'INVALID_JSON' | 'INVALID_FRAME' | 'TRUNCATED_FRAME' | 'DECODER_CLOSED';
15
+ export declare class NdjsonFrameError extends Error {
16
+ readonly code: NdjsonFrameErrorCode;
17
+ constructor(code: NdjsonFrameErrorCode, message: string);
18
+ }
19
+ export declare function encodeNdjsonFrame(value: JsonObject, maxFrameBytes?: number): Uint8Array;
20
+ export declare class NdjsonFrameDecoder {
21
+ private readonly maxFrameBytes;
22
+ private buffered;
23
+ private closed;
24
+ private failed;
25
+ constructor(maxFrameBytes?: number);
26
+ push(chunk: Uint8Array): readonly DecodedNdjsonFrame[];
27
+ end(): readonly DecodedNdjsonFrame[];
28
+ private assertOpen;
29
+ private fail;
30
+ }
31
+ //# sourceMappingURL=ndjson-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ndjson-frame.d.ts","sourceRoot":"","sources":["../../../src/conformance/stdio-harness/ndjson-frame.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAwB,CAAC;AAE9D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAED,MAAM,MAAM,oBAAoB,GAC5B,iBAAiB,GACjB,cAAc,GACd,cAAc,GACd,eAAe,GACf,iBAAiB,GACjB,gBAAgB,CAAC;AAErB,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB;gBAA1B,IAAI,EAAE,oBAAoB,EACnC,OAAO,EAAE,MAAM;CAKlB;AAyCD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,aAAa,SAAyB,GACrC,UAAU,CAmBZ;AAED,qBAAa,kBAAkB;IAKjB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAJ1C,OAAO,CAAC,QAAQ,CAAmB;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;gBAEM,aAAa,SAAyB;IAInE,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,kBAAkB,EAAE;IAkDtD,GAAG,IAAI,SAAS,kBAAkB,EAAE;IAapC,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,IAAI;CAIb"}
@@ -0,0 +1,125 @@
1
+ import { MAX_FRAME_BYTES } from '../../wire/constants.js';
2
+ /**
3
+ * NDJSON frame ceiling — derived from the canonical wire constant.
4
+ * P-1b consumes P-1a's truth; this alias exists for harness-local naming.
5
+ * Widened to `number` so callers can pass stricter sub-limits.
6
+ */
7
+ export const MAX_NDJSON_FRAME_BYTES = MAX_FRAME_BYTES;
8
+ export class NdjsonFrameError extends Error {
9
+ code;
10
+ constructor(code, message) {
11
+ super(message);
12
+ this.code = code;
13
+ this.name = 'NdjsonFrameError';
14
+ }
15
+ }
16
+ function validateMaxFrameBytes(maxFrameBytes) {
17
+ if (!Number.isSafeInteger(maxFrameBytes) ||
18
+ maxFrameBytes <= 0 ||
19
+ maxFrameBytes > MAX_NDJSON_FRAME_BYTES) {
20
+ throw new RangeError(`NDJSON maxFrameBytes must be a positive safe integer no greater than ${MAX_NDJSON_FRAME_BYTES}`);
21
+ }
22
+ }
23
+ function assertJsonObject(value) {
24
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
25
+ throw new NdjsonFrameError('INVALID_FRAME', 'NDJSON frames must contain one non-array JSON object');
26
+ }
27
+ }
28
+ function decodeFrame(frame) {
29
+ let text;
30
+ try {
31
+ text = new TextDecoder('utf-8', { fatal: true }).decode(frame);
32
+ }
33
+ catch {
34
+ throw new NdjsonFrameError('INVALID_UTF8', 'NDJSON frame is not valid UTF-8');
35
+ }
36
+ let value;
37
+ try {
38
+ value = JSON.parse(text);
39
+ }
40
+ catch {
41
+ throw new NdjsonFrameError('INVALID_JSON', 'NDJSON frame is not valid JSON');
42
+ }
43
+ assertJsonObject(value);
44
+ return { raw: Buffer.from(frame), value };
45
+ }
46
+ export function encodeNdjsonFrame(value, maxFrameBytes = MAX_NDJSON_FRAME_BYTES) {
47
+ validateMaxFrameBytes(maxFrameBytes);
48
+ assertJsonObject(value);
49
+ const serialized = JSON.stringify(value);
50
+ if (serialized === undefined) {
51
+ throw new NdjsonFrameError('INVALID_FRAME', 'NDJSON frames must serialize to one non-array JSON object');
52
+ }
53
+ assertJsonObject(JSON.parse(serialized));
54
+ const frame = Buffer.from(serialized, 'utf8');
55
+ if (frame.byteLength > maxFrameBytes) {
56
+ throw new NdjsonFrameError('FRAME_TOO_LARGE', `NDJSON frame is ${frame.byteLength} bytes; limit is ${maxFrameBytes}`);
57
+ }
58
+ return Buffer.concat([frame, Buffer.from('\n')], frame.byteLength + 1);
59
+ }
60
+ export class NdjsonFrameDecoder {
61
+ maxFrameBytes;
62
+ buffered = Buffer.alloc(0);
63
+ closed = false;
64
+ failed = false;
65
+ constructor(maxFrameBytes = MAX_NDJSON_FRAME_BYTES) {
66
+ this.maxFrameBytes = maxFrameBytes;
67
+ validateMaxFrameBytes(maxFrameBytes);
68
+ }
69
+ push(chunk) {
70
+ this.assertOpen();
71
+ if (chunk.byteLength === 0) {
72
+ return [];
73
+ }
74
+ const incoming = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
75
+ const combined = this.buffered.byteLength === 0
76
+ ? incoming
77
+ : Buffer.concat([this.buffered, incoming], this.buffered.byteLength + incoming.byteLength);
78
+ const frames = [];
79
+ let frameStart = 0;
80
+ try {
81
+ let newline = combined.indexOf(0x0a, frameStart);
82
+ while (newline !== -1) {
83
+ const frameLength = newline - frameStart;
84
+ if (frameLength > this.maxFrameBytes) {
85
+ throw new NdjsonFrameError('FRAME_TOO_LARGE', `NDJSON frame is ${frameLength} bytes; limit is ${this.maxFrameBytes}`);
86
+ }
87
+ if (frameLength === 0) {
88
+ throw new NdjsonFrameError('INVALID_FRAME', 'blank NDJSON frames are not allowed');
89
+ }
90
+ frames.push(decodeFrame(combined.subarray(frameStart, newline)));
91
+ frameStart = newline + 1;
92
+ newline = combined.indexOf(0x0a, frameStart);
93
+ }
94
+ const remainder = combined.subarray(frameStart);
95
+ if (remainder.byteLength > this.maxFrameBytes) {
96
+ throw new NdjsonFrameError('FRAME_TOO_LARGE', `unterminated NDJSON frame exceeded ${this.maxFrameBytes} bytes`);
97
+ }
98
+ this.buffered = Buffer.from(remainder);
99
+ return frames;
100
+ }
101
+ catch (error) {
102
+ this.fail();
103
+ throw error;
104
+ }
105
+ }
106
+ end() {
107
+ this.assertOpen();
108
+ this.closed = true;
109
+ if (this.buffered.byteLength === 0) {
110
+ return [];
111
+ }
112
+ this.buffered = Buffer.alloc(0);
113
+ throw new NdjsonFrameError('TRUNCATED_FRAME', 'NDJSON stream ended before the final LF delimiter');
114
+ }
115
+ assertOpen() {
116
+ if (this.closed || this.failed) {
117
+ throw new NdjsonFrameError('DECODER_CLOSED', 'NDJSON decoder is closed');
118
+ }
119
+ }
120
+ fail() {
121
+ this.failed = true;
122
+ this.buffered = Buffer.alloc(0);
123
+ }
124
+ }
125
+ //# sourceMappingURL=ndjson-frame.js.map