@gh-symphony/cli 0.0.18 → 0.0.20
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 +85 -14
- package/dist/{project-O57C32WF.js → chunk-3AWF54PI.js} +104 -90
- package/dist/{chunk-ZYYY55WB.js → chunk-EKKT5USP.js} +74 -23
- package/dist/{chunk-LZE6YUSB.js → chunk-HZVDTAPS.js} +32 -72
- package/dist/{chunk-5YLETHMR.js → chunk-RN2PACNV.js} +345 -169
- package/dist/{chunk-62L6QQE6.js → chunk-TILHWBP6.js} +277 -1
- package/dist/{config-cmd-AZ7POMAA.js → config-cmd-DNXNL26Z.js} +3 -1
- package/dist/doctor-IYHCFXOZ.js +1126 -0
- package/dist/index.js +144 -18
- package/dist/init-KZT6YNOH.js +33 -0
- package/dist/project-UUVHS3ZR.js +22 -0
- package/dist/{recover-UGUTQTWA.js → recover-5KQI7WH5.js} +2 -2
- package/dist/repo-HDDE7OUI.js +321 -0
- package/dist/{run-5H2R6CHB.js → run-ETC5UTRA.js} +2 -2
- package/dist/setup-VWB7RZUQ.js +431 -0
- package/dist/{start-5JGGJIMC.js → start-ENFLZUI6.js} +4 -4
- package/dist/upgrade-3YNF3VKY.js +165 -0
- package/dist/{version-N7YXKG6V.js → version-NUBTTOG7.js} +1 -1
- package/dist/worker-entry.js +71 -193
- package/dist/workflow-TBIFY5MO.js +497 -0
- package/package.json +2 -2
- package/dist/chunk-7UBUBSMH.js +0 -134
- package/dist/doctor-3QT5CZN4.js +0 -532
- package/dist/init-E432UZ32.js +0 -18
- package/dist/repo-R3XBIVAX.js +0 -121
- package/dist/{chunk-OL73UN2X.js → chunk-M3IFVLQS.js} +77 -77
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
resolveIssueWorkspaceDirectory,
|
|
27
27
|
safeReadDir,
|
|
28
28
|
scheduleRetryAt
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-M3IFVLQS.js";
|
|
30
30
|
|
|
31
31
|
// ../orchestrator/dist/service.js
|
|
32
32
|
import { mkdir as mkdir3, readFile as readFile3, rm as rm3, writeFile as writeFile3 } from "fs/promises";
|
|
@@ -501,6 +501,9 @@ function normalizeProjectItem(projectId, item, lifecycle = DEFAULT_WORKFLOW_LIFE
|
|
|
501
501
|
state: normalizeBlockerState(node.state, lifecycle)
|
|
502
502
|
}
|
|
503
503
|
] : []);
|
|
504
|
+
const issueUpdatedAtMs = parseTimestampMs(item.content.updatedAt);
|
|
505
|
+
const itemUpdatedAtMs = parseTimestampMs(item.updatedAt);
|
|
506
|
+
const trackedUpdatedAt = itemUpdatedAtMs !== null && (issueUpdatedAtMs === null || itemUpdatedAtMs > issueUpdatedAtMs) ? item.updatedAt : item.content.updatedAt ?? item.updatedAt;
|
|
504
507
|
return {
|
|
505
508
|
id: item.content.id,
|
|
506
509
|
identifier: `${repository.owner.login}/${repository.name}#${item.content.number}`,
|
|
@@ -514,7 +517,7 @@ function normalizeProjectItem(projectId, item, lifecycle = DEFAULT_WORKFLOW_LIFE
|
|
|
514
517
|
labels: (item.content.labels?.nodes ?? []).flatMap((label) => label?.name ? [label.name.toLowerCase()] : []).sort(),
|
|
515
518
|
blockedBy,
|
|
516
519
|
createdAt: item.content.createdAt,
|
|
517
|
-
updatedAt:
|
|
520
|
+
updatedAt: trackedUpdatedAt,
|
|
518
521
|
repository: {
|
|
519
522
|
owner: repository.owner.login,
|
|
520
523
|
name: repository.name,
|
|
@@ -1381,8 +1384,6 @@ var DEFAULT_POLL_INTERVAL_MS = 3e4;
|
|
|
1381
1384
|
var DEFAULT_CONCURRENCY = 3;
|
|
1382
1385
|
var DEFAULT_RETRY_BACKOFF_MS = 3e4;
|
|
1383
1386
|
var CONTINUATION_RETRY_DELAY_MS = 1e3;
|
|
1384
|
-
var DEFAULT_GLOBAL_MAX_TURNS = 100;
|
|
1385
|
-
var DEFAULT_MAX_TOKENS = 256e3;
|
|
1386
1387
|
var DEFAULT_WORKER_COMMAND = "node packages/worker/dist/index.js";
|
|
1387
1388
|
var DEFAULT_MAX_NONPRODUCTIVE_TURNS = 3;
|
|
1388
1389
|
var LOW_RATE_LIMIT_WARNING_THRESHOLD = 0.05;
|
|
@@ -1624,7 +1625,7 @@ var OrchestratorService = class {
|
|
|
1624
1625
|
const availableSlots = Math.max(0, concurrency - currentlyActive);
|
|
1625
1626
|
const latestRunsByIssueId = buildLatestRunMapByIssueId(projectRunsAfterReconcile);
|
|
1626
1627
|
const unscheduledCandidates = actionableCandidates.filter((issue) => {
|
|
1627
|
-
if (hasConvergenceLockedRun(projectRunsAfterReconcile, issue.id, issue.state)) {
|
|
1628
|
+
if (hasConvergenceLockedRun(projectRunsAfterReconcile, issue.id, issue.state, issue.updatedAt)) {
|
|
1628
1629
|
return false;
|
|
1629
1630
|
}
|
|
1630
1631
|
return !issueRecords.some((record) => record.issueId === issue.id && isIssueOrchestrationClaimed(record.state));
|
|
@@ -1647,9 +1648,6 @@ var OrchestratorService = class {
|
|
|
1647
1648
|
if (await this.isFailureRetrySuppressedIssue(tenant, issue, issueRecords, latestRunsByIssueId.get(issue.id) ?? null)) {
|
|
1648
1649
|
continue;
|
|
1649
1650
|
}
|
|
1650
|
-
if (isIssueBudgetExceeded(resolveIssueBudgetSnapshot(projectRunsAfterReconcile, issue.id), now)) {
|
|
1651
|
-
continue;
|
|
1652
|
-
}
|
|
1653
1651
|
const stateLimit = maxConcurrentByState[issue.state];
|
|
1654
1652
|
if (stateLimit !== void 0) {
|
|
1655
1653
|
const activeInState = activeByState.get(issue.state) ?? 0;
|
|
@@ -2011,7 +2009,7 @@ var OrchestratorService = class {
|
|
|
2011
2009
|
const resolution = await loadRepositoryWorkflow(repositoryDirectory, repository);
|
|
2012
2010
|
return this.resolveWorkflowResolution(repository, cacheRoot, resolution, changed);
|
|
2013
2011
|
}
|
|
2014
|
-
async startRun(tenant, issue
|
|
2012
|
+
async startRun(tenant, issue) {
|
|
2015
2013
|
if (this.shuttingDown || !this.running) {
|
|
2016
2014
|
throw new Error("Orchestrator is shutting down and cannot start new runs.");
|
|
2017
2015
|
}
|
|
@@ -2073,8 +2071,6 @@ var OrchestratorService = class {
|
|
|
2073
2071
|
if (!isUsableWorkflowResolution(workflow)) {
|
|
2074
2072
|
throw new Error(workflow.validationError ?? "Invalid repository WORKFLOW.md");
|
|
2075
2073
|
}
|
|
2076
|
-
const allProjectRuns = (await this.store.loadAllRuns()).filter((run) => run.projectId === tenant.projectId);
|
|
2077
|
-
const issueBudgetSnapshot = resolveIssueBudgetSnapshot(allProjectRuns, issue.id);
|
|
2078
2074
|
const promptVariables = buildPromptVariables(issue, {
|
|
2079
2075
|
attempt: null
|
|
2080
2076
|
// first execution
|
|
@@ -2144,17 +2140,19 @@ var OrchestratorService = class {
|
|
|
2144
2140
|
SYMPHONY_THREAD_SANDBOX: workflow.workflow.codex.threadSandbox ?? "",
|
|
2145
2141
|
SYMPHONY_TURN_SANDBOX_POLICY: workflow.workflow.codex.turnSandboxPolicy ?? "",
|
|
2146
2142
|
SYMPHONY_MAX_TURNS: String(workflow.workflow.agent.maxTurns),
|
|
2147
|
-
SYMPHONY_GLOBAL_MAX_TURNS: process.env.SYMPHONY_GLOBAL_MAX_TURNS ?? "",
|
|
2148
|
-
SYMPHONY_MAX_TOKENS: process.env.SYMPHONY_MAX_TOKENS ?? "",
|
|
2149
2143
|
SYMPHONY_MAX_NONPRODUCTIVE_TURNS: process.env.SYMPHONY_MAX_NONPRODUCTIVE_TURNS ?? String(DEFAULT_MAX_NONPRODUCTIVE_TURNS),
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2144
|
+
// Clear legacy resume/budget env so fresh worker sessions do not
|
|
2145
|
+
// inherit stale process-level values.
|
|
2146
|
+
SYMPHONY_GLOBAL_MAX_TURNS: "",
|
|
2147
|
+
SYMPHONY_MAX_TOKENS: "",
|
|
2148
|
+
SYMPHONY_SESSION_TIMEOUT_MS: "",
|
|
2149
|
+
SYMPHONY_RESUME_THREAD_ID: "",
|
|
2150
|
+
SYMPHONY_CUMULATIVE_TURN_COUNT: "0",
|
|
2151
|
+
SYMPHONY_CUMULATIVE_INPUT_TOKENS: "0",
|
|
2152
|
+
SYMPHONY_CUMULATIVE_OUTPUT_TOKENS: "0",
|
|
2153
|
+
SYMPHONY_CUMULATIVE_TOTAL_TOKENS: "0",
|
|
2154
|
+
SYMPHONY_LAST_TURN_SUMMARY: "",
|
|
2155
|
+
SYMPHONY_SESSION_STARTED_AT: "",
|
|
2158
2156
|
SYMPHONY_READ_TIMEOUT_MS: String(workflow.workflow.codex.readTimeoutMs),
|
|
2159
2157
|
SYMPHONY_TURN_TIMEOUT_MS: String(workflow.workflow.codex.turnTimeoutMs)
|
|
2160
2158
|
}),
|
|
@@ -2399,17 +2397,17 @@ var OrchestratorService = class {
|
|
|
2399
2397
|
}
|
|
2400
2398
|
return this.restartRun(tenant, run, issueRecords, now, workerSessionId);
|
|
2401
2399
|
}
|
|
2402
|
-
if (workerInfo.exitClassification === "
|
|
2400
|
+
if (workerInfo.exitClassification === "convergence-detected") {
|
|
2403
2401
|
const completedRun = {
|
|
2404
2402
|
...runWithTokens,
|
|
2405
|
-
status:
|
|
2403
|
+
status: "failed",
|
|
2406
2404
|
processId: null,
|
|
2407
2405
|
updatedAt: now.toISOString(),
|
|
2408
2406
|
completedAt: now.toISOString(),
|
|
2409
2407
|
nextRetryAt: null,
|
|
2410
2408
|
retryKind: null,
|
|
2411
|
-
lastError:
|
|
2412
|
-
runPhase: runWithTokens.runPhase ??
|
|
2409
|
+
lastError: runWithTokens.lastError,
|
|
2410
|
+
runPhase: runWithTokens.runPhase ?? "failed"
|
|
2413
2411
|
};
|
|
2414
2412
|
await this.store.saveRun(completedRun);
|
|
2415
2413
|
this.logVerbose(`[run-completed] ${completedRun.runId} status=${completedRun.status}`);
|
|
@@ -2746,9 +2744,6 @@ var OrchestratorService = class {
|
|
|
2746
2744
|
}
|
|
2747
2745
|
async resolveRetryRestartAction(tenant, run, trackerDependencies = {}) {
|
|
2748
2746
|
try {
|
|
2749
|
-
if (isIssueBudgetExceeded(resolveIssueBudgetSnapshot((await this.store.loadAllRuns()).filter((candidate) => candidate.projectId === tenant.projectId), run.issueId), this.now())) {
|
|
2750
|
-
return "release";
|
|
2751
|
-
}
|
|
2752
2747
|
const eligibleContext = await this.fetchTrackedIssueEligibilityContext(tenant, run.issueIdentifier, trackerDependencies);
|
|
2753
2748
|
if (!eligibleContext) {
|
|
2754
2749
|
return "release";
|
|
@@ -2860,18 +2855,14 @@ var OrchestratorService = class {
|
|
|
2860
2855
|
};
|
|
2861
2856
|
await this.store.saveRun(supersededRecord);
|
|
2862
2857
|
const issue = resolveTrackerAdapter2(tenant.tracker).reviveIssue(tenant, run);
|
|
2863
|
-
const restarted = await this.startRun(tenant, issue
|
|
2864
|
-
threadId: run.threadId ?? run.runtimeSession?.threadId ?? null,
|
|
2865
|
-
cumulativeTurnCount: resolvePersistedCumulativeTurnCount(run),
|
|
2866
|
-
lastTurnSummary: run.lastTurnSummary ?? null
|
|
2867
|
-
});
|
|
2858
|
+
const restarted = await this.startRun(tenant, issue);
|
|
2868
2859
|
const recoveredRecord = {
|
|
2869
2860
|
...restarted,
|
|
2870
2861
|
attempt: run.attempt,
|
|
2871
2862
|
retryKind: run.retryKind ?? "recovery",
|
|
2872
2863
|
createdAt: run.createdAt,
|
|
2873
2864
|
issueWorkspaceKey: run.issueWorkspaceKey,
|
|
2874
|
-
threadId:
|
|
2865
|
+
threadId: null,
|
|
2875
2866
|
cumulativeTurnCount: resolvePersistedCumulativeTurnCount(run),
|
|
2876
2867
|
lastTurnSummary: run.lastTurnSummary ?? null,
|
|
2877
2868
|
turnCount: 0
|
|
@@ -3264,48 +3255,17 @@ function buildRuntimeSession(existing, sessionId, threadId, status, startedAt, u
|
|
|
3264
3255
|
function resolvePersistedCumulativeTurnCount(run) {
|
|
3265
3256
|
return run.cumulativeTurnCount ?? run.turnCount ?? 0;
|
|
3266
3257
|
}
|
|
3267
|
-
function hasConvergenceLockedRun(runs, issueId, issueState) {
|
|
3258
|
+
function hasConvergenceLockedRun(runs, issueId, issueState, issueUpdatedAt) {
|
|
3268
3259
|
const latestRun = runs.filter((run) => run.issueId === issueId).sort((left, right) => new Date(right.updatedAt).getTime() - new Date(left.updatedAt).getTime())[0];
|
|
3269
|
-
|
|
3270
|
-
}
|
|
3271
|
-
function resolveIssueBudgetSnapshot(runs, issueId) {
|
|
3272
|
-
const issueRuns = runs.filter((run) => run.issueId === issueId);
|
|
3273
|
-
const startedAtCandidates = issueRuns.map((run) => run.startedAt).filter((value) => typeof value === "string");
|
|
3274
|
-
return {
|
|
3275
|
-
cumulativeTurnCount: issueRuns.reduce((total, run) => total + resolvePersistedCumulativeTurnCount(run), 0),
|
|
3276
|
-
tokenUsage: issueRuns.reduce((total, run) => ({
|
|
3277
|
-
inputTokens: total.inputTokens + (run.tokenUsage?.inputTokens ?? 0),
|
|
3278
|
-
outputTokens: total.outputTokens + (run.tokenUsage?.outputTokens ?? 0),
|
|
3279
|
-
totalTokens: total.totalTokens + (run.tokenUsage?.totalTokens ?? 0)
|
|
3280
|
-
}), {
|
|
3281
|
-
inputTokens: 0,
|
|
3282
|
-
outputTokens: 0,
|
|
3283
|
-
totalTokens: 0
|
|
3284
|
-
}),
|
|
3285
|
-
sessionStartedAt: startedAtCandidates.sort((left, right) => left.localeCompare(right))[0] ?? null
|
|
3286
|
-
};
|
|
3287
|
-
}
|
|
3288
|
-
function isIssueBudgetExceeded(snapshot, now, env = process.env) {
|
|
3289
|
-
const globalMaxTurns = parsePositiveInteger(env.SYMPHONY_GLOBAL_MAX_TURNS ?? "") ?? DEFAULT_GLOBAL_MAX_TURNS;
|
|
3290
|
-
if (snapshot.cumulativeTurnCount >= globalMaxTurns) {
|
|
3291
|
-
return true;
|
|
3292
|
-
}
|
|
3293
|
-
const maxTokens = parsePositiveInteger(env.SYMPHONY_MAX_TOKENS ?? "") ?? DEFAULT_MAX_TOKENS;
|
|
3294
|
-
if (snapshot.tokenUsage.totalTokens >= maxTokens) {
|
|
3295
|
-
return true;
|
|
3296
|
-
}
|
|
3297
|
-
const sessionTimeoutMs = parsePositiveInteger(env.SYMPHONY_SESSION_TIMEOUT_MS ?? "");
|
|
3298
|
-
if (sessionTimeoutMs === null || snapshot.sessionStartedAt === null) {
|
|
3260
|
+
if (latestRun?.runtimeSession?.exitClassification !== "convergence-detected" || latestRun.issueState !== issueState) {
|
|
3299
3261
|
return false;
|
|
3300
3262
|
}
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
3306
|
-
return null;
|
|
3263
|
+
const convergedAtMs = parseTimestampMs2(latestRun.completedAt ?? latestRun.updatedAt);
|
|
3264
|
+
const issueUpdatedAtMs = parseTimestampMs2(issueUpdatedAt);
|
|
3265
|
+
if (convergedAtMs === null || issueUpdatedAtMs === null) {
|
|
3266
|
+
return true;
|
|
3307
3267
|
}
|
|
3308
|
-
return
|
|
3268
|
+
return issueUpdatedAtMs <= convergedAtMs;
|
|
3309
3269
|
}
|
|
3310
3270
|
function resolveCumulativeTurnCount(run, turnCount) {
|
|
3311
3271
|
const carriedTotal = resolvePersistedCumulativeTurnCount(run);
|