fly-to-moon 0.1.16 → 0.1.18
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 +1 -0
- package/dist/cli.mjs +277 -59
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -174,6 +174,7 @@ npm link
|
|
|
174
174
|
| `--max-tokens <n>` | Abort after `n` total input+output tokens | unlimited |
|
|
175
175
|
| `--detach` | Run in daemon mode (background execution with `--max-iterations`) | `false` (foreground) |
|
|
176
176
|
| `--prevent-sleep <mode>` | Prevent system sleep during the run (`on`/`off` or `true`/`false`) | config file (`on`) |
|
|
177
|
+
| `--commit` | Commit both successful and failed iterations (default: only on success) | `false` |
|
|
177
178
|
| `--version` | Show version | |
|
|
178
179
|
|
|
179
180
|
## Configuration
|
package/dist/cli.mjs
CHANGED
|
@@ -135,18 +135,108 @@ function loadConfig(overrides) {
|
|
|
135
135
|
}
|
|
136
136
|
//#endregion
|
|
137
137
|
//#region src/core/debug-log.ts
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
const PRE_INIT_BUFFER_CAPACITY = 1e3;
|
|
139
|
+
const STACK_LINE_LIMIT = 12;
|
|
140
|
+
const CAUSE_DEPTH_LIMIT = 6;
|
|
141
|
+
let logPath = null;
|
|
142
|
+
let preInitBuffer = [];
|
|
143
|
+
let preInitDroppedCount = 0;
|
|
144
|
+
function formatLine(event, details) {
|
|
145
|
+
const base = {
|
|
146
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
147
|
+
pid: process.pid,
|
|
148
|
+
event
|
|
149
|
+
};
|
|
141
150
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
pid: process.pid,
|
|
145
|
-
event,
|
|
151
|
+
return `${JSON.stringify({
|
|
152
|
+
...base,
|
|
146
153
|
...details
|
|
147
|
-
})}\n
|
|
154
|
+
})}\n`;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
return `${JSON.stringify({
|
|
157
|
+
...base,
|
|
158
|
+
logError: error instanceof Error ? `${error.name}: ${error.message}` : String(error),
|
|
159
|
+
detailsKeys: Object.keys(details)
|
|
160
|
+
})}\n`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function initDebugLog(path) {
|
|
164
|
+
const resolvedPath = process.env.GNHF_DEBUG_LOG_PATH ?? path;
|
|
165
|
+
logPath = resolvedPath;
|
|
166
|
+
try {
|
|
167
|
+
mkdirSync(dirname(resolvedPath), { recursive: true });
|
|
168
|
+
} catch {}
|
|
169
|
+
if (preInitBuffer.length === 0 && preInitDroppedCount === 0) return;
|
|
170
|
+
const droppedSentinel = preInitDroppedCount > 0 ? formatLine("debug-log:pre-init-overflow", {
|
|
171
|
+
droppedCount: preInitDroppedCount,
|
|
172
|
+
bufferCapacity: PRE_INIT_BUFFER_CAPACITY
|
|
173
|
+
}) : "";
|
|
174
|
+
try {
|
|
175
|
+
appendFileSync(resolvedPath, droppedSentinel + preInitBuffer.join(""), "utf-8");
|
|
176
|
+
} catch {} finally {
|
|
177
|
+
preInitBuffer = [];
|
|
178
|
+
preInitDroppedCount = 0;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function appendDebugLog(event, details = {}) {
|
|
182
|
+
const line = formatLine(event, details);
|
|
183
|
+
if (logPath === null) {
|
|
184
|
+
const envLogPath = process.env.GNHF_DEBUG_LOG_PATH;
|
|
185
|
+
if (envLogPath) logPath = envLogPath;
|
|
186
|
+
else {
|
|
187
|
+
preInitBuffer.push(line);
|
|
188
|
+
if (preInitBuffer.length > PRE_INIT_BUFFER_CAPACITY) {
|
|
189
|
+
preInitBuffer.shift();
|
|
190
|
+
preInitDroppedCount += 1;
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
appendFileSync(logPath, line, "utf-8");
|
|
148
197
|
} catch {}
|
|
149
198
|
}
|
|
199
|
+
function serializeError(error, depth = 0) {
|
|
200
|
+
try {
|
|
201
|
+
return serializeErrorUnsafe(error, depth);
|
|
202
|
+
} catch (serializationError) {
|
|
203
|
+
return {
|
|
204
|
+
value: "[serialization failed]",
|
|
205
|
+
serializationError: serializationError instanceof Error ? `${serializationError.name}: ${serializationError.message}` : String(serializationError)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function tryRead(read) {
|
|
210
|
+
try {
|
|
211
|
+
return read();
|
|
212
|
+
} catch {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function serializeErrorUnsafe(error, depth) {
|
|
217
|
+
if (depth > CAUSE_DEPTH_LIMIT) return { value: "[cause chain truncated]" };
|
|
218
|
+
if (error instanceof Error) {
|
|
219
|
+
const result = {
|
|
220
|
+
name: tryRead(() => error.name) ?? "Error",
|
|
221
|
+
message: tryRead(() => error.message) ?? ""
|
|
222
|
+
};
|
|
223
|
+
const code = tryRead(() => error.code);
|
|
224
|
+
if (typeof code === "string" || typeof code === "number") result.code = code;
|
|
225
|
+
const stack = tryRead(() => error.stack);
|
|
226
|
+
if (typeof stack === "string") result.stack = stack.split("\n").slice(0, STACK_LINE_LIMIT).join("\n");
|
|
227
|
+
const cause = tryRead(() => "cause" in error ? error.cause : void 0);
|
|
228
|
+
if (cause !== void 0) result.cause = serializeError(cause, depth + 1);
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
if (error === null || error === void 0) return { value: String(error) };
|
|
232
|
+
if (typeof error === "bigint") return { value: error.toString() };
|
|
233
|
+
if (typeof error === "object") try {
|
|
234
|
+
return { value: JSON.parse(JSON.stringify(error)) };
|
|
235
|
+
} catch {
|
|
236
|
+
return { value: String(error) };
|
|
237
|
+
}
|
|
238
|
+
return { value: String(error) };
|
|
239
|
+
}
|
|
150
240
|
//#endregion
|
|
151
241
|
//#region src/core/git.ts
|
|
152
242
|
const NOT_GIT_REPOSITORY_MESSAGE = "This command must be run inside a Git repository. Change into a repo or run \"git init\" first.";
|
|
@@ -274,6 +364,7 @@ function setupRun(runId, prompt, baseCommit, cwd) {
|
|
|
274
364
|
writeFileSync(notesPath, `# fttm run: ${runId}\n\nObjective: ${prompt}\n\n## Iteration Log\n`, "utf-8");
|
|
275
365
|
const schemaPath = join(runDir, "output-schema.json");
|
|
276
366
|
writeSchemaFile(schemaPath);
|
|
367
|
+
const logPath = join(runDir, "debug.jsonl");
|
|
277
368
|
const baseCommitPath = join(runDir, "base-commit");
|
|
278
369
|
const hasStoredBaseCommit = existsSync(baseCommitPath);
|
|
279
370
|
const resolvedBaseCommit = hasStoredBaseCommit ? readFileSync(baseCommitPath, "utf-8").trim() : baseCommit;
|
|
@@ -284,6 +375,7 @@ function setupRun(runId, prompt, baseCommit, cwd) {
|
|
|
284
375
|
promptPath,
|
|
285
376
|
notesPath,
|
|
286
377
|
schemaPath,
|
|
378
|
+
logPath,
|
|
287
379
|
baseCommit: resolvedBaseCommit,
|
|
288
380
|
baseCommitPath
|
|
289
381
|
};
|
|
@@ -294,6 +386,7 @@ function resumeRun(runId, cwd) {
|
|
|
294
386
|
const promptPath = join(runDir, "prompt.md");
|
|
295
387
|
const notesPath = join(runDir, "notes.md");
|
|
296
388
|
const schemaPath = join(runDir, "output-schema.json");
|
|
389
|
+
const logPath = join(runDir, "debug.jsonl");
|
|
297
390
|
writeSchemaFile(schemaPath);
|
|
298
391
|
const baseCommitPath = join(runDir, "base-commit");
|
|
299
392
|
return {
|
|
@@ -302,6 +395,7 @@ function resumeRun(runId, cwd) {
|
|
|
302
395
|
promptPath,
|
|
303
396
|
notesPath,
|
|
304
397
|
schemaPath,
|
|
398
|
+
logPath,
|
|
305
399
|
baseCommit: existsSync(baseCommitPath) ? readFileSync(baseCommitPath, "utf-8").trim() : backfillLegacyBaseCommit(runId, baseCommitPath, cwd),
|
|
306
400
|
baseCommitPath
|
|
307
401
|
};
|
|
@@ -1199,6 +1293,14 @@ var OpenCodeAgent = class {
|
|
|
1199
1293
|
return await this.streamMessage(server, sessionId, buildPrompt(prompt), runController.signal, logStream, onUsage, onMessage);
|
|
1200
1294
|
} catch (error) {
|
|
1201
1295
|
if (runController.signal.aborted || isAbortError$1(error)) throw createAbortError$1();
|
|
1296
|
+
appendDebugLog("opencode:run:error", {
|
|
1297
|
+
sessionId,
|
|
1298
|
+
cwd,
|
|
1299
|
+
error: serializeError(error),
|
|
1300
|
+
serverClosed: this.server?.closed ?? true,
|
|
1301
|
+
serverStderr: this.server?.stderr.slice(-2048),
|
|
1302
|
+
serverStdout: this.server?.stdout.slice(-2048)
|
|
1303
|
+
});
|
|
1202
1304
|
throw error;
|
|
1203
1305
|
} finally {
|
|
1204
1306
|
signal?.removeEventListener("abort", onAbort);
|
|
@@ -1328,31 +1430,32 @@ var OpenCodeAgent = class {
|
|
|
1328
1430
|
let messageRequestError = null;
|
|
1329
1431
|
const messageRequest = (async () => {
|
|
1330
1432
|
try {
|
|
1433
|
+
await this.request(server, `/session/${sessionId}/prompt_async`, {
|
|
1434
|
+
method: "POST",
|
|
1435
|
+
body: {
|
|
1436
|
+
role: "user",
|
|
1437
|
+
parts: [{
|
|
1438
|
+
type: "text",
|
|
1439
|
+
text: prompt
|
|
1440
|
+
}],
|
|
1441
|
+
...this.model ? { model: (() => {
|
|
1442
|
+
const parts = this.model.split("/");
|
|
1443
|
+
if (parts.length === 2) return {
|
|
1444
|
+
providerID: parts[0],
|
|
1445
|
+
modelID: parts[1]
|
|
1446
|
+
};
|
|
1447
|
+
return {
|
|
1448
|
+
providerID: "opencode",
|
|
1449
|
+
modelID: this.model
|
|
1450
|
+
};
|
|
1451
|
+
})() } : {},
|
|
1452
|
+
format: STRUCTURED_OUTPUT_FORMAT
|
|
1453
|
+
},
|
|
1454
|
+
signal
|
|
1455
|
+
});
|
|
1331
1456
|
return {
|
|
1332
1457
|
ok: true,
|
|
1333
|
-
body:
|
|
1334
|
-
method: "POST",
|
|
1335
|
-
body: {
|
|
1336
|
-
role: "user",
|
|
1337
|
-
parts: [{
|
|
1338
|
-
type: "text",
|
|
1339
|
-
text: prompt
|
|
1340
|
-
}],
|
|
1341
|
-
...this.model ? { model: (() => {
|
|
1342
|
-
const parts = this.model.split("/");
|
|
1343
|
-
if (parts.length === 2) return {
|
|
1344
|
-
providerID: parts[0],
|
|
1345
|
-
modelID: parts[1]
|
|
1346
|
-
};
|
|
1347
|
-
return {
|
|
1348
|
-
providerID: "opencode",
|
|
1349
|
-
modelID: this.model
|
|
1350
|
-
};
|
|
1351
|
-
})() } : {},
|
|
1352
|
-
format: STRUCTURED_OUTPUT_FORMAT
|
|
1353
|
-
},
|
|
1354
|
-
signal
|
|
1355
|
-
})
|
|
1458
|
+
body: ""
|
|
1356
1459
|
};
|
|
1357
1460
|
} catch (error) {
|
|
1358
1461
|
messageRequestError = error;
|
|
@@ -1374,6 +1477,7 @@ var OpenCodeAgent = class {
|
|
|
1374
1477
|
let lastText = null;
|
|
1375
1478
|
let lastFinalAnswerText = null;
|
|
1376
1479
|
let lastUsageSignature = "0:0:0:0";
|
|
1480
|
+
let structuredOutputFromSSE = null;
|
|
1377
1481
|
const updateUsage = (messageId, tokens) => {
|
|
1378
1482
|
if (!messageId || !tokens) return;
|
|
1379
1483
|
usageByMessageId.set(messageId, toUsage(tokens));
|
|
@@ -1437,6 +1541,7 @@ var OpenCodeAgent = class {
|
|
|
1437
1541
|
}
|
|
1438
1542
|
if (payload?.type === "message.updated") {
|
|
1439
1543
|
if (properties.info?.role === "assistant") updateUsage(properties.info.id, properties.info.tokens);
|
|
1544
|
+
if (properties.info?.structured) structuredOutputFromSSE = properties.info.structured;
|
|
1440
1545
|
return false;
|
|
1441
1546
|
}
|
|
1442
1547
|
return payload?.type === "session.idle";
|
|
@@ -1513,21 +1618,13 @@ var OpenCodeAgent = class {
|
|
|
1513
1618
|
throw messageResult.error;
|
|
1514
1619
|
}
|
|
1515
1620
|
const body = messageResult.body;
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
response = JSON.parse(body);
|
|
1621
|
+
if (body) try {
|
|
1622
|
+
JSON.parse(body);
|
|
1519
1623
|
} catch (error) {
|
|
1520
1624
|
throw new Error(`Failed to parse opencode response: ${error instanceof Error ? error.message : String(error)}`);
|
|
1521
1625
|
}
|
|
1522
|
-
if (
|
|
1523
|
-
|
|
1524
|
-
if (part.type !== "text" || typeof part.text !== "string") continue;
|
|
1525
|
-
if (!part.text.trim()) continue;
|
|
1526
|
-
lastText = part.text;
|
|
1527
|
-
if (part.metadata?.openai?.phase === "final_answer") lastFinalAnswerText = part.text;
|
|
1528
|
-
}
|
|
1529
|
-
if (response.info?.structured) return {
|
|
1530
|
-
output: response.info.structured,
|
|
1626
|
+
if (structuredOutputFromSSE) return {
|
|
1627
|
+
output: structuredOutputFromSSE,
|
|
1531
1628
|
usage
|
|
1532
1629
|
};
|
|
1533
1630
|
const outputText = lastFinalAnswerText ?? lastText;
|
|
@@ -1592,12 +1689,24 @@ var OpenCodeAgent = class {
|
|
|
1592
1689
|
const headers = new Headers(options.headers);
|
|
1593
1690
|
if (options.body !== void 0) headers.set("content-type", "application/json");
|
|
1594
1691
|
const signal = withTimeoutSignal$1(options.signal, options.timeoutMs);
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1692
|
+
let response;
|
|
1693
|
+
try {
|
|
1694
|
+
response = await this.fetchFn(`${server.baseUrl}${path}`, {
|
|
1695
|
+
method: options.method,
|
|
1696
|
+
headers,
|
|
1697
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
1698
|
+
signal
|
|
1699
|
+
});
|
|
1700
|
+
} catch (error) {
|
|
1701
|
+
appendDebugLog("opencode:request:error", {
|
|
1702
|
+
method: options.method,
|
|
1703
|
+
path,
|
|
1704
|
+
timeoutMs: options.timeoutMs,
|
|
1705
|
+
error: serializeError(error),
|
|
1706
|
+
serverClosed: server.closed
|
|
1707
|
+
});
|
|
1708
|
+
throw error;
|
|
1709
|
+
}
|
|
1601
1710
|
if (!response.ok) {
|
|
1602
1711
|
const body = await response.text();
|
|
1603
1712
|
throw new Error(`opencode ${options.method} ${path} failed with ${response.status}: ${body}`);
|
|
@@ -1740,6 +1849,14 @@ var RovoDevAgent = class {
|
|
|
1740
1849
|
return await this.streamChat(server, sessionId, runController.signal, logStream, onUsage, onMessage);
|
|
1741
1850
|
} catch (error) {
|
|
1742
1851
|
if (runController.signal.aborted || isAbortError(error)) throw createAbortError();
|
|
1852
|
+
appendDebugLog("rovodev:run:error", {
|
|
1853
|
+
sessionId,
|
|
1854
|
+
cwd,
|
|
1855
|
+
error: serializeError(error),
|
|
1856
|
+
serverClosed: this.server?.closed ?? true,
|
|
1857
|
+
serverStderr: this.server?.stderr.slice(-2048),
|
|
1858
|
+
serverStdout: this.server?.stdout.slice(-2048)
|
|
1859
|
+
});
|
|
1743
1860
|
throw error;
|
|
1744
1861
|
} finally {
|
|
1745
1862
|
signal?.removeEventListener("abort", onAbort);
|
|
@@ -2070,12 +2187,24 @@ var RovoDevAgent = class {
|
|
|
2070
2187
|
if (options.sessionId) headers.set("x-session-id", options.sessionId);
|
|
2071
2188
|
if (options.body !== void 0 && !headers.has("content-type")) headers.set("content-type", "application/json");
|
|
2072
2189
|
const signal = withTimeoutSignal(options.signal, options.timeoutMs);
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2190
|
+
let response;
|
|
2191
|
+
try {
|
|
2192
|
+
response = await this.fetchFn(`${server.baseUrl}${path}`, {
|
|
2193
|
+
method: options.method,
|
|
2194
|
+
headers,
|
|
2195
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
2196
|
+
signal
|
|
2197
|
+
});
|
|
2198
|
+
} catch (error) {
|
|
2199
|
+
appendDebugLog("rovodev:request:error", {
|
|
2200
|
+
method: options.method,
|
|
2201
|
+
path,
|
|
2202
|
+
timeoutMs: options.timeoutMs,
|
|
2203
|
+
error: serializeError(error),
|
|
2204
|
+
serverClosed: server.closed
|
|
2205
|
+
});
|
|
2206
|
+
throw error;
|
|
2207
|
+
}
|
|
2079
2208
|
if (!response.ok) {
|
|
2080
2209
|
const body = await response.text();
|
|
2081
2210
|
throw new Error(`rovodev ${options.method} ${path} failed with ${response.status}: ${body}`);
|
|
@@ -2177,6 +2306,11 @@ var Orchestrator = class extends EventEmitter {
|
|
|
2177
2306
|
}
|
|
2178
2307
|
stop() {
|
|
2179
2308
|
this.stopRequested = true;
|
|
2309
|
+
appendDebugLog("orchestrator:stop-requested", {
|
|
2310
|
+
iteration: this.state.currentIteration,
|
|
2311
|
+
hasActiveIteration: this.activeIterationPromise !== null,
|
|
2312
|
+
loopDone: this.loopDone
|
|
2313
|
+
});
|
|
2180
2314
|
this.activeAbortController?.abort();
|
|
2181
2315
|
if (this.loopDone) {
|
|
2182
2316
|
this.emit("stopped");
|
|
@@ -2211,6 +2345,15 @@ var Orchestrator = class extends EventEmitter {
|
|
|
2211
2345
|
this.state.startTime = /* @__PURE__ */ new Date();
|
|
2212
2346
|
this.state.status = "running";
|
|
2213
2347
|
this.emit("state", this.getState());
|
|
2348
|
+
appendDebugLog("orchestrator:start", {
|
|
2349
|
+
agent: this.agent.name,
|
|
2350
|
+
runId: this.runInfo.runId,
|
|
2351
|
+
startIteration: this.state.currentIteration,
|
|
2352
|
+
maxIterations: this.limits.maxIterations,
|
|
2353
|
+
maxTokens: this.limits.maxTokens,
|
|
2354
|
+
maxConsecutiveFailures: this.config.maxConsecutiveFailures,
|
|
2355
|
+
initialCommitCount: this.state.commitCount
|
|
2356
|
+
});
|
|
2214
2357
|
try {
|
|
2215
2358
|
while (!this.stopRequested) {
|
|
2216
2359
|
const preIterationAbortReason = this.getPreIterationAbortReason();
|
|
@@ -2266,6 +2409,15 @@ var Orchestrator = class extends EventEmitter {
|
|
|
2266
2409
|
if (this.stopPromise) await this.stopPromise;
|
|
2267
2410
|
else await this.closeAgent();
|
|
2268
2411
|
this.loopDone = true;
|
|
2412
|
+
appendDebugLog("orchestrator:end", {
|
|
2413
|
+
status: this.state.status,
|
|
2414
|
+
iterations: this.state.currentIteration,
|
|
2415
|
+
successCount: this.state.successCount,
|
|
2416
|
+
failCount: this.state.failCount,
|
|
2417
|
+
totalInputTokens: this.state.totalInputTokens,
|
|
2418
|
+
totalOutputTokens: this.state.totalOutputTokens,
|
|
2419
|
+
commitCount: this.state.commitCount
|
|
2420
|
+
});
|
|
2269
2421
|
}
|
|
2270
2422
|
}
|
|
2271
2423
|
async runIteration(prompt) {
|
|
@@ -2288,6 +2440,12 @@ var Orchestrator = class extends EventEmitter {
|
|
|
2288
2440
|
this.emit("state", this.getState());
|
|
2289
2441
|
};
|
|
2290
2442
|
const logPath = join(this.runInfo.runDir, `iteration-${this.state.currentIteration}.jsonl`);
|
|
2443
|
+
const agentStartedAt = Date.now();
|
|
2444
|
+
appendDebugLog("agent:run:start", {
|
|
2445
|
+
iteration: this.state.currentIteration,
|
|
2446
|
+
agent: this.agent.name,
|
|
2447
|
+
logPath
|
|
2448
|
+
});
|
|
2291
2449
|
try {
|
|
2292
2450
|
const result = await this.agent.run(prompt, this.cwd, {
|
|
2293
2451
|
onUsage,
|
|
@@ -2295,6 +2453,15 @@ var Orchestrator = class extends EventEmitter {
|
|
|
2295
2453
|
signal: this.activeAbortController.signal,
|
|
2296
2454
|
logPath
|
|
2297
2455
|
});
|
|
2456
|
+
appendDebugLog("agent:run:end", {
|
|
2457
|
+
iteration: this.state.currentIteration,
|
|
2458
|
+
elapsedMs: Date.now() - agentStartedAt,
|
|
2459
|
+
success: result.output.success,
|
|
2460
|
+
inputTokens: result.usage.inputTokens,
|
|
2461
|
+
outputTokens: result.usage.outputTokens,
|
|
2462
|
+
cacheReadTokens: result.usage.cacheReadTokens,
|
|
2463
|
+
cacheCreationTokens: result.usage.cacheCreationTokens
|
|
2464
|
+
});
|
|
2298
2465
|
if (this.stopRequested) return { type: "stopped" };
|
|
2299
2466
|
if (result.output.success) return {
|
|
2300
2467
|
type: "completed",
|
|
@@ -2306,13 +2473,29 @@ var Orchestrator = class extends EventEmitter {
|
|
|
2306
2473
|
};
|
|
2307
2474
|
} catch (err) {
|
|
2308
2475
|
if (this.pendingAbortReason && err instanceof Error && err.message === "Agent was aborted") {
|
|
2476
|
+
appendDebugLog("agent:run:aborted", {
|
|
2477
|
+
iteration: this.state.currentIteration,
|
|
2478
|
+
elapsedMs: Date.now() - agentStartedAt,
|
|
2479
|
+
reason: this.pendingAbortReason
|
|
2480
|
+
});
|
|
2309
2481
|
resetHard(this.cwd);
|
|
2310
2482
|
return {
|
|
2311
2483
|
type: "aborted",
|
|
2312
2484
|
reason: this.pendingAbortReason
|
|
2313
2485
|
};
|
|
2314
2486
|
}
|
|
2315
|
-
if (this.stopRequested)
|
|
2487
|
+
if (this.stopRequested) {
|
|
2488
|
+
appendDebugLog("agent:run:stopped", {
|
|
2489
|
+
iteration: this.state.currentIteration,
|
|
2490
|
+
elapsedMs: Date.now() - agentStartedAt
|
|
2491
|
+
});
|
|
2492
|
+
return { type: "stopped" };
|
|
2493
|
+
}
|
|
2494
|
+
appendDebugLog("agent:run:error", {
|
|
2495
|
+
iteration: this.state.currentIteration,
|
|
2496
|
+
elapsedMs: Date.now() - agentStartedAt,
|
|
2497
|
+
error: serializeError(err)
|
|
2498
|
+
});
|
|
2316
2499
|
const summary = err instanceof Error ? err.message : String(err);
|
|
2317
2500
|
return {
|
|
2318
2501
|
type: "completed",
|
|
@@ -2387,13 +2570,20 @@ var Orchestrator = class extends EventEmitter {
|
|
|
2387
2570
|
this.state.status = "aborted";
|
|
2388
2571
|
this.state.lastMessage = reason;
|
|
2389
2572
|
this.state.waitingUntil = null;
|
|
2573
|
+
appendDebugLog("orchestrator:abort", {
|
|
2574
|
+
reason,
|
|
2575
|
+
iteration: this.state.currentIteration,
|
|
2576
|
+
consecutiveFailures: this.state.consecutiveFailures
|
|
2577
|
+
});
|
|
2390
2578
|
this.emit("abort", reason);
|
|
2391
2579
|
this.emit("state", this.getState());
|
|
2392
2580
|
}
|
|
2393
2581
|
async closeAgent() {
|
|
2394
2582
|
try {
|
|
2395
2583
|
await this.agent.close?.();
|
|
2396
|
-
} catch {
|
|
2584
|
+
} catch (err) {
|
|
2585
|
+
appendDebugLog("agent:close:error", { error: serializeError(err) });
|
|
2586
|
+
}
|
|
2397
2587
|
}
|
|
2398
2588
|
};
|
|
2399
2589
|
//#endregion
|
|
@@ -3310,7 +3500,22 @@ program.name("fttm").description("Fly to the moon, fly to the mars - AI agents f
|
|
|
3310
3500
|
if (!reexeced) persistedPrompt?.cleanup();
|
|
3311
3501
|
}
|
|
3312
3502
|
}
|
|
3313
|
-
|
|
3503
|
+
initDebugLog(runInfo.logPath);
|
|
3504
|
+
appendDebugLog("run:start", {
|
|
3505
|
+
args: process$1.argv.slice(2),
|
|
3506
|
+
runId: runInfo.runId,
|
|
3507
|
+
runDir: runInfo.runDir,
|
|
3508
|
+
agent: config.agent,
|
|
3509
|
+
promptLength: prompt.length,
|
|
3510
|
+
promptFromStdin,
|
|
3511
|
+
startIteration,
|
|
3512
|
+
maxIterations: options.maxIterations,
|
|
3513
|
+
maxTokens: options.maxTokens,
|
|
3514
|
+
preventSleep: config.preventSleep,
|
|
3515
|
+
platform: process$1.platform,
|
|
3516
|
+
nodeVersion: process$1.version,
|
|
3517
|
+
fttmVersion: packageVersion
|
|
3518
|
+
});
|
|
3314
3519
|
const orchestrator = new Orchestrator(config, createAgent(config.agent, runInfo, config.agentPathOverride[config.agent], options.model), runInfo, prompt, cwd, startIteration, {
|
|
3315
3520
|
maxIterations: options.maxIterations,
|
|
3316
3521
|
maxTokens: options.maxTokens,
|
|
@@ -3334,6 +3539,7 @@ program.name("fttm").description("Fly to the moon, fly to the mars - AI agents f
|
|
|
3334
3539
|
const orchestratorPromise = orchestrator.start().finally(() => {
|
|
3335
3540
|
if (!(orchestrator.getState().status === "aborted" && process$1.stdin.isTTY)) renderer.stop();
|
|
3336
3541
|
}).catch((err) => {
|
|
3542
|
+
appendDebugLog("orchestrator:fatal", { error: serializeError(err) });
|
|
3337
3543
|
exitAltScreen();
|
|
3338
3544
|
die(err instanceof Error ? err.message : String(err));
|
|
3339
3545
|
});
|
|
@@ -3355,7 +3561,19 @@ program.name("fttm").description("Fly to the moon, fly to the mars - AI agents f
|
|
|
3355
3561
|
process$1.off("SIGTERM", handleSigTerm);
|
|
3356
3562
|
await sleepPreventionCleanup?.();
|
|
3357
3563
|
}
|
|
3358
|
-
|
|
3564
|
+
{
|
|
3565
|
+
const finalState = orchestrator.getState();
|
|
3566
|
+
appendDebugLog("run:complete", {
|
|
3567
|
+
signal: shutdownSignal,
|
|
3568
|
+
status: finalState.status,
|
|
3569
|
+
iterations: finalState.currentIteration,
|
|
3570
|
+
successCount: finalState.successCount,
|
|
3571
|
+
failCount: finalState.failCount,
|
|
3572
|
+
totalInputTokens: finalState.totalInputTokens,
|
|
3573
|
+
totalOutputTokens: finalState.totalOutputTokens,
|
|
3574
|
+
commitCount: finalState.commitCount
|
|
3575
|
+
});
|
|
3576
|
+
}
|
|
3359
3577
|
if (shutdownSignal) process$1.exit(getSignalExitCode(shutdownSignal));
|
|
3360
3578
|
});
|
|
3361
3579
|
function enterAltScreen() {
|