@gobing-ai/ts-runtime 0.4.13 → 0.4.15
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/README.md +4 -1
- package/dist/file-system-node.d.ts +3 -1
- package/dist/file-system-node.d.ts.map +1 -1
- package/dist/file-system-node.js +3 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/process-executor.d.ts +11 -1
- package/dist/process-executor.d.ts.map +1 -1
- package/dist/process-executor.js +31 -3
- package/dist/runtime-paths.d.ts +21 -0
- package/dist/runtime-paths.d.ts.map +1 -0
- package/dist/runtime-paths.js +15 -0
- package/package.json +4 -4
- package/src/file-system-node.ts +4 -2
- package/src/index.ts +2 -0
- package/src/process-executor.ts +42 -4
- package/src/runtime-paths.ts +31 -0
package/README.md
CHANGED
|
@@ -601,7 +601,10 @@ maxOutput, forceBuffered, an optional synchronous `onOutput({ stream, chunk,
|
|
|
601
601
|
timestamp })` observer, and registry fields (`source`, `teamId`, `agentId`).
|
|
602
602
|
`onOutput` observes live chunks while the returned `ProcessResult` retains the
|
|
603
603
|
complete buffered stdout/stderr; observers must enqueue and return, and thrown
|
|
604
|
-
observer errors are isolated from the child.
|
|
604
|
+
observer errors are isolated from the child. When `signal` is supplied, one-shot
|
|
605
|
+
commands run in an isolated process group on Unix so abort terminates descendants
|
|
606
|
+
that could otherwise retain the output pipes; Windows falls back to direct-child
|
|
607
|
+
cancellation. Inject the same `ProcessRegistry` into every executor that should
|
|
605
608
|
appear in one watch list; without a registry, behavior is unchanged.
|
|
606
609
|
|
|
607
610
|
Cloudflare Workers do not expose process execution; check
|
|
@@ -10,12 +10,14 @@
|
|
|
10
10
|
* variant.
|
|
11
11
|
*/
|
|
12
12
|
import type { FileSystem } from './file-system';
|
|
13
|
+
import type { RuntimePaths } from './runtime-paths';
|
|
13
14
|
/**
|
|
14
15
|
* Create a {@link FileSystem} backed by `node:fs`.
|
|
15
16
|
*
|
|
16
17
|
* @param root - Project root directory (default: walks up from `process.cwd()` looking for `bun.lock` or `package.json`).
|
|
18
|
+
* @param paths - Optional {@link RuntimePaths} anchor; `paths.cwd` seeds the project-root walk when `root` is absent. Defaults to the ambient process cwd.
|
|
17
19
|
*/
|
|
18
|
-
export declare function createNodeFileSystem(root?: string): FileSystem;
|
|
20
|
+
export declare function createNodeFileSystem(root?: string, paths?: RuntimePaths): FileSystem;
|
|
19
21
|
/**
|
|
20
22
|
* Find the project root by walking up from `startDir` looking for a `bun.lock`
|
|
21
23
|
* or `package.json` marker. Uses `existsSync`, so it works on both Node and Bun.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-system-node.d.ts","sourceRoot":"","sources":["../src/file-system-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmBH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"file-system-node.d.ts","sourceRoot":"","sources":["../src/file-system-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmBH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,UAAU,CA+EpF;AAWD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAaxD"}
|
package/dist/file-system-node.js
CHANGED
|
@@ -15,9 +15,10 @@ import { dirname, resolve as resolvePath } from 'node:path';
|
|
|
15
15
|
* Create a {@link FileSystem} backed by `node:fs`.
|
|
16
16
|
*
|
|
17
17
|
* @param root - Project root directory (default: walks up from `process.cwd()` looking for `bun.lock` or `package.json`).
|
|
18
|
+
* @param paths - Optional {@link RuntimePaths} anchor; `paths.cwd` seeds the project-root walk when `root` is absent. Defaults to the ambient process cwd.
|
|
18
19
|
*/
|
|
19
|
-
export function createNodeFileSystem(root) {
|
|
20
|
-
const projectRoot = root ?? findProjectRoot(process.cwd());
|
|
20
|
+
export function createNodeFileSystem(root, paths) {
|
|
21
|
+
const projectRoot = root ?? findProjectRoot(paths?.cwd ?? process.cwd());
|
|
21
22
|
return {
|
|
22
23
|
getProjectRoot: () => projectRoot,
|
|
23
24
|
resolve: (...segments) => resolvePath(projectRoot, ...segments),
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export { createInMemoryProcessRegistry, InMemoryProcessRegistry } from './proces
|
|
|
15
15
|
export { cloudflareWorkersFactory } from './runtime-cf';
|
|
16
16
|
export type { RuntimeFactory } from './runtime-factory';
|
|
17
17
|
export { _resetNodeFileSystem, nodeBunFactory } from './runtime-node-bun';
|
|
18
|
+
export type { RuntimePaths } from './runtime-paths';
|
|
19
|
+
export { ambientRuntimePaths } from './runtime-paths';
|
|
18
20
|
export * from './schema-validation';
|
|
19
21
|
export * from './types';
|
|
20
22
|
export { BunPipeProcessSpawner, BunSyncProcessExecutor } from './process-executor';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACH,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,aAAa,GAChB,MAAM,MAAM,CAAC;AACd,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EACR,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,UAAU,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,YAAY,EACR,8BAA8B,EAC9B,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,6BAA6B,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC1E,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AAIxB,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEnF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,sBAAsB,CAAC,CAAC;AAE3G;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,qBAAqB,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EACH,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,aAAa,GAChB,MAAM,MAAM,CAAC;AACd,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACjG,YAAY,EACR,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,UAAU,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,YAAY,EACR,8BAA8B,EAC9B,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,6BAA6B,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC1E,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AAIxB,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEnF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,sBAAsB,CAAC,CAAC;AAE3G;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC,cAAc,oBAAoB,EAAE,qBAAqB,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export { NodeProcessExecutor, ProcessExecutor } from './process-executor.js';
|
|
|
11
11
|
export { createInMemoryProcessRegistry, InMemoryProcessRegistry } from './process-registry.js';
|
|
12
12
|
export { cloudflareWorkersFactory } from './runtime-cf.js';
|
|
13
13
|
export { _resetNodeFileSystem, nodeBunFactory } from './runtime-node-bun.js';
|
|
14
|
+
export { ambientRuntimePaths } from './runtime-paths.js';
|
|
14
15
|
export * from './schema-validation.js';
|
|
15
16
|
export * from './types.js';
|
|
16
17
|
// ── Deprecated re-exports (backward compatibility) ──────────────────────
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ProcessExecutionSource, ProcessRegistry } from './process-registry';
|
|
2
|
+
import type { RuntimePaths } from './runtime-paths';
|
|
2
3
|
/** Controls how stdout/stderr is captured: buffered in memory or streamed to the caller's terminal. */
|
|
3
4
|
export type OutputPolicy = {
|
|
4
5
|
mode: 'buffered';
|
|
@@ -19,6 +20,12 @@ export interface ProcessExecutorConfig {
|
|
|
19
20
|
* Share one registry across all executors that should appear in the same watch list.
|
|
20
21
|
*/
|
|
21
22
|
registry?: ProcessRegistry;
|
|
23
|
+
/**
|
|
24
|
+
* Optional cwd/home anchor (ADR-023 A1 / task 0042). When set, `paths.cwd` is applied to
|
|
25
|
+
* any `run` that carries no explicit per-call `cwd`. Precedence is total:
|
|
26
|
+
* explicit per-call `cwd` > injected `paths.cwd` > ambient process cwd.
|
|
27
|
+
*/
|
|
28
|
+
paths?: RuntimePaths;
|
|
22
29
|
}
|
|
23
30
|
/** Options for spawning a child process. */
|
|
24
31
|
export interface ProcessOptions {
|
|
@@ -31,7 +38,10 @@ export interface ProcessOptions {
|
|
|
31
38
|
label?: string;
|
|
32
39
|
rejectOnError?: boolean;
|
|
33
40
|
forceBuffered?: boolean;
|
|
34
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* AbortSignal forwarded to execa and, on Unix, to the child's isolated
|
|
43
|
+
* process group so descendants cannot outlive a cancelled one-shot run.
|
|
44
|
+
*/
|
|
35
45
|
signal?: AbortSignal;
|
|
36
46
|
/**
|
|
37
47
|
* Optional non-blocking observer for incremental stdout/stderr.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-executor.d.ts","sourceRoot":"","sources":["../src/process-executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"process-executor.d.ts","sourceRoot":"","sources":["../src/process-executor.ts"],"names":[],"mappings":"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"}
|
package/dist/process-executor.js
CHANGED
|
@@ -24,7 +24,7 @@ export class NodeProcessExecutor {
|
|
|
24
24
|
async runUntraced(options) {
|
|
25
25
|
const args = options.args ?? [];
|
|
26
26
|
const execaOptions = buildExecaOptions({
|
|
27
|
-
cwd: options.cwd,
|
|
27
|
+
cwd: options.cwd ?? this.config.paths?.cwd,
|
|
28
28
|
env: options.env,
|
|
29
29
|
timeout: options.timeout ?? this.config.defaultTimeout,
|
|
30
30
|
maxOutput: options.maxOutput ?? this.config.defaultMaxOutput,
|
|
@@ -53,9 +53,10 @@ export class NodeProcessExecutor {
|
|
|
53
53
|
});
|
|
54
54
|
try {
|
|
55
55
|
const subprocess = execa(options.command, args, execaOptions);
|
|
56
|
+
const stopGroupCancellation = observeProcessGroupCancellation(subprocess, options.signal);
|
|
56
57
|
observeOutput(subprocess.stdout, 'stdout', options.onOutput);
|
|
57
58
|
observeOutput(subprocess.stderr, 'stderr', options.onOutput);
|
|
58
|
-
const result = await subprocess;
|
|
59
|
+
const result = await subprocess.finally(stopGroupCancellation);
|
|
59
60
|
// execa@9 Result does not expose pid — buffered runs leave pid unset.
|
|
60
61
|
const processResult = {
|
|
61
62
|
command: options.command,
|
|
@@ -355,8 +356,35 @@ function buildExecaOptions(opts) {
|
|
|
355
356
|
...(opts.env !== undefined ? { env: opts.env } : {}),
|
|
356
357
|
...(opts.timeout !== undefined ? { timeout: opts.timeout } : {}),
|
|
357
358
|
...(opts.maxOutput !== undefined ? { maxBuffer: opts.maxOutput } : {}),
|
|
358
|
-
...(opts.signal !== undefined
|
|
359
|
+
...(opts.signal !== undefined
|
|
360
|
+
? {
|
|
361
|
+
cancelSignal: opts.signal,
|
|
362
|
+
// Node's negative-pid group signal requires the child to lead
|
|
363
|
+
// a distinct process group. Windows has no equivalent.
|
|
364
|
+
...(process.platform !== 'win32' ? { detached: true } : {}),
|
|
365
|
+
}
|
|
366
|
+
: {}),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
function observeProcessGroupCancellation(subprocess, signal) {
|
|
370
|
+
const pid = subprocess.pid;
|
|
371
|
+
if (signal === undefined || process.platform === 'win32' || pid === undefined)
|
|
372
|
+
return () => { };
|
|
373
|
+
const abort = () => {
|
|
374
|
+
try {
|
|
375
|
+
process.kill(-pid, 'SIGTERM');
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
// The leader may already have exited through execa's cancelSignal.
|
|
379
|
+
// Fall back to the direct child without changing cancellation semantics.
|
|
380
|
+
subprocess.kill('SIGTERM');
|
|
381
|
+
}
|
|
359
382
|
};
|
|
383
|
+
if (signal.aborted)
|
|
384
|
+
abort();
|
|
385
|
+
else
|
|
386
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
387
|
+
return () => signal.removeEventListener('abort', abort);
|
|
360
388
|
}
|
|
361
389
|
function observeOutput(stream, name, observer) {
|
|
362
390
|
if (!stream || !observer)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injectable cwd/home anchor consumed by runtime seams ({@link createNodeFileSystem},
|
|
3
|
+
* {@link NodeProcessExecutor}, and the JSONL importer's root resolution).
|
|
4
|
+
*
|
|
5
|
+
* Defaults to the ambient process environment via {@link ambientRuntimePaths}; inject a fake
|
|
6
|
+
* in tests or whenever a consumer must not reach for ambient cwd/home state.
|
|
7
|
+
*/
|
|
8
|
+
export interface RuntimePaths {
|
|
9
|
+
/** Absolute working-directory anchor. */
|
|
10
|
+
readonly cwd: string;
|
|
11
|
+
/** Absolute home-directory anchor. */
|
|
12
|
+
readonly home: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Capture the current ambient {@link RuntimePaths}: `process.cwd()` for `cwd`, and `HOME` /
|
|
16
|
+
* `USERPROFILE` for `home`. When `home` is unset (e.g. on Cloudflare Workers), falls back to
|
|
17
|
+
* `cwd` so the field stays a non-optional absolute anchor — matching the `/`-fallback philosophy
|
|
18
|
+
* of {@link getProcessCwd}: a degraded but always-absolute anchor.
|
|
19
|
+
*/
|
|
20
|
+
export declare function ambientRuntimePaths(): RuntimePaths;
|
|
21
|
+
//# sourceMappingURL=runtime-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-paths.d.ts","sourceRoot":"","sources":["../src/runtime-paths.ts"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IACzB,yCAAyC;IACzC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,YAAY,CAGlD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Injectable cwd/home anchor for runtime seams. Composes {@link getProcessCwd} (path.ts) and
|
|
2
|
+
// {@link getHomeDir} (config.ts) so the two owning modules stay focused; this third module is the
|
|
3
|
+
// single home for the injectable shape and its ambient factory (ADR-023 A1 / task 0042).
|
|
4
|
+
import { getHomeDir } from './config.js';
|
|
5
|
+
import { getProcessCwd } from './path.js';
|
|
6
|
+
/**
|
|
7
|
+
* Capture the current ambient {@link RuntimePaths}: `process.cwd()` for `cwd`, and `HOME` /
|
|
8
|
+
* `USERPROFILE` for `home`. When `home` is unset (e.g. on Cloudflare Workers), falls back to
|
|
9
|
+
* `cwd` so the field stays a non-optional absolute anchor — matching the `/`-fallback philosophy
|
|
10
|
+
* of {@link getProcessCwd}: a degraded but always-absolute anchor.
|
|
11
|
+
*/
|
|
12
|
+
export function ambientRuntimePaths() {
|
|
13
|
+
const cwd = getProcessCwd();
|
|
14
|
+
return { cwd, home: getHomeDir() ?? cwd };
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/ts-runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.15",
|
|
4
4
|
"description": "@gobing-ai/ts-runtime — Runtime abstractions for Bun, Node, and Cloudflare Workers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -58,17 +58,17 @@
|
|
|
58
58
|
"release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-runtime-v<version> && git push --tags' && exit 1"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@gobing-ai/ts-utils": "^0.4.
|
|
61
|
+
"@gobing-ai/ts-utils": "^0.4.15",
|
|
62
62
|
"execa": "^9.5.0",
|
|
63
63
|
"yaml": "^2.7.0",
|
|
64
64
|
"zod": "^4.1.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
67
|
+
"@gobing-ai/ts-db": "^0.4.15",
|
|
68
68
|
"@types/bun": "1.3.14"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
71
|
+
"@gobing-ai/ts-db": "^0.4.15"
|
|
72
72
|
},
|
|
73
73
|
"peerDependenciesMeta": {
|
|
74
74
|
"@gobing-ai/ts-db": {
|
package/src/file-system-node.ts
CHANGED
|
@@ -28,14 +28,16 @@ import {
|
|
|
28
28
|
import { dirname, resolve as resolvePath } from 'node:path';
|
|
29
29
|
|
|
30
30
|
import type { FileSystem } from './file-system';
|
|
31
|
+
import type { RuntimePaths } from './runtime-paths';
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Create a {@link FileSystem} backed by `node:fs`.
|
|
34
35
|
*
|
|
35
36
|
* @param root - Project root directory (default: walks up from `process.cwd()` looking for `bun.lock` or `package.json`).
|
|
37
|
+
* @param paths - Optional {@link RuntimePaths} anchor; `paths.cwd` seeds the project-root walk when `root` is absent. Defaults to the ambient process cwd.
|
|
36
38
|
*/
|
|
37
|
-
export function createNodeFileSystem(root?: string): FileSystem {
|
|
38
|
-
const projectRoot = root ?? findProjectRoot(process.cwd());
|
|
39
|
+
export function createNodeFileSystem(root?: string, paths?: RuntimePaths): FileSystem {
|
|
40
|
+
const projectRoot = root ?? findProjectRoot(paths?.cwd ?? process.cwd());
|
|
39
41
|
|
|
40
42
|
return {
|
|
41
43
|
getProjectRoot: () => projectRoot,
|
package/src/index.ts
CHANGED
|
@@ -47,6 +47,8 @@ export { createInMemoryProcessRegistry, InMemoryProcessRegistry } from './proces
|
|
|
47
47
|
export { cloudflareWorkersFactory } from './runtime-cf';
|
|
48
48
|
export type { RuntimeFactory } from './runtime-factory';
|
|
49
49
|
export { _resetNodeFileSystem, nodeBunFactory } from './runtime-node-bun';
|
|
50
|
+
export type { RuntimePaths } from './runtime-paths';
|
|
51
|
+
export { ambientRuntimePaths } from './runtime-paths';
|
|
50
52
|
export * from './schema-validation';
|
|
51
53
|
export * from './types';
|
|
52
54
|
|
package/src/process-executor.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isatty } from 'node:tty';
|
|
2
2
|
import { type Options as ExecaOptions, execa } from 'execa';
|
|
3
3
|
import type { ProcessExecutionSource, ProcessRegistry } from './process-registry';
|
|
4
|
+
import type { RuntimePaths } from './runtime-paths';
|
|
4
5
|
|
|
5
6
|
// ── Types ────────────────────────────────────────────────────────────────
|
|
6
7
|
|
|
@@ -20,6 +21,12 @@ export interface ProcessExecutorConfig {
|
|
|
20
21
|
* Share one registry across all executors that should appear in the same watch list.
|
|
21
22
|
*/
|
|
22
23
|
registry?: ProcessRegistry;
|
|
24
|
+
/**
|
|
25
|
+
* Optional cwd/home anchor (ADR-023 A1 / task 0042). When set, `paths.cwd` is applied to
|
|
26
|
+
* any `run` that carries no explicit per-call `cwd`. Precedence is total:
|
|
27
|
+
* explicit per-call `cwd` > injected `paths.cwd` > ambient process cwd.
|
|
28
|
+
*/
|
|
29
|
+
paths?: RuntimePaths;
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
/** Options for spawning a child process. */
|
|
@@ -33,7 +40,10 @@ export interface ProcessOptions {
|
|
|
33
40
|
label?: string;
|
|
34
41
|
rejectOnError?: boolean;
|
|
35
42
|
forceBuffered?: boolean;
|
|
36
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* AbortSignal forwarded to execa and, on Unix, to the child's isolated
|
|
45
|
+
* process group so descendants cannot outlive a cancelled one-shot run.
|
|
46
|
+
*/
|
|
37
47
|
signal?: AbortSignal;
|
|
38
48
|
/**
|
|
39
49
|
* Optional non-blocking observer for incremental stdout/stderr.
|
|
@@ -191,7 +201,7 @@ export class NodeProcessExecutor implements ProcessExecutor {
|
|
|
191
201
|
private async runUntraced(options: ProcessOptions): Promise<ProcessResult> {
|
|
192
202
|
const args = options.args ?? [];
|
|
193
203
|
const execaOptions = buildExecaOptions({
|
|
194
|
-
cwd: options.cwd,
|
|
204
|
+
cwd: options.cwd ?? this.config.paths?.cwd,
|
|
195
205
|
env: options.env,
|
|
196
206
|
timeout: options.timeout ?? this.config.defaultTimeout,
|
|
197
207
|
maxOutput: options.maxOutput ?? this.config.defaultMaxOutput,
|
|
@@ -221,9 +231,10 @@ export class NodeProcessExecutor implements ProcessExecutor {
|
|
|
221
231
|
|
|
222
232
|
try {
|
|
223
233
|
const subprocess = execa(options.command, args, execaOptions);
|
|
234
|
+
const stopGroupCancellation = observeProcessGroupCancellation(subprocess, options.signal);
|
|
224
235
|
observeOutput(subprocess.stdout, 'stdout', options.onOutput);
|
|
225
236
|
observeOutput(subprocess.stderr, 'stderr', options.onOutput);
|
|
226
|
-
const result = await subprocess;
|
|
237
|
+
const result = await subprocess.finally(stopGroupCancellation);
|
|
227
238
|
// execa@9 Result does not expose pid — buffered runs leave pid unset.
|
|
228
239
|
const processResult = {
|
|
229
240
|
command: options.command,
|
|
@@ -602,8 +613,35 @@ function buildExecaOptions(opts: {
|
|
|
602
613
|
...(opts.env !== undefined ? { env: opts.env } : {}),
|
|
603
614
|
...(opts.timeout !== undefined ? { timeout: opts.timeout } : {}),
|
|
604
615
|
...(opts.maxOutput !== undefined ? { maxBuffer: opts.maxOutput } : {}),
|
|
605
|
-
...(opts.signal !== undefined
|
|
616
|
+
...(opts.signal !== undefined
|
|
617
|
+
? {
|
|
618
|
+
cancelSignal: opts.signal,
|
|
619
|
+
// Node's negative-pid group signal requires the child to lead
|
|
620
|
+
// a distinct process group. Windows has no equivalent.
|
|
621
|
+
...(process.platform !== 'win32' ? { detached: true } : {}),
|
|
622
|
+
}
|
|
623
|
+
: {}),
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function observeProcessGroupCancellation(
|
|
628
|
+
subprocess: { pid?: number; kill(signal?: NodeJS.Signals | number): boolean },
|
|
629
|
+
signal: AbortSignal | undefined,
|
|
630
|
+
): () => void {
|
|
631
|
+
const pid = subprocess.pid;
|
|
632
|
+
if (signal === undefined || process.platform === 'win32' || pid === undefined) return () => {};
|
|
633
|
+
const abort = (): void => {
|
|
634
|
+
try {
|
|
635
|
+
process.kill(-pid, 'SIGTERM');
|
|
636
|
+
} catch {
|
|
637
|
+
// The leader may already have exited through execa's cancelSignal.
|
|
638
|
+
// Fall back to the direct child without changing cancellation semantics.
|
|
639
|
+
subprocess.kill('SIGTERM');
|
|
640
|
+
}
|
|
606
641
|
};
|
|
642
|
+
if (signal.aborted) abort();
|
|
643
|
+
else signal.addEventListener('abort', abort, { once: true });
|
|
644
|
+
return () => signal.removeEventListener('abort', abort);
|
|
607
645
|
}
|
|
608
646
|
|
|
609
647
|
function observeOutput(
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Injectable cwd/home anchor for runtime seams. Composes {@link getProcessCwd} (path.ts) and
|
|
2
|
+
// {@link getHomeDir} (config.ts) so the two owning modules stay focused; this third module is the
|
|
3
|
+
// single home for the injectable shape and its ambient factory (ADR-023 A1 / task 0042).
|
|
4
|
+
|
|
5
|
+
import { getHomeDir } from './config';
|
|
6
|
+
import { getProcessCwd } from './path';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Injectable cwd/home anchor consumed by runtime seams ({@link createNodeFileSystem},
|
|
10
|
+
* {@link NodeProcessExecutor}, and the JSONL importer's root resolution).
|
|
11
|
+
*
|
|
12
|
+
* Defaults to the ambient process environment via {@link ambientRuntimePaths}; inject a fake
|
|
13
|
+
* in tests or whenever a consumer must not reach for ambient cwd/home state.
|
|
14
|
+
*/
|
|
15
|
+
export interface RuntimePaths {
|
|
16
|
+
/** Absolute working-directory anchor. */
|
|
17
|
+
readonly cwd: string;
|
|
18
|
+
/** Absolute home-directory anchor. */
|
|
19
|
+
readonly home: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Capture the current ambient {@link RuntimePaths}: `process.cwd()` for `cwd`, and `HOME` /
|
|
24
|
+
* `USERPROFILE` for `home`. When `home` is unset (e.g. on Cloudflare Workers), falls back to
|
|
25
|
+
* `cwd` so the field stays a non-optional absolute anchor — matching the `/`-fallback philosophy
|
|
26
|
+
* of {@link getProcessCwd}: a degraded but always-absolute anchor.
|
|
27
|
+
*/
|
|
28
|
+
export function ambientRuntimePaths(): RuntimePaths {
|
|
29
|
+
const cwd = getProcessCwd();
|
|
30
|
+
return { cwd, home: getHomeDir() ?? cwd };
|
|
31
|
+
}
|