codeharness 0.31.2 → 0.31.3
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.
|
@@ -2895,7 +2895,7 @@ function generateDockerfileTemplate(projectDir, stackOrDetections) {
|
|
|
2895
2895
|
}
|
|
2896
2896
|
|
|
2897
2897
|
// src/modules/infra/init-project.ts
|
|
2898
|
-
var HARNESS_VERSION = true ? "0.31.
|
|
2898
|
+
var HARNESS_VERSION = true ? "0.31.3" : "0.0.0-dev";
|
|
2899
2899
|
function failResult(opts, error) {
|
|
2900
2900
|
return {
|
|
2901
2901
|
status: "fail",
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
validateDockerfile,
|
|
41
41
|
warn,
|
|
42
42
|
writeState
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-A4ECRBVK.js";
|
|
44
44
|
|
|
45
45
|
// src/index.ts
|
|
46
46
|
import { Command } from "commander";
|
|
@@ -5036,6 +5036,13 @@ function StoryMessageLine({ msg }) {
|
|
|
5036
5036
|
] });
|
|
5037
5037
|
}
|
|
5038
5038
|
function CompletedTool({ entry }) {
|
|
5039
|
+
if (entry.isText) {
|
|
5040
|
+
const text = entry.args.length > 80 ? entry.args.slice(0, 80) + "\u2026" : entry.args;
|
|
5041
|
+
return /* @__PURE__ */ jsxs(Text, { wrap: "truncate-end", children: [
|
|
5042
|
+
/* @__PURE__ */ jsx(Text, { children: "\u{1F4AD} " }),
|
|
5043
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: text })
|
|
5044
|
+
] });
|
|
5045
|
+
}
|
|
5039
5046
|
const argsSummary = entry.args.length > 60 ? entry.args.slice(0, 60) + "\u2026" : entry.args;
|
|
5040
5047
|
return /* @__PURE__ */ jsxs(Text, { wrap: "truncate-end", children: [
|
|
5041
5048
|
/* @__PURE__ */ jsx(Text, { color: "green", children: "\u2713 " }),
|
|
@@ -5188,11 +5195,14 @@ function WorkflowGraph({ flow, currentTask, taskStates, taskMeta }) {
|
|
|
5188
5195
|
for (let j = 0; j < loopBlock.loop.length; j++) {
|
|
5189
5196
|
if (j > 0) elements2.push(/* @__PURE__ */ jsx2(Text2, { children: " \u2192 " }, `la-${j}`));
|
|
5190
5197
|
const tn = loopBlock.loop[j];
|
|
5198
|
+
const loopKey = `loop:${tn}`;
|
|
5199
|
+
const status = taskStates[loopKey] ?? taskStates[tn];
|
|
5200
|
+
const driver = meta[loopKey]?.driver ?? meta[tn]?.driver;
|
|
5191
5201
|
elements2.push(
|
|
5192
|
-
/* @__PURE__ */ jsx2(TaskNode, { name: tn, status
|
|
5202
|
+
/* @__PURE__ */ jsx2(TaskNode, { name: tn, status, spinnerFrame, driver }, `lt-${j}`)
|
|
5193
5203
|
);
|
|
5194
5204
|
}
|
|
5195
|
-
const loopDone = loopBlock.loop.every((t) => taskStates[t] === "done");
|
|
5205
|
+
const loopDone = loopBlock.loop.every((t) => (taskStates[`loop:${t}`] ?? taskStates[t]) === "done");
|
|
5196
5206
|
if (loopDone) {
|
|
5197
5207
|
let afterLoop = false;
|
|
5198
5208
|
for (const step of flow) {
|
|
@@ -5821,6 +5831,11 @@ function startRenderer(options) {
|
|
|
5821
5831
|
}
|
|
5822
5832
|
break;
|
|
5823
5833
|
case "text":
|
|
5834
|
+
if (state.lastThought) {
|
|
5835
|
+
const textEntry = { name: "", args: state.lastThought, isText: true };
|
|
5836
|
+
const updated = [...state.completedTools, textEntry];
|
|
5837
|
+
state.completedTools = updated.length > MAX_COMPLETED_TOOLS ? updated.slice(updated.length - MAX_COMPLETED_TOOLS) : updated;
|
|
5838
|
+
}
|
|
5824
5839
|
state.lastThought = event.text;
|
|
5825
5840
|
state.retryInfo = null;
|
|
5826
5841
|
break;
|
|
@@ -6251,11 +6266,32 @@ function registerRunCommand(program) {
|
|
|
6251
6266
|
epicData[epicId] = { storiesDone: epic.storiesDone ?? 0, storiesTotal: epic.storiesTotal ?? 0 };
|
|
6252
6267
|
}
|
|
6253
6268
|
}
|
|
6269
|
+
const preLoopTasks = /* @__PURE__ */ new Set();
|
|
6270
|
+
const loopTasks = /* @__PURE__ */ new Set();
|
|
6271
|
+
for (const step of parsedWorkflow.flow) {
|
|
6272
|
+
if (typeof step === "string") {
|
|
6273
|
+
preLoopTasks.add(step);
|
|
6274
|
+
} else if (typeof step === "object" && "loop" in step) {
|
|
6275
|
+
for (const lt of step.loop) loopTasks.add(lt);
|
|
6276
|
+
}
|
|
6277
|
+
}
|
|
6278
|
+
let pastLoop = false;
|
|
6279
|
+
for (const step of parsedWorkflow.flow) {
|
|
6280
|
+
if (typeof step === "object" && "loop" in step) {
|
|
6281
|
+
pastLoop = true;
|
|
6282
|
+
continue;
|
|
6283
|
+
}
|
|
6284
|
+
if (pastLoop && typeof step === "string") preLoopTasks.add(step);
|
|
6285
|
+
}
|
|
6286
|
+
let inLoop = false;
|
|
6254
6287
|
const taskStates = {};
|
|
6255
6288
|
const taskMeta = {};
|
|
6256
6289
|
for (const [tn, task] of Object.entries(parsedWorkflow.tasks)) {
|
|
6257
6290
|
taskStates[tn] = "pending";
|
|
6258
|
-
|
|
6291
|
+
if (loopTasks.has(tn)) taskStates[`loop:${tn}`] = "pending";
|
|
6292
|
+
const driverLabel2 = task.model ?? task.driver ?? "claude-code";
|
|
6293
|
+
taskMeta[tn] = { driver: driverLabel2 };
|
|
6294
|
+
if (loopTasks.has(tn)) taskMeta[`loop:${tn}`] = { driver: driverLabel2 };
|
|
6259
6295
|
}
|
|
6260
6296
|
const storyEntries = [];
|
|
6261
6297
|
for (const [key, status] of Object.entries(statuses)) {
|
|
@@ -6271,8 +6307,18 @@ function registerRunCommand(program) {
|
|
|
6271
6307
|
renderer.update(event.streamEvent, event.driverName);
|
|
6272
6308
|
}
|
|
6273
6309
|
if (event.type === "dispatch-start") {
|
|
6310
|
+
if (event.storyKey !== currentStoryKey && preLoopTasks.has(event.taskName)) {
|
|
6311
|
+
inLoop = false;
|
|
6312
|
+
for (const tn of Object.keys(taskStates)) {
|
|
6313
|
+
taskStates[tn] = "pending";
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6274
6316
|
currentStoryKey = event.storyKey;
|
|
6275
6317
|
currentTaskName = event.taskName;
|
|
6318
|
+
if (loopTasks.has(event.taskName) && taskStates[event.taskName] === "done") {
|
|
6319
|
+
inLoop = true;
|
|
6320
|
+
}
|
|
6321
|
+
const stateKey = inLoop && loopTasks.has(event.taskName) ? `loop:${event.taskName}` : event.taskName;
|
|
6276
6322
|
const epicId = extractEpicId2(event.storyKey);
|
|
6277
6323
|
const epic = epicData[epicId];
|
|
6278
6324
|
renderer.updateSprintState({
|
|
@@ -6286,7 +6332,7 @@ function registerRunCommand(program) {
|
|
|
6286
6332
|
epicStoriesDone: epic?.storiesDone ?? 0,
|
|
6287
6333
|
epicStoriesTotal: epic?.storiesTotal ?? 0
|
|
6288
6334
|
});
|
|
6289
|
-
taskStates[
|
|
6335
|
+
taskStates[stateKey] = "active";
|
|
6290
6336
|
renderer.updateWorkflowState(parsedWorkflow.flow, event.taskName, { ...taskStates }, { ...taskMeta });
|
|
6291
6337
|
const idx = storyEntries.findIndex((s) => s.key === event.storyKey);
|
|
6292
6338
|
if (idx >= 0 && storyEntries[idx].status === "pending") {
|
|
@@ -6296,11 +6342,12 @@ function registerRunCommand(program) {
|
|
|
6296
6342
|
}
|
|
6297
6343
|
if (event.type === "dispatch-end") {
|
|
6298
6344
|
totalCostUsd += event.costUsd ?? 0;
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6345
|
+
const stateKey = inLoop && loopTasks.has(event.taskName) ? `loop:${event.taskName}` : event.taskName;
|
|
6346
|
+
taskStates[stateKey] = "done";
|
|
6347
|
+
taskMeta[stateKey] = {
|
|
6348
|
+
...taskMeta[stateKey],
|
|
6349
|
+
costUsd: (taskMeta[stateKey]?.costUsd ?? 0) + (event.costUsd ?? 0),
|
|
6350
|
+
elapsedMs: (taskMeta[stateKey]?.elapsedMs ?? 0) + (event.elapsedMs ?? 0)
|
|
6304
6351
|
};
|
|
6305
6352
|
renderer.updateWorkflowState(parsedWorkflow.flow, event.taskName, { ...taskStates }, { ...taskMeta });
|
|
6306
6353
|
renderer.updateSprintState({
|
|
@@ -6312,7 +6359,8 @@ function registerRunCommand(program) {
|
|
|
6312
6359
|
});
|
|
6313
6360
|
}
|
|
6314
6361
|
if (event.type === "dispatch-error") {
|
|
6315
|
-
|
|
6362
|
+
const stateKey = inLoop && loopTasks.has(event.taskName) ? `loop:${event.taskName}` : event.taskName;
|
|
6363
|
+
taskStates[stateKey] = "failed";
|
|
6316
6364
|
renderer.updateWorkflowState(parsedWorkflow.flow, event.taskName, { ...taskStates }, { ...taskMeta });
|
|
6317
6365
|
renderer.addMessage({
|
|
6318
6366
|
type: "fail",
|
|
@@ -11211,7 +11259,7 @@ function registerTeardownCommand(program) {
|
|
|
11211
11259
|
} else if (otlpMode === "remote-routed") {
|
|
11212
11260
|
if (!options.keepDocker) {
|
|
11213
11261
|
try {
|
|
11214
|
-
const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-
|
|
11262
|
+
const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-A35UFVYH.js");
|
|
11215
11263
|
stopCollectorOnly2();
|
|
11216
11264
|
result.docker.stopped = true;
|
|
11217
11265
|
if (!isJson) {
|
|
@@ -11243,7 +11291,7 @@ function registerTeardownCommand(program) {
|
|
|
11243
11291
|
info("Shared stack: kept running (other projects may use it)");
|
|
11244
11292
|
}
|
|
11245
11293
|
} else if (isLegacyStack) {
|
|
11246
|
-
const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-
|
|
11294
|
+
const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-A35UFVYH.js");
|
|
11247
11295
|
let stackRunning = false;
|
|
11248
11296
|
try {
|
|
11249
11297
|
stackRunning = isStackRunning2(composeFile);
|
|
@@ -13683,6 +13731,68 @@ function classifyError2(err) {
|
|
|
13683
13731
|
}
|
|
13684
13732
|
return "UNKNOWN";
|
|
13685
13733
|
}
|
|
13734
|
+
function parseLineMulti(line) {
|
|
13735
|
+
const trimmed = line.trim();
|
|
13736
|
+
if (trimmed.length === 0) return [];
|
|
13737
|
+
let parsed;
|
|
13738
|
+
try {
|
|
13739
|
+
parsed = JSON.parse(trimmed);
|
|
13740
|
+
} catch {
|
|
13741
|
+
return [];
|
|
13742
|
+
}
|
|
13743
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return [];
|
|
13744
|
+
const type = parsed.type;
|
|
13745
|
+
const item = parsed.item;
|
|
13746
|
+
if (type === "item.started" && item) {
|
|
13747
|
+
const itemType = item.type;
|
|
13748
|
+
if (itemType === "command_execution") {
|
|
13749
|
+
const cmd = item.command ?? "";
|
|
13750
|
+
return [
|
|
13751
|
+
{ type: "tool-start", name: "Bash", id: item.id ?? "" },
|
|
13752
|
+
{ type: "tool-input", partial: cmd }
|
|
13753
|
+
];
|
|
13754
|
+
}
|
|
13755
|
+
if (itemType === "file_edit") {
|
|
13756
|
+
const path = item.file_path ?? item.path ?? "";
|
|
13757
|
+
return [
|
|
13758
|
+
{ type: "tool-start", name: "Edit", id: item.id ?? "" },
|
|
13759
|
+
{ type: "tool-input", partial: path }
|
|
13760
|
+
];
|
|
13761
|
+
}
|
|
13762
|
+
if (itemType === "file_read") {
|
|
13763
|
+
const path = item.file_path ?? item.path ?? "";
|
|
13764
|
+
return [
|
|
13765
|
+
{ type: "tool-start", name: "Read", id: item.id ?? "" },
|
|
13766
|
+
{ type: "tool-input", partial: path }
|
|
13767
|
+
];
|
|
13768
|
+
}
|
|
13769
|
+
return [];
|
|
13770
|
+
}
|
|
13771
|
+
if (type === "item.completed" && item) {
|
|
13772
|
+
const itemType = item.type;
|
|
13773
|
+
if (itemType === "command_execution") return [{ type: "tool-complete" }];
|
|
13774
|
+
if (itemType === "agent_message") {
|
|
13775
|
+
const text = item.text;
|
|
13776
|
+
return text ? [{ type: "text", text }] : [];
|
|
13777
|
+
}
|
|
13778
|
+
if (itemType === "file_edit" || itemType === "file_read") return [{ type: "tool-complete" }];
|
|
13779
|
+
return [];
|
|
13780
|
+
}
|
|
13781
|
+
if (type === "turn.completed") {
|
|
13782
|
+
const usage = parsed.usage;
|
|
13783
|
+
if (usage) {
|
|
13784
|
+
return [{
|
|
13785
|
+
type: "result",
|
|
13786
|
+
cost: 0,
|
|
13787
|
+
sessionId: "",
|
|
13788
|
+
cost_usd: null
|
|
13789
|
+
}];
|
|
13790
|
+
}
|
|
13791
|
+
return [];
|
|
13792
|
+
}
|
|
13793
|
+
const legacy = parseLine(line);
|
|
13794
|
+
return legacy ? [legacy] : [];
|
|
13795
|
+
}
|
|
13686
13796
|
function parseLine(line) {
|
|
13687
13797
|
const trimmed = line.trim();
|
|
13688
13798
|
if (trimmed.length === 0) return null;
|
|
@@ -13814,7 +13924,7 @@ var CodexDriver = class {
|
|
|
13814
13924
|
opts.plugins
|
|
13815
13925
|
);
|
|
13816
13926
|
}
|
|
13817
|
-
const args = ["exec", "--json"];
|
|
13927
|
+
const args = ["exec", "--json", "--full-auto"];
|
|
13818
13928
|
const model = opts.model && !opts.model.startsWith("claude-") ? opts.model : void 0;
|
|
13819
13929
|
if (model) {
|
|
13820
13930
|
args.push("--model", model);
|
|
@@ -13845,8 +13955,8 @@ var CodexDriver = class {
|
|
|
13845
13955
|
});
|
|
13846
13956
|
try {
|
|
13847
13957
|
for await (const line of rl) {
|
|
13848
|
-
const
|
|
13849
|
-
|
|
13958
|
+
const events = parseLineMulti(line);
|
|
13959
|
+
for (const event of events) {
|
|
13850
13960
|
if (event.type === "result") {
|
|
13851
13961
|
const resultEvent = event;
|
|
13852
13962
|
if (typeof resultEvent.cost_usd === "number") {
|
|
@@ -13857,8 +13967,6 @@ var CodexDriver = class {
|
|
|
13857
13967
|
} else {
|
|
13858
13968
|
yield event;
|
|
13859
13969
|
}
|
|
13860
|
-
} else {
|
|
13861
|
-
console.debug("[CodexDriver] Skipping unparseable line:", line);
|
|
13862
13970
|
}
|
|
13863
13971
|
}
|
|
13864
13972
|
const exitCode = await closePromise;
|
|
@@ -14170,7 +14278,7 @@ function registerDriversCommand(program) {
|
|
|
14170
14278
|
}
|
|
14171
14279
|
|
|
14172
14280
|
// src/index.ts
|
|
14173
|
-
var VERSION = true ? "0.31.
|
|
14281
|
+
var VERSION = true ? "0.31.3" : "0.0.0-dev";
|
|
14174
14282
|
function createProgram() {
|
|
14175
14283
|
const program = new Command();
|
|
14176
14284
|
program.name("codeharness").description("Makes autonomous coding agents produce software that actually works").version(VERSION).option("--json", "Output in machine-readable JSON format");
|