@cardor/agent-harness-kit 2.2.0 → 2.3.0
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 +3 -1
- package/dist/cli.js +78 -72
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -272,7 +272,7 @@ ahk build --force
|
|
|
272
272
|
- **It discards your customizations.** Every agent file is rewritten from the template. Prompt edits, `model:` lines, and restriction tweaks are all lost.
|
|
273
273
|
- **It backs up first.** Before overwriting anything, the current content of every affected file is copied under `.harness/backups/` — agent files to `agents-<timestamp>/`, hand-edited `AGENTS.md`/`CLAUDE.md` to `derived-<timestamp>/`. If that backup cannot be written, the command aborts and **no file is modified** — the same fail-safe as [`ahk migrate storage --force`](#storage-migration).
|
|
274
274
|
- **It names what it touched.** The command prints every file it overwrote and the backup location, so you can diff or restore.
|
|
275
|
-
- **Claude Code
|
|
275
|
+
- **Claude Code and Codex CLI also re-prompt for models.** Before regenerating, `ahk build --force` runs the same per-role prompt as `ahk init` for the current provider — the model prompt on Claude Code, or the model **and** reasoning-effort prompt on Codex CLI (see above) — and injects the fresh choices into the regenerated frontmatter/TOML. OpenCode and Grok Build are unaffected — no prompt appears for them, since neither has a closed model enum to prompt against.
|
|
276
276
|
|
|
277
277
|
`--force` also regenerates a hand-edited `AGENTS.md` or `CLAUDE.md` (backing it up first) — the only time you need it for those files, since an *unedited* one already re-generates on its own when config changes.
|
|
278
278
|
|
|
@@ -471,6 +471,8 @@ ahk migrate provider --to grok-cli
|
|
|
471
471
|
ahk migrate --to opencode
|
|
472
472
|
```
|
|
473
473
|
|
|
474
|
+
Migrating always regenerates the target provider's agent files from scratch, so — same as `ahk init` and `ahk build --force` — it also runs that target's per-role prompt first, before anything is written: the model prompt when migrating **to** Claude Code, or the model **and** reasoning-effort prompt when migrating **to** Codex CLI (see [`ahk init`](#ahk-init) above for what each prompt asks). Migrating to OpenCode or Grok CLI shows no prompt at all, since neither has a closed model enum to prompt against.
|
|
475
|
+
|
|
474
476
|
#### `ahk migrate storage` — ⚠️ sensitive, reads/writes real harness data
|
|
475
477
|
|
|
476
478
|
Migrates the harness database between storage backends: **local↔global scope** (moving `.harness/harness.db` in/out of `~/.harness/dbs/<projectId>/`) and **sqlite↔postgres/mysql** (dumping and reloading all 6 tables — tasks, task_acceptance, actions, action_sections, action_files, action_tools — inside a single transaction). It is **not interactive** — `agent-harness-kit.config.ts` (`storage.scope`, `storage.sqlitePath` (local scope only), `database.type`/`connectionString`) is the only source of truth for the desired target, compared against the real current state recorded in `.harness/storage-state.json`.
|
package/dist/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import pc21 from "picocolors";
|
|
|
20
20
|
|
|
21
21
|
// src/commands/build.ts
|
|
22
22
|
import { watch } from "fs";
|
|
23
|
-
import * as
|
|
23
|
+
import * as p3 from "@clack/prompts";
|
|
24
24
|
import pc2 from "picocolors";
|
|
25
25
|
|
|
26
26
|
// src/core/materializer/claude-code.ts
|
|
@@ -1387,20 +1387,69 @@ async function promptClaudeAgentModels(provider) {
|
|
|
1387
1387
|
return claudeAgentModels;
|
|
1388
1388
|
}
|
|
1389
1389
|
|
|
1390
|
+
// src/commands/codex-model-prompt.ts
|
|
1391
|
+
import * as p2 from "@clack/prompts";
|
|
1392
|
+
var AGENT_LABELS2 = [
|
|
1393
|
+
{ key: "lead", label: "Lead" },
|
|
1394
|
+
{ key: "explorer", label: "Explorer" },
|
|
1395
|
+
{ key: "consultant", label: "Consultant" },
|
|
1396
|
+
{ key: "builder", label: "Builder" },
|
|
1397
|
+
{ key: "reviewer", label: "Reviewer" }
|
|
1398
|
+
];
|
|
1399
|
+
var CODEX_MODEL_CHOICES = [
|
|
1400
|
+
"gpt-5.6-sol",
|
|
1401
|
+
"gpt-5.6-terra",
|
|
1402
|
+
"gpt-5.6-luna",
|
|
1403
|
+
"gpt-5.5",
|
|
1404
|
+
"gpt-5.4",
|
|
1405
|
+
"gpt-5.4-mini",
|
|
1406
|
+
"gpt-5.3-codex-spark"
|
|
1407
|
+
];
|
|
1408
|
+
var CODEX_EFFORT_CHOICES = ["minimal", "low", "medium", "high", "xhigh"];
|
|
1409
|
+
async function promptCodexAgentModels(provider) {
|
|
1410
|
+
const codexAgentModels = {};
|
|
1411
|
+
if (provider !== "codex-cli") return codexAgentModels;
|
|
1412
|
+
for (const agent of AGENT_LABELS2) {
|
|
1413
|
+
const modelVal = await p2.select({
|
|
1414
|
+
message: `Model for ${agent.label}`,
|
|
1415
|
+
options: CODEX_MODEL_CHOICES.map((value) => ({ value, label: value })),
|
|
1416
|
+
initialValue: "gpt-5.6-terra"
|
|
1417
|
+
});
|
|
1418
|
+
if (p2.isCancel(modelVal)) {
|
|
1419
|
+
p2.cancel("Cancelled.");
|
|
1420
|
+
process.exit(0);
|
|
1421
|
+
}
|
|
1422
|
+
const effortVal = await p2.select({
|
|
1423
|
+
message: `Reasoning effort for ${agent.label}`,
|
|
1424
|
+
options: CODEX_EFFORT_CHOICES.map((value) => ({ value, label: value })),
|
|
1425
|
+
initialValue: "medium"
|
|
1426
|
+
});
|
|
1427
|
+
if (p2.isCancel(effortVal)) {
|
|
1428
|
+
p2.cancel("Cancelled.");
|
|
1429
|
+
process.exit(0);
|
|
1430
|
+
}
|
|
1431
|
+
codexAgentModels[agent.key] = {
|
|
1432
|
+
model: modelVal,
|
|
1433
|
+
effort: effortVal
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
return codexAgentModels;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1390
1439
|
// src/commands/build.ts
|
|
1391
1440
|
async function runBuild(cwd2, opts) {
|
|
1392
1441
|
await buildOnce(cwd2, opts.force);
|
|
1393
1442
|
if (opts.sync) {
|
|
1394
|
-
|
|
1443
|
+
p3.log.step("Syncing agent permissions...");
|
|
1395
1444
|
const config = await loadConfig(cwd2);
|
|
1396
1445
|
const materializer = getMaterializer(config.provider);
|
|
1397
1446
|
await materializer.syncPermissions(cwd2);
|
|
1398
1447
|
}
|
|
1399
1448
|
if (opts.watch) {
|
|
1400
|
-
|
|
1449
|
+
p3.log.info(`Watching agent-harness-kit.config.ts for changes...`);
|
|
1401
1450
|
watch(cwd2, { recursive: false }, async (_, filename) => {
|
|
1402
1451
|
if (filename?.startsWith("agent-harness-kit.config")) {
|
|
1403
|
-
|
|
1452
|
+
p3.log.step("Config changed \u2014 rebuilding...");
|
|
1404
1453
|
await buildOnce(cwd2, false);
|
|
1405
1454
|
}
|
|
1406
1455
|
});
|
|
@@ -1413,41 +1462,45 @@ async function buildOnce(cwd2, force) {
|
|
|
1413
1462
|
try {
|
|
1414
1463
|
config = await loadConfig(cwd2);
|
|
1415
1464
|
} catch (err) {
|
|
1416
|
-
|
|
1465
|
+
p3.log.error(err instanceof Error ? err.message : String(err));
|
|
1417
1466
|
process.exit(1);
|
|
1418
1467
|
}
|
|
1419
1468
|
let claudeAgentModels;
|
|
1420
1469
|
if (force && config.provider === "claude-code") {
|
|
1421
1470
|
claudeAgentModels = await promptClaudeAgentModels(config.provider);
|
|
1422
1471
|
}
|
|
1423
|
-
|
|
1472
|
+
let codexAgentModels;
|
|
1473
|
+
if (force && config.provider === "codex-cli") {
|
|
1474
|
+
codexAgentModels = await promptCodexAgentModels(config.provider);
|
|
1475
|
+
}
|
|
1476
|
+
const spinner6 = p3.spinner();
|
|
1424
1477
|
spinner6.start("Rebuilding files...");
|
|
1425
1478
|
try {
|
|
1426
1479
|
const materializer = getMaterializer(config.provider);
|
|
1427
|
-
const report = await materializer.build(config, cwd2, { force, claudeAgentModels });
|
|
1480
|
+
const report = await materializer.build(config, cwd2, { force, claudeAgentModels, codexAgentModels });
|
|
1428
1481
|
spinner6.stop(pc2.green("Build complete"));
|
|
1429
1482
|
const d = report.derived;
|
|
1430
1483
|
const upToDate = [...d.created, ...d.current, ...d.propagated];
|
|
1431
1484
|
if (upToDate.length > 0) {
|
|
1432
|
-
|
|
1485
|
+
p3.log.success(upToDate.join(", "));
|
|
1433
1486
|
}
|
|
1434
1487
|
if (d.propagated.length > 0) {
|
|
1435
|
-
|
|
1488
|
+
p3.log.info(`Propagated config changes to ${d.propagated.length} generated file(s):
|
|
1436
1489
|
${d.propagated.join("\n ")}`);
|
|
1437
1490
|
}
|
|
1438
1491
|
if (d.overwritten.length > 0) {
|
|
1439
|
-
|
|
1492
|
+
p3.log.warn(
|
|
1440
1493
|
pc2.yellow(
|
|
1441
1494
|
`--force REGENERATED ${d.overwritten.length} hand-edited generated file(s), discarding your edits:
|
|
1442
1495
|
` + d.overwritten.join("\n ")
|
|
1443
1496
|
)
|
|
1444
1497
|
);
|
|
1445
1498
|
if (d.backupDir) {
|
|
1446
|
-
|
|
1499
|
+
p3.log.info(pc2.yellow(` Previous content backed up \u2192 ${d.backupDir}`));
|
|
1447
1500
|
}
|
|
1448
1501
|
}
|
|
1449
1502
|
if (d.preserved.length > 0) {
|
|
1450
|
-
|
|
1503
|
+
p3.log.warn(
|
|
1451
1504
|
pc2.yellow(
|
|
1452
1505
|
`Left ${d.preserved.length} hand-edited generated file(s) UNTOUCHED \u2014 your edits are safe:
|
|
1453
1506
|
` + d.preserved.join("\n ") + `
|
|
@@ -1456,26 +1509,26 @@ async function buildOnce(cwd2, force) {
|
|
|
1456
1509
|
)
|
|
1457
1510
|
);
|
|
1458
1511
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1512
|
+
p3.log.success(`Agent definitions (${config.provider})`);
|
|
1513
|
+
p3.log.success("MCP config");
|
|
1461
1514
|
const { created, overwritten, preserved, backupDir } = report.agents;
|
|
1462
1515
|
if (created.length > 0) {
|
|
1463
|
-
|
|
1516
|
+
p3.log.info(`Created ${created.length} missing agent file(s):
|
|
1464
1517
|
${created.join("\n ")}`);
|
|
1465
1518
|
}
|
|
1466
1519
|
if (overwritten.length > 0) {
|
|
1467
|
-
|
|
1520
|
+
p3.log.warn(
|
|
1468
1521
|
pc2.yellow(
|
|
1469
1522
|
`--force REGENERATED ${overwritten.length} existing agent file(s), discarding any customizations:
|
|
1470
1523
|
` + overwritten.join("\n ")
|
|
1471
1524
|
)
|
|
1472
1525
|
);
|
|
1473
1526
|
if (backupDir) {
|
|
1474
|
-
|
|
1527
|
+
p3.log.info(pc2.yellow(` Previous content backed up \u2192 ${backupDir}`));
|
|
1475
1528
|
}
|
|
1476
1529
|
}
|
|
1477
1530
|
if (preserved.length > 0) {
|
|
1478
|
-
|
|
1531
|
+
p3.log.info(
|
|
1479
1532
|
`Left ${preserved.length} existing agent file(s) untouched \u2014 agent files are yours to edit.
|
|
1480
1533
|
Re-run with --force to regenerate them from the packaged templates (this DESTROYS your edits;
|
|
1481
1534
|
a backup is written first).`
|
|
@@ -1483,7 +1536,7 @@ async function buildOnce(cwd2, force) {
|
|
|
1483
1536
|
}
|
|
1484
1537
|
} catch (err) {
|
|
1485
1538
|
spinner6.stop(pc2.red("Build failed"));
|
|
1486
|
-
|
|
1539
|
+
p3.log.error(err instanceof Error ? err.message : String(err));
|
|
1487
1540
|
process.exit(1);
|
|
1488
1541
|
}
|
|
1489
1542
|
}
|
|
@@ -2136,7 +2189,7 @@ var taskDescriptionSchema = v2.pipe(
|
|
|
2136
2189
|
);
|
|
2137
2190
|
|
|
2138
2191
|
// src/utils/form.ts
|
|
2139
|
-
import * as
|
|
2192
|
+
import * as p4 from "@clack/prompts";
|
|
2140
2193
|
import * as v3 from "valibot";
|
|
2141
2194
|
var cliFormWithRetry = async (formFn, schema) => {
|
|
2142
2195
|
while (true) {
|
|
@@ -2144,60 +2197,11 @@ var cliFormWithRetry = async (formFn, schema) => {
|
|
|
2144
2197
|
const result = v3.safeParse(schema, res);
|
|
2145
2198
|
if (result.success) return result.output;
|
|
2146
2199
|
const messages = result.issues.map((i) => i.message).join(", ");
|
|
2147
|
-
|
|
2148
|
-
|
|
2200
|
+
p4.log.error(messages);
|
|
2201
|
+
p4.log.info("Please try again.\n");
|
|
2149
2202
|
}
|
|
2150
2203
|
};
|
|
2151
2204
|
|
|
2152
|
-
// src/commands/codex-model-prompt.ts
|
|
2153
|
-
import * as p4 from "@clack/prompts";
|
|
2154
|
-
var AGENT_LABELS2 = [
|
|
2155
|
-
{ key: "lead", label: "Lead" },
|
|
2156
|
-
{ key: "explorer", label: "Explorer" },
|
|
2157
|
-
{ key: "consultant", label: "Consultant" },
|
|
2158
|
-
{ key: "builder", label: "Builder" },
|
|
2159
|
-
{ key: "reviewer", label: "Reviewer" }
|
|
2160
|
-
];
|
|
2161
|
-
var CODEX_MODEL_CHOICES = [
|
|
2162
|
-
"gpt-5.6-sol",
|
|
2163
|
-
"gpt-5.6-terra",
|
|
2164
|
-
"gpt-5.6-luna",
|
|
2165
|
-
"gpt-5.5",
|
|
2166
|
-
"gpt-5.4",
|
|
2167
|
-
"gpt-5.4-mini",
|
|
2168
|
-
"gpt-5.3-codex-spark"
|
|
2169
|
-
];
|
|
2170
|
-
var CODEX_EFFORT_CHOICES = ["minimal", "low", "medium", "high", "xhigh"];
|
|
2171
|
-
async function promptCodexAgentModels(provider) {
|
|
2172
|
-
const codexAgentModels = {};
|
|
2173
|
-
if (provider !== "codex-cli") return codexAgentModels;
|
|
2174
|
-
for (const agent of AGENT_LABELS2) {
|
|
2175
|
-
const modelVal = await p4.select({
|
|
2176
|
-
message: `Model for ${agent.label}`,
|
|
2177
|
-
options: CODEX_MODEL_CHOICES.map((value) => ({ value, label: value })),
|
|
2178
|
-
initialValue: "gpt-5.6-terra"
|
|
2179
|
-
});
|
|
2180
|
-
if (p4.isCancel(modelVal)) {
|
|
2181
|
-
p4.cancel("Cancelled.");
|
|
2182
|
-
process.exit(0);
|
|
2183
|
-
}
|
|
2184
|
-
const effortVal = await p4.select({
|
|
2185
|
-
message: `Reasoning effort for ${agent.label}`,
|
|
2186
|
-
options: CODEX_EFFORT_CHOICES.map((value) => ({ value, label: value })),
|
|
2187
|
-
initialValue: "medium"
|
|
2188
|
-
});
|
|
2189
|
-
if (p4.isCancel(effortVal)) {
|
|
2190
|
-
p4.cancel("Cancelled.");
|
|
2191
|
-
process.exit(0);
|
|
2192
|
-
}
|
|
2193
|
-
codexAgentModels[agent.key] = {
|
|
2194
|
-
model: modelVal,
|
|
2195
|
-
effort: effortVal
|
|
2196
|
-
};
|
|
2197
|
-
}
|
|
2198
|
-
return codexAgentModels;
|
|
2199
|
-
}
|
|
2200
|
-
|
|
2201
2205
|
// src/commands/init-helpers.ts
|
|
2202
2206
|
import { randomUUID } from "crypto";
|
|
2203
2207
|
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
@@ -2609,11 +2613,13 @@ async function runMigrate(cwd2, opts) {
|
|
|
2609
2613
|
console.log(pc9.dim(`Already on ${target} \u2014 nothing to migrate.`));
|
|
2610
2614
|
return;
|
|
2611
2615
|
}
|
|
2616
|
+
const claudeAgentModels = await promptClaudeAgentModels(target);
|
|
2617
|
+
const codexAgentModels = await promptCodexAgentModels(target);
|
|
2612
2618
|
const spinner6 = p6.spinner();
|
|
2613
2619
|
spinner6.start(`Migrating from ${config.provider} to ${target}...`);
|
|
2614
2620
|
try {
|
|
2615
2621
|
const targetMaterializer = getMaterializer(target);
|
|
2616
|
-
await targetMaterializer.build(config, cwd2);
|
|
2622
|
+
await targetMaterializer.build(config, cwd2, { claudeAgentModels, codexAgentModels });
|
|
2617
2623
|
spinner6.stop(pc9.green(`Migrated to ${target}`));
|
|
2618
2624
|
p6.log.warn(`Update agent-harness-kit.config.ts: set provider: '${target}'`);
|
|
2619
2625
|
p6.log.warn(`Then run: ahk build`);
|