haansi 0.1.56 → 0.1.57
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/haansi.js +142 -25
- package/package.json +1 -1
package/dist/haansi.js
CHANGED
|
@@ -95,7 +95,7 @@ var require_package = __commonJS({
|
|
|
95
95
|
"package.json"(exports2, module2) {
|
|
96
96
|
module2.exports = {
|
|
97
97
|
name: "haansi",
|
|
98
|
-
version: "0.1.
|
|
98
|
+
version: "0.1.57",
|
|
99
99
|
description: "Haansi CLI - Session collector and MCP server for Claude Code & OpenAI Codex",
|
|
100
100
|
bin: {
|
|
101
101
|
haansi: "./dist/haansi.js"
|
|
@@ -19220,6 +19220,24 @@ var init_exclusions = __esm({
|
|
|
19220
19220
|
model: ["operational", "The model name the replay ran with."],
|
|
19221
19221
|
run_ref: ["not-personal", "A link to the customer's CI run."]
|
|
19222
19222
|
}),
|
|
19223
|
+
...exchangeExclusions(INTEL, "replay_sessions", {
|
|
19224
|
+
excluded_process_ids: [
|
|
19225
|
+
"join-key",
|
|
19226
|
+
"process_registry.process_id of the replayed workstream, matched by equality."
|
|
19227
|
+
],
|
|
19228
|
+
excluded_family_ids: [
|
|
19229
|
+
"join-key",
|
|
19230
|
+
"problem_families ids holding the replayed workstream, matched by equality."
|
|
19231
|
+
]
|
|
19232
|
+
}),
|
|
19233
|
+
...exchangeExclusions(INTEL, "replay_session_calls", {
|
|
19234
|
+
server: ["operational", "The MCP server's name, e.g. haansi-skills."],
|
|
19235
|
+
tool: ["operational", "The MCP tool's name, e.g. search_skills."],
|
|
19236
|
+
returned_ids: [
|
|
19237
|
+
"join-key",
|
|
19238
|
+
"Ids of the solutions, skills and revisions a tool returned."
|
|
19239
|
+
]
|
|
19240
|
+
}),
|
|
19223
19241
|
...exchangeExclusions(INTEL, "replay_task_results", {
|
|
19224
19242
|
inputs_fingerprint: [
|
|
19225
19243
|
"derived",
|
|
@@ -19315,7 +19333,11 @@ var init_exclusions = __esm({
|
|
|
19315
19333
|
"The CI's setup and test commands an org admin or CI owner typed, runtime versions, the runner image and the CLI version."
|
|
19316
19334
|
],
|
|
19317
19335
|
calibration_runs: ["operational", "Exit codes of the test runs."],
|
|
19318
|
-
calibration_run_ref: ["not-personal", "A link to the customer's CI run."]
|
|
19336
|
+
calibration_run_ref: ["not-personal", "A link to the customer's CI run."],
|
|
19337
|
+
review_state: [
|
|
19338
|
+
"operational",
|
|
19339
|
+
"Closed CHECK vocabulary (approved, excluded)."
|
|
19340
|
+
]
|
|
19319
19341
|
}),
|
|
19320
19342
|
...exchangeExclusions(INTEL, "problem_family_members", {
|
|
19321
19343
|
process_id: [
|
|
@@ -26583,6 +26605,12 @@ var init_table_registry = __esm({
|
|
|
26583
26605
|
entry("intelligence", INTELLIGENCE_DB, "replay_task_results", "direct", {
|
|
26584
26606
|
scopingColumn: "organization_id"
|
|
26585
26607
|
}),
|
|
26608
|
+
entry("intelligence", INTELLIGENCE_DB, "replay_sessions", "direct", {
|
|
26609
|
+
scopingColumn: "organization_id"
|
|
26610
|
+
}),
|
|
26611
|
+
entry("intelligence", INTELLIGENCE_DB, "replay_session_calls", "direct", {
|
|
26612
|
+
scopingColumn: "organization_id"
|
|
26613
|
+
}),
|
|
26586
26614
|
// A person's revert verdicts, the checks that validate a change and the
|
|
26587
26615
|
// replay commands, per repository (outcome evidence v2 plan).
|
|
26588
26616
|
entry("intelligence", INTELLIGENCE_DB, "revert_labels", "direct", {
|
|
@@ -83604,7 +83632,7 @@ function resolveToken3() {
|
|
|
83604
83632
|
return null;
|
|
83605
83633
|
}
|
|
83606
83634
|
function triggerCollectInBackground() {
|
|
83607
|
-
if (isCollecting) return;
|
|
83635
|
+
if (isCollecting || REPLAY_SESSION) return;
|
|
83608
83636
|
isCollecting = true;
|
|
83609
83637
|
collect({}).then(() => {
|
|
83610
83638
|
lastCollectTime = Date.now();
|
|
@@ -83621,7 +83649,8 @@ function maybeCollect() {
|
|
|
83621
83649
|
async function apiGet2(path2, options) {
|
|
83622
83650
|
const headers = {
|
|
83623
83651
|
Authorization: `Bearer ${TOKEN}`,
|
|
83624
|
-
...options?.extraHeaders
|
|
83652
|
+
...options?.extraHeaders,
|
|
83653
|
+
...REPLAY_HEADERS
|
|
83625
83654
|
};
|
|
83626
83655
|
const response = await fetchWithTimeout(`${API_URL}/api/v1${path2}`, {
|
|
83627
83656
|
headers
|
|
@@ -83636,7 +83665,8 @@ async function apiPost(path2, body, options) {
|
|
|
83636
83665
|
const headers = {
|
|
83637
83666
|
Authorization: `Bearer ${TOKEN}`,
|
|
83638
83667
|
"Content-Type": "application/json",
|
|
83639
|
-
...options?.extraHeaders
|
|
83668
|
+
...options?.extraHeaders,
|
|
83669
|
+
...REPLAY_HEADERS
|
|
83640
83670
|
};
|
|
83641
83671
|
const response = await fetchWithTimeout(`${API_URL}/api/v1${path2}`, {
|
|
83642
83672
|
method: "POST",
|
|
@@ -83681,7 +83711,7 @@ async function main3() {
|
|
|
83681
83711
|
}
|
|
83682
83712
|
warmupInBackground();
|
|
83683
83713
|
}
|
|
83684
|
-
var import_dotenv3, import_path5, import_fs6, import_os5, DEFAULT_API_URL3, CREDENTIALS_FILE5, API_URL, AGENT_SOURCE, DEFAULT_SOURCE_TOOL, TOKEN, contextSchema, isCollecting, lastCollectTime, COLLECT_COOLDOWN_MS, mcpServer, server;
|
|
83714
|
+
var import_dotenv3, import_path5, import_fs6, import_os5, DEFAULT_API_URL3, CREDENTIALS_FILE5, API_URL, REPLAY_SESSION, REPLAY_HEADERS, AGENT_SOURCE, DEFAULT_SOURCE_TOOL, TOKEN, contextSchema, isCollecting, lastCollectTime, COLLECT_COOLDOWN_MS, mcpServer, server;
|
|
83685
83715
|
var init_mcp_server2 = __esm({
|
|
83686
83716
|
"../service-capture/agent-sessions/mcp-server.ts"() {
|
|
83687
83717
|
"use strict";
|
|
@@ -83700,6 +83730,10 @@ var init_mcp_server2 = __esm({
|
|
|
83700
83730
|
DEFAULT_API_URL3 = SERVICE_URL_DEFAULTS.haansiApiBaseUrl;
|
|
83701
83731
|
CREDENTIALS_FILE5 = (0, import_path5.join)((0, import_os5.homedir)(), ".haansi", "credentials.json");
|
|
83702
83732
|
API_URL = process.env.HAANSI_API_URL ?? DEFAULT_API_URL3;
|
|
83733
|
+
REPLAY_SESSION = /^[0-9a-f-]{36}$/i.test(
|
|
83734
|
+
process.env.HAANSI_REPLAY_SESSION?.trim() ?? ""
|
|
83735
|
+
) ? process.env.HAANSI_REPLAY_SESSION.trim() : null;
|
|
83736
|
+
REPLAY_HEADERS = REPLAY_SESSION ? { "X-Haansi-Replay-Session": REPLAY_SESSION } : {};
|
|
83703
83737
|
AGENT_SOURCE = process.env.HAANSI_AGENT_SOURCE?.toLowerCase();
|
|
83704
83738
|
DEFAULT_SOURCE_TOOL = AGENT_SOURCE === "codex" ? "codex-mcp" : "claude-code-mcp";
|
|
83705
83739
|
TOKEN = resolveToken3();
|
|
@@ -83920,6 +83954,13 @@ var init_mcp_server2 = __esm({
|
|
|
83920
83954
|
};
|
|
83921
83955
|
}
|
|
83922
83956
|
case "save_solution": {
|
|
83957
|
+
if (REPLAY_SESSION) {
|
|
83958
|
+
return {
|
|
83959
|
+
content: [
|
|
83960
|
+
{ type: "text", text: "Not saved: nothing is recorded here." }
|
|
83961
|
+
]
|
|
83962
|
+
};
|
|
83963
|
+
}
|
|
83923
83964
|
const {
|
|
83924
83965
|
problem_description,
|
|
83925
83966
|
solution_summary,
|
|
@@ -85565,13 +85606,17 @@ them all.`;
|
|
|
85565
85606
|
// src/commands/replay-tasks.ts
|
|
85566
85607
|
var replay_tasks_exports = {};
|
|
85567
85608
|
__export(replay_tasks_exports, {
|
|
85609
|
+
HAANSI_LINE: () => HAANSI_LINE,
|
|
85568
85610
|
areaOf: () => areaOf,
|
|
85569
85611
|
cardPrompt: () => cardPrompt,
|
|
85570
85612
|
changedFiles: () => changedFiles,
|
|
85613
|
+
haansiText: () => haansiText,
|
|
85614
|
+
haansiUseOf: () => haansiUseOf,
|
|
85615
|
+
mcpConfig: () => mcpConfig,
|
|
85571
85616
|
overlapOf: () => overlapOf,
|
|
85572
85617
|
runStoredReplays: () => runStoredReplays
|
|
85573
85618
|
});
|
|
85574
|
-
function cardPrompt(task, feedback) {
|
|
85619
|
+
function cardPrompt(task, feedback, arm = "baseline") {
|
|
85575
85620
|
return [
|
|
85576
85621
|
"# Task",
|
|
85577
85622
|
"",
|
|
@@ -85582,10 +85627,40 @@ function cardPrompt(task, feedback) {
|
|
|
85582
85627
|
task.card.acceptance,
|
|
85583
85628
|
...task.card.area ? ["", "## Part of the code", "", task.card.area] : [],
|
|
85584
85629
|
"",
|
|
85630
|
+
...arm === "haansi" ? [HAANSI_LINE, ""] : [],
|
|
85585
85631
|
...feedback ? [FEEDBACK_HEADER, "", "```", feedback, "```", ""] : [],
|
|
85586
85632
|
"Work in this repository as it is now. Do not look at later commits or other branches."
|
|
85587
85633
|
].join("\n");
|
|
85588
85634
|
}
|
|
85635
|
+
function mcpConfig(arm, session) {
|
|
85636
|
+
if (arm !== "haansi" || !session) return JSON.stringify({ mcpServers: {} });
|
|
85637
|
+
const base = session.apiUrl.replace(/\/+$/, "");
|
|
85638
|
+
return JSON.stringify(
|
|
85639
|
+
{
|
|
85640
|
+
mcpServers: {
|
|
85641
|
+
"haansi-solutions": {
|
|
85642
|
+
command: "haansi",
|
|
85643
|
+
args: ["mcp-server"],
|
|
85644
|
+
env: {
|
|
85645
|
+
HAANSI_API_URL: base,
|
|
85646
|
+
HAANSI_TOKEN: session.token,
|
|
85647
|
+
HAANSI_REPLAY_SESSION: session.sessionId
|
|
85648
|
+
}
|
|
85649
|
+
},
|
|
85650
|
+
"haansi-skills": {
|
|
85651
|
+
type: "http",
|
|
85652
|
+
url: `${base}/api/v1/memory/skills/mcp`,
|
|
85653
|
+
headers: {
|
|
85654
|
+
Authorization: `Bearer ${session.token}`,
|
|
85655
|
+
"X-Haansi-Replay-Session": session.sessionId
|
|
85656
|
+
}
|
|
85657
|
+
}
|
|
85658
|
+
}
|
|
85659
|
+
},
|
|
85660
|
+
null,
|
|
85661
|
+
2
|
|
85662
|
+
);
|
|
85663
|
+
}
|
|
85589
85664
|
function areaOf(path2) {
|
|
85590
85665
|
const dirs = path2.split("/").slice(0, -1);
|
|
85591
85666
|
return dirs.length ? dirs.slice(0, 2).join("/") : ".";
|
|
@@ -85644,13 +85719,7 @@ async function runStoredReplays(options, deps) {
|
|
|
85644
85719
|
(t) => states.get(t.taskId) === "valid" && t.testFiles.length > 0 && t.testFiles.every(safeTestFile) && SHA.test(t.baseSha) && SHA.test(t.targetSha)
|
|
85645
85720
|
);
|
|
85646
85721
|
const notValid = set2.tasks.length - valid.length;
|
|
85647
|
-
|
|
85648
|
-
if (arms.includes("haansi")) {
|
|
85649
|
-
deps.log(
|
|
85650
|
-
"The with-Haansi arm on stored tasks needs Haansi answering as of each task's start; running the baseline arm only."
|
|
85651
|
-
);
|
|
85652
|
-
arms = arms.filter((a) => a !== "haansi");
|
|
85653
|
-
}
|
|
85722
|
+
const arms = options.arms;
|
|
85654
85723
|
const chosen = options.limit ? valid.slice(0, options.limit) : valid;
|
|
85655
85724
|
const results = [];
|
|
85656
85725
|
for (const task of chosen) {
|
|
@@ -85670,17 +85739,27 @@ async function runStoredReplays(options, deps) {
|
|
|
85670
85739
|
for (const arm of arms) {
|
|
85671
85740
|
let changed = [];
|
|
85672
85741
|
try {
|
|
85742
|
+
const session = arm === "haansi" ? {
|
|
85743
|
+
...await deps.openSession(task.taskId),
|
|
85744
|
+
apiUrl: deps.apiUrl,
|
|
85745
|
+
token: deps.token
|
|
85746
|
+
} : null;
|
|
85747
|
+
const configPath = `${deps.workDir()}/${task.taskId}-${arm}.mcp.json`;
|
|
85748
|
+
deps.writeFile(configPath, mcpConfig(arm, session));
|
|
85673
85749
|
const r = await replayArm(
|
|
85674
85750
|
deps,
|
|
85675
85751
|
{ ...options, setupCmd, testCmd },
|
|
85676
85752
|
asTask,
|
|
85677
85753
|
arm,
|
|
85678
85754
|
null,
|
|
85679
|
-
(feedback) => cardPrompt(task, feedback),
|
|
85755
|
+
(feedback) => cardPrompt(task, feedback, arm),
|
|
85680
85756
|
async (dir) => {
|
|
85681
85757
|
changed = await changedFiles(deps, dir, task.baseSha);
|
|
85682
|
-
}
|
|
85758
|
+
},
|
|
85759
|
+
{ HAANSI_REPLAY_MCP_CONFIG: configPath }
|
|
85683
85760
|
);
|
|
85761
|
+
deps.removeFile(configPath);
|
|
85762
|
+
const haansi = session ? haansiUseOf((await deps.getCalls(session.sessionId)).calls) : null;
|
|
85684
85763
|
const overlap = overlapOf(changed, task);
|
|
85685
85764
|
results.push({
|
|
85686
85765
|
taskId: task.taskId,
|
|
@@ -85691,10 +85770,11 @@ async function runStoredReplays(options, deps) {
|
|
|
85691
85770
|
attempts: r.attempts,
|
|
85692
85771
|
maxAttempts: r.maxAttempts,
|
|
85693
85772
|
durationMs: r.durationMs,
|
|
85694
|
-
overlap
|
|
85773
|
+
overlap,
|
|
85774
|
+
haansi
|
|
85695
85775
|
});
|
|
85696
85776
|
deps.log(
|
|
85697
|
-
`${r.passed ? "pass" : "fail"} ${arm.padEnd(8)} ${label} (${r.attempts}/${r.maxAttempts} attempts; files ${pct(overlap.fileRecall)} of the target's, ${pct(overlap.filePrecision)} of its own on target)`
|
|
85777
|
+
`${r.passed ? "pass" : "fail"} ${arm.padEnd(8)} ${label} (${r.attempts}/${r.maxAttempts} attempts; files ${pct(overlap.fileRecall)} of the target's, ${pct(overlap.filePrecision)} of its own on target${haansi ? `; ${haansiText(haansi)}` : ""})`
|
|
85698
85778
|
);
|
|
85699
85779
|
} catch (err2) {
|
|
85700
85780
|
deps.log(
|
|
@@ -85721,7 +85801,16 @@ async function runStoredReplays(options, deps) {
|
|
|
85721
85801
|
}
|
|
85722
85802
|
return { results, notValid, recorded };
|
|
85723
85803
|
}
|
|
85724
|
-
|
|
85804
|
+
function haansiUseOf(calls) {
|
|
85805
|
+
return {
|
|
85806
|
+
calls: calls.length,
|
|
85807
|
+
returned: calls.reduce((n, c) => n + c.returnedIds.length, 0)
|
|
85808
|
+
};
|
|
85809
|
+
}
|
|
85810
|
+
function haansiText(use) {
|
|
85811
|
+
return use.calls === 0 ? "did not call Haansi" : `called Haansi ${use.calls}\xD7, ${use.returned} item${use.returned === 1 ? "" : "s"} returned`;
|
|
85812
|
+
}
|
|
85813
|
+
var FEEDBACK_HEADER, REPORT_CHUNK2, HAANSI_LINE, share, pct;
|
|
85725
85814
|
var init_replay_tasks = __esm({
|
|
85726
85815
|
"src/commands/replay-tasks.ts"() {
|
|
85727
85816
|
"use strict";
|
|
@@ -85729,6 +85818,7 @@ var init_replay_tasks = __esm({
|
|
|
85729
85818
|
init_replay();
|
|
85730
85819
|
FEEDBACK_HEADER = "Your previous attempt did not pass the tests. Their output ends with:";
|
|
85731
85820
|
REPORT_CHUNK2 = 200;
|
|
85821
|
+
HAANSI_LINE = "Haansi's MCP servers are available to you: they give access to your organization's knowledge (solutions to past problems, team skills, digests, guides and Exchange). Use them if they help.";
|
|
85732
85822
|
share = (part, whole) => whole === 0 ? null : Math.round(part / whole * 1e3) / 1e3;
|
|
85733
85823
|
pct = (v) => v === null ? "n/a" : `${Math.round(v * 100)}%`;
|
|
85734
85824
|
}
|
|
@@ -85902,7 +85992,7 @@ async function cleanClone(deps, dir, sha, unreachable) {
|
|
|
85902
85992
|
function cleanCheckout(deps, dir, task) {
|
|
85903
85993
|
return cleanClone(deps, dir, task.baseSha, task.targetSha);
|
|
85904
85994
|
}
|
|
85905
|
-
async function replayArm(deps, options, task, arm, playbook, promptOf = (feedback) => replayPrompt(task, arm, feedback), inspect) {
|
|
85995
|
+
async function replayArm(deps, options, task, arm, playbook, promptOf = (feedback) => replayPrompt(task, arm, feedback), inspect, agentEnv = {}) {
|
|
85906
85996
|
const started = deps.now();
|
|
85907
85997
|
const dir = (0, import_node_path10.join)(
|
|
85908
85998
|
deps.workDir(),
|
|
@@ -85931,6 +86021,11 @@ async function replayArm(deps, options, task, arm, playbook, promptOf = (feedbac
|
|
|
85931
86021
|
deps.log(`\u2026 ${label}: set up in ${since(at)}`);
|
|
85932
86022
|
}
|
|
85933
86023
|
const promptFile = (0, import_node_path10.join)(dir, ".haansi-replay", "prompt.md");
|
|
86024
|
+
let mcpConfigFile = agentEnv.HAANSI_REPLAY_MCP_CONFIG;
|
|
86025
|
+
if (!mcpConfigFile) {
|
|
86026
|
+
mcpConfigFile = `${dir}.mcp.json`;
|
|
86027
|
+
deps.writeFile(mcpConfigFile, JSON.stringify({ mcpServers: {} }));
|
|
86028
|
+
}
|
|
85934
86029
|
if (arm === "haansi" && playbook)
|
|
85935
86030
|
deps.writeFile(
|
|
85936
86031
|
(0, import_node_path10.join)(dir, ".haansi-replay", "playbook.md"),
|
|
@@ -85947,7 +86042,12 @@ async function replayArm(deps, options, task, arm, playbook, promptOf = (feedbac
|
|
|
85947
86042
|
await deps.shell(
|
|
85948
86043
|
options.agentCmd,
|
|
85949
86044
|
dir,
|
|
85950
|
-
{
|
|
86045
|
+
{
|
|
86046
|
+
...agentEnv,
|
|
86047
|
+
HAANSI_REPLAY_MCP_CONFIG: mcpConfigFile,
|
|
86048
|
+
HAANSI_REPLAY_PROMPT: prompt2,
|
|
86049
|
+
HAANSI_REPLAY_PROMPT_FILE: promptFile
|
|
86050
|
+
},
|
|
85951
86051
|
options.timeoutMs
|
|
85952
86052
|
);
|
|
85953
86053
|
const own = new Map(files.map((f) => [f, deps.readFile((0, import_node_path10.join)(dir, f))]));
|
|
@@ -86001,6 +86101,7 @@ async function replayArm(deps, options, task, arm, playbook, promptOf = (feedbac
|
|
|
86001
86101
|
};
|
|
86002
86102
|
} finally {
|
|
86003
86103
|
deps.removeDir(dir);
|
|
86104
|
+
if (!agentEnv.HAANSI_REPLAY_MCP_CONFIG) deps.removeFile(`${dir}.mcp.json`);
|
|
86004
86105
|
}
|
|
86005
86106
|
}
|
|
86006
86107
|
async function runReplays(options, deps) {
|
|
@@ -86222,12 +86323,28 @@ async function replayStored(options, token, apiUrl2) {
|
|
|
86222
86323
|
apiUrl2
|
|
86223
86324
|
),
|
|
86224
86325
|
env: process.env,
|
|
86225
|
-
cliVersion: cliVersion2()
|
|
86326
|
+
cliVersion: cliVersion2(),
|
|
86327
|
+
openSession: async (taskId) => await apiPost2(
|
|
86328
|
+
`/memory/replays/tasks/${encodeURIComponent(taskId)}/sessions`,
|
|
86329
|
+
{},
|
|
86330
|
+
token,
|
|
86331
|
+
apiUrl2
|
|
86332
|
+
),
|
|
86333
|
+
getCalls: (sessionId) => apiGet3(
|
|
86334
|
+
`/memory/replays/sessions/${encodeURIComponent(sessionId)}/calls`,
|
|
86335
|
+
token,
|
|
86336
|
+
apiUrl2
|
|
86337
|
+
),
|
|
86338
|
+
apiUrl: apiUrl2,
|
|
86339
|
+
token
|
|
86226
86340
|
});
|
|
86227
|
-
const
|
|
86341
|
+
const arm = (a) => {
|
|
86342
|
+
const mine = results.filter((r) => r.arm === a);
|
|
86343
|
+
return `${mine.filter((r) => r.passed).length}/${mine.length}`;
|
|
86344
|
+
};
|
|
86228
86345
|
console.log(
|
|
86229
86346
|
`
|
|
86230
|
-
Baseline: ${passed
|
|
86347
|
+
Baseline: ${arm("baseline")} passed \xB7 With Haansi: ${arm("haansi")} passed \xB7 ${notValid} task(s) not valid to replay`
|
|
86231
86348
|
);
|
|
86232
86349
|
console.log(
|
|
86233
86350
|
recorded === null ? options.dryRun ? "Dry run: nothing reported." : "Nothing to report." : `Reported ${recorded} result(s) to Haansi.`
|
|
@@ -86272,7 +86389,7 @@ repository in Haansi (Settings \u2192 Data sources) for any not given here.
|
|
|
86272
86389
|
|
|
86273
86390
|
Run from a clone of the repository. Example (GitHub Actions):
|
|
86274
86391
|
haansi replay run --family "$FAMILY_ID" --setup-cmd 'npm ci' \\
|
|
86275
|
-
--agent-cmd 'claude -p "$HAANSI_REPLAY_PROMPT" --permission-mode acceptEdits' \\
|
|
86392
|
+
--agent-cmd 'claude -p "$HAANSI_REPLAY_PROMPT" --permission-mode acceptEdits --mcp-config "$HAANSI_REPLAY_MCP_CONFIG"' \\
|
|
86276
86393
|
--test-cmd 'npx vitest run $HAANSI_REPLAY_TEST_FILES' \\
|
|
86277
86394
|
--agent-name claude-code --model claude-sonnet-5-5`;
|
|
86278
86395
|
}
|