@tagma/sdk 0.4.1 → 0.4.3
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/LICENSE +21 -0
- package/dist/adapters/stdin-approval.d.ts +6 -0
- package/dist/adapters/stdin-approval.d.ts.map +1 -0
- package/dist/adapters/stdin-approval.js +90 -0
- package/dist/adapters/stdin-approval.js.map +1 -0
- package/dist/adapters/websocket-approval.d.ts +28 -0
- package/dist/adapters/websocket-approval.d.ts.map +1 -0
- package/dist/adapters/websocket-approval.js +145 -0
- package/dist/adapters/websocket-approval.js.map +1 -0
- package/dist/approval.d.ts +13 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +91 -0
- package/dist/approval.js.map +1 -0
- package/dist/bootstrap.d.ts +2 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +30 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/completions/exit-code.d.ts +3 -0
- package/dist/completions/exit-code.d.ts.map +1 -0
- package/dist/completions/exit-code.js +25 -0
- package/dist/completions/exit-code.js.map +1 -0
- package/dist/completions/file-exists.d.ts +3 -0
- package/dist/completions/file-exists.d.ts.map +1 -0
- package/dist/completions/file-exists.js +58 -0
- package/dist/completions/file-exists.js.map +1 -0
- package/dist/completions/output-check.d.ts +3 -0
- package/dist/completions/output-check.d.ts.map +1 -0
- package/dist/completions/output-check.js +81 -0
- package/dist/completions/output-check.js.map +1 -0
- package/dist/config-ops.d.ts +55 -0
- package/dist/config-ops.d.ts.map +1 -0
- package/dist/config-ops.js +258 -0
- package/dist/config-ops.js.map +1 -0
- package/dist/dag.d.ts +46 -0
- package/dist/dag.d.ts.map +1 -0
- package/dist/dag.js +193 -0
- package/dist/dag.js.map +1 -0
- package/dist/drivers/claude-code.d.ts +3 -0
- package/dist/drivers/claude-code.d.ts.map +1 -0
- package/dist/drivers/claude-code.js +210 -0
- package/dist/drivers/claude-code.js.map +1 -0
- package/dist/engine.d.ts +89 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +815 -0
- package/dist/engine.js.map +1 -0
- package/dist/hooks.d.ts +73 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +103 -0
- package/dist/hooks.js.map +1 -0
- package/dist/logger.d.ts +61 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +151 -0
- package/dist/logger.js.map +1 -0
- package/dist/middlewares/static-context.d.ts +3 -0
- package/dist/middlewares/static-context.d.ts.map +1 -0
- package/dist/middlewares/static-context.js +36 -0
- package/dist/middlewares/static-context.js.map +1 -0
- package/dist/pipeline-runner.d.ts +50 -0
- package/dist/pipeline-runner.d.ts.map +1 -0
- package/dist/pipeline-runner.js +139 -0
- package/dist/pipeline-runner.js.map +1 -0
- package/dist/registry.d.ts +43 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +182 -0
- package/dist/registry.js.map +1 -0
- package/dist/runner.d.ts +19 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +364 -0
- package/dist/runner.js.map +1 -0
- package/dist/schema.d.ts +27 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +373 -0
- package/dist/schema.js.map +1 -0
- package/dist/sdk.d.ts +27 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +33 -0
- package/dist/sdk.js.map +1 -0
- package/dist/templates.d.ts +20 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +93 -0
- package/dist/templates.js.map +1 -0
- package/dist/triggers/file.d.ts +3 -0
- package/dist/triggers/file.d.ts.map +1 -0
- package/dist/triggers/file.js +123 -0
- package/dist/triggers/file.js.map +1 -0
- package/dist/triggers/manual.d.ts +3 -0
- package/dist/triggers/manual.d.ts.map +1 -0
- package/dist/triggers/manual.js +73 -0
- package/dist/triggers/manual.js.map +1 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +14 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +138 -0
- package/dist/utils.js.map +1 -0
- package/dist/validate-raw.d.ts +26 -0
- package/dist/validate-raw.d.ts.map +1 -0
- package/dist/validate-raw.js +260 -0
- package/dist/validate-raw.js.map +1 -0
- package/package.json +26 -17
- package/src/adapters/websocket-approval.ts +20 -4
- package/src/approval.ts +5 -3
- package/src/registry.ts +214 -214
- package/scripts/preinstall.js +0 -38
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { watch } from 'chokidar';
|
|
2
|
+
import { resolve, dirname } from 'path';
|
|
3
|
+
import { mkdir } from 'fs/promises';
|
|
4
|
+
import { parseDuration, validatePath } from '../utils';
|
|
5
|
+
import { TriggerTimeoutError } from '../engine';
|
|
6
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
7
|
+
function pathsEqual(a, b) {
|
|
8
|
+
return IS_WINDOWS ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
9
|
+
}
|
|
10
|
+
export const FileTrigger = {
|
|
11
|
+
name: 'file',
|
|
12
|
+
schema: {
|
|
13
|
+
description: 'Wait for a file to appear or be modified before the task runs.',
|
|
14
|
+
fields: {
|
|
15
|
+
path: {
|
|
16
|
+
type: 'path',
|
|
17
|
+
required: true,
|
|
18
|
+
description: 'Path to the file to watch (relative to workDir or absolute).',
|
|
19
|
+
placeholder: 'e.g. build/output.json',
|
|
20
|
+
},
|
|
21
|
+
timeout: {
|
|
22
|
+
type: 'duration',
|
|
23
|
+
description: 'Maximum wait time (e.g. 30s, 5m). Omit or 0 to wait indefinitely.',
|
|
24
|
+
placeholder: '30s',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
watch(config, ctx) {
|
|
29
|
+
const filePath = config.path;
|
|
30
|
+
if (!filePath)
|
|
31
|
+
throw new Error(`file trigger: "path" is required`);
|
|
32
|
+
const safePath = validatePath(filePath, ctx.workDir);
|
|
33
|
+
const timeoutMs = config.timeout != null ? parseDuration(String(config.timeout)) : 0;
|
|
34
|
+
return new Promise(async (resolve_p, reject) => {
|
|
35
|
+
if (ctx.signal.aborted) {
|
|
36
|
+
reject(new Error('Pipeline aborted'));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
let settled = false;
|
|
40
|
+
let timer = null;
|
|
41
|
+
// Ensure the parent directory exists so the watcher doesn't fail
|
|
42
|
+
// with ENOENT for nested paths like `build/output/result.json`.
|
|
43
|
+
const dir = dirname(safePath);
|
|
44
|
+
try {
|
|
45
|
+
await mkdir(dir, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
catch { /* best effort — dir may already exist */ }
|
|
48
|
+
const watcher = watch(dir, {
|
|
49
|
+
ignoreInitial: true,
|
|
50
|
+
depth: 0,
|
|
51
|
+
awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 50 },
|
|
52
|
+
});
|
|
53
|
+
const cleanup = () => {
|
|
54
|
+
if (settled)
|
|
55
|
+
return;
|
|
56
|
+
settled = true;
|
|
57
|
+
watcher.close().catch(() => { });
|
|
58
|
+
if (timer)
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
ctx.signal.removeEventListener('abort', onAbort);
|
|
61
|
+
};
|
|
62
|
+
const onAbort = () => {
|
|
63
|
+
cleanup();
|
|
64
|
+
reject(new Error('Pipeline aborted'));
|
|
65
|
+
};
|
|
66
|
+
watcher.on('add', (addedPath) => {
|
|
67
|
+
if (settled)
|
|
68
|
+
return;
|
|
69
|
+
if (pathsEqual(resolve(addedPath), safePath)) {
|
|
70
|
+
cleanup();
|
|
71
|
+
resolve_p({ path: safePath });
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
// Also fire on 'change' so that overwriting an existing file is detected.
|
|
75
|
+
// Without this, upstream tasks that truncate-and-rewrite a file emit only
|
|
76
|
+
// a 'change' event and the downstream trigger would never resolve.
|
|
77
|
+
watcher.on('change', (changedPath) => {
|
|
78
|
+
if (settled)
|
|
79
|
+
return;
|
|
80
|
+
if (pathsEqual(resolve(changedPath), safePath)) {
|
|
81
|
+
cleanup();
|
|
82
|
+
resolve_p({ path: safePath });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
watcher.on('error', (err) => {
|
|
86
|
+
if (settled)
|
|
87
|
+
return;
|
|
88
|
+
cleanup();
|
|
89
|
+
reject(new Error(`file trigger watch error: ${err instanceof Error ? err.message : String(err)}`));
|
|
90
|
+
});
|
|
91
|
+
// After the watcher finishes its initial scan, check if the file already exists.
|
|
92
|
+
// Doing this inside 'ready' eliminates the race window between existence check
|
|
93
|
+
// and watcher startup, so we neither miss events nor double-resolve.
|
|
94
|
+
watcher.on('ready', () => {
|
|
95
|
+
if (settled)
|
|
96
|
+
return;
|
|
97
|
+
Bun.file(safePath).exists().then((exists) => {
|
|
98
|
+
if (settled)
|
|
99
|
+
return;
|
|
100
|
+
if (exists) {
|
|
101
|
+
cleanup();
|
|
102
|
+
resolve_p({ path: safePath });
|
|
103
|
+
}
|
|
104
|
+
}).catch((err) => {
|
|
105
|
+
if (settled)
|
|
106
|
+
return;
|
|
107
|
+
cleanup();
|
|
108
|
+
reject(new Error(`file trigger existence check failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
if (timeoutMs > 0) {
|
|
112
|
+
timer = setTimeout(() => {
|
|
113
|
+
if (settled)
|
|
114
|
+
return;
|
|
115
|
+
cleanup();
|
|
116
|
+
reject(new TriggerTimeoutError(`file trigger timeout: ${filePath} did not appear within ${config.timeout}`));
|
|
117
|
+
}, timeoutMs);
|
|
118
|
+
}
|
|
119
|
+
ctx.signal.addEventListener('abort', onAbort);
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/triggers/file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manual.d.ts","sourceRoot":"","sources":["../../src/triggers/manual.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,UAAU,CAAC;AAI9D,eAAO,MAAM,aAAa,EAAE,aA4E3B,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { parseDuration } from '../utils';
|
|
2
|
+
import { TriggerBlockedError, TriggerTimeoutError } from '../engine';
|
|
3
|
+
export const ManualTrigger = {
|
|
4
|
+
name: 'manual',
|
|
5
|
+
schema: {
|
|
6
|
+
description: 'Pause the task until a user approves via the approval gateway.',
|
|
7
|
+
fields: {
|
|
8
|
+
message: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: 'Prompt shown to the approver. Defaults to a generic message if empty.',
|
|
11
|
+
placeholder: 'Confirm deployment to production?',
|
|
12
|
+
},
|
|
13
|
+
timeout: {
|
|
14
|
+
type: 'duration',
|
|
15
|
+
description: 'Maximum wait time (e.g. 10m). Omit or 0 to wait indefinitely.',
|
|
16
|
+
placeholder: '10m',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
async watch(config, ctx) {
|
|
21
|
+
const message = config.message ?? `Manual confirmation required for task "${ctx.taskId}"`;
|
|
22
|
+
const timeoutMs = config.timeout ? parseDuration(config.timeout) : 0;
|
|
23
|
+
const metadata = config.metadata && typeof config.metadata === 'object'
|
|
24
|
+
? config.metadata
|
|
25
|
+
: undefined;
|
|
26
|
+
const decisionPromise = ctx.approvalGateway.request({
|
|
27
|
+
taskId: ctx.taskId,
|
|
28
|
+
trackId: ctx.trackId,
|
|
29
|
+
message,
|
|
30
|
+
timeoutMs,
|
|
31
|
+
metadata,
|
|
32
|
+
});
|
|
33
|
+
// Wire AbortSignal → try to resolve this specific request as aborted.
|
|
34
|
+
// We can't directly cancel via the gateway (no id yet at .request() call site),
|
|
35
|
+
// so instead we race against an abort promise and let engine status logic
|
|
36
|
+
// fall back to pipelineAborted → skipped. abortAll() on gateway still runs
|
|
37
|
+
// from engine shutdown path to clean up any truly-pending entries.
|
|
38
|
+
const onAbort = () => { };
|
|
39
|
+
const abortPromise = new Promise((_, reject) => {
|
|
40
|
+
if (ctx.signal.aborted) {
|
|
41
|
+
reject(new Error('Pipeline aborted'));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const handler = () => reject(new Error('Pipeline aborted'));
|
|
45
|
+
// Store reference so we can remove it after the race settles.
|
|
46
|
+
onAbort.handler = handler;
|
|
47
|
+
ctx.signal.addEventListener('abort', handler, { once: true });
|
|
48
|
+
});
|
|
49
|
+
let decision;
|
|
50
|
+
try {
|
|
51
|
+
decision = await Promise.race([decisionPromise, abortPromise]);
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
// Clean up the abort listener to prevent leaking on normal completion.
|
|
55
|
+
const handler = onAbort.handler;
|
|
56
|
+
if (handler)
|
|
57
|
+
ctx.signal.removeEventListener('abort', handler);
|
|
58
|
+
}
|
|
59
|
+
switch (decision.outcome) {
|
|
60
|
+
case 'approved':
|
|
61
|
+
return { confirmed: true, approvalId: decision.approvalId, actor: decision.actor };
|
|
62
|
+
case 'rejected':
|
|
63
|
+
// A7: Use typed error for proper classification in the engine.
|
|
64
|
+
throw new TriggerBlockedError(`Manual trigger rejected by ${decision.actor ?? 'user'}` +
|
|
65
|
+
(decision.reason ? `: ${decision.reason}` : ''));
|
|
66
|
+
case 'timeout':
|
|
67
|
+
throw new TriggerTimeoutError(`Manual trigger timeout: ${decision.reason ?? 'no decision made'}`);
|
|
68
|
+
case 'aborted':
|
|
69
|
+
throw new TriggerBlockedError(`Manual trigger aborted: ${decision.reason ?? 'pipeline aborted'}`);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=manual.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manual.js","sourceRoot":"","sources":["../../src/triggers/manual.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,cAAc,cAAc,CAAC;AAE7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAIhD,eAAO,MAAM,mBAAmB,EAAE,WAIjC,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// ═══ Engine-facing type surface ═══
|
|
2
|
+
//
|
|
3
|
+
// All type definitions live in the shared `@tagma/types` workspace package
|
|
4
|
+
// so that plugins under plugins/* can depend on the same types without
|
|
5
|
+
// reaching into the engine's internals. This file re-exports everything
|
|
6
|
+
// and adds runtime-only values (constants) that plugins don't need.
|
|
7
|
+
export * from '@tagma/types';
|
|
8
|
+
// ═══ Runtime Constants ═══
|
|
9
|
+
export const DEFAULT_PERMISSIONS = {
|
|
10
|
+
read: true,
|
|
11
|
+
write: false,
|
|
12
|
+
execute: false,
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,wEAAwE;AACxE,oEAAoE;AAEpE,cAAc,cAAc,CAAC;AAI7B,4BAA4B;AAE5B,MAAM,CAAC,MAAM,mBAAmB,GAAgB;IAC9C,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,KAAK;CACf,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function parseDuration(input: string): number;
|
|
2
|
+
export declare function validatePath(filePath: string, projectRoot: string): string;
|
|
3
|
+
export declare function validatePathParam(filePath: string): void;
|
|
4
|
+
export declare function generateRunId(): string;
|
|
5
|
+
export declare function truncateForName(text: string, maxLen?: number): string;
|
|
6
|
+
export declare function nowISO(): string;
|
|
7
|
+
export declare function shellArgs(command: string): readonly string[];
|
|
8
|
+
/**
|
|
9
|
+
* Convert an args array to shell-wrapped args suitable for Bun.spawn.
|
|
10
|
+
* Each arg is quoted as needed, then joined and passed through shellArgs.
|
|
11
|
+
*/
|
|
12
|
+
export declare function shellArgsFromArray(args: readonly string[]): readonly string[];
|
|
13
|
+
export declare function _resetShellCache(): void;
|
|
14
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAcnD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAY1E;AAID,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAUxD;AAID,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,MAAM,CAMjE;AAED,wBAAgB,MAAM,IAAI,MAAM,CAE/B;AAsDD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAU5D;AAcD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAE7E;AAGD,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { resolve, relative } from 'path';
|
|
2
|
+
import { randomBytes } from 'crypto';
|
|
3
|
+
const DURATION_RE = /^(\d*\.?\d+)\s*(s|m|h|d)$/;
|
|
4
|
+
export function parseDuration(input) {
|
|
5
|
+
const match = DURATION_RE.exec(input.trim());
|
|
6
|
+
if (!match) {
|
|
7
|
+
throw new Error(`Invalid duration format: "${input}". Expected format: <number>(s|m|h|d)`);
|
|
8
|
+
}
|
|
9
|
+
const value = parseFloat(match[1]);
|
|
10
|
+
const unit = match[2];
|
|
11
|
+
switch (unit) {
|
|
12
|
+
case 's': return value * 1000;
|
|
13
|
+
case 'm': return value * 60_000;
|
|
14
|
+
case 'h': return value * 3_600_000;
|
|
15
|
+
case 'd': return value * 86_400_000;
|
|
16
|
+
default: throw new Error(`Unknown duration unit: "${unit}"`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function validatePath(filePath, projectRoot) {
|
|
20
|
+
const resolved = resolve(projectRoot, filePath);
|
|
21
|
+
const rel = relative(projectRoot, resolved);
|
|
22
|
+
if (rel.startsWith('..') || rel.startsWith('/') || /^[a-zA-Z]:/.test(rel)) {
|
|
23
|
+
throw new Error(`Security: path "${filePath}" escapes project root. ` +
|
|
24
|
+
`All file references must be within "${projectRoot}".`);
|
|
25
|
+
}
|
|
26
|
+
return resolved;
|
|
27
|
+
}
|
|
28
|
+
const SHELL_META_CHARS = /[;&|$`\\!><()\[\]{}*?#~]/;
|
|
29
|
+
export function validatePathParam(filePath) {
|
|
30
|
+
if (filePath.includes('..')) {
|
|
31
|
+
throw new Error(`Template param type=path: ".." traversal not allowed in "${filePath}"`);
|
|
32
|
+
}
|
|
33
|
+
if (resolve(filePath) === filePath) {
|
|
34
|
+
throw new Error(`Template param type=path: absolute path not allowed: "${filePath}"`);
|
|
35
|
+
}
|
|
36
|
+
if (SHELL_META_CHARS.test(filePath)) {
|
|
37
|
+
throw new Error(`Template param type=path: shell metacharacters not allowed in "${filePath}"`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
let runCounter = 0;
|
|
41
|
+
export function generateRunId() {
|
|
42
|
+
const ts = Date.now().toString(36);
|
|
43
|
+
const seq = (runCounter++).toString(36).padStart(2, '0');
|
|
44
|
+
// Random suffix prevents ID collisions when two pipelines start within
|
|
45
|
+
// the same millisecond or after a process restart resets the counter.
|
|
46
|
+
const rand = randomBytes(3).toString('hex');
|
|
47
|
+
return `run_${ts}_${seq}_${rand}`;
|
|
48
|
+
}
|
|
49
|
+
export function truncateForName(text, maxLen = 40) {
|
|
50
|
+
const first = text.split('\n')[0].trim();
|
|
51
|
+
// Guard: if the first line is empty (e.g. prompt is all whitespace/newlines),
|
|
52
|
+
// fall back to the raw text trimmed rather than silently producing an empty name.
|
|
53
|
+
if (!first)
|
|
54
|
+
return text.trim().slice(0, maxLen) || '...';
|
|
55
|
+
return first.length > maxLen ? first.slice(0, maxLen) + '...' : first;
|
|
56
|
+
}
|
|
57
|
+
export function nowISO() {
|
|
58
|
+
return new Date().toISOString();
|
|
59
|
+
}
|
|
60
|
+
// ═══ Platform-aware shell ═══
|
|
61
|
+
//
|
|
62
|
+
// Resolution order:
|
|
63
|
+
// 1. Env override: PIPELINE_SHELL="bash" or PIPELINE_SHELL="cmd" etc.
|
|
64
|
+
// 2. Windows: prefer sh (Git Bash / MSYS2) if on PATH, fall back to cmd.exe
|
|
65
|
+
// 3. Unix: sh
|
|
66
|
+
//
|
|
67
|
+
// Resolution is cached once on first call to avoid repeated PATH lookups.
|
|
68
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
69
|
+
let resolvedShell = null;
|
|
70
|
+
function detectShell() {
|
|
71
|
+
// Env override takes precedence
|
|
72
|
+
const override = process.env.PIPELINE_SHELL;
|
|
73
|
+
if (override) {
|
|
74
|
+
const kind = override;
|
|
75
|
+
return { kind, path: override };
|
|
76
|
+
}
|
|
77
|
+
if (!IS_WINDOWS) {
|
|
78
|
+
return { kind: 'sh', path: 'sh' };
|
|
79
|
+
}
|
|
80
|
+
// Windows: probe PATH for sh (bundled with Git for Windows / MSYS2)
|
|
81
|
+
const pathEnv = process.env.PATH ?? '';
|
|
82
|
+
const pathExt = (process.env.PATHEXT ?? '.EXE;.CMD;.BAT').split(';');
|
|
83
|
+
const dirs = pathEnv.split(';').filter(Boolean);
|
|
84
|
+
for (const dir of dirs) {
|
|
85
|
+
for (const ext of ['', ...pathExt]) {
|
|
86
|
+
const candidate = `${dir}\\sh${ext}`;
|
|
87
|
+
try {
|
|
88
|
+
if (Bun.file(candidate).size > 0) {
|
|
89
|
+
return { kind: 'sh', path: candidate };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch { /* ignore */ }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Fallback: cmd.exe (always present on Windows)
|
|
96
|
+
const systemRoot = process.env.SystemRoot ?? 'C:\\Windows';
|
|
97
|
+
return { kind: 'cmd', path: `${systemRoot}\\System32\\cmd.exe` };
|
|
98
|
+
}
|
|
99
|
+
function getShell() {
|
|
100
|
+
if (!resolvedShell)
|
|
101
|
+
resolvedShell = detectShell();
|
|
102
|
+
return resolvedShell;
|
|
103
|
+
}
|
|
104
|
+
export function shellArgs(command) {
|
|
105
|
+
const sh = getShell();
|
|
106
|
+
if (sh.kind === 'cmd') {
|
|
107
|
+
return [sh.path, '/c', command];
|
|
108
|
+
}
|
|
109
|
+
if (sh.kind === 'powershell') {
|
|
110
|
+
return [sh.path, '-Command', command];
|
|
111
|
+
}
|
|
112
|
+
// sh or bash
|
|
113
|
+
return [sh.path, '-c', command];
|
|
114
|
+
}
|
|
115
|
+
/** Quote a single argument for inclusion in a shell command string. */
|
|
116
|
+
function quoteArg(arg) {
|
|
117
|
+
if (!/[\s"'\\<>|&;`$!^%]/.test(arg))
|
|
118
|
+
return arg;
|
|
119
|
+
if (IS_WINDOWS) {
|
|
120
|
+
// On Windows (cmd.exe), double-quote and escape embedded quotes + backslashes
|
|
121
|
+
return '"' + arg.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
|
|
122
|
+
}
|
|
123
|
+
// On Unix, use single quotes to prevent $variable expansion.
|
|
124
|
+
// Escape embedded single quotes via the '\'' idiom.
|
|
125
|
+
return "'" + arg.replace(/'/g, "'\\''") + "'";
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Convert an args array to shell-wrapped args suitable for Bun.spawn.
|
|
129
|
+
* Each arg is quoted as needed, then joined and passed through shellArgs.
|
|
130
|
+
*/
|
|
131
|
+
export function shellArgsFromArray(args) {
|
|
132
|
+
return shellArgs(args.map(quoteArg).join(' '));
|
|
133
|
+
}
|
|
134
|
+
// For tests: allow resetting the cached shell detection
|
|
135
|
+
export function _resetShellCache() {
|
|
136
|
+
resolvedShell = null;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RawPipelineConfig } from './types';
|
|
2
|
+
export type ValidationSeverity = 'error' | 'warning';
|
|
3
|
+
export interface ValidationError {
|
|
4
|
+
/** JSONPath-style location, e.g. "tracks[0].tasks[1].prompt" */
|
|
5
|
+
path: string;
|
|
6
|
+
message: string;
|
|
7
|
+
/**
|
|
8
|
+
* H8: not all "errors" are equally fatal. The DAG runtime is happy to
|
|
9
|
+
* insert implicit `continue_from → depends_on` ordering, so the matching
|
|
10
|
+
* validate-raw check is a *style* nit, not a hard failure. Severity lets
|
|
11
|
+
* the editor render it as a soft warning instead of blocking save / run.
|
|
12
|
+
* Existing call sites that don't read this field still treat every entry
|
|
13
|
+
* as fatal — defaulting `severity` to undefined preserves that behaviour.
|
|
14
|
+
*/
|
|
15
|
+
severity?: ValidationSeverity;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validate a raw pipeline config.
|
|
19
|
+
* Checks structure, required fields, prompt/command exclusivity,
|
|
20
|
+
* depends_on reference integrity, and circular dependencies.
|
|
21
|
+
*
|
|
22
|
+
* Does NOT check plugin registration — plugins may not be loaded yet
|
|
23
|
+
* when the frontend is editing a config offline.
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateRaw(config: RawPipelineConfig): ValidationError[];
|
|
26
|
+
//# sourceMappingURL=validate-raw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-raw.d.ts","sourceRoot":"","sources":["../src/validate-raw.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAUjD,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,EAAE,CAyKxE"}
|