@overlordai/worker 1.0.53 → 1.0.54
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/dist/clean-output-buffer.d.ts +21 -0
- package/dist/clean-output-buffer.d.ts.map +1 -0
- package/dist/clean-output-buffer.js +70 -0
- package/dist/clean-output-buffer.js.map +1 -0
- package/dist/config.d.ts +4 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +54 -39
- package/dist/config.js.map +1 -1
- package/dist/executor/base.executor.d.ts +30 -11
- package/dist/executor/base.executor.d.ts.map +1 -1
- package/dist/executor/base.executor.js +25 -2
- package/dist/executor/base.executor.js.map +1 -1
- package/dist/executor/claude.executor.d.ts +7 -8
- package/dist/executor/claude.executor.d.ts.map +1 -1
- package/dist/executor/claude.executor.js +36 -26
- package/dist/executor/claude.executor.js.map +1 -1
- package/dist/executor/codex.executor.d.ts +7 -8
- package/dist/executor/codex.executor.d.ts.map +1 -1
- package/dist/executor/codex.executor.js +64 -26
- package/dist/executor/codex.executor.js.map +1 -1
- package/dist/executor/cursor.executor.d.ts +6 -7
- package/dist/executor/cursor.executor.d.ts.map +1 -1
- package/dist/executor/cursor.executor.js +12 -22
- package/dist/executor/cursor.executor.js.map +1 -1
- package/dist/executor/custom.executor.d.ts +15 -7
- package/dist/executor/custom.executor.d.ts.map +1 -1
- package/dist/executor/custom.executor.js +25 -28
- package/dist/executor/custom.executor.js.map +1 -1
- package/dist/git-operations.d.ts +14 -12
- package/dist/git-operations.d.ts.map +1 -1
- package/dist/git-operations.js +50 -98
- package/dist/git-operations.js.map +1 -1
- package/dist/git-token-helper.d.ts +27 -0
- package/dist/git-token-helper.d.ts.map +1 -0
- package/dist/git-token-helper.js +114 -0
- package/dist/git-token-helper.js.map +1 -0
- package/dist/healthz.d.ts.map +1 -1
- package/dist/healthz.js +3 -7
- package/dist/healthz.js.map +1 -1
- package/dist/http-post.d.ts +2 -0
- package/dist/http-post.d.ts.map +1 -0
- package/dist/http-post.js +74 -0
- package/dist/http-post.js.map +1 -0
- package/dist/jwt-manager.d.ts +2 -3
- package/dist/jwt-manager.d.ts.map +1 -1
- package/dist/jwt-manager.js +5 -43
- package/dist/jwt-manager.js.map +1 -1
- package/dist/lease-manager.d.ts +4 -1
- package/dist/lease-manager.d.ts.map +1 -1
- package/dist/lease-manager.js +2 -6
- package/dist/lease-manager.js.map +1 -1
- package/dist/main.js +147 -277
- package/dist/main.js.map +1 -1
- package/dist/orphan-reaper.d.ts +1 -1
- package/dist/orphan-reaper.d.ts.map +1 -1
- package/dist/orphan-reaper.js +46 -30
- package/dist/orphan-reaper.js.map +1 -1
- package/dist/pipeline-compiler.d.ts +10 -0
- package/dist/pipeline-compiler.d.ts.map +1 -0
- package/dist/pipeline-compiler.js +179 -0
- package/dist/pipeline-compiler.js.map +1 -0
- package/dist/pipeline-parser.d.ts.map +1 -1
- package/dist/pipeline-parser.js +4 -3
- package/dist/pipeline-parser.js.map +1 -1
- package/dist/pipeline-runner.d.ts +1 -0
- package/dist/pipeline-runner.d.ts.map +1 -1
- package/dist/pipeline-runner.js +37 -27
- package/dist/pipeline-runner.js.map +1 -1
- package/dist/project-mutex.d.ts +1 -0
- package/dist/project-mutex.d.ts.map +1 -1
- package/dist/project-mutex.js +9 -1
- package/dist/project-mutex.js.map +1 -1
- package/dist/pty-manager.d.ts +2 -0
- package/dist/pty-manager.d.ts.map +1 -1
- package/dist/pty-manager.js +68 -42
- package/dist/pty-manager.js.map +1 -1
- package/dist/pty-relay-client.d.ts +38 -0
- package/dist/pty-relay-client.d.ts.map +1 -0
- package/dist/pty-relay-client.js +146 -0
- package/dist/pty-relay-client.js.map +1 -0
- package/dist/pty-stdin-writer.d.ts +11 -0
- package/dist/pty-stdin-writer.d.ts.map +1 -0
- package/dist/pty-stdin-writer.js +22 -0
- package/dist/pty-stdin-writer.js.map +1 -0
- package/dist/ringbuffer.d.ts +2 -0
- package/dist/ringbuffer.d.ts.map +1 -1
- package/dist/ringbuffer.js +10 -1
- package/dist/ringbuffer.js.map +1 -1
- package/dist/stage-monitor.d.ts +72 -0
- package/dist/stage-monitor.d.ts.map +1 -0
- package/dist/stage-monitor.js +234 -0
- package/dist/stage-monitor.js.map +1 -0
- package/dist/task-handler.d.ts +18 -12
- package/dist/task-handler.d.ts.map +1 -1
- package/dist/task-handler.js +298 -78
- package/dist/task-handler.js.map +1 -1
- package/dist/tunnel-manager.d.ts +16 -6
- package/dist/tunnel-manager.d.ts.map +1 -1
- package/dist/tunnel-manager.js +117 -16
- package/dist/tunnel-manager.js.map +1 -1
- package/dist/worker-client.d.ts +16 -7
- package/dist/worker-client.d.ts.map +1 -1
- package/dist/worker-client.js +40 -52
- package/dist/worker-client.js.map +1 -1
- package/dist/workspace-manager.d.ts +1 -0
- package/dist/workspace-manager.d.ts.map +1 -1
- package/dist/workspace-manager.js +102 -82
- package/dist/workspace-manager.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed-size ring buffer for clean PTY output used in stage/prompt detection.
|
|
3
|
+
* Avoids O(n^2) string concatenation by storing chunks in a circular array
|
|
4
|
+
* and only rebuilding the full string on demand (with dirty-flag caching).
|
|
5
|
+
*/
|
|
6
|
+
export declare class CleanOutputBuffer {
|
|
7
|
+
private chunks;
|
|
8
|
+
private totalLength;
|
|
9
|
+
private readonly maxBytes;
|
|
10
|
+
private dirty;
|
|
11
|
+
private cached;
|
|
12
|
+
constructor(maxBytes?: number);
|
|
13
|
+
/** Append a chunk of clean output. */
|
|
14
|
+
push(chunk: string): void;
|
|
15
|
+
/** Get the buffered contents (up to maxBytes from the end). */
|
|
16
|
+
getContents(): string;
|
|
17
|
+
/** Reset the buffer. */
|
|
18
|
+
reset(): void;
|
|
19
|
+
private compact;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=clean-output-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clean-output-buffer.d.ts","sourceRoot":"","sources":["../src/clean-output-buffer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAM;gBAER,QAAQ,GAAE,MAAa;IAInC,sCAAsC;IACtC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAWzB,+DAA+D;IAC/D,WAAW,IAAI,MAAM;IAqBrB,wBAAwB;IACxB,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,OAAO;CAahB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CleanOutputBuffer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Fixed-size ring buffer for clean PTY output used in stage/prompt detection.
|
|
6
|
+
* Avoids O(n^2) string concatenation by storing chunks in a circular array
|
|
7
|
+
* and only rebuilding the full string on demand (with dirty-flag caching).
|
|
8
|
+
*/
|
|
9
|
+
class CleanOutputBuffer {
|
|
10
|
+
chunks = [];
|
|
11
|
+
totalLength = 0;
|
|
12
|
+
maxBytes;
|
|
13
|
+
dirty = true;
|
|
14
|
+
cached = '';
|
|
15
|
+
constructor(maxBytes = 8192) {
|
|
16
|
+
this.maxBytes = maxBytes;
|
|
17
|
+
}
|
|
18
|
+
/** Append a chunk of clean output. */
|
|
19
|
+
push(chunk) {
|
|
20
|
+
this.chunks.push(chunk);
|
|
21
|
+
this.totalLength += chunk.length;
|
|
22
|
+
this.dirty = true;
|
|
23
|
+
// Trim when we exceed 2x the limit to amortize trimming cost
|
|
24
|
+
if (this.totalLength > this.maxBytes * 2) {
|
|
25
|
+
this.compact();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Get the buffered contents (up to maxBytes from the end). */
|
|
29
|
+
getContents() {
|
|
30
|
+
if (!this.dirty)
|
|
31
|
+
return this.cached;
|
|
32
|
+
if (this.totalLength === 0) {
|
|
33
|
+
this.cached = '';
|
|
34
|
+
this.dirty = false;
|
|
35
|
+
return this.cached;
|
|
36
|
+
}
|
|
37
|
+
let joined = this.chunks.join('');
|
|
38
|
+
if (joined.length > this.maxBytes) {
|
|
39
|
+
const truncated = joined.slice(-this.maxBytes);
|
|
40
|
+
const nlIdx = truncated.indexOf('\n');
|
|
41
|
+
joined = nlIdx !== -1 ? truncated.slice(nlIdx + 1) : truncated;
|
|
42
|
+
}
|
|
43
|
+
this.cached = joined;
|
|
44
|
+
this.dirty = false;
|
|
45
|
+
return this.cached;
|
|
46
|
+
}
|
|
47
|
+
/** Reset the buffer. */
|
|
48
|
+
reset() {
|
|
49
|
+
this.chunks = [];
|
|
50
|
+
this.totalLength = 0;
|
|
51
|
+
this.dirty = true;
|
|
52
|
+
this.cached = '';
|
|
53
|
+
}
|
|
54
|
+
compact() {
|
|
55
|
+
const joined = this.chunks.join('');
|
|
56
|
+
if (joined.length > this.maxBytes) {
|
|
57
|
+
const truncated = joined.slice(-this.maxBytes);
|
|
58
|
+
const nlIdx = truncated.indexOf('\n');
|
|
59
|
+
const compacted = nlIdx !== -1 ? truncated.slice(nlIdx + 1) : truncated;
|
|
60
|
+
this.chunks = [compacted];
|
|
61
|
+
this.totalLength = compacted.length;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.chunks = [joined];
|
|
65
|
+
this.totalLength = joined.length;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.CleanOutputBuffer = CleanOutputBuffer;
|
|
70
|
+
//# sourceMappingURL=clean-output-buffer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clean-output-buffer.js","sourceRoot":"","sources":["../src/clean-output-buffer.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export interface WorkerConfigData {
|
|
2
2
|
overlordHost: string;
|
|
3
3
|
workerToken: string;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
workerName: string;
|
|
5
|
+
workerId: string;
|
|
6
6
|
recoverySecret: string;
|
|
7
7
|
workspaceRoot: string;
|
|
8
8
|
maxSlots: number;
|
|
@@ -12,8 +12,8 @@ export interface WorkerConfigData {
|
|
|
12
12
|
export declare class WorkerConfig implements WorkerConfigData {
|
|
13
13
|
overlordHost: string;
|
|
14
14
|
workerToken: string;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
workerName: string;
|
|
16
|
+
workerId: string;
|
|
17
17
|
recoverySecret: string;
|
|
18
18
|
workspaceRoot: string;
|
|
19
19
|
maxSlots: number;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AA0BD,qBAAa,YAAa,YAAW,gBAAgB;IACnD,YAAY,SAAM;IAClB,WAAW,SAAM;IACjB,UAAU,SAAM;IAChB,QAAQ,SAAM;IACd,cAAc,SAAM;IACpB,aAAa,SAAM;IACnB,QAAQ,SAAK;IACb,OAAO,SAAM;IACb,UAAU,SAAM;IAEhB,OAAO,CAAC,OAAO,CAAM;IAErB,MAAM,CAAC,IAAI,IAAI,YAAY;IAoD3B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IA0BzC,OAAO,CAAC,WAAW;CAiBpB"}
|
package/dist/config.js
CHANGED
|
@@ -41,11 +41,29 @@ const fs = __importStar(require("node:fs"));
|
|
|
41
41
|
const path = __importStar(require("node:path"));
|
|
42
42
|
const pino_1 = __importDefault(require("pino"));
|
|
43
43
|
const log = (0, pino_1.default)({ name: 'worker-config' });
|
|
44
|
+
function resolveDeprecated(envValues, newKey, oldKey) {
|
|
45
|
+
const newVal = process.env[newKey] || envValues[newKey];
|
|
46
|
+
const oldVal = process.env[oldKey] || envValues[oldKey];
|
|
47
|
+
if (!newVal && oldVal) {
|
|
48
|
+
log.warn(`${oldKey} is deprecated; please rename to ${newKey}`);
|
|
49
|
+
}
|
|
50
|
+
return newVal || oldVal || '';
|
|
51
|
+
}
|
|
52
|
+
const ENV_TO_PROP = {
|
|
53
|
+
OVERLORD_HOST: 'overlordHost',
|
|
54
|
+
OVERLORD_WORKER_TOKEN: 'workerToken',
|
|
55
|
+
OVERLORD_WORKER_NAME: 'workerName',
|
|
56
|
+
OVERLORD_WORKER_ID: 'workerId',
|
|
57
|
+
OVERLORD_RECOVERY_SECRET: 'recoverySecret',
|
|
58
|
+
OVERLORD_WORKSPACE_ROOT: 'workspaceRoot',
|
|
59
|
+
OVERLORD_MAX_SLOTS: 'maxSlots',
|
|
60
|
+
OVERLORD_SSH_KEY_PATH: 'sshKeyPath',
|
|
61
|
+
};
|
|
44
62
|
class WorkerConfig {
|
|
45
63
|
overlordHost = '';
|
|
46
64
|
workerToken = '';
|
|
47
|
-
|
|
48
|
-
|
|
65
|
+
workerName = '';
|
|
66
|
+
workerId = '';
|
|
49
67
|
recoverySecret = '';
|
|
50
68
|
workspaceRoot = '';
|
|
51
69
|
maxSlots = 2;
|
|
@@ -60,64 +78,61 @@ class WorkerConfig {
|
|
|
60
78
|
if (!fs.existsSync(dataDir)) {
|
|
61
79
|
fs.mkdirSync(dataDir, { recursive: true, mode: 0o700 });
|
|
62
80
|
}
|
|
63
|
-
// Load from environment first, then from .env file
|
|
64
81
|
const envValues = config.readEnvFile();
|
|
65
|
-
|
|
66
|
-
config.
|
|
67
|
-
config.
|
|
68
|
-
config.
|
|
69
|
-
config.
|
|
70
|
-
config.
|
|
71
|
-
config.
|
|
72
|
-
|
|
82
|
+
const env = (key, fallback = '') => process.env[key] || envValues[key] || fallback;
|
|
83
|
+
config.overlordHost = env('OVERLORD_HOST');
|
|
84
|
+
config.workerToken = env('OVERLORD_WORKER_TOKEN');
|
|
85
|
+
config.workerName = resolveDeprecated(envValues, 'OVERLORD_WORKER_NAME', 'OVERLORD_MACHINE_NAME');
|
|
86
|
+
config.workerId = resolveDeprecated(envValues, 'OVERLORD_WORKER_ID', 'OVERLORD_MACHINE_ID');
|
|
87
|
+
config.recoverySecret = env('OVERLORD_RECOVERY_SECRET');
|
|
88
|
+
config.workspaceRoot = env('OVERLORD_WORKSPACE_ROOT', path.join(dataDir, 'workspaces'));
|
|
89
|
+
const rawMaxSlots = parseInt(env('OVERLORD_MAX_SLOTS', '2'), 10);
|
|
90
|
+
if (isNaN(rawMaxSlots) || rawMaxSlots < 1) {
|
|
91
|
+
log.warn({ rawMaxSlots }, 'OVERLORD_MAX_SLOTS is invalid (NaN or < 1), falling back to default (2)');
|
|
92
|
+
config.maxSlots = 2;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
config.maxSlots = rawMaxSlots;
|
|
96
|
+
}
|
|
97
|
+
config.sshKeyPath = env('OVERLORD_SSH_KEY_PATH');
|
|
73
98
|
if (!config.overlordHost) {
|
|
74
99
|
throw new Error('OVERLORD_HOST is required');
|
|
75
100
|
}
|
|
76
|
-
if (!config.workerToken && !config.
|
|
77
|
-
throw new Error('OVERLORD_WORKER_TOKEN or
|
|
101
|
+
if (!config.workerToken && !config.workerId) {
|
|
102
|
+
throw new Error('OVERLORD_WORKER_TOKEN or OVERLORD_WORKER_ID is required');
|
|
78
103
|
}
|
|
79
|
-
if (!config.
|
|
104
|
+
if (!config.workerName) {
|
|
80
105
|
const os = require('node:os');
|
|
81
|
-
config.
|
|
106
|
+
config.workerName = os.hostname();
|
|
82
107
|
}
|
|
83
108
|
// Ensure workspace root exists
|
|
84
109
|
if (!fs.existsSync(config.workspaceRoot)) {
|
|
85
110
|
fs.mkdirSync(config.workspaceRoot, { recursive: true, mode: 0o755 });
|
|
86
111
|
}
|
|
87
|
-
log.info({ dataDir: config.dataDir, overlordHost: config.overlordHost,
|
|
112
|
+
log.info({ dataDir: config.dataDir, overlordHost: config.overlordHost, workerName: config.workerName }, 'Config loaded');
|
|
88
113
|
return config;
|
|
89
114
|
}
|
|
90
115
|
persist(key, value) {
|
|
116
|
+
// Validate key format to prevent .env injection via crafted keys
|
|
117
|
+
if (!/^[A-Z_][A-Z0-9_]*$/.test(key)) {
|
|
118
|
+
throw new Error(`Cannot persist: invalid key format '${key}'`);
|
|
119
|
+
}
|
|
91
120
|
// Reject values containing newlines or control characters to prevent .env injection
|
|
92
121
|
if (/[\n\r\0]/.test(value)) {
|
|
93
122
|
throw new Error(`Cannot persist value for ${key}: contains newline or control character`);
|
|
94
123
|
}
|
|
95
124
|
const envValues = this.readEnvFile();
|
|
96
125
|
envValues[key] = value;
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
126
|
+
const content = Object.entries(envValues).map(([k, v]) => `${k}=${v}`).join('\n') + '\n';
|
|
127
|
+
const tmpPath = this.envPath + '.tmp';
|
|
128
|
+
fs.writeFileSync(tmpPath, content, { mode: 0o600 });
|
|
129
|
+
fs.renameSync(tmpPath, this.envPath);
|
|
130
|
+
const prop = ENV_TO_PROP[key];
|
|
131
|
+
if (prop === 'maxSlots') {
|
|
132
|
+
this.maxSlots = parseInt(value, 10);
|
|
100
133
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const propMap = {
|
|
104
|
-
'OVERLORD_HOST': 'overlordHost',
|
|
105
|
-
'OVERLORD_WORKER_TOKEN': 'workerToken',
|
|
106
|
-
'OVERLORD_MACHINE_NAME': 'machineName',
|
|
107
|
-
'OVERLORD_MACHINE_ID': 'machineId',
|
|
108
|
-
'OVERLORD_RECOVERY_SECRET': 'recoverySecret',
|
|
109
|
-
'OVERLORD_WORKSPACE_ROOT': 'workspaceRoot',
|
|
110
|
-
'OVERLORD_MAX_SLOTS': 'maxSlots',
|
|
111
|
-
'OVERLORD_SSH_KEY_PATH': 'sshKeyPath',
|
|
112
|
-
};
|
|
113
|
-
const prop = propMap[key];
|
|
114
|
-
if (prop) {
|
|
115
|
-
if (prop === 'maxSlots') {
|
|
116
|
-
this[prop] = parseInt(value, 10);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
this[prop] = value;
|
|
120
|
-
}
|
|
134
|
+
else if (prop) {
|
|
135
|
+
this[prop] = value;
|
|
121
136
|
}
|
|
122
137
|
}
|
|
123
138
|
readEnvFile() {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAC9B,gDAAkC;AAClC,gDAAwB;AAExB,MAAM,GAAG,GAAG,IAAA,cAAI,EAAC,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;AAc5C,MAAa,YAAY;IACvB,YAAY,GAAG,EAAE,CAAC;IAClB,WAAW,GAAG,EAAE,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { IPty } from 'node-pty';
|
|
2
|
-
import type { AgentType, ConfigSnapshot
|
|
2
|
+
import type { AgentType, ConfigSnapshot } from '@overlordai/protocol';
|
|
3
3
|
export type FailureType = 'binary_missing' | 'auth_failure' | 'rate_limit' | 'unknown';
|
|
4
4
|
export interface AuthErrorResult {
|
|
5
5
|
detected: boolean;
|
|
6
6
|
failureType: FailureType;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Auth error pattern entry: a regex to test against PTY output
|
|
10
|
+
* and the failure type to report when matched.
|
|
11
|
+
*/
|
|
12
|
+
export interface AuthErrorPattern {
|
|
13
|
+
pattern: RegExp;
|
|
14
|
+
failureType: FailureType;
|
|
15
|
+
}
|
|
8
16
|
/**
|
|
9
17
|
* Abstract base class for agent executors.
|
|
10
18
|
* Each supported agent CLI (Claude, Cursor, etc.) extends this class
|
|
@@ -12,13 +20,29 @@ export interface AuthErrorResult {
|
|
|
12
20
|
*/
|
|
13
21
|
export declare abstract class AgentExecutor {
|
|
14
22
|
abstract readonly agentType: AgentType;
|
|
23
|
+
/**
|
|
24
|
+
* Auth error patterns for this executor.
|
|
25
|
+
* Subclasses should set this to define agent-specific error detection.
|
|
26
|
+
*/
|
|
27
|
+
protected abstract readonly authErrorPatterns: AuthErrorPattern[];
|
|
15
28
|
/**
|
|
16
29
|
* Build CLI arguments for the agent command.
|
|
17
30
|
* @param config - The task's configuration snapshot.
|
|
18
31
|
* @param workspacePath - The workspace directory path (for checking local config files).
|
|
19
|
-
* @param taskDescription - Optional task description for non-interactive (-p) mode.
|
|
20
32
|
*/
|
|
21
|
-
abstract buildArgs(config: ConfigSnapshot, workspacePath: string
|
|
33
|
+
abstract buildArgs(config: ConfigSnapshot, workspacePath: string): string[];
|
|
34
|
+
/**
|
|
35
|
+
* Prepare the worktree directory with agent-specific config files.
|
|
36
|
+
* Called after worktree creation, before PTY spawn.
|
|
37
|
+
* @param worktreePath - The isolated workspace directory (also used as HOME).
|
|
38
|
+
* @param realHome - The real user home directory for symlink sources.
|
|
39
|
+
*/
|
|
40
|
+
abstract prepareEnvironment(worktreePath: string, realHome: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Return agent-specific environment variables to merge into PTY env.
|
|
43
|
+
* @param realHome - The real user home directory.
|
|
44
|
+
*/
|
|
45
|
+
abstract buildEnvVars(realHome: string): Record<string, string>;
|
|
22
46
|
/**
|
|
23
47
|
* Return the CLI command to invoke (e.g. 'claude', 'cursor').
|
|
24
48
|
*/
|
|
@@ -35,22 +59,17 @@ export declare abstract class AgentExecutor {
|
|
|
35
59
|
* @param cleanOutput - ANSI-stripped recent PTY output.
|
|
36
60
|
* @param stage - The current stage name to check for.
|
|
37
61
|
*/
|
|
38
|
-
|
|
62
|
+
detectStageComplete(cleanOutput: string, stage: string): boolean;
|
|
39
63
|
/**
|
|
40
64
|
* Detect authentication or availability errors in early PTY output.
|
|
41
65
|
* Returns null if no error detected.
|
|
42
66
|
* @param cleanOutput - ANSI-stripped recent PTY output.
|
|
43
67
|
*/
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Format a stage command as input text to send to the agent CLI.
|
|
47
|
-
* @param stage - The pipeline stage configuration.
|
|
48
|
-
*/
|
|
49
|
-
abstract formatCommand(stage: StageConfig): string;
|
|
68
|
+
detectAuthError(cleanOutput: string): AuthErrorResult | null;
|
|
50
69
|
/**
|
|
51
70
|
* Spawn a PTY process for this agent.
|
|
52
71
|
* Uses node-pty to create the pseudo-terminal.
|
|
53
72
|
*/
|
|
54
|
-
spawn(workspacePath: string, env: Record<string, string>, config: ConfigSnapshot
|
|
73
|
+
spawn(workspacePath: string, env: Record<string, string>, config: ConfigSnapshot): IPty;
|
|
55
74
|
}
|
|
56
75
|
//# sourceMappingURL=base.executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.executor.d.ts","sourceRoot":"","sources":["../../src/executor/base.executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"base.executor.d.ts","sourceRoot":"","sources":["../../src/executor/base.executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,cAAc,GAAG,YAAY,GAAG,SAAS,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;;;GAIG;AACH,8BAAsB,aAAa;IACjC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAEvC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IAElE;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE;IAE3E;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAEzE;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAE/D;;OAEG;IACH,QAAQ,CAAC,eAAe,IAAI,MAAM;IAElC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAEnD;;;;;OAKG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhE;;;;OAIG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAS5D;;;OAGG;IACH,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI;CAexF"}
|
|
@@ -1,22 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AgentExecutor = void 0;
|
|
4
|
+
const protocol_1 = require("@overlordai/protocol");
|
|
4
5
|
/**
|
|
5
6
|
* Abstract base class for agent executors.
|
|
6
7
|
* Each supported agent CLI (Claude, Cursor, etc.) extends this class
|
|
7
8
|
* to provide agent-specific argument building, prompt detection, and error handling.
|
|
8
9
|
*/
|
|
9
10
|
class AgentExecutor {
|
|
11
|
+
/**
|
|
12
|
+
* Detect whether a pipeline stage has completed, by checking for
|
|
13
|
+
* the STAGE_DONE_SENTINEL marker in the output.
|
|
14
|
+
* @param cleanOutput - ANSI-stripped recent PTY output.
|
|
15
|
+
* @param stage - The current stage name to check for.
|
|
16
|
+
*/
|
|
17
|
+
detectStageComplete(cleanOutput, stage) {
|
|
18
|
+
return cleanOutput.includes(`${protocol_1.STAGE_DONE_SENTINEL}${stage}]]`);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Detect authentication or availability errors in early PTY output.
|
|
22
|
+
* Returns null if no error detected.
|
|
23
|
+
* @param cleanOutput - ANSI-stripped recent PTY output.
|
|
24
|
+
*/
|
|
25
|
+
detectAuthError(cleanOutput) {
|
|
26
|
+
for (const { pattern, failureType } of this.authErrorPatterns) {
|
|
27
|
+
if (pattern.test(cleanOutput)) {
|
|
28
|
+
return { detected: true, failureType };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
10
33
|
/**
|
|
11
34
|
* Spawn a PTY process for this agent.
|
|
12
35
|
* Uses node-pty to create the pseudo-terminal.
|
|
13
36
|
*/
|
|
14
|
-
spawn(workspacePath, env, config
|
|
37
|
+
spawn(workspacePath, env, config) {
|
|
15
38
|
// Lazy require to avoid issues if node-pty native module isn't available at import time
|
|
16
39
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
40
|
const pty = require('node-pty');
|
|
18
41
|
const command = this.getStartCommand();
|
|
19
|
-
const args = this.buildArgs(config, workspacePath
|
|
42
|
+
const args = this.buildArgs(config, workspacePath);
|
|
20
43
|
return pty.spawn(command, args, {
|
|
21
44
|
name: 'xterm-256color',
|
|
22
45
|
cols: 120,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.executor.js","sourceRoot":"","sources":["../../src/executor/base.executor.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"base.executor.js","sourceRoot":"","sources":["../../src/executor/base.executor.ts"],"names":[],"mappings":";;;AAEA,mDAA2D;AAiB3D;;;;GAIG;AACH,MAAsB,aAAa;IA0CjC;;;;;OAKG;IACH,mBAAmB,CAAC,WAAmB,EAAE,KAAa;QACpD,OAAO,WAAW,CAAC,QAAQ,CAAC,GAAG,8BAAmB,GAAG,KAAK,IAAI,CAAC,CAAC;IAClE,CAAC;IAED;;;;OAIG;IACH,eAAe,CAAC,WAAmB;QACjC,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC9D,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC9B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;YACzC,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAqB,EAAE,GAA2B,EAAE,MAAsB;QAC9E,wFAAwF;QACxF,iEAAiE;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAA8B,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAEnD,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YAC9B,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,aAAa;YAClB,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;CACF;AArFD,sCAqFC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { ConfigSnapshot, StageConfig } from '@overlordai/protocol';
|
|
1
|
+
import type { ConfigSnapshot } from '@overlordai/protocol';
|
|
3
2
|
import { AgentExecutor } from './base.executor.js';
|
|
4
|
-
import type {
|
|
3
|
+
import type { AuthErrorPattern } from './base.executor.js';
|
|
5
4
|
/**
|
|
6
5
|
* Executor for Claude Code CLI.
|
|
7
6
|
*
|
|
@@ -11,13 +10,13 @@ import type { AuthErrorResult } from './base.executor.js';
|
|
|
11
10
|
* - If project has .claude/settings.json → use project settings
|
|
12
11
|
*/
|
|
13
12
|
export declare class ClaudeExecutor extends AgentExecutor {
|
|
14
|
-
readonly agentType
|
|
13
|
+
readonly agentType: "claude";
|
|
14
|
+
protected readonly authErrorPatterns: AuthErrorPattern[];
|
|
15
15
|
getStartCommand(): string;
|
|
16
|
-
buildArgs(config: ConfigSnapshot, workspacePath: string
|
|
16
|
+
buildArgs(config: ConfigSnapshot, workspacePath: string): string[];
|
|
17
17
|
detectPrompt(cleanOutput: string): boolean;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
formatCommand(stage: StageConfig): string;
|
|
18
|
+
prepareEnvironment(worktreePath: string, realHome: string): void;
|
|
19
|
+
buildEnvVars(realHome: string): Record<string, string>;
|
|
21
20
|
private hasProjectSettings;
|
|
22
21
|
}
|
|
23
22
|
//# sourceMappingURL=claude.executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.executor.d.ts","sourceRoot":"","sources":["../../src/executor/claude.executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude.executor.d.ts","sourceRoot":"","sources":["../../src/executor/claude.executor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAK3D;;;;;;;GAOG;AACH,qBAAa,cAAe,SAAQ,aAAa;IAC/C,QAAQ,CAAC,SAAS,WAAoB;IAEtC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,CAItD;IAEF,eAAe,IAAI,MAAM;IAIzB,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE;IAiBlE,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAK1C,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAqBhE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAMtD,OAAO,CAAC,kBAAkB;CAI3B"}
|
|
@@ -32,12 +32,17 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.ClaudeExecutor = void 0;
|
|
37
40
|
const fs = __importStar(require("node:fs"));
|
|
38
41
|
const path = __importStar(require("node:path"));
|
|
39
42
|
const protocol_1 = require("@overlordai/protocol");
|
|
40
43
|
const base_executor_js_1 = require("./base.executor.js");
|
|
44
|
+
const pino_1 = __importDefault(require("pino"));
|
|
45
|
+
const log = (0, pino_1.default)({ name: 'claude-executor' });
|
|
41
46
|
/**
|
|
42
47
|
* Executor for Claude Code CLI.
|
|
43
48
|
*
|
|
@@ -48,10 +53,15 @@ const base_executor_js_1 = require("./base.executor.js");
|
|
|
48
53
|
*/
|
|
49
54
|
class ClaudeExecutor extends base_executor_js_1.AgentExecutor {
|
|
50
55
|
agentType = protocol_1.AgentType.CLAUDE;
|
|
56
|
+
authErrorPatterns = [
|
|
57
|
+
{ pattern: /Authentication failed|Please log in/i, failureType: 'auth_failure' },
|
|
58
|
+
{ pattern: /Rate limit exceeded/i, failureType: 'rate_limit' },
|
|
59
|
+
{ pattern: /command not found|ENOENT/i, failureType: 'binary_missing' },
|
|
60
|
+
];
|
|
51
61
|
getStartCommand() {
|
|
52
62
|
return 'claude';
|
|
53
63
|
}
|
|
54
|
-
buildArgs(config, workspacePath
|
|
64
|
+
buildArgs(config, workspacePath) {
|
|
55
65
|
const args = [];
|
|
56
66
|
// Permission strategy: default to dangerously-skip-permissions
|
|
57
67
|
if (config.allowedTools && config.allowedTools !== 'DANGEROUSLY_SKIP') {
|
|
@@ -60,13 +70,8 @@ class ClaudeExecutor extends base_executor_js_1.AgentExecutor {
|
|
|
60
70
|
else if (!this.hasProjectSettings(workspacePath)) {
|
|
61
71
|
args.push('--dangerously-skip-permissions');
|
|
62
72
|
}
|
|
63
|
-
args.push('--max-turns', String(config.maxTurns ?? 50));
|
|
64
73
|
if (config.skillsPath) {
|
|
65
|
-
args.push('--
|
|
66
|
-
}
|
|
67
|
-
// Use non-interactive print mode (-p) to avoid TUI trust dialogs
|
|
68
|
-
if (taskDescription) {
|
|
69
|
-
args.push('-p', taskDescription);
|
|
74
|
+
args.push('--plugin-dir', config.skillsPath);
|
|
70
75
|
}
|
|
71
76
|
return args;
|
|
72
77
|
}
|
|
@@ -74,28 +79,33 @@ class ClaudeExecutor extends base_executor_js_1.AgentExecutor {
|
|
|
74
79
|
// Match Claude Code's ❯ or > prompt at end of output
|
|
75
80
|
return /[❯>]\s*$/.test(cleanOutput.trimEnd());
|
|
76
81
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
prepareEnvironment(worktreePath, realHome) {
|
|
83
|
+
const claudeDir = path.join(worktreePath, '.claude');
|
|
84
|
+
try {
|
|
85
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
86
|
+
// Symlink auth/onboarding files but NOT settings.json
|
|
87
|
+
// (settings.json would trigger hasProjectSettings() → drop --dangerously-skip-permissions)
|
|
88
|
+
const filesToLink = ['.claude.json', '.credentials.json'];
|
|
89
|
+
for (const file of filesToLink) {
|
|
90
|
+
const src = path.join(realHome, '.claude', file);
|
|
91
|
+
const dst = path.join(claudeDir, file);
|
|
92
|
+
try {
|
|
93
|
+
fs.symlinkSync(src, dst);
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
if (e.code !== 'EEXIST' && e.code !== 'ENOENT')
|
|
97
|
+
throw e;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
88
100
|
}
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
catch (err) {
|
|
102
|
+
log.warn({ worktreePath, err }, 'Claude environment setup failed (non-fatal)');
|
|
91
103
|
}
|
|
92
|
-
if (/command not found|ENOENT/i.test(cleanOutput)) {
|
|
93
|
-
return { detected: true, failureType: 'binary_missing' };
|
|
94
|
-
}
|
|
95
|
-
return null;
|
|
96
104
|
}
|
|
97
|
-
|
|
98
|
-
return
|
|
105
|
+
buildEnvVars(realHome) {
|
|
106
|
+
return {
|
|
107
|
+
CLAUDE_CONFIG_DIR: process.env.CLAUDE_CONFIG_DIR ?? `${realHome}/.claude`,
|
|
108
|
+
};
|
|
99
109
|
}
|
|
100
110
|
hasProjectSettings(workspacePath) {
|
|
101
111
|
const settingsPath = path.join(workspacePath, '.claude', 'settings.json');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.executor.js","sourceRoot":"","sources":["../../src/executor/claude.executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude.executor.js","sourceRoot":"","sources":["../../src/executor/claude.executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { ConfigSnapshot, StageConfig } from '@overlordai/protocol';
|
|
1
|
+
import type { ConfigSnapshot } from '@overlordai/protocol';
|
|
3
2
|
import { AgentExecutor } from './base.executor.js';
|
|
4
|
-
import type {
|
|
3
|
+
import type { AuthErrorPattern } from './base.executor.js';
|
|
5
4
|
/**
|
|
6
5
|
* Executor for OpenAI Codex CLI.
|
|
7
6
|
*
|
|
@@ -9,12 +8,12 @@ import type { AuthErrorResult } from './base.executor.js';
|
|
|
9
8
|
* Uses --full-auto flag for fully automated mode.
|
|
10
9
|
*/
|
|
11
10
|
export declare class CodexExecutor extends AgentExecutor {
|
|
12
|
-
readonly agentType
|
|
11
|
+
readonly agentType: "codex";
|
|
12
|
+
protected readonly authErrorPatterns: AuthErrorPattern[];
|
|
13
13
|
getStartCommand(): string;
|
|
14
|
-
buildArgs(
|
|
14
|
+
buildArgs(_config: ConfigSnapshot, _workspacePath: string): string[];
|
|
15
|
+
prepareEnvironment(worktreePath: string, realHome: string): void;
|
|
16
|
+
buildEnvVars(_realHome: string): Record<string, string>;
|
|
15
17
|
detectPrompt(cleanOutput: string): boolean;
|
|
16
|
-
detectStageComplete(cleanOutput: string, stage: string): boolean;
|
|
17
|
-
detectAuthError(cleanOutput: string): AuthErrorResult | null;
|
|
18
|
-
formatCommand(stage: StageConfig): string;
|
|
19
18
|
}
|
|
20
19
|
//# sourceMappingURL=codex.executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.executor.d.ts","sourceRoot":"","sources":["../../src/executor/codex.executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codex.executor.d.ts","sourceRoot":"","sources":["../../src/executor/codex.executor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAK3D;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,aAAa;IAC9C,QAAQ,CAAC,SAAS,UAAmB;IAErC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,CAItD;IAEF,eAAe,IAAI,MAAM;IAIzB,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE;IAIpE,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAchE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIvD,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CAI3C"}
|