codeharness 0.31.2 → 0.31.4
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.4" : "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-WI2XM5WP.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) {
|
|
@@ -5803,6 +5813,11 @@ function startRenderer(options) {
|
|
|
5803
5813
|
}
|
|
5804
5814
|
switch (event.type) {
|
|
5805
5815
|
case "tool-start":
|
|
5816
|
+
if (state.lastThought) {
|
|
5817
|
+
const textEntry = { name: "", args: state.lastThought, isText: true };
|
|
5818
|
+
const updated = [...state.completedTools, textEntry];
|
|
5819
|
+
state.completedTools = updated.length > MAX_COMPLETED_TOOLS ? updated.slice(updated.length - MAX_COMPLETED_TOOLS) : updated;
|
|
5820
|
+
}
|
|
5806
5821
|
promoteActiveTool(false);
|
|
5807
5822
|
state.activeTool = { name: event.name };
|
|
5808
5823
|
state.activeToolArgs = "";
|
|
@@ -5821,6 +5836,11 @@ function startRenderer(options) {
|
|
|
5821
5836
|
}
|
|
5822
5837
|
break;
|
|
5823
5838
|
case "text":
|
|
5839
|
+
if (state.lastThought) {
|
|
5840
|
+
const textEntry = { name: "", args: state.lastThought, isText: true };
|
|
5841
|
+
const updated = [...state.completedTools, textEntry];
|
|
5842
|
+
state.completedTools = updated.length > MAX_COMPLETED_TOOLS ? updated.slice(updated.length - MAX_COMPLETED_TOOLS) : updated;
|
|
5843
|
+
}
|
|
5824
5844
|
state.lastThought = event.text;
|
|
5825
5845
|
state.retryInfo = null;
|
|
5826
5846
|
break;
|
|
@@ -6251,11 +6271,32 @@ function registerRunCommand(program) {
|
|
|
6251
6271
|
epicData[epicId] = { storiesDone: epic.storiesDone ?? 0, storiesTotal: epic.storiesTotal ?? 0 };
|
|
6252
6272
|
}
|
|
6253
6273
|
}
|
|
6274
|
+
const preLoopTasks = /* @__PURE__ */ new Set();
|
|
6275
|
+
const loopTasks = /* @__PURE__ */ new Set();
|
|
6276
|
+
for (const step of parsedWorkflow.flow) {
|
|
6277
|
+
if (typeof step === "string") {
|
|
6278
|
+
preLoopTasks.add(step);
|
|
6279
|
+
} else if (typeof step === "object" && "loop" in step) {
|
|
6280
|
+
for (const lt of step.loop) loopTasks.add(lt);
|
|
6281
|
+
}
|
|
6282
|
+
}
|
|
6283
|
+
let pastLoop = false;
|
|
6284
|
+
for (const step of parsedWorkflow.flow) {
|
|
6285
|
+
if (typeof step === "object" && "loop" in step) {
|
|
6286
|
+
pastLoop = true;
|
|
6287
|
+
continue;
|
|
6288
|
+
}
|
|
6289
|
+
if (pastLoop && typeof step === "string") preLoopTasks.add(step);
|
|
6290
|
+
}
|
|
6291
|
+
let inLoop = false;
|
|
6254
6292
|
const taskStates = {};
|
|
6255
6293
|
const taskMeta = {};
|
|
6256
6294
|
for (const [tn, task] of Object.entries(parsedWorkflow.tasks)) {
|
|
6257
6295
|
taskStates[tn] = "pending";
|
|
6258
|
-
|
|
6296
|
+
if (loopTasks.has(tn)) taskStates[`loop:${tn}`] = "pending";
|
|
6297
|
+
const driverLabel2 = task.model ?? task.driver ?? "claude-code";
|
|
6298
|
+
taskMeta[tn] = { driver: driverLabel2 };
|
|
6299
|
+
if (loopTasks.has(tn)) taskMeta[`loop:${tn}`] = { driver: driverLabel2 };
|
|
6259
6300
|
}
|
|
6260
6301
|
const storyEntries = [];
|
|
6261
6302
|
for (const [key, status] of Object.entries(statuses)) {
|
|
@@ -6271,8 +6312,18 @@ function registerRunCommand(program) {
|
|
|
6271
6312
|
renderer.update(event.streamEvent, event.driverName);
|
|
6272
6313
|
}
|
|
6273
6314
|
if (event.type === "dispatch-start") {
|
|
6315
|
+
if (event.storyKey !== currentStoryKey && preLoopTasks.has(event.taskName)) {
|
|
6316
|
+
inLoop = false;
|
|
6317
|
+
for (const tn of Object.keys(taskStates)) {
|
|
6318
|
+
taskStates[tn] = "pending";
|
|
6319
|
+
}
|
|
6320
|
+
}
|
|
6274
6321
|
currentStoryKey = event.storyKey;
|
|
6275
6322
|
currentTaskName = event.taskName;
|
|
6323
|
+
if (loopTasks.has(event.taskName) && taskStates[event.taskName] === "done") {
|
|
6324
|
+
inLoop = true;
|
|
6325
|
+
}
|
|
6326
|
+
const stateKey = inLoop && loopTasks.has(event.taskName) ? `loop:${event.taskName}` : event.taskName;
|
|
6276
6327
|
const epicId = extractEpicId2(event.storyKey);
|
|
6277
6328
|
const epic = epicData[epicId];
|
|
6278
6329
|
renderer.updateSprintState({
|
|
@@ -6286,7 +6337,7 @@ function registerRunCommand(program) {
|
|
|
6286
6337
|
epicStoriesDone: epic?.storiesDone ?? 0,
|
|
6287
6338
|
epicStoriesTotal: epic?.storiesTotal ?? 0
|
|
6288
6339
|
});
|
|
6289
|
-
taskStates[
|
|
6340
|
+
taskStates[stateKey] = "active";
|
|
6290
6341
|
renderer.updateWorkflowState(parsedWorkflow.flow, event.taskName, { ...taskStates }, { ...taskMeta });
|
|
6291
6342
|
const idx = storyEntries.findIndex((s) => s.key === event.storyKey);
|
|
6292
6343
|
if (idx >= 0 && storyEntries[idx].status === "pending") {
|
|
@@ -6296,11 +6347,12 @@ function registerRunCommand(program) {
|
|
|
6296
6347
|
}
|
|
6297
6348
|
if (event.type === "dispatch-end") {
|
|
6298
6349
|
totalCostUsd += event.costUsd ?? 0;
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6350
|
+
const stateKey = inLoop && loopTasks.has(event.taskName) ? `loop:${event.taskName}` : event.taskName;
|
|
6351
|
+
taskStates[stateKey] = "done";
|
|
6352
|
+
taskMeta[stateKey] = {
|
|
6353
|
+
...taskMeta[stateKey],
|
|
6354
|
+
costUsd: (taskMeta[stateKey]?.costUsd ?? 0) + (event.costUsd ?? 0),
|
|
6355
|
+
elapsedMs: (taskMeta[stateKey]?.elapsedMs ?? 0) + (event.elapsedMs ?? 0)
|
|
6304
6356
|
};
|
|
6305
6357
|
renderer.updateWorkflowState(parsedWorkflow.flow, event.taskName, { ...taskStates }, { ...taskMeta });
|
|
6306
6358
|
renderer.updateSprintState({
|
|
@@ -6312,7 +6364,8 @@ function registerRunCommand(program) {
|
|
|
6312
6364
|
});
|
|
6313
6365
|
}
|
|
6314
6366
|
if (event.type === "dispatch-error") {
|
|
6315
|
-
|
|
6367
|
+
const stateKey = inLoop && loopTasks.has(event.taskName) ? `loop:${event.taskName}` : event.taskName;
|
|
6368
|
+
taskStates[stateKey] = "failed";
|
|
6316
6369
|
renderer.updateWorkflowState(parsedWorkflow.flow, event.taskName, { ...taskStates }, { ...taskMeta });
|
|
6317
6370
|
renderer.addMessage({
|
|
6318
6371
|
type: "fail",
|
|
@@ -11211,7 +11264,7 @@ function registerTeardownCommand(program) {
|
|
|
11211
11264
|
} else if (otlpMode === "remote-routed") {
|
|
11212
11265
|
if (!options.keepDocker) {
|
|
11213
11266
|
try {
|
|
11214
|
-
const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-
|
|
11267
|
+
const { stopCollectorOnly: stopCollectorOnly2 } = await import("./docker-KXQ6RJW6.js");
|
|
11215
11268
|
stopCollectorOnly2();
|
|
11216
11269
|
result.docker.stopped = true;
|
|
11217
11270
|
if (!isJson) {
|
|
@@ -11243,7 +11296,7 @@ function registerTeardownCommand(program) {
|
|
|
11243
11296
|
info("Shared stack: kept running (other projects may use it)");
|
|
11244
11297
|
}
|
|
11245
11298
|
} else if (isLegacyStack) {
|
|
11246
|
-
const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-
|
|
11299
|
+
const { isStackRunning: isStackRunning2, stopStack } = await import("./docker-KXQ6RJW6.js");
|
|
11247
11300
|
let stackRunning = false;
|
|
11248
11301
|
try {
|
|
11249
11302
|
stackRunning = isStackRunning2(composeFile);
|
|
@@ -13683,6 +13736,68 @@ function classifyError2(err) {
|
|
|
13683
13736
|
}
|
|
13684
13737
|
return "UNKNOWN";
|
|
13685
13738
|
}
|
|
13739
|
+
function parseLineMulti(line) {
|
|
13740
|
+
const trimmed = line.trim();
|
|
13741
|
+
if (trimmed.length === 0) return [];
|
|
13742
|
+
let parsed;
|
|
13743
|
+
try {
|
|
13744
|
+
parsed = JSON.parse(trimmed);
|
|
13745
|
+
} catch {
|
|
13746
|
+
return [];
|
|
13747
|
+
}
|
|
13748
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return [];
|
|
13749
|
+
const type = parsed.type;
|
|
13750
|
+
const item = parsed.item;
|
|
13751
|
+
if (type === "item.started" && item) {
|
|
13752
|
+
const itemType = item.type;
|
|
13753
|
+
if (itemType === "command_execution") {
|
|
13754
|
+
const cmd = item.command ?? "";
|
|
13755
|
+
return [
|
|
13756
|
+
{ type: "tool-start", name: "Bash", id: item.id ?? "" },
|
|
13757
|
+
{ type: "tool-input", partial: cmd }
|
|
13758
|
+
];
|
|
13759
|
+
}
|
|
13760
|
+
if (itemType === "file_edit") {
|
|
13761
|
+
const path = item.file_path ?? item.path ?? "";
|
|
13762
|
+
return [
|
|
13763
|
+
{ type: "tool-start", name: "Edit", id: item.id ?? "" },
|
|
13764
|
+
{ type: "tool-input", partial: path }
|
|
13765
|
+
];
|
|
13766
|
+
}
|
|
13767
|
+
if (itemType === "file_read") {
|
|
13768
|
+
const path = item.file_path ?? item.path ?? "";
|
|
13769
|
+
return [
|
|
13770
|
+
{ type: "tool-start", name: "Read", id: item.id ?? "" },
|
|
13771
|
+
{ type: "tool-input", partial: path }
|
|
13772
|
+
];
|
|
13773
|
+
}
|
|
13774
|
+
return [];
|
|
13775
|
+
}
|
|
13776
|
+
if (type === "item.completed" && item) {
|
|
13777
|
+
const itemType = item.type;
|
|
13778
|
+
if (itemType === "command_execution") return [{ type: "tool-complete" }];
|
|
13779
|
+
if (itemType === "agent_message") {
|
|
13780
|
+
const text = item.text;
|
|
13781
|
+
return text ? [{ type: "text", text }] : [];
|
|
13782
|
+
}
|
|
13783
|
+
if (itemType === "file_edit" || itemType === "file_read") return [{ type: "tool-complete" }];
|
|
13784
|
+
return [];
|
|
13785
|
+
}
|
|
13786
|
+
if (type === "turn.completed") {
|
|
13787
|
+
const usage = parsed.usage;
|
|
13788
|
+
if (usage) {
|
|
13789
|
+
return [{
|
|
13790
|
+
type: "result",
|
|
13791
|
+
cost: 0,
|
|
13792
|
+
sessionId: "",
|
|
13793
|
+
cost_usd: null
|
|
13794
|
+
}];
|
|
13795
|
+
}
|
|
13796
|
+
return [];
|
|
13797
|
+
}
|
|
13798
|
+
const legacy = parseLine(line);
|
|
13799
|
+
return legacy ? [legacy] : [];
|
|
13800
|
+
}
|
|
13686
13801
|
function parseLine(line) {
|
|
13687
13802
|
const trimmed = line.trim();
|
|
13688
13803
|
if (trimmed.length === 0) return null;
|
|
@@ -13814,7 +13929,7 @@ var CodexDriver = class {
|
|
|
13814
13929
|
opts.plugins
|
|
13815
13930
|
);
|
|
13816
13931
|
}
|
|
13817
|
-
const args = ["exec", "--json"];
|
|
13932
|
+
const args = ["exec", "--json", "--full-auto"];
|
|
13818
13933
|
const model = opts.model && !opts.model.startsWith("claude-") ? opts.model : void 0;
|
|
13819
13934
|
if (model) {
|
|
13820
13935
|
args.push("--model", model);
|
|
@@ -13845,8 +13960,8 @@ var CodexDriver = class {
|
|
|
13845
13960
|
});
|
|
13846
13961
|
try {
|
|
13847
13962
|
for await (const line of rl) {
|
|
13848
|
-
const
|
|
13849
|
-
|
|
13963
|
+
const events = parseLineMulti(line);
|
|
13964
|
+
for (const event of events) {
|
|
13850
13965
|
if (event.type === "result") {
|
|
13851
13966
|
const resultEvent = event;
|
|
13852
13967
|
if (typeof resultEvent.cost_usd === "number") {
|
|
@@ -13857,8 +13972,6 @@ var CodexDriver = class {
|
|
|
13857
13972
|
} else {
|
|
13858
13973
|
yield event;
|
|
13859
13974
|
}
|
|
13860
|
-
} else {
|
|
13861
|
-
console.debug("[CodexDriver] Skipping unparseable line:", line);
|
|
13862
13975
|
}
|
|
13863
13976
|
}
|
|
13864
13977
|
const exitCode = await closePromise;
|
|
@@ -14170,7 +14283,7 @@ function registerDriversCommand(program) {
|
|
|
14170
14283
|
}
|
|
14171
14284
|
|
|
14172
14285
|
// src/index.ts
|
|
14173
|
-
var VERSION = true ? "0.31.
|
|
14286
|
+
var VERSION = true ? "0.31.4" : "0.0.0-dev";
|
|
14174
14287
|
function createProgram() {
|
|
14175
14288
|
const program = new Command();
|
|
14176
14289
|
program.name("codeharness").description("Makes autonomous coding agents produce software that actually works").version(VERSION).option("--json", "Output in machine-readable JSON format");
|