executant 1.10.0 → 1.10.1
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/index.js +121 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -887,7 +887,7 @@ init_update();
|
|
|
887
887
|
|
|
888
888
|
// src/ui/App.tsx
|
|
889
889
|
import { useEffect as useEffect2, useReducer, useState } from "react";
|
|
890
|
-
import { Box as Box5, Text as Text5, useApp, useStdin } from "ink";
|
|
890
|
+
import { Box as Box5, Text as Text5, useApp, useStdin, useStdout } from "ink";
|
|
891
891
|
|
|
892
892
|
// src/ui/KeyboardHandler.tsx
|
|
893
893
|
import { useInput } from "ink";
|
|
@@ -1022,7 +1022,7 @@ function reducer(state, event) {
|
|
|
1022
1022
|
case "output:text": {
|
|
1023
1023
|
const idx = event.index;
|
|
1024
1024
|
if (idx >= state.tasks.length) return state;
|
|
1025
|
-
return
|
|
1025
|
+
return appendLines(state, idx, event.text);
|
|
1026
1026
|
}
|
|
1027
1027
|
case "output:tool": {
|
|
1028
1028
|
const idx = event.index;
|
|
@@ -1046,7 +1046,7 @@ function reducer(state, event) {
|
|
|
1046
1046
|
case "log": {
|
|
1047
1047
|
const idx = state.currentIndex;
|
|
1048
1048
|
if (idx >= state.tasks.length) return state;
|
|
1049
|
-
return
|
|
1049
|
+
return appendLines(state, idx, `[${event.level}] ${event.text}`);
|
|
1050
1050
|
}
|
|
1051
1051
|
default: {
|
|
1052
1052
|
const _ = event;
|
|
@@ -1055,6 +1055,11 @@ function reducer(state, event) {
|
|
|
1055
1055
|
}
|
|
1056
1056
|
}
|
|
1057
1057
|
}
|
|
1058
|
+
var ANSI_RE2 = /\x1B(?:\[[0-9;?]*[A-Za-z]|\][^\x07]*\x07)|[\r]/g;
|
|
1059
|
+
var MAX_LOG_LINES = 300;
|
|
1060
|
+
function normalizeLines(text) {
|
|
1061
|
+
return text.replace(ANSI_RE2, "").split("\n");
|
|
1062
|
+
}
|
|
1058
1063
|
function updateTask(state, index, patch) {
|
|
1059
1064
|
const tasks = state.tasks.map(
|
|
1060
1065
|
(t, i) => i === index ? { ...t, ...patch } : t
|
|
@@ -1062,9 +1067,14 @@ function updateTask(state, index, patch) {
|
|
|
1062
1067
|
return { ...state, tasks };
|
|
1063
1068
|
}
|
|
1064
1069
|
function appendLine(state, index, line) {
|
|
1070
|
+
return appendLines(state, index, line);
|
|
1071
|
+
}
|
|
1072
|
+
function appendLines(state, index, text) {
|
|
1073
|
+
const newLines = normalizeLines(text);
|
|
1065
1074
|
const tasks = state.tasks.map((t, i) => {
|
|
1066
1075
|
if (i !== index) return t;
|
|
1067
|
-
const
|
|
1076
|
+
const combined = [...t.lines, ...newLines];
|
|
1077
|
+
const lines = combined.length > MAX_LOG_LINES ? combined.slice(-MAX_LOG_LINES) : combined;
|
|
1068
1078
|
return { ...t, lines };
|
|
1069
1079
|
});
|
|
1070
1080
|
return { ...state, tasks };
|
|
@@ -1222,14 +1232,24 @@ function LogPane({ lines, isActive = false, maxLines = 15 }) {
|
|
|
1222
1232
|
if (visible.length === 0) {
|
|
1223
1233
|
return /* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: isActive ? "\u2838 waiting for output\u2026" : "\u2014 no output yet \u2014" }) });
|
|
1224
1234
|
}
|
|
1225
|
-
return /* @__PURE__ */ jsx3(
|
|
1226
|
-
|
|
1235
|
+
return /* @__PURE__ */ jsx3(
|
|
1236
|
+
Box3,
|
|
1227
1237
|
{
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1238
|
+
flexDirection: "column",
|
|
1239
|
+
marginTop: 1,
|
|
1240
|
+
borderStyle: "single",
|
|
1241
|
+
borderColor: theme.border,
|
|
1242
|
+
paddingX: 1,
|
|
1243
|
+
children: visible.map((line, i) => /* @__PURE__ */ jsx3(
|
|
1244
|
+
LogLine,
|
|
1245
|
+
{
|
|
1246
|
+
text: line,
|
|
1247
|
+
cursor: isActive && i === visible.length - 1
|
|
1248
|
+
},
|
|
1249
|
+
i
|
|
1250
|
+
))
|
|
1251
|
+
}
|
|
1252
|
+
);
|
|
1233
1253
|
}
|
|
1234
1254
|
function LogLine({ text, cursor }) {
|
|
1235
1255
|
const suffix = cursor ? /* @__PURE__ */ jsx3(Text3, { color: theme.primary, children: " \u258C" }) : null;
|
|
@@ -1242,18 +1262,41 @@ function LogLine({ text, cursor }) {
|
|
|
1242
1262
|
suffix
|
|
1243
1263
|
] });
|
|
1244
1264
|
}
|
|
1245
|
-
if (/^\s*\$\s/.test(text))
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1265
|
+
if (/^\s*\$\s/.test(text))
|
|
1266
|
+
return /* @__PURE__ */ jsxs3(Text3, { color: theme.warning, children: [
|
|
1267
|
+
text,
|
|
1268
|
+
suffix
|
|
1269
|
+
] });
|
|
1270
|
+
if (text.startsWith("[warn]"))
|
|
1271
|
+
return /* @__PURE__ */ jsxs3(Text3, { color: theme.warning, children: [
|
|
1272
|
+
text,
|
|
1273
|
+
suffix
|
|
1274
|
+
] });
|
|
1275
|
+
if (text.startsWith("[error]"))
|
|
1276
|
+
return /* @__PURE__ */ jsxs3(Text3, { color: theme.error, children: [
|
|
1277
|
+
text,
|
|
1278
|
+
suffix
|
|
1279
|
+
] });
|
|
1280
|
+
if (/^[\s]*(✓|✔|✅|done|success|compiled|built|passed)/i.test(text) && !/\b(error|fail|failed|warn|warning)\b/i.test(text))
|
|
1281
|
+
return /* @__PURE__ */ jsxs3(Text3, { color: theme.success, children: [
|
|
1282
|
+
text,
|
|
1283
|
+
suffix
|
|
1284
|
+
] });
|
|
1285
|
+
if (/\b(error|failed|fail)\b/i.test(text))
|
|
1286
|
+
return /* @__PURE__ */ jsxs3(Text3, { color: theme.error, children: [
|
|
1287
|
+
text,
|
|
1288
|
+
suffix
|
|
1289
|
+
] });
|
|
1290
|
+
if (/\b(warn|warning)\b/i.test(text))
|
|
1291
|
+
return /* @__PURE__ */ jsxs3(Text3, { color: theme.warning, children: [
|
|
1292
|
+
text,
|
|
1293
|
+
suffix
|
|
1294
|
+
] });
|
|
1295
|
+
if (/^[·…⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/.test(text))
|
|
1296
|
+
return /* @__PURE__ */ jsxs3(Text3, { color: theme.muted, children: [
|
|
1297
|
+
text,
|
|
1298
|
+
suffix
|
|
1299
|
+
] });
|
|
1257
1300
|
return /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1258
1301
|
text,
|
|
1259
1302
|
suffix
|
|
@@ -1324,6 +1367,13 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1324
1367
|
};
|
|
1325
1368
|
}, [events2, exit]);
|
|
1326
1369
|
const { isRawModeSupported } = useStdin();
|
|
1370
|
+
const { stdout } = useStdout();
|
|
1371
|
+
const terminalRows = stdout?.rows ?? 24;
|
|
1372
|
+
const FIXED_OVERHEAD = 12;
|
|
1373
|
+
const logPaneMaxLines = Math.max(
|
|
1374
|
+
5,
|
|
1375
|
+
terminalRows - FIXED_OVERHEAD - state.tasks.length
|
|
1376
|
+
);
|
|
1327
1377
|
const [tick, setTick] = useState(0);
|
|
1328
1378
|
useInterval(() => {
|
|
1329
1379
|
if (!state.endTime) setTick((t) => t + 1);
|
|
@@ -1376,7 +1426,8 @@ function App({ workflow: workflow2, events: events2, options: options2, updateCh
|
|
|
1376
1426
|
LogPane,
|
|
1377
1427
|
{
|
|
1378
1428
|
lines: activeTask.lines,
|
|
1379
|
-
isActive: activeTask.status === "running"
|
|
1429
|
+
isActive: activeTask.status === "running",
|
|
1430
|
+
maxLines: logPaneMaxLines
|
|
1380
1431
|
}
|
|
1381
1432
|
),
|
|
1382
1433
|
state.endTime !== void 0 && state.writtenFiles.length > 0 && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -2330,7 +2381,13 @@ async function* withLogger(gen, logger2) {
|
|
|
2330
2381
|
}
|
|
2331
2382
|
|
|
2332
2383
|
// src/retrospective.ts
|
|
2333
|
-
import {
|
|
2384
|
+
import {
|
|
2385
|
+
existsSync as existsSync3,
|
|
2386
|
+
mkdirSync as mkdirSync4,
|
|
2387
|
+
readdirSync as readdirSync2,
|
|
2388
|
+
readFileSync as readFileSync5,
|
|
2389
|
+
writeFileSync as writeFileSync4
|
|
2390
|
+
} from "node:fs";
|
|
2334
2391
|
import { basename as basename2, dirname as dirname4, join as join4, resolve as resolve3 } from "node:path";
|
|
2335
2392
|
import { spawnSync } from "node:child_process";
|
|
2336
2393
|
import { load as parseYaml2 } from "js-yaml";
|
|
@@ -2342,10 +2399,17 @@ var RetrospectiveOutputSchema = z4.object({
|
|
|
2342
2399
|
var RETROSPECTIVE_PROMPT = loadPrompt("retrospective-analysis");
|
|
2343
2400
|
async function runRetrospective(workflowFilePath, workflow2, highlightsDir, runTimestamp) {
|
|
2344
2401
|
try {
|
|
2345
|
-
await doRetrospective(
|
|
2402
|
+
await doRetrospective(
|
|
2403
|
+
workflowFilePath,
|
|
2404
|
+
workflow2,
|
|
2405
|
+
highlightsDir,
|
|
2406
|
+
runTimestamp
|
|
2407
|
+
);
|
|
2346
2408
|
} catch (err) {
|
|
2347
|
-
console.warn(
|
|
2348
|
-
|
|
2409
|
+
console.warn(
|
|
2410
|
+
`
|
|
2411
|
+
Self-improvement: retrospective failed: ${getErrorMessage(err)}`
|
|
2412
|
+
);
|
|
2349
2413
|
}
|
|
2350
2414
|
}
|
|
2351
2415
|
async function doRetrospective(workflowFilePath, workflow2, highlightsDir, runTimestamp) {
|
|
@@ -2356,13 +2420,17 @@ async function doRetrospective(workflowFilePath, workflow2, highlightsDir, runTi
|
|
|
2356
2420
|
const allFiles = readdirSync2(highlightsDir);
|
|
2357
2421
|
const runHighlights = allFiles.filter((f) => f.startsWith(runTimestamp) && f.endsWith(".md")).sort();
|
|
2358
2422
|
if (runHighlights.length === 0) {
|
|
2359
|
-
console.log(
|
|
2423
|
+
console.log(
|
|
2424
|
+
"\nSelf-improvement: no highlights for this run \u2014 task completed without issues, skipping."
|
|
2425
|
+
);
|
|
2360
2426
|
return;
|
|
2361
2427
|
}
|
|
2362
2428
|
const divider = "\u2501".repeat(51);
|
|
2363
2429
|
console.log(`
|
|
2364
2430
|
${divider}`);
|
|
2365
|
-
console.log(
|
|
2431
|
+
console.log(
|
|
2432
|
+
"Self-Improvement: Analyzing execution and generating improvements..."
|
|
2433
|
+
);
|
|
2366
2434
|
console.log(`${divider}
|
|
2367
2435
|
`);
|
|
2368
2436
|
console.log(`Found ${runHighlights.length} highlight(s) to analyze`);
|
|
@@ -2408,15 +2476,23 @@ ${content}`;
|
|
|
2408
2476
|
"--output-format",
|
|
2409
2477
|
"text"
|
|
2410
2478
|
],
|
|
2411
|
-
{
|
|
2479
|
+
{
|
|
2480
|
+
encoding: "utf8",
|
|
2481
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
2482
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
2483
|
+
}
|
|
2412
2484
|
);
|
|
2413
2485
|
if (result.error) {
|
|
2414
|
-
console.warn(
|
|
2486
|
+
console.warn(
|
|
2487
|
+
`Self-improvement: failed to run claude: ${result.error.message}`
|
|
2488
|
+
);
|
|
2415
2489
|
return;
|
|
2416
2490
|
}
|
|
2417
2491
|
if (result.status !== 0) {
|
|
2418
2492
|
const stderr = result.stderr ?? "";
|
|
2419
|
-
console.warn(
|
|
2493
|
+
console.warn(
|
|
2494
|
+
`Self-improvement: claude exited with code ${result.status}${stderr ? ": " + stderr : ""}`
|
|
2495
|
+
);
|
|
2420
2496
|
return;
|
|
2421
2497
|
}
|
|
2422
2498
|
const response = result.stdout ?? "";
|
|
@@ -2424,13 +2500,17 @@ ${content}`;
|
|
|
2424
2500
|
try {
|
|
2425
2501
|
parsed = JSON.parse(extractJson(response));
|
|
2426
2502
|
} catch {
|
|
2427
|
-
console.warn(
|
|
2428
|
-
|
|
2503
|
+
console.warn(
|
|
2504
|
+
`Self-improvement: could not parse Claude response as JSON.
|
|
2505
|
+
Response: ${response.trim()}`
|
|
2506
|
+
);
|
|
2429
2507
|
return;
|
|
2430
2508
|
}
|
|
2431
2509
|
const zodResult = RetrospectiveOutputSchema.safeParse(parsed);
|
|
2432
2510
|
if (!zodResult.success) {
|
|
2433
|
-
console.warn(
|
|
2511
|
+
console.warn(
|
|
2512
|
+
"Self-improvement: response schema mismatch \u2014 improved YAML not saved."
|
|
2513
|
+
);
|
|
2434
2514
|
return;
|
|
2435
2515
|
}
|
|
2436
2516
|
const improvedYaml = zodResult.data.improved_yaml.trim();
|
|
@@ -2438,7 +2518,9 @@ Response: ${response.trim()}`);
|
|
|
2438
2518
|
try {
|
|
2439
2519
|
parseYaml2(improvedYaml);
|
|
2440
2520
|
} catch (err) {
|
|
2441
|
-
console.warn(
|
|
2521
|
+
console.warn(
|
|
2522
|
+
`Self-improvement: generated YAML is invalid (${getErrorMessage(err)}), skipping save.`
|
|
2523
|
+
);
|
|
2442
2524
|
return;
|
|
2443
2525
|
}
|
|
2444
2526
|
const startDir = dirname4(resolve3(workflowFilePath));
|
|
@@ -2463,7 +2545,8 @@ ${divider}`);
|
|
|
2463
2545
|
function extractJson(text) {
|
|
2464
2546
|
const start = text.indexOf("{");
|
|
2465
2547
|
const end = text.lastIndexOf("}");
|
|
2466
|
-
if (start === -1 || end === -1 || end <= start)
|
|
2548
|
+
if (start === -1 || end === -1 || end <= start)
|
|
2549
|
+
throw new Error("no JSON object found in response");
|
|
2467
2550
|
return text.slice(start, end + 1);
|
|
2468
2551
|
}
|
|
2469
2552
|
|