@gh-symphony/cli 0.0.21 → 0.0.22
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 +36 -0
- package/dist/{chunk-SXGT7LOF.js → chunk-2TSM3INR.js} +26 -1
- package/dist/{chunk-A67CMOYE.js → chunk-2UW7NQLX.js} +1 -1
- package/dist/{chunk-MVRF7BES.js → chunk-36KYEDEO.js} +10 -1
- package/dist/{chunk-C7G7RJ4G.js → chunk-DDL4BWSL.js} +1 -1
- package/dist/{chunk-XN5ABWZ6.js → chunk-DFLXHNYQ.js} +26 -30
- package/dist/{chunk-KY6WKH66.js → chunk-E7HYEEZD.js} +70 -52
- package/dist/{chunk-QEONJ5DZ.js → chunk-EEQQWTXS.js} +1288 -92
- package/dist/chunk-GDE6FYN4.js +26 -0
- package/dist/{chunk-Y6TYJMNT.js → chunk-GSX2FV3M.js} +10 -16
- package/dist/{chunk-JN3TQVFV.js → chunk-HMLBBZNY.js} +11 -2
- package/dist/{chunk-5NV3LSAJ.js → chunk-IWFX2FMA.js} +5 -1
- package/dist/{chunk-MYVJ6HK4.js → chunk-PUDXVBSN.js} +706 -376
- package/dist/{chunk-ROGRTUFI.js → chunk-QIRE2VXS.js} +14 -3
- package/dist/{chunk-S6VIK4FF.js → chunk-ZHOKYUO3.js} +337 -13
- package/dist/{config-cmd-DNXNL26Z.js → config-cmd-Z3A7V6NC.js} +1 -1
- package/dist/{doctor-4HBRICHP.js → doctor-EJUMPBMW.js} +4 -4
- package/dist/index.js +88 -21
- package/dist/{init-HZ3JEDGQ.js → init-54HMKNYI.js} +3 -3
- package/dist/{logs-6JKKYDGJ.js → logs-GTZ4U5JE.js} +2 -2
- package/dist/project-RMYMZSFV.js +25 -0
- package/dist/{recover-L3MJHHDA.js → recover-LTLKMTRX.js} +7 -7
- package/dist/repo-WI7GF6XQ.js +749 -0
- package/dist/{run-XJQ6BF7U.js → run-IHN3ZL35.js} +21 -9
- package/dist/{setup-B2SVLW2R.js → setup-TZJSM3QV.js} +14 -13
- package/dist/start-RTAHQMR2.js +19 -0
- package/dist/status-F4D52OVK.js +12 -0
- package/dist/stop-MDKMJPVR.js +10 -0
- package/dist/{upgrade-OJXPZRYE.js → upgrade-O33S2SJK.js} +2 -2
- package/dist/{version-TBDCTKDO.js → version-CW54Q7BK.js} +1 -1
- package/dist/worker-entry.js +369 -13
- package/dist/{workflow-BLJH2HC3.js → workflow-L3KT6HB7.js} +5 -5
- package/package.json +3 -3
- package/dist/project-25NQ4J4Y.js +0 -24
- package/dist/repo-TDCWQR6P.js +0 -379
- package/dist/start-I2CC7BLW.js +0 -18
- package/dist/status-QSCFVGRQ.js +0 -11
- package/dist/stop-7MFCBQVW.js +0 -9
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runCli
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-PUDXVBSN.js";
|
|
5
|
+
import "./chunk-2UW7NQLX.js";
|
|
6
|
+
import "./chunk-2TSM3INR.js";
|
|
7
|
+
import "./chunk-EEQQWTXS.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveRuntimeRoot
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IWFX2FMA.js";
|
|
11
11
|
import {
|
|
12
12
|
handleMissingManagedProjectConfig,
|
|
13
13
|
resolveManagedProjectConfig
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-DDL4BWSL.js";
|
|
15
|
+
import "./chunk-QIRE2VXS.js";
|
|
16
16
|
|
|
17
17
|
// src/commands/run.ts
|
|
18
18
|
function parseRunArgs(args) {
|
|
@@ -72,10 +72,22 @@ var handler = async (args, options) => {
|
|
|
72
72
|
const runtimeRoot = resolveRuntimeRoot(options.configDir);
|
|
73
73
|
const projectId = projectConfig.projectId;
|
|
74
74
|
const [repoSpec] = parsed.issue.split("#");
|
|
75
|
-
|
|
75
|
+
const configuredRepos = [
|
|
76
|
+
...projectConfig.repository ? [projectConfig.repository] : [],
|
|
77
|
+
...projectConfig.repositories ?? []
|
|
78
|
+
].filter((repository) => repository.owner && repository.name).map((repository) => `${repository.owner}/${repository.name}`);
|
|
79
|
+
const configuredRepoSet = new Set(configuredRepos);
|
|
80
|
+
if (configuredRepoSet.size === 0) {
|
|
81
|
+
process.stderr.write(
|
|
82
|
+
"No repository is configured in this project. Run 'gh-symphony repo add owner/name' first.\n"
|
|
83
|
+
);
|
|
84
|
+
process.exitCode = 1;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (repoSpec && !configuredRepoSet.has(repoSpec)) {
|
|
76
88
|
process.stderr.write(
|
|
77
89
|
`Repository "${repoSpec}" is not configured in this project.
|
|
78
|
-
Configured
|
|
90
|
+
Configured repo: ${configuredRepos.join(", ")}
|
|
79
91
|
`
|
|
80
92
|
);
|
|
81
93
|
process.exitCode = 1;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
promptProjectRegistrationOptions,
|
|
4
4
|
renderProjectRegistrationSummary
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZHOKYUO3.js";
|
|
6
6
|
import {
|
|
7
7
|
abortIfCancelled,
|
|
8
8
|
buildAutomaticStateMappings,
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
writeConfig,
|
|
17
17
|
writeEcosystem,
|
|
18
18
|
writeWorkflowPlan
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-HMLBBZNY.js";
|
|
20
|
+
import "./chunk-E7HYEEZD.js";
|
|
21
|
+
import "./chunk-PUDXVBSN.js";
|
|
22
|
+
import "./chunk-2UW7NQLX.js";
|
|
23
|
+
import "./chunk-2TSM3INR.js";
|
|
24
24
|
import {
|
|
25
25
|
GhAuthError,
|
|
26
26
|
GitHubScopeError,
|
|
@@ -32,13 +32,14 @@ import {
|
|
|
32
32
|
listUserProjects,
|
|
33
33
|
validateToken
|
|
34
34
|
} from "./chunk-C67H3OUL.js";
|
|
35
|
-
import "./chunk-
|
|
36
|
-
import "./chunk-
|
|
37
|
-
import "./chunk-
|
|
38
|
-
import "./chunk-
|
|
39
|
-
import "./chunk-
|
|
40
|
-
import "./chunk-
|
|
41
|
-
import "./chunk-
|
|
35
|
+
import "./chunk-EEQQWTXS.js";
|
|
36
|
+
import "./chunk-DFLXHNYQ.js";
|
|
37
|
+
import "./chunk-36KYEDEO.js";
|
|
38
|
+
import "./chunk-IWFX2FMA.js";
|
|
39
|
+
import "./chunk-GSX2FV3M.js";
|
|
40
|
+
import "./chunk-GDE6FYN4.js";
|
|
41
|
+
import "./chunk-DDL4BWSL.js";
|
|
42
|
+
import "./chunk-QIRE2VXS.js";
|
|
42
43
|
|
|
43
44
|
// src/commands/setup.ts
|
|
44
45
|
import * as p from "@clack/prompts";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
shutdownForegroundOrchestrator,
|
|
4
|
+
start_default
|
|
5
|
+
} from "./chunk-E7HYEEZD.js";
|
|
6
|
+
import "./chunk-PUDXVBSN.js";
|
|
7
|
+
import "./chunk-2UW7NQLX.js";
|
|
8
|
+
import "./chunk-2TSM3INR.js";
|
|
9
|
+
import "./chunk-C67H3OUL.js";
|
|
10
|
+
import "./chunk-EEQQWTXS.js";
|
|
11
|
+
import "./chunk-36KYEDEO.js";
|
|
12
|
+
import "./chunk-IWFX2FMA.js";
|
|
13
|
+
import "./chunk-GDE6FYN4.js";
|
|
14
|
+
import "./chunk-DDL4BWSL.js";
|
|
15
|
+
import "./chunk-QIRE2VXS.js";
|
|
16
|
+
export {
|
|
17
|
+
start_default as default,
|
|
18
|
+
shutdownForegroundOrchestrator
|
|
19
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
status_default
|
|
4
|
+
} from "./chunk-DFLXHNYQ.js";
|
|
5
|
+
import "./chunk-36KYEDEO.js";
|
|
6
|
+
import "./chunk-IWFX2FMA.js";
|
|
7
|
+
import "./chunk-GDE6FYN4.js";
|
|
8
|
+
import "./chunk-DDL4BWSL.js";
|
|
9
|
+
import "./chunk-QIRE2VXS.js";
|
|
10
|
+
export {
|
|
11
|
+
status_default as default
|
|
12
|
+
};
|
|
@@ -16,8 +16,8 @@ function execFileAsync(file, args, execFileImpl = execFileCallback) {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
function resolveCurrentCliVersion() {
|
|
19
|
-
if ("0.0.
|
|
20
|
-
return "0.0.
|
|
19
|
+
if ("0.0.22".length > 0) {
|
|
20
|
+
return "0.0.22";
|
|
21
21
|
}
|
|
22
22
|
const pkg = JSON.parse(
|
|
23
23
|
readFileSync(new URL("../../package.json", import.meta.url), "utf8")
|
package/dist/worker-entry.js
CHANGED
|
@@ -6,20 +6,22 @@ import {
|
|
|
6
6
|
normalizeCodexRuntimeEvents,
|
|
7
7
|
prepareCodexRuntimePlan,
|
|
8
8
|
resolveLocalRuntimeLaunchConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2UW7NQLX.js";
|
|
10
10
|
import {
|
|
11
11
|
DEFAULT_AGENT_INPUT_REQUIRED_REASON,
|
|
12
12
|
classifySessionExit,
|
|
13
|
+
createClaudePrintRuntimeAdapter,
|
|
14
|
+
extractEnvForClaude,
|
|
13
15
|
formatClaudePreflightText,
|
|
14
16
|
isClaudeRuntimeCommand,
|
|
15
17
|
parseWorkflowMarkdown,
|
|
16
18
|
resolveClaudeCommandBinary,
|
|
17
19
|
resolveWorkflowRuntimeCommand,
|
|
18
20
|
runClaudePreflight
|
|
19
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-EEQQWTXS.js";
|
|
20
22
|
|
|
21
23
|
// ../worker/src/index.ts
|
|
22
|
-
import { spawn } from "child_process";
|
|
24
|
+
import { spawn as spawn2 } from "child_process";
|
|
23
25
|
import { readFile } from "fs/promises";
|
|
24
26
|
import { join as join2 } from "path";
|
|
25
27
|
|
|
@@ -124,6 +126,152 @@ function normalizeError(value) {
|
|
|
124
126
|
return normalized.length > 0 ? normalized : null;
|
|
125
127
|
}
|
|
126
128
|
|
|
129
|
+
// ../worker/src/non-codex-runtime.ts
|
|
130
|
+
import {
|
|
131
|
+
spawn
|
|
132
|
+
} from "child_process";
|
|
133
|
+
import { finished } from "stream/promises";
|
|
134
|
+
var CustomCommandWorkerRuntimeAdapter = class {
|
|
135
|
+
constructor(config, dependencies = {}) {
|
|
136
|
+
this.config = config;
|
|
137
|
+
this.dependencies = dependencies;
|
|
138
|
+
}
|
|
139
|
+
activeChild = null;
|
|
140
|
+
prepare() {
|
|
141
|
+
}
|
|
142
|
+
async spawnTurn(input) {
|
|
143
|
+
const command = this.config.command;
|
|
144
|
+
const args = [...this.config.args];
|
|
145
|
+
const cwd = input.cwd ?? this.config.workingDirectory;
|
|
146
|
+
const child = (this.dependencies.spawnImpl ?? spawn)(command, args, {
|
|
147
|
+
cwd,
|
|
148
|
+
env: {
|
|
149
|
+
...this.config.env,
|
|
150
|
+
...input.env,
|
|
151
|
+
SYMPHONY_RENDERED_PROMPT: input.prompt
|
|
152
|
+
},
|
|
153
|
+
stdio: "pipe"
|
|
154
|
+
});
|
|
155
|
+
this.activeChild = child;
|
|
156
|
+
this.config.onSpawned?.(child);
|
|
157
|
+
let stdout = "";
|
|
158
|
+
let stderr = "";
|
|
159
|
+
let spawnError;
|
|
160
|
+
child.stdout?.setEncoding("utf8");
|
|
161
|
+
child.stderr?.setEncoding("utf8");
|
|
162
|
+
child.stdout?.on("data", (chunk) => {
|
|
163
|
+
stdout += chunk;
|
|
164
|
+
});
|
|
165
|
+
child.stderr?.on("data", (chunk) => {
|
|
166
|
+
stderr += chunk;
|
|
167
|
+
});
|
|
168
|
+
child.once("error", (error) => {
|
|
169
|
+
spawnError = error.message;
|
|
170
|
+
});
|
|
171
|
+
if (child.stdin && !child.stdin.destroyed) {
|
|
172
|
+
child.stdin.end(input.prompt);
|
|
173
|
+
}
|
|
174
|
+
const { exitCode, signal } = await waitForChildExit(child);
|
|
175
|
+
await Promise.all([
|
|
176
|
+
child.stdout ? finished(child.stdout).catch(() => void 0) : void 0,
|
|
177
|
+
child.stderr ? finished(child.stderr).catch(() => void 0) : void 0
|
|
178
|
+
]);
|
|
179
|
+
this.activeChild = null;
|
|
180
|
+
const result = exitCode === 0 && signal === null && !spawnError ? "success" : "process-error";
|
|
181
|
+
return {
|
|
182
|
+
command,
|
|
183
|
+
args,
|
|
184
|
+
cwd,
|
|
185
|
+
stdout,
|
|
186
|
+
stderr,
|
|
187
|
+
exitCode,
|
|
188
|
+
signal,
|
|
189
|
+
result,
|
|
190
|
+
errorMessage: spawnError
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
onEvent(_handler) {
|
|
194
|
+
return () => {
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
resolveCredentials(brokerResponse) {
|
|
198
|
+
if (!this.config.authEnvKey) {
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
return extractEnvForClaude(brokerResponse.env, this.config.authEnvKey);
|
|
202
|
+
}
|
|
203
|
+
shutdown() {
|
|
204
|
+
this.stopActiveChild();
|
|
205
|
+
}
|
|
206
|
+
cancel() {
|
|
207
|
+
this.stopActiveChild();
|
|
208
|
+
}
|
|
209
|
+
stopActiveChild() {
|
|
210
|
+
if (!this.activeChild || this.activeChild.killed) {
|
|
211
|
+
this.activeChild = null;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
this.activeChild.kill("SIGTERM");
|
|
215
|
+
this.activeChild = null;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
function createWorkerNonCodexRuntimeAdapter(workflow, context) {
|
|
219
|
+
const runtime = workflow.runtime;
|
|
220
|
+
if (!runtime || runtime.kind === "codex-app-server") {
|
|
221
|
+
throw new Error(
|
|
222
|
+
"Worker non-Codex runtime adapter requested for a Codex runtime."
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
switch (runtime.kind) {
|
|
226
|
+
case "claude-print":
|
|
227
|
+
return createClaudePrintRuntimeAdapter(
|
|
228
|
+
{
|
|
229
|
+
workingDirectory: context.workingDirectory,
|
|
230
|
+
runtimeRoot: context.runtimeRoot,
|
|
231
|
+
runtimeDirectory: context.runtimeDirectory,
|
|
232
|
+
command: runtime.command,
|
|
233
|
+
args: runtime.args,
|
|
234
|
+
env: context.env,
|
|
235
|
+
authEnvKey: runtime.auth.env ?? void 0,
|
|
236
|
+
isolation: {
|
|
237
|
+
bare: runtime.isolation.bare,
|
|
238
|
+
strictMcpConfig: runtime.isolation.strictMcpConfig
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
...context.claudeDependencies,
|
|
243
|
+
onSpawned: context.onSpawned
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
case "custom":
|
|
247
|
+
return new CustomCommandWorkerRuntimeAdapter(
|
|
248
|
+
{
|
|
249
|
+
workingDirectory: context.workingDirectory,
|
|
250
|
+
command: runtime.command,
|
|
251
|
+
args: runtime.args,
|
|
252
|
+
env: context.env,
|
|
253
|
+
authEnvKey: runtime.auth.env ?? void 0,
|
|
254
|
+
onSpawned: context.onSpawned
|
|
255
|
+
},
|
|
256
|
+
context.customDependencies
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function waitForChildExit(child) {
|
|
261
|
+
return new Promise((resolve) => {
|
|
262
|
+
let settled = false;
|
|
263
|
+
const settle = (exitCode, signal) => {
|
|
264
|
+
if (settled) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
settled = true;
|
|
268
|
+
resolve({ exitCode, signal });
|
|
269
|
+
};
|
|
270
|
+
child.once("exit", settle);
|
|
271
|
+
child.once("error", () => settle(1, null));
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
127
275
|
// ../worker/src/run-phase.ts
|
|
128
276
|
var TERMINAL_RUN_PHASES = /* @__PURE__ */ new Set([
|
|
129
277
|
"succeeded",
|
|
@@ -139,6 +287,15 @@ function resolveExitRunPhase(currentRunPhase, exit) {
|
|
|
139
287
|
return exit.code === 0 && !exit.signal ? "succeeded" : "failed";
|
|
140
288
|
}
|
|
141
289
|
|
|
290
|
+
// ../worker/src/runtime-routing.ts
|
|
291
|
+
function resolveWorkerRuntimeRoute(workflow) {
|
|
292
|
+
const kind = workflow.runtime?.kind;
|
|
293
|
+
if (!kind || kind === "codex-app-server") {
|
|
294
|
+
return "codex-app-server";
|
|
295
|
+
}
|
|
296
|
+
return "runtime-adapter";
|
|
297
|
+
}
|
|
298
|
+
|
|
142
299
|
// ../worker/src/thread-resume.ts
|
|
143
300
|
var DEFAULT_CONTINUATION_GUIDANCE = "Continue working on the issue. Review your progress and complete any remaining tasks.";
|
|
144
301
|
function parseNonNegativeInteger(value) {
|
|
@@ -298,6 +455,7 @@ console.log(
|
|
|
298
455
|
)
|
|
299
456
|
);
|
|
300
457
|
var childProcess = null;
|
|
458
|
+
var runtimeAdapter = null;
|
|
301
459
|
var shutdownPromise = null;
|
|
302
460
|
var orchestratorChannelDrainPending = false;
|
|
303
461
|
var pendingOrchestratorChannelPayloads = [];
|
|
@@ -328,6 +486,7 @@ function shutdown(signal) {
|
|
|
328
486
|
} catch {
|
|
329
487
|
}
|
|
330
488
|
}
|
|
489
|
+
await runtimeAdapter?.cancel(`worker received ${signal}`);
|
|
331
490
|
stopOrchestratorHeartbeatTimer();
|
|
332
491
|
emitOrchestratorHeartbeat();
|
|
333
492
|
await persistSessionTokenUsageArtifact(launcherEnv);
|
|
@@ -569,7 +728,8 @@ async function startAssignedRun() {
|
|
|
569
728
|
await readFile(workflowPath, "utf8"),
|
|
570
729
|
launcherEnv
|
|
571
730
|
);
|
|
572
|
-
|
|
731
|
+
const route = resolveWorkerRuntimeRoute(workflow);
|
|
732
|
+
if (route === "runtime-adapter" && workflow.runtime?.kind === "claude-print" && isClaudeRuntimeCommand(resolveWorkflowRuntimeCommand(workflow))) {
|
|
573
733
|
const hasGitHubGraphqlToken = typeof launcherEnv.GITHUB_GRAPHQL_TOKEN === "string" && launcherEnv.GITHUB_GRAPHQL_TOKEN.trim().length > 0;
|
|
574
734
|
const preflight = await runClaudePreflight({
|
|
575
735
|
cwd: launcherEnv.WORKING_DIRECTORY,
|
|
@@ -587,19 +747,19 @@ async function startAssignedRun() {
|
|
|
587
747
|
);
|
|
588
748
|
return;
|
|
589
749
|
}
|
|
590
|
-
await exitWorkerStartupFailure(
|
|
591
|
-
"Claude runtime worker launch is not yet implemented in this branch."
|
|
592
|
-
);
|
|
593
|
-
return;
|
|
594
750
|
}
|
|
595
751
|
runtimeState.executionPhase = resolveInitialExecutionPhase({
|
|
596
752
|
issueState: runtimeState.run?.state,
|
|
597
753
|
blockerCheckStates: workflow.lifecycle.blockerCheckStates,
|
|
598
754
|
activeStates: workflow.lifecycle.activeStates
|
|
599
755
|
});
|
|
756
|
+
runtimeState.runPhase = "launching_agent";
|
|
757
|
+
if (route === "runtime-adapter") {
|
|
758
|
+
await runNonCodexRuntimeAdapterLifecycle(workflow, launcherEnv);
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
600
761
|
const config = resolveLocalRuntimeLaunchConfig(launcherEnv);
|
|
601
762
|
config.agentCommand = resolveWorkflowRuntimeCommand(workflow);
|
|
602
|
-
runtimeState.runPhase = "launching_agent";
|
|
603
763
|
const plan = await prepareCodexRuntimePlan(config);
|
|
604
764
|
childProcess = launchCodexAppServer(plan);
|
|
605
765
|
runtimeState.status = "running";
|
|
@@ -640,14 +800,210 @@ async function startAssignedRun() {
|
|
|
640
800
|
void persistSessionTokenUsageArtifact(launcherEnv);
|
|
641
801
|
});
|
|
642
802
|
} catch (error) {
|
|
803
|
+
const message = error instanceof Error ? error.message : "Unknown worker startup error";
|
|
643
804
|
runtimeState.status = "failed";
|
|
644
805
|
runtimeState.runPhase = "failed";
|
|
645
806
|
if (runtimeState.run) {
|
|
646
|
-
runtimeState.run.lastError =
|
|
807
|
+
runtimeState.run.lastError = message;
|
|
647
808
|
}
|
|
809
|
+
process.stderr.write(`[worker] startup failed: ${message}
|
|
810
|
+
`);
|
|
648
811
|
await persistSessionTokenUsageArtifact(launcherEnv);
|
|
649
812
|
}
|
|
650
813
|
}
|
|
814
|
+
async function runNonCodexRuntimeAdapterLifecycle(workflow, env) {
|
|
815
|
+
const renderedPrompt = env.SYMPHONY_RENDERED_PROMPT;
|
|
816
|
+
if (!renderedPrompt) {
|
|
817
|
+
await exitWorkerStartupFailure(
|
|
818
|
+
"SYMPHONY_RENDERED_PROMPT not set; cannot run runtime adapter lifecycle."
|
|
819
|
+
);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
const runId = env.SYMPHONY_RUN_ID;
|
|
823
|
+
if (!runId) {
|
|
824
|
+
await exitWorkerStartupFailure(
|
|
825
|
+
"SYMPHONY_RUN_ID not set; cannot prepare runtime adapter lifecycle."
|
|
826
|
+
);
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
const runtimeKind = workflow.runtime?.kind;
|
|
830
|
+
if (runtimeKind !== "claude-print" && runtimeKind !== "custom") {
|
|
831
|
+
await exitWorkerStartupFailure(
|
|
832
|
+
"Runtime adapter lifecycle requested for an unsupported runtime kind."
|
|
833
|
+
);
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
const adapter = createWorkerNonCodexRuntimeAdapter(workflow, {
|
|
837
|
+
workingDirectory: env.WORKING_DIRECTORY,
|
|
838
|
+
env,
|
|
839
|
+
runtimeRoot: env.WORKSPACE_RUNTIME_DIR,
|
|
840
|
+
runtimeDirectory: env.WORKSPACE_RUNTIME_DIR,
|
|
841
|
+
onSpawned: (child) => {
|
|
842
|
+
childProcess = child;
|
|
843
|
+
if (runtimeState.run) {
|
|
844
|
+
runtimeState.run.processId = child.pid ?? null;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
runtimeAdapter = adapter;
|
|
849
|
+
let terminalFailure = null;
|
|
850
|
+
const unsubscribe = adapter.onEvent((event) => {
|
|
851
|
+
const agentEvent = event;
|
|
852
|
+
handleNonCodexRuntimeEvent(agentEvent);
|
|
853
|
+
if (agentEvent.name === "agent.inputRequired") {
|
|
854
|
+
terminalFailure = agentEvent.payload.reason;
|
|
855
|
+
}
|
|
856
|
+
if (agentEvent.name === "agent.turnFailed" || agentEvent.name === "agent.error") {
|
|
857
|
+
terminalFailure = agentEvent.name === "agent.error" ? agentEvent.payload.error : JSON.stringify(agentEvent.payload.params);
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
const turnTelemetry = {
|
|
861
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
862
|
+
threadId: null,
|
|
863
|
+
turnId: `${runId}-turn-1`,
|
|
864
|
+
turnCount: 1,
|
|
865
|
+
sessionId: runId,
|
|
866
|
+
tokenUsageBaseline: cloneTokenUsageSnapshot()
|
|
867
|
+
};
|
|
868
|
+
try {
|
|
869
|
+
await adapter.prepare({
|
|
870
|
+
runId
|
|
871
|
+
});
|
|
872
|
+
runtimeState.status = "running";
|
|
873
|
+
runtimeState.runPhase = "streaming_turn";
|
|
874
|
+
runtimeState.sessionInfo = {
|
|
875
|
+
threadId: turnTelemetry.threadId,
|
|
876
|
+
turnId: turnTelemetry.turnId,
|
|
877
|
+
turnCount: turnTelemetry.turnCount,
|
|
878
|
+
sessionId: turnTelemetry.sessionId,
|
|
879
|
+
exitClassification: null
|
|
880
|
+
};
|
|
881
|
+
runtimeState.sessionId = turnTelemetry.sessionId;
|
|
882
|
+
emitTurnStartedEvent(turnTelemetry);
|
|
883
|
+
const result = await spawnNonCodexRuntimeTurn(
|
|
884
|
+
adapter,
|
|
885
|
+
runtimeKind,
|
|
886
|
+
renderedPrompt,
|
|
887
|
+
env
|
|
888
|
+
);
|
|
889
|
+
if (isNonCodexTurnFailure(result)) {
|
|
890
|
+
terminalFailure = describeNonCodexTurnFailure(result);
|
|
891
|
+
}
|
|
892
|
+
runtimeState.status = terminalFailure ? "failed" : "completed";
|
|
893
|
+
runtimeState.runPhase = terminalFailure ? "failed" : "succeeded";
|
|
894
|
+
if (runtimeState.run) {
|
|
895
|
+
runtimeState.run.lastError = terminalFailure;
|
|
896
|
+
}
|
|
897
|
+
runtimeState.sessionInfo.exitClassification = classifySessionExit({
|
|
898
|
+
runPhase: runtimeState.runPhase,
|
|
899
|
+
userInputRequired: terminalFailure === DEFAULT_AGENT_INPUT_REQUIRED_REASON || terminalFailure?.startsWith("turn_input_required:") === true,
|
|
900
|
+
budgetExceeded: false,
|
|
901
|
+
convergenceDetected: false,
|
|
902
|
+
maxTurnsReached: false
|
|
903
|
+
});
|
|
904
|
+
if (terminalFailure) {
|
|
905
|
+
emitTurnFailedEvent(turnTelemetry, terminalFailure);
|
|
906
|
+
} else {
|
|
907
|
+
emitTurnCompletedEvent(turnTelemetry);
|
|
908
|
+
}
|
|
909
|
+
} catch (error) {
|
|
910
|
+
const message = error instanceof Error ? error.message : "Unknown runtime adapter lifecycle error";
|
|
911
|
+
runtimeState.status = "failed";
|
|
912
|
+
runtimeState.runPhase = "failed";
|
|
913
|
+
if (runtimeState.run) {
|
|
914
|
+
runtimeState.run.lastError = message;
|
|
915
|
+
}
|
|
916
|
+
runtimeState.sessionInfo.exitClassification = classifySessionExit({
|
|
917
|
+
runPhase: runtimeState.runPhase,
|
|
918
|
+
userInputRequired: false,
|
|
919
|
+
budgetExceeded: false,
|
|
920
|
+
convergenceDetected: false,
|
|
921
|
+
maxTurnsReached: false
|
|
922
|
+
});
|
|
923
|
+
emitTurnFailedEvent(turnTelemetry, message);
|
|
924
|
+
} finally {
|
|
925
|
+
unsubscribe();
|
|
926
|
+
await adapter.shutdown();
|
|
927
|
+
runtimeAdapter = null;
|
|
928
|
+
childProcess = null;
|
|
929
|
+
runtimeState.runPhase = runtimeState.runPhase ?? "failed";
|
|
930
|
+
stopOrchestratorHeartbeatTimer();
|
|
931
|
+
emitOrchestratorHeartbeat();
|
|
932
|
+
await persistSessionTokenUsageArtifact(env);
|
|
933
|
+
await waitForPendingOrchestratorChannelFlush(
|
|
934
|
+
resolveTerminalOrchestratorChannelFlushTimeoutMs()
|
|
935
|
+
);
|
|
936
|
+
setTimeout(() => {
|
|
937
|
+
process.exit(runtimeState.status === "completed" ? 0 : 1);
|
|
938
|
+
}, 1500);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
async function spawnNonCodexRuntimeTurn(adapter, runtimeKind, renderedPrompt, env) {
|
|
942
|
+
if (runtimeKind === "claude-print") {
|
|
943
|
+
return await adapter.spawnTurn({
|
|
944
|
+
messages: [{ type: "user", text: renderedPrompt }],
|
|
945
|
+
cwd: env.WORKING_DIRECTORY,
|
|
946
|
+
env
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
return await adapter.spawnTurn({
|
|
950
|
+
prompt: renderedPrompt,
|
|
951
|
+
cwd: env.WORKING_DIRECTORY,
|
|
952
|
+
env
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
function handleNonCodexRuntimeEvent(event) {
|
|
956
|
+
if (event.payload.suppressUpdate) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
runtimeState.lastEventAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
960
|
+
switch (event.name) {
|
|
961
|
+
case "agent.tokenUsageUpdated": {
|
|
962
|
+
const tokenUsage = extractAbsoluteTokenUsage(event.payload.params);
|
|
963
|
+
if (tokenUsage) {
|
|
964
|
+
applyTokenUsageUpdate(
|
|
965
|
+
event.payload.observabilityEvent ?? event.name,
|
|
966
|
+
tokenUsage
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
case "agent.rateLimit": {
|
|
972
|
+
const rateLimits = extractRateLimitPayload(event.payload.params);
|
|
973
|
+
if (rateLimits) {
|
|
974
|
+
applyRateLimitUpdate(
|
|
975
|
+
event.payload.observabilityEvent ?? event.name,
|
|
976
|
+
rateLimits,
|
|
977
|
+
"runtime-adapter"
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
break;
|
|
981
|
+
}
|
|
982
|
+
case "agent.inputRequired":
|
|
983
|
+
runtimeState.status = "failed";
|
|
984
|
+
if (runtimeState.run) {
|
|
985
|
+
runtimeState.run.lastError = event.payload.reason;
|
|
986
|
+
}
|
|
987
|
+
break;
|
|
988
|
+
case "agent.turnFailed":
|
|
989
|
+
case "agent.turnCancelled":
|
|
990
|
+
case "agent.error":
|
|
991
|
+
runtimeState.status = "failed";
|
|
992
|
+
if (runtimeState.run) {
|
|
993
|
+
runtimeState.run.lastError = event.name === "agent.error" ? event.payload.error : JSON.stringify(event.payload.params);
|
|
994
|
+
}
|
|
995
|
+
break;
|
|
996
|
+
default:
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
emitOrchestratorChannelEvent(event.payload.observabilityEvent ?? event.name);
|
|
1000
|
+
}
|
|
1001
|
+
function isNonCodexTurnFailure(result) {
|
|
1002
|
+
return result.result !== "success";
|
|
1003
|
+
}
|
|
1004
|
+
function describeNonCodexTurnFailure(result) {
|
|
1005
|
+
return result.errorMessage ?? `${result.command} exited with ${result.signal ?? result.exitCode ?? "unknown"}`;
|
|
1006
|
+
}
|
|
651
1007
|
async function exitWorkerStartupFailure(message) {
|
|
652
1008
|
runtimeState.status = "failed";
|
|
653
1009
|
runtimeState.runPhase = "failed";
|
|
@@ -1328,10 +1684,10 @@ function applyTokenUsageUpdate(source, tokenUsage) {
|
|
|
1328
1684
|
`
|
|
1329
1685
|
);
|
|
1330
1686
|
}
|
|
1331
|
-
function applyRateLimitUpdate(source, rateLimits) {
|
|
1687
|
+
function applyRateLimitUpdate(source, rateLimits, runtimeSource = "codex") {
|
|
1332
1688
|
runtimeState.rateLimits = {
|
|
1333
1689
|
...rateLimits,
|
|
1334
|
-
source:
|
|
1690
|
+
source: runtimeSource
|
|
1335
1691
|
};
|
|
1336
1692
|
process.stderr.write(
|
|
1337
1693
|
`[worker] rate_limits source=${source} payload=${JSON.stringify(runtimeState.rateLimits).slice(0, 300)}
|
|
@@ -1483,7 +1839,7 @@ function runToolProcess(toolDef, inputJson) {
|
|
|
1483
1839
|
...process.env,
|
|
1484
1840
|
...toolDef.env
|
|
1485
1841
|
};
|
|
1486
|
-
const toolProc =
|
|
1842
|
+
const toolProc = spawn2(toolDef.command, toolDef.args, {
|
|
1487
1843
|
env: toolEnv,
|
|
1488
1844
|
stdio: "pipe"
|
|
1489
1845
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
init_default
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HMLBBZNY.js";
|
|
5
5
|
import {
|
|
6
6
|
fetchGithubProjectIssueByRepositoryAndNumber
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2TSM3INR.js";
|
|
8
8
|
import {
|
|
9
9
|
GitHubApiError,
|
|
10
10
|
createClient,
|
|
@@ -17,11 +17,11 @@ import {
|
|
|
17
17
|
buildPromptVariables,
|
|
18
18
|
parseWorkflowMarkdown,
|
|
19
19
|
renderPrompt
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-EEQQWTXS.js";
|
|
21
21
|
import {
|
|
22
22
|
inspectManagedProjectSelection
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-DDL4BWSL.js";
|
|
24
|
+
import "./chunk-QIRE2VXS.js";
|
|
25
25
|
|
|
26
26
|
// src/commands/workflow.ts
|
|
27
27
|
import { readFile } from "fs/promises";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gh-symphony/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "hojinzs",
|
|
6
6
|
"description": "Interactive CLI for GitHub Symphony orchestration",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"tsup": "^8.5.1",
|
|
44
|
-
"@gh-symphony/control-plane": "0.0.14",
|
|
45
44
|
"@gh-symphony/core": "0.0.14",
|
|
46
|
-
"@gh-symphony/
|
|
45
|
+
"@gh-symphony/control-plane": "0.0.15",
|
|
47
46
|
"@gh-symphony/dashboard": "0.0.14",
|
|
47
|
+
"@gh-symphony/orchestrator": "0.0.14",
|
|
48
48
|
"@gh-symphony/runtime-claude": "0.0.14",
|
|
49
49
|
"@gh-symphony/tracker-github": "0.0.14",
|
|
50
50
|
"@gh-symphony/worker": "0.0.14"
|