stitchkit 0.103.9 → 0.103.11

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 (44) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  3. package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -1
  4. package/dist/entrypoints/agent-runtime/coding-tools.js +2 -1
  5. package/dist/entrypoints/agent-runtime/sandbox.js +28 -14
  6. package/dist/entrypoints/application/diagnostic-journal.js +2 -1
  7. package/dist/entrypoints/files.js +14 -4
  8. package/dist/entrypoints/process.d.ts +2 -1
  9. package/dist/entrypoints/process.d.ts.map +1 -1
  10. package/dist/entrypoints/process.js +9 -2
  11. package/dist/index-32jkwkdm.js +565 -0
  12. package/dist/{index-a4ajxwmb.js → index-g4jxe7ve.js} +113 -131
  13. package/dist/index-nybn2err.js +213 -0
  14. package/dist/index-ttf0y7b8.js +246 -0
  15. package/dist/internal/exclusive-lock-read.d.ts +20 -0
  16. package/dist/internal/exclusive-lock-read.d.ts.map +1 -0
  17. package/dist/internal/exclusive-lock.d.ts +3 -1
  18. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  19. package/dist/internal/process-instance.d.ts +46 -9
  20. package/dist/internal/process-instance.d.ts.map +1 -1
  21. package/dist/internal/with-exclusive-lock.d.ts +4 -3
  22. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  23. package/dist/process/command-owner.d.ts +7 -2
  24. package/dist/process/command-owner.d.ts.map +1 -1
  25. package/dist/process/contract.d.ts +22 -1
  26. package/dist/process/contract.d.ts.map +1 -1
  27. package/dist/process/group.d.ts +6 -1
  28. package/dist/process/group.d.ts.map +1 -1
  29. package/dist/process/launch.d.ts +65 -0
  30. package/dist/process/launch.d.ts.map +1 -0
  31. package/dist/process/leader-settlement.d.ts +6 -0
  32. package/dist/process/leader-settlement.d.ts.map +1 -0
  33. package/dist/process/start-failure.d.ts +7 -0
  34. package/dist/process/start-failure.d.ts.map +1 -0
  35. package/llms/agent-runtime.txt +7 -1
  36. package/llms/files.txt +1 -1
  37. package/llms/process.txt +115 -2
  38. package/llms-full.txt +123 -4
  39. package/llms.txt +3 -3
  40. package/native/darwin-arm64.node +0 -0
  41. package/native/darwin-x64.node +0 -0
  42. package/package.json +2 -2
  43. package/dist/index-7kxw1awn.js +0 -328
  44. package/dist/index-eeqmg7qm.js +0 -202
@@ -1,328 +0,0 @@
1
- import {
2
- loadDarwinBinding
3
- } from "./index-d4pa2bgs.js";
4
- import {
5
- isRecord
6
- } from "./index-9jfdm5tg.js";
7
-
8
- // src/internal/exclusive-lock.ts
9
- import { constants } from "node:fs";
10
- import { lstat, open, unlink } from "node:fs/promises";
11
- import { hostname } from "node:os";
12
- import { z as z2 } from "zod";
13
-
14
- // src/internal/process-identity.ts
15
- import { execFile } from "node:child_process";
16
- import { readFile } from "node:fs/promises";
17
- import { platform } from "node:os";
18
- import { promisify } from "node:util";
19
- var detectedIdentity;
20
- async function firstReadableLine(paths) {
21
- for (const path of paths) {
22
- try {
23
- const text = (await readFile(path, "utf8")).trim();
24
- if (text.length > 0)
25
- return text;
26
- } catch {}
27
- }
28
- return null;
29
- }
30
- var run = promisify(execFile);
31
- function parsePlatformUuid(dump) {
32
- return /"IOPlatformUUID"\s*=\s*"([^"]+)"/.exec(dump)?.[1] ?? null;
33
- }
34
- async function readDarwinPlatformUuid(command = "ioreg") {
35
- try {
36
- const { stdout } = await run(command, ["-rd1", "-c", "IOPlatformExpertDevice"], {
37
- timeout: 2000,
38
- maxBuffer: 1 << 20,
39
- encoding: "utf8"
40
- });
41
- return parsePlatformUuid(stdout);
42
- } catch {
43
- return null;
44
- }
45
- }
46
- async function machineIdentity(declared) {
47
- if (declared !== undefined)
48
- return declared;
49
- if (detectedIdentity !== undefined)
50
- return detectedIdentity;
51
- detectedIdentity = platform() === "darwin" ? await readDarwinPlatformUuid() : await firstReadableLine(["/etc/machine-id", "/var/lib/dbus/machine-id"]);
52
- return detectedIdentity;
53
- }
54
- async function probeLiveness(pid, reach = (target) => process.kill(target, 0)) {
55
- try {
56
- reach(pid);
57
- } catch (error) {
58
- return isRecord(error) && error.code === "ESRCH" ? "gone" : "alive";
59
- }
60
- return await isZombieProcess(pid) ? "gone" : "alive";
61
- }
62
- async function isZombieProcess(pid, seam = {}) {
63
- const { procRoot = "/proc", psCommand = "ps" } = seam;
64
- try {
65
- const stat = await readFile(`${procRoot}/${pid}/stat`, "utf8");
66
- return stat.slice(stat.lastIndexOf(")") + 1).trimStart().startsWith("Z");
67
- } catch {}
68
- try {
69
- const { stdout } = await run(psCommand, ["-o", "state=", "-p", String(pid)], {
70
- timeout: 2000,
71
- maxBuffer: 1 << 16,
72
- encoding: "utf8"
73
- });
74
- return stdout.trim().startsWith("Z");
75
- } catch {
76
- return false;
77
- }
78
- }
79
-
80
- // src/internal/process-instance.ts
81
- import { readFile as readFile2, readlink } from "node:fs/promises";
82
- import { platform as platform2 } from "node:os";
83
- import { z } from "zod";
84
- var ProcessInstanceSchema = z.object({
85
- platform: z.enum(["linux", "darwin"]),
86
- bootId: z.string().min(1),
87
- namespace: z.string().min(1),
88
- startId: z.string().regex(/^\d+$/)
89
- }).strict();
90
- function linuxProcessStart(stat, pid) {
91
- if (!stat.startsWith(`${pid} (`))
92
- return null;
93
- const end = stat.lastIndexOf(")");
94
- if (end < 0)
95
- return null;
96
- const start = stat.slice(end + 1).trim().split(/\s+/)[19];
97
- return start !== undefined && /^\d+$/.test(start) ? start : null;
98
- }
99
- async function readProcessInstance(pid, procRoot = "/proc") {
100
- try {
101
- if (platform2() === "darwin") {
102
- const result = ProcessInstanceSchema.safeParse(loadDarwinBinding().processIdentity(pid));
103
- return result.success ? result.data : null;
104
- }
105
- if (platform2() !== "linux")
106
- return null;
107
- const [bootId, namespace, ownStatus, timeNamespace, ownStat, stat] = await Promise.all([
108
- readFile2(`${procRoot}/sys/kernel/random/boot_id`, "utf8"),
109
- readlink(`${procRoot}/self/ns/pid`),
110
- readFile2(`${procRoot}/self/status`, "utf8"),
111
- readlink(`${procRoot}/self/ns/time`).catch((error) => {
112
- if (error instanceof Error && "code" in error && error.code === "ENOENT")
113
- return "";
114
- throw error;
115
- }),
116
- readFile2(`${procRoot}/self/stat`, "utf8"),
117
- readFile2(`${procRoot}/${pid}/stat`, "utf8")
118
- ]);
119
- const namespacePids = ownStatus.match(/^NStgid:[ \t]*(.*)$/m)?.[1]?.trim().split(/\s+/);
120
- if (namespacePids?.length !== 1 || namespacePids[0] !== String(process.pid) || linuxProcessStart(ownStat, process.pid) === null)
121
- return null;
122
- const startId = linuxProcessStart(stat, pid);
123
- if (startId === null || !bootId.trim())
124
- return null;
125
- return {
126
- platform: "linux",
127
- bootId: bootId.trim(),
128
- namespace: `${namespace};${timeNamespace}`,
129
- startId
130
- };
131
- } catch {
132
- return null;
133
- }
134
- }
135
- async function probeProcessOwner(pid, recorded, probes = { read: readProcessInstance, liveness: probeLiveness }) {
136
- if (recorded === undefined)
137
- return { liveness: await probes.liveness(pid), identity: "legacy" };
138
- const unavailable = {
139
- liveness: "not-probed",
140
- identity: "unavailable"
141
- };
142
- if (recorded === null)
143
- return unavailable;
144
- const current = await probes.read(process.pid);
145
- if (!current || recorded.platform !== current.platform)
146
- return unavailable;
147
- if (recorded.bootId !== current.bootId)
148
- return { liveness: "gone", identity: "different-boot" };
149
- if (recorded.namespace !== current.namespace)
150
- return unavailable;
151
- const liveness = await probes.liveness(pid);
152
- if (liveness === "gone")
153
- return { liveness, identity: "pid-gone" };
154
- const observed = await probes.read(pid);
155
- if (!observed || observed.bootId !== current.bootId || observed.namespace !== current.namespace)
156
- return unavailable;
157
- if (recorded.startId !== observed.startId)
158
- return { liveness: "gone", identity: "reused-pid" };
159
- return { liveness: "alive", identity: "matched" };
160
- }
161
-
162
- // src/internal/exclusive-lock.ts
163
- var ExclusiveLockOwnerSchema = z2.object({
164
- pid: z2.number().int().positive().max(Number.MAX_SAFE_INTEGER),
165
- host: z2.string().min(1),
166
- acquiredAt: z2.string(),
167
- machine: z2.string().min(1).optional().catch(undefined),
168
- process: ProcessInstanceSchema.nullable().optional().catch(null)
169
- });
170
- function isCode(error, code) {
171
- return isRecord(error) && error.code === code;
172
- }
173
- function readOwner(text) {
174
- let parsed;
175
- try {
176
- parsed = JSON.parse(text);
177
- } catch {
178
- return;
179
- }
180
- const owner = ExclusiveLockOwnerSchema.safeParse(parsed);
181
- return owner.success ? owner.data : undefined;
182
- }
183
- function attribute(owner, identity) {
184
- if (identity !== null && owner.machine !== undefined) {
185
- return owner.machine === identity ? "this-machine" : "another-machine";
186
- }
187
- return owner.host === hostname() ? "this-machine" : "unattributable";
188
- }
189
- async function diagnose(owner, declaredIdentity) {
190
- if (!owner)
191
- return { attribution: "unattributable", liveness: "not-probed", owner: null };
192
- const attribution = attribute(owner, await machineIdentity(declaredIdentity));
193
- if (attribution !== "this-machine")
194
- return { attribution, liveness: "not-probed", owner };
195
- return { attribution, ...await probeProcessOwner(owner.pid, owner.process), owner };
196
- }
197
- async function readLockFile(path) {
198
- let handle;
199
- try {
200
- handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
201
- const info = await handle.stat();
202
- return {
203
- owner: readOwner(await handle.readFile("utf8")),
204
- ino: info.ino,
205
- mtimeMs: info.mtimeMs
206
- };
207
- } catch {
208
- return;
209
- } finally {
210
- await handle?.close().catch(() => {
211
- return;
212
- });
213
- }
214
- }
215
- async function unlinkIfSame(path, ino) {
216
- try {
217
- if ((await lstat(path)).ino !== ino)
218
- return;
219
- await unlink(path);
220
- } catch (error) {
221
- if (!isCode(error, "ENOENT"))
222
- throw error;
223
- }
224
- }
225
- async function createOwned(path, options, reclaimed) {
226
- const identity = await machineIdentity(options.machineIdentity);
227
- const instance = await readProcessInstance(process.pid);
228
- const handle = await open(path, "wx", options.mode);
229
- const owner = {
230
- pid: process.pid,
231
- process: instance,
232
- host: hostname(),
233
- acquiredAt: new Date().toISOString(),
234
- ...identity !== null && { machine: identity }
235
- };
236
- let ino;
237
- try {
238
- await handle.writeFile(`${JSON.stringify(owner)}
239
- `, "utf8");
240
- ino = (await handle.stat()).ino;
241
- } catch (error) {
242
- await handle.close().catch(() => {
243
- return;
244
- });
245
- await unlink(path).catch(() => {
246
- return;
247
- });
248
- throw error;
249
- }
250
- let released = false;
251
- return {
252
- path,
253
- owner,
254
- reclaimed,
255
- async release() {
256
- if (released)
257
- return;
258
- released = true;
259
- try {
260
- await handle.close();
261
- } finally {
262
- await unlinkIfSame(path, ino);
263
- }
264
- }
265
- };
266
- }
267
- function reclaimable(state, diagnosis, graceMs) {
268
- if (state.owner)
269
- return diagnosis.liveness === "gone";
270
- return graceMs !== undefined && Date.now() - state.mtimeMs >= graceMs;
271
- }
272
- async function reclaimUnderGuard(path, options) {
273
- const guardPath = `${path}.reclaim`;
274
- let guard;
275
- try {
276
- guard = await createOwned(guardPath, options, false);
277
- } catch (error) {
278
- if (!isCode(error, "EEXIST"))
279
- throw error;
280
- const stale = await readLockFile(guardPath);
281
- if (stale) {
282
- const verdict = await diagnose(stale.owner, options.machineIdentity);
283
- if (reclaimable(stale, verdict, options.ownerlessGraceMs ?? 5000)) {
284
- await unlinkIfSame(guardPath, stale.ino);
285
- }
286
- }
287
- return;
288
- }
289
- try {
290
- const state = await readLockFile(path);
291
- if (state) {
292
- const diagnosis = await diagnose(state.owner, options.machineIdentity);
293
- if (!reclaimable(state, diagnosis, options.ownerlessGraceMs))
294
- return "refused";
295
- await unlinkIfSame(path, state.ino);
296
- }
297
- return await createOwned(path, options, state !== undefined).catch((error) => {
298
- if (isCode(error, "EEXIST"))
299
- return "refused";
300
- throw error;
301
- });
302
- } finally {
303
- await guard.release().catch(() => {
304
- return;
305
- });
306
- }
307
- }
308
- async function attemptExclusiveLock(path, options) {
309
- try {
310
- return { held: await createOwned(path, options, false) };
311
- } catch (error) {
312
- if (!isCode(error, "EEXIST"))
313
- throw error;
314
- if (!options.reclaim)
315
- return { error };
316
- const state = await readLockFile(path);
317
- const diagnosis = await diagnose(state?.owner, options.machineIdentity);
318
- if (!state || !reclaimable(state, diagnosis, options.ownerlessGraceMs)) {
319
- return { error, diagnosis };
320
- }
321
- const reclaimed = await reclaimUnderGuard(path, options);
322
- if (reclaimed !== undefined && reclaimed !== "refused")
323
- return { held: reclaimed };
324
- return { error, diagnosis };
325
- }
326
- }
327
-
328
- export { attemptExclusiveLock };
@@ -1,202 +0,0 @@
1
- import {
2
- raceAbort
3
- } from "./index-mbnnw3f2.js";
4
-
5
- // src/process/contract.ts
6
- import { z } from "zod";
7
- var NativeCommandOptionsSchema = z.strictObject({
8
- executable: z.string().min(1),
9
- args: z.array(z.string()).default([]),
10
- cwd: z.string().optional(),
11
- env: z.record(z.string(), z.string()).optional(),
12
- envPolicy: z.enum(["declared-only", "ambient"]).default("declared-only"),
13
- signal: z.custom((v) => v instanceof AbortSignal).optional(),
14
- timeoutMs: z.number().int().positive().max(2147483647).optional(),
15
- maxOutputBytes: z.number().int().positive().optional(),
16
- capture: z.boolean().default(false),
17
- stdin: z.custom((v) => v instanceof Uint8Array).optional(),
18
- maxStdinBytes: z.number().int().positive().default(1024 * 1024),
19
- onOutput: z.custom((v) => typeof v === "function").optional(),
20
- killGraceMs: z.number().int().nonnegative().max(1e4).default(100),
21
- cleanupTimeoutMs: z.number().int().positive().max(30000).default(2000)
22
- }).superRefine((input, ctx) => {
23
- if (!input.signal && input.timeoutMs === undefined)
24
- ctx.addIssue({ code: "custom", message: "Declare a caller signal or a finite timeout" });
25
- if (input.capture && input.maxOutputBytes === undefined)
26
- ctx.addIssue({
27
- code: "custom",
28
- message: "Capture requires a finite combined output budget"
29
- });
30
- if (input.stdin && input.stdin.byteLength > input.maxStdinBytes)
31
- ctx.addIssue({ code: "custom", message: "stdin exceeds maxStdinBytes" });
32
- });
33
- var NativeCommandResultSchema = z.object({
34
- exitCode: z.number().int().nullable(),
35
- signal: z.string().nullable(),
36
- stdout: z.instanceof(Uint8Array),
37
- stderr: z.instanceof(Uint8Array)
38
- });
39
-
40
- class NativeCommandError2 extends Error {
41
- code;
42
- constructor(code, message, options) {
43
- super(message, options);
44
- this.code = code;
45
- this.name = "NativeCommandError";
46
- }
47
- }
48
-
49
- // src/process/command-owner.ts
50
- import { spawn } from "node:child_process";
51
-
52
- // src/process/group.ts
53
- function signalGroup(pid, signal) {
54
- if (pid === undefined)
55
- return;
56
- try {
57
- process.kill(-pid, signal);
58
- } catch (error) {
59
- if (!(error instanceof Error && ("code" in error) && error.code === "ESRCH"))
60
- throw error;
61
- }
62
- }
63
- function exists(pid) {
64
- if (pid === undefined)
65
- return false;
66
- try {
67
- process.kill(-pid, 0);
68
- return true;
69
- } catch (error) {
70
- if (error instanceof Error && "code" in error && error.code === "ESRCH")
71
- return false;
72
- throw error;
73
- }
74
- }
75
- async function stopCommandGroup(pid, graceMs) {
76
- signalGroup(pid, "SIGTERM");
77
- const until = Date.now() + graceMs;
78
- while (Date.now() < until && exists(pid))
79
- await new Promise((resolve) => setTimeout(resolve, Math.min(10, until - Date.now())));
80
- signalGroup(pid, "SIGKILL");
81
- }
82
- function commandCleanupError(cause) {
83
- return new NativeCommandError2("COMMAND_CLEANUP", "Command cleanup did not complete", {
84
- cause
85
- });
86
- }
87
- function waitForCommandClose(closed, timeoutMs) {
88
- return raceAbort(closed, AbortSignal.timeout(timeoutMs));
89
- }
90
-
91
- // src/process/command-owner.ts
92
- function startNativeCommand(input, onSpawn) {
93
- const options = NativeCommandOptionsSchema.parse(input);
94
- options.signal?.throwIfAborted();
95
- if (process.platform === "win32")
96
- throw new NativeCommandError2("COMMAND_UNAVAILABLE", "POSIX process groups are required");
97
- const controller = new AbortController;
98
- const abort = () => controller.abort(options.signal?.reason);
99
- options.signal?.addEventListener("abort", abort, { once: true });
100
- if (options.signal?.aborted)
101
- abort();
102
- const timer = options.timeoutMs === undefined ? undefined : setTimeout(() => controller.abort(new NativeCommandError2("COMMAND_LIMIT", "Command deadline exceeded")), options.timeoutMs);
103
- let child;
104
- try {
105
- child = spawn(options.executable, options.args, {
106
- cwd: options.cwd,
107
- env: options.envPolicy === "ambient" ? { ...process.env, ...options.env } : options.env ?? {},
108
- detached: true,
109
- stdio: ["pipe", "pipe", "pipe"]
110
- });
111
- } catch (cause) {
112
- if (timer !== undefined)
113
- clearTimeout(timer);
114
- options.signal?.removeEventListener("abort", abort);
115
- throw new NativeCommandError2("COMMAND_UNAVAILABLE", "Command could not start", { cause });
116
- }
117
- const stdout = [];
118
- const stderr = [];
119
- let total = 0;
120
- let finished = false;
121
- let spawnFailure;
122
- const closed = new Promise((resolve) => {
123
- child.once("error", (error) => {
124
- spawnFailure = new NativeCommandError2("COMMAND_UNAVAILABLE", "Command could not start", {
125
- cause: error
126
- });
127
- controller.abort(spawnFailure);
128
- });
129
- child.once("close", (exitCode, signal) => resolve({ exitCode, signal }));
130
- });
131
- child.stdin.on("error", (error) => {
132
- if (!(("code" in error) && error.code === "EPIPE"))
133
- controller.abort(error);
134
- });
135
- const drain = async (stream, channel, captured) => {
136
- for await (const chunk of stream) {
137
- controller.signal.throwIfAborted();
138
- if (!(chunk instanceof Uint8Array))
139
- throw new TypeError("Expected binary command output");
140
- total += chunk.byteLength;
141
- if (options.maxOutputBytes !== undefined && total > options.maxOutputBytes)
142
- throw new NativeCommandError2("COMMAND_LIMIT", "Command output budget exceeded");
143
- if (options.capture)
144
- captured.push(Uint8Array.from(chunk));
145
- if (options.onOutput)
146
- await raceAbort(Promise.resolve().then(() => {
147
- controller.signal.throwIfAborted();
148
- return options.onOutput?.(chunk, channel, controller.signal);
149
- }), controller.signal);
150
- }
151
- };
152
- const result = (async () => {
153
- try {
154
- onSpawn?.(child);
155
- child.stdin.end(options.stdin);
156
- const drains = Promise.all([
157
- drain(child.stdout, "stdout", stdout),
158
- drain(child.stderr, "stderr", stderr)
159
- ]);
160
- await raceAbort(drains, controller.signal);
161
- const status = await raceAbort(closed, controller.signal);
162
- if (spawnFailure !== undefined)
163
- throw spawnFailure;
164
- return { ...status, stdout: Buffer.concat(stdout), stderr: Buffer.concat(stderr) };
165
- } catch (error) {
166
- controller.abort(error);
167
- child.stdin.destroy();
168
- child.stdout.destroy();
169
- child.stderr.destroy();
170
- try {
171
- await stopCommandGroup(child.pid, options.killGraceMs);
172
- await waitForCommandClose(closed, options.cleanupTimeoutMs);
173
- } catch (cleanup) {
174
- throw commandCleanupError(new AggregateError([error, cleanup], "Command failed and cleanup failed"));
175
- }
176
- throw error;
177
- } finally {
178
- finished = true;
179
- if (timer !== undefined)
180
- clearTimeout(timer);
181
- options.signal?.removeEventListener("abort", abort);
182
- controller.abort(new Error("Command completed"));
183
- }
184
- })();
185
- result.catch(() => {
186
- return;
187
- });
188
- return {
189
- result,
190
- async stop() {
191
- if (!finished)
192
- controller.abort(new DOMException("Command stopped", "AbortError"));
193
- await result.then(() => {
194
- return;
195
- }, () => {
196
- return;
197
- });
198
- }
199
- };
200
- }
201
-
202
- export { NativeCommandError2, startNativeCommand };