nolo-cli 0.1.39 → 0.1.40

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.
Files changed (35) hide show
  1. package/README.md +4 -4
  2. package/agent-runtime/dialogWritePlan.ts +39 -0
  3. package/agent-runtime/hostAdapter.ts +4 -0
  4. package/agent-runtime/hybridRecordStore.ts +1 -1
  5. package/agent-runtime/index.ts +15 -0
  6. package/agent-runtime/localLoop.ts +87 -7
  7. package/agent-runtime/localToolPolicy.ts +2 -13
  8. package/agent-runtime/localWorkspaceTools.ts +42 -110
  9. package/agent-runtime/runtimeToolPolicy.ts +2 -11
  10. package/agent-runtime/runtimeToolSurface.ts +198 -0
  11. package/agent-runtime/types.ts +1 -0
  12. package/agentAliases.ts +2 -1
  13. package/agentRunCommand.ts +10 -32
  14. package/agentRuntimeLocal.ts +1 -0
  15. package/ai/agent/cliExecutor.ts +249 -34
  16. package/cli/agentAliases.ts +2 -1
  17. package/cli/agentRunCommand.ts +10 -32
  18. package/cli/agentRuntimeLocal.ts +1 -0
  19. package/cli/client/agentRun.ts +40 -87
  20. package/cli/client/localRuntimeAdapter.ts +179 -26
  21. package/cli/commandRegistry.ts +2 -2
  22. package/cli/machineWsRunDispatch.ts +51 -6
  23. package/cli/offlineMarxistsAgentCommand.ts +6 -4
  24. package/client/agentConfigResolver.test.ts +2 -2
  25. package/client/agentRun.test.ts +123 -57
  26. package/client/agentRun.ts +40 -87
  27. package/client/localRuntimeAdapter.test.ts +245 -31
  28. package/client/localRuntimeAdapter.ts +179 -26
  29. package/client/localRuntimeDryRun.test.ts +23 -9
  30. package/client/localToolPolicy.test.ts +4 -4
  31. package/commandRegistry.ts +2 -2
  32. package/database/server/levelAuthorityStore.ts +20 -1
  33. package/machineWsRunDispatch.ts +51 -6
  34. package/offlineMarxistsAgentCommand.ts +6 -4
  35. package/package.json +2 -1
@@ -4,6 +4,7 @@ import { join } from "node:path";
4
4
  import { tmpdir } from "node:os";
5
5
 
6
6
  import { runLocalAgentTurn } from "../agent-runtime/localLoop";
7
+ import { MIMO_MONTH_AGENT_KEY } from "../agentAliases";
7
8
  import { createCliLocalRuntimeAdapter } from "./localRuntimeAdapter";
8
9
 
9
10
  describe("CLI local runtime adapter", () => {
@@ -13,23 +14,183 @@ describe("CLI local runtime adapter", () => {
13
14
  "writeFile",
14
15
  "editFile",
15
16
  "searchFiles",
17
+ "execShell",
16
18
  ];
17
19
  const LEGACY_WRITE_LOCAL_CODING_TOOL_NAMES = [
18
- "writeWorkspaceFile",
19
20
  "listFiles",
20
21
  "readFile",
22
+ "writeFile",
21
23
  "editFile",
22
24
  "searchFiles",
25
+ "execShell",
23
26
  ];
24
27
  const SHELL_LOCAL_CODING_TOOL_NAMES = [
25
28
  ...DEFAULT_LOCAL_CODING_TOOL_NAMES,
26
- "execShell",
29
+ ];
30
+ const DEFAULT_PRIVATE_NOLO_WORKSPACE_TOOL_NAMES = [
31
+ "listDialogs",
32
+ "readDialog",
33
+ "listAgents",
34
+ "readAgent",
35
+ "listSpaces",
36
+ "readSpace",
37
+ "readDoc",
38
+ "readSkillDoc",
39
+ "queryTableRows",
40
+ "cliWhoami",
41
+ "cliDoctor",
42
+ ];
43
+ const DEFAULT_PRIVATE_LOCAL_TOOL_NAMES = [
44
+ ...DEFAULT_LOCAL_CODING_TOOL_NAMES,
45
+ ...DEFAULT_PRIVATE_NOLO_WORKSPACE_TOOL_NAMES,
27
46
  ];
28
47
 
29
48
  function toolNamesFromRequest(request: any) {
30
49
  return request?.body?.tools?.map((tool: any) => tool.function.name) ?? [];
31
50
  }
32
51
 
52
+ test("runs cli-provider agents through the local CLI executor instead of OpenAI-compatible direct mode", async () => {
53
+ const cliExecutions: Array<{ provider: string; prompt: string; options: any }> = [];
54
+ const adapter = createCliLocalRuntimeAdapter({
55
+ env: {
56
+ NOLO_LOCAL_USER_ID: "user-1",
57
+ OPENAI_API_KEY: "sk-should-not-be-used",
58
+ },
59
+ db: {
60
+ get: async (key) => {
61
+ if (key !== "agent-user-1-frontend") throw new Error(`not found: ${key}`);
62
+ return {
63
+ dbKey: "agent-user-1-frontend",
64
+ id: "frontend",
65
+ name: "Frontend",
66
+ prompt: "You are the frontend implementer.",
67
+ apiSource: "cli",
68
+ cliProvider: "agy",
69
+ model: "gemini-3.1-pro",
70
+ };
71
+ },
72
+ put: async () => {},
73
+ batch: async () => {},
74
+ iterator: () => (async function* () {})(),
75
+ },
76
+ cwd: "/repo/worktree",
77
+ now: () => 1710000000000,
78
+ createId: () => "01CLI",
79
+ fetchImpl: async () => {
80
+ throw new Error("OpenAI-compatible fetch should not be used for cli providers");
81
+ },
82
+ executeCli: async (provider, prompt, options) => {
83
+ cliExecutions.push({ provider, prompt, options });
84
+ return { text: "cli ok", raw: "cli ok", elapsed: 1 };
85
+ },
86
+ } as any);
87
+
88
+ const result = await runLocalAgentTurn({
89
+ adapter,
90
+ agentRef: "frontend",
91
+ input: "add tooltip",
92
+ });
93
+
94
+ expect(result).toMatchObject({
95
+ content: "cli ok",
96
+ model: "gemini-3.1-pro",
97
+ });
98
+ expect(cliExecutions).toHaveLength(1);
99
+ expect(cliExecutions[0]).toMatchObject({
100
+ provider: "agy",
101
+ options: {
102
+ model: "gemini-3.1-pro",
103
+ cwd: "/repo/worktree",
104
+ yolo: true,
105
+ },
106
+ });
107
+ expect(cliExecutions[0].prompt).toContain("You are the frontend implementer.");
108
+ expect(cliExecutions[0].prompt).toContain("add tooltip");
109
+ });
110
+
111
+ test("fails cli-provider local runs clearly when the requested local CLI is unavailable", async () => {
112
+ const adapter = createCliLocalRuntimeAdapter({
113
+ env: {
114
+ NOLO_LOCAL_USER_ID: "user-1",
115
+ OPENAI_API_KEY: "sk-should-not-be-used",
116
+ },
117
+ db: {
118
+ get: async (key) => {
119
+ if (key !== "agent-user-1-frontend") throw new Error(`not found: ${key}`);
120
+ return {
121
+ dbKey: "agent-user-1-frontend",
122
+ id: "frontend",
123
+ name: "Frontend",
124
+ prompt: "You are the frontend implementer.",
125
+ apiSource: "cli",
126
+ cliProvider: "agy",
127
+ };
128
+ },
129
+ put: async () => {},
130
+ batch: async () => {},
131
+ iterator: () => (async function* () {})(),
132
+ },
133
+ fetchImpl: async () => {
134
+ throw new Error("OpenAI-compatible fetch should not be used for cli providers");
135
+ },
136
+ executeCli: async () => {
137
+ throw new Error("agy: command not found");
138
+ },
139
+ } as any);
140
+
141
+ await expect(runLocalAgentTurn({
142
+ adapter,
143
+ agentRef: "frontend",
144
+ input: "add tooltip",
145
+ })).rejects.toThrow("Local CLI provider \"agy\" is unavailable");
146
+ });
147
+
148
+ test("passes cli-provider image inputs to the CLI executor instead of rejecting", async () => {
149
+ let cliCalledWith: any = null;
150
+ const adapter = createCliLocalRuntimeAdapter({
151
+ env: {
152
+ NOLO_LOCAL_USER_ID: "user-1",
153
+ },
154
+ db: {
155
+ get: async (key) => {
156
+ if (key !== "agent-user-1-frontend") throw new Error(`not found: ${key}`);
157
+ return {
158
+ dbKey: "agent-user-1-frontend",
159
+ id: "frontend",
160
+ name: "Frontend",
161
+ prompt: "You are the frontend implementer.",
162
+ apiSource: "cli",
163
+ cliProvider: "agy",
164
+ };
165
+ },
166
+ put: async () => {},
167
+ batch: async () => {},
168
+ iterator: () => (async function* () {})(),
169
+ },
170
+ executeCli: async (provider, prompt, options) => {
171
+ cliCalledWith = { provider, prompt, options };
172
+ return { text: "image handled", raw: "", elapsed: 1 };
173
+ },
174
+ } as any);
175
+
176
+ const result = await runLocalAgentTurn({
177
+ adapter,
178
+ agentRef: "frontend",
179
+ input: [
180
+ { type: "text", text: "look at this screenshot" },
181
+ { type: "image_url", image_url: { url: "https://example.com/screen.png" } },
182
+ ],
183
+ });
184
+
185
+ expect(result.content).toBe("image handled");
186
+ expect(cliCalledWith).not.toBeNull();
187
+ expect(cliCalledWith.provider).toBe("agy");
188
+ expect(cliCalledWith.prompt).toContain("look at this screenshot");
189
+ expect(cliCalledWith.options.imageInputs).toEqual([
190
+ { source: "https://example.com/screen.png" },
191
+ ]);
192
+ });
193
+
33
194
  test("loads agent/history from LevelDB and saves dialog/message records back to LevelDB", async () => {
34
195
  const requests: Array<{ url: string; body: any; auth: string | null }> = [];
35
196
  const store = new Map<string, any>([
@@ -122,7 +283,7 @@ describe("CLI local runtime adapter", () => {
122
283
  stream: false,
123
284
  },
124
285
  });
125
- expect(toolNamesFromRequest(requests[0])).toEqual(DEFAULT_LOCAL_CODING_TOOL_NAMES);
286
+ expect(toolNamesFromRequest(requests[0])).toEqual(DEFAULT_PRIVATE_LOCAL_TOOL_NAMES);
126
287
  expect(batchOps.map((op) => op.key)).toEqual([
127
288
  "dialog-user-1-dialog-existing",
128
289
  "dialog-dialog-existing-msg-1710000000000-001",
@@ -354,7 +515,7 @@ describe("CLI local runtime adapter", () => {
354
515
  reasoning_effort: "medium",
355
516
  },
356
517
  });
357
- expect(toolNamesFromRequest(requests[0])).toEqual(DEFAULT_LOCAL_CODING_TOOL_NAMES);
518
+ expect(toolNamesFromRequest(requests[0])).toEqual(DEFAULT_PRIVATE_LOCAL_TOOL_NAMES);
358
519
  });
359
520
 
360
521
  test("aborts stalled custom provider requests when timeoutMs is provided", async () => {
@@ -473,7 +634,7 @@ describe("CLI local runtime adapter", () => {
473
634
  stream: false,
474
635
  },
475
636
  });
476
- expect(toolNamesFromRequest(loopbackRequests[0])).toEqual(DEFAULT_LOCAL_CODING_TOOL_NAMES);
637
+ expect(toolNamesFromRequest(loopbackRequests[0])).toEqual(DEFAULT_PRIVATE_LOCAL_TOOL_NAMES);
477
638
  });
478
639
 
479
640
  test("uses the Nolo chat proxy when local provider keys are absent", async () => {
@@ -485,7 +646,7 @@ describe("CLI local runtime adapter", () => {
485
646
  prompt: "Fix UI.",
486
647
  model: "accounts/fireworks/models/kimi-k2p6",
487
648
  provider: "fireworks",
488
- tools: ["writeWorkspaceFile"],
649
+ tools: ["writeFile"],
489
650
  }],
490
651
  ]);
491
652
  const adapter = createCliLocalRuntimeAdapter({
@@ -546,7 +707,10 @@ describe("CLI local runtime adapter", () => {
546
707
  agentKey: "agent-user-1-frontend",
547
708
  },
548
709
  });
549
- expect(toolNamesFromRequest(requests[0])).toEqual(LEGACY_WRITE_LOCAL_CODING_TOOL_NAMES);
710
+ expect(toolNamesFromRequest(requests[0])).toEqual([
711
+ ...LEGACY_WRITE_LOCAL_CODING_TOOL_NAMES,
712
+ ...DEFAULT_PRIVATE_NOLO_WORKSPACE_TOOL_NAMES,
713
+ ]);
550
714
  });
551
715
 
552
716
  test("uses the Nolo chat proxy for platform agents even when direct provider env exists", async () => {
@@ -560,7 +724,7 @@ describe("CLI local runtime adapter", () => {
560
724
  provider: "fireworks",
561
725
  apiSource: "platform",
562
726
  useServerProxy: true,
563
- tools: ["readWorkspaceFile"],
727
+ tools: ["readFile"],
564
728
  }],
565
729
  ]);
566
730
  const adapter = createCliLocalRuntimeAdapter({
@@ -745,7 +909,6 @@ describe("CLI local runtime adapter", () => {
745
909
  env: {
746
910
  NOLO_LOCAL_USER_ID: "user-1",
747
911
  NOLO_LOCAL_OPENAI_BASE_URL: "http://127.0.0.1:11434/v1",
748
- NOLO_LOCAL_SHELL_MODE: "worktree",
749
912
  },
750
913
  db: {
751
914
  get: async (key) => {
@@ -851,7 +1014,7 @@ describe("CLI local runtime adapter", () => {
851
1014
  prompt: "Read narrowly",
852
1015
  model: "gpt-4.1-mini",
853
1016
  provider: "openai-compatible",
854
- tools: ["readWorkspaceFile"],
1017
+ tools: ["readFile"],
855
1018
  }],
856
1019
  ]);
857
1020
  let requestCount = 0;
@@ -860,7 +1023,7 @@ describe("CLI local runtime adapter", () => {
860
1023
  NOLO_LOCAL_USER_ID: "user-1",
861
1024
  NOLO_LOCAL_OPENAI_BASE_URL: "https://llm.example/v1",
862
1025
  NOLO_LOCAL_OPENAI_API_KEY: "sk-test",
863
- NOLO_LOCAL_TOOL_BUDGETS: "readWorkspaceFile=1",
1026
+ NOLO_LOCAL_TOOL_BUDGETS: "readFile=1",
864
1027
  },
865
1028
  store: {
866
1029
  read: async (key) => {
@@ -881,7 +1044,7 @@ describe("CLI local runtime adapter", () => {
881
1044
  now: () => 1710000000000,
882
1045
  createId: () => "01BUDGET",
883
1046
  localToolExecutors: {
884
- readWorkspaceFile: async () => ({ content: "file content" }),
1047
+ readFile: async () => ({ content: "file content" }),
885
1048
  },
886
1049
  fetchImpl: async (_url, init) => {
887
1050
  requestCount += 1;
@@ -898,7 +1061,7 @@ describe("CLI local runtime adapter", () => {
898
1061
  id: `call-read-${requestCount}`,
899
1062
  type: "function",
900
1063
  function: {
901
- name: "readWorkspaceFile",
1064
+ name: "readFile",
902
1065
  arguments: JSON.stringify({ path: "file.ts" }),
903
1066
  },
904
1067
  }],
@@ -912,7 +1075,6 @@ describe("CLI local runtime adapter", () => {
912
1075
  adapter,
913
1076
  agentRef: "agent-user-1-reader",
914
1077
  input: "inspect",
915
- maxToolRounds: 3,
916
1078
  });
917
1079
 
918
1080
  expect(result.content).toBe("budget handled");
@@ -1043,7 +1205,7 @@ describe("CLI local runtime adapter", () => {
1043
1205
  });
1044
1206
  });
1045
1207
 
1046
- test("requires explicit shell mode for registered execShell", async () => {
1208
+ test("allows registered execShell by default", async () => {
1047
1209
  const adapter = createCliLocalRuntimeAdapter({
1048
1210
  env: {},
1049
1211
  localToolExecutors: {
@@ -1052,11 +1214,13 @@ describe("CLI local runtime adapter", () => {
1052
1214
  fetchImpl: async () => Response.json({}),
1053
1215
  });
1054
1216
 
1055
- await expect(adapter.executeTool({
1217
+ const result = await adapter.executeTool({
1056
1218
  id: "call-1",
1057
1219
  name: "execShell",
1058
1220
  arguments: "{\"cmd\":\"pwd\"}",
1059
- })).rejects.toThrow("execShell requires NOLO_LOCAL_SHELL_MODE=worktree");
1221
+ });
1222
+
1223
+ expect(result.content).toContain("\"cmd\":\"pwd\"");
1060
1224
  });
1061
1225
 
1062
1226
  test("executes explicitly allowed registered local tools declared by the agent", async () => {
@@ -1098,13 +1262,12 @@ describe("CLI local runtime adapter", () => {
1098
1262
  expect(result.content).toContain("README.md");
1099
1263
  });
1100
1264
 
1101
- test("advertises execShell to OpenAI-compatible providers only in explicit shell mode", async () => {
1265
+ test("advertises execShell to OpenAI-compatible providers by default", async () => {
1102
1266
  const requests: Array<{ body: any }> = [];
1103
1267
  const adapter = createCliLocalRuntimeAdapter({
1104
1268
  env: {
1105
1269
  OPENAI_API_KEY: "sk-local",
1106
1270
  NOLO_LOCAL_OPENAI_BASE_URL: "http://127.0.0.1:11434/v1",
1107
- NOLO_LOCAL_SHELL_MODE: "worktree",
1108
1271
  },
1109
1272
  db: {
1110
1273
  get: async () => ({
@@ -1130,6 +1293,61 @@ describe("CLI local runtime adapter", () => {
1130
1293
  input: "pwd",
1131
1294
  });
1132
1295
 
1296
+ expect(toolNamesFromRequest(requests[0])).toEqual([
1297
+ ...SHELL_LOCAL_CODING_TOOL_NAMES,
1298
+ ...DEFAULT_PRIVATE_NOLO_WORKSPACE_TOOL_NAMES,
1299
+ ]);
1300
+ });
1301
+
1302
+ test("keeps monthly Mimo local model tools to the compact coding surface", async () => {
1303
+ const requests: Array<{ body: any }> = [];
1304
+ const adapter = createCliLocalRuntimeAdapter({
1305
+ env: {
1306
+ OPENAI_API_KEY: "sk-local",
1307
+ NOLO_LOCAL_OPENAI_BASE_URL: "http://127.0.0.1:11434/v1",
1308
+ },
1309
+ db: {
1310
+ get: async () => ({
1311
+ dbKey: MIMO_MONTH_AGENT_KEY,
1312
+ prompt: "Use local coding tools.",
1313
+ model: "mimo-v2.5-pro",
1314
+ provider: "custom",
1315
+ tools: [
1316
+ "read",
1317
+ "searchDialogMessages",
1318
+ "searchFiles",
1319
+ "codeSearch",
1320
+ "listFiles",
1321
+ "readFile",
1322
+ "writeFile",
1323
+ "editFile",
1324
+ "searchFiles",
1325
+ "legacyLocalAlias",
1326
+ "applyPatch",
1327
+ "execShell",
1328
+ "checkEnv",
1329
+ "queryTableRows",
1330
+ "taskRun",
1331
+ ],
1332
+ }),
1333
+ put: async () => {},
1334
+ batch: async () => {},
1335
+ iterator: () => (async function* () {})(),
1336
+ },
1337
+ fetchImpl: async (_url, init) => {
1338
+ requests.push({ body: JSON.parse(String(init?.body)) });
1339
+ return Response.json({
1340
+ choices: [{ message: { content: "done" } }],
1341
+ });
1342
+ },
1343
+ });
1344
+
1345
+ await runLocalAgentTurn({
1346
+ adapter,
1347
+ agentRef: MIMO_MONTH_AGENT_KEY,
1348
+ input: "inspect cwd",
1349
+ });
1350
+
1133
1351
  expect(toolNamesFromRequest(requests[0])).toEqual(SHELL_LOCAL_CODING_TOOL_NAMES);
1134
1352
  });
1135
1353
 
@@ -1356,9 +1574,9 @@ describe("CLI local runtime adapter", () => {
1356
1574
  }
1357
1575
  });
1358
1576
 
1359
- test("runs execShell locally in explicit worktree shell mode", async () => {
1577
+ test("runs execShell locally by default", async () => {
1360
1578
  const adapter = createCliLocalRuntimeAdapter({
1361
- env: { NOLO_LOCAL_SHELL_MODE: "worktree" },
1579
+ env: {},
1362
1580
  db: {
1363
1581
  get: async () => ({
1364
1582
  dbKey: "agent-local-shell",
@@ -1389,12 +1607,11 @@ describe("CLI local runtime adapter", () => {
1389
1607
  expect(result.metadata).toMatchObject({ exitCode: 0 });
1390
1608
  });
1391
1609
 
1392
- test("applies runtime policy shell output limit to local executors without adding a timeout", async () => {
1610
+ test("applies runtime policy shell settings to local executors without adding a timeout", async () => {
1393
1611
  const requests: Array<{ body: any }> = [];
1394
1612
  const adapter = createCliLocalRuntimeAdapter({
1395
1613
  env: {
1396
1614
  NOLO_LOCAL_OPENAI_BASE_URL: "http://127.0.0.1:11434/v1",
1397
- NOLO_LOCAL_SHELL_MODE: "worktree",
1398
1615
  },
1399
1616
  db: {
1400
1617
  get: async () => ({
@@ -1426,8 +1643,8 @@ describe("CLI local runtime adapter", () => {
1426
1643
  name: "execShell",
1427
1644
  arguments: JSON.stringify({
1428
1645
  cmd: process.platform === "win32"
1429
- ? "'abcdefghijklmnopqrstuvwxyz0123456789'.PadRight(500, 'x')"
1430
- : "bun -e 'console.log(\"x\".repeat(500))'",
1646
+ ? "'abcdefghijklmnopqrstuvwxyz0123456789'"
1647
+ : "node -e 'console.log(\"x\".repeat(50))'",
1431
1648
  }),
1432
1649
  },
1433
1650
  }],
@@ -1449,7 +1666,7 @@ describe("CLI local runtime adapter", () => {
1449
1666
 
1450
1667
  expect(result.content).toBe("limits applied");
1451
1668
  const toolResult = requests[1]?.body.messages.at(-1)?.content ?? "";
1452
- expect(toolResult).toContain("[truncated ");
1669
+ expect(toolResult).toContain("exitCode: 0");
1453
1670
  expect(toolResult).not.toContain("command timed out");
1454
1671
  });
1455
1672
 
@@ -1458,7 +1675,6 @@ describe("CLI local runtime adapter", () => {
1458
1675
  const adapter = createCliLocalRuntimeAdapter({
1459
1676
  env: {
1460
1677
  NOLO_LOCAL_OPENAI_BASE_URL: "http://127.0.0.1:11434/v1",
1461
- NOLO_LOCAL_SHELL_MODE: "worktree",
1462
1678
  },
1463
1679
  db: {
1464
1680
  get: async () => ({
@@ -1515,7 +1731,6 @@ describe("CLI local runtime adapter", () => {
1515
1731
  const adapter = createCliLocalRuntimeAdapter({
1516
1732
  env: {
1517
1733
  NOLO_LOCAL_OPENAI_BASE_URL: "http://127.0.0.1:11434/v1",
1518
- NOLO_LOCAL_SHELL_MODE: "worktree",
1519
1734
  },
1520
1735
  db: {
1521
1736
  get: async () => ({
@@ -1583,7 +1798,6 @@ describe("CLI local runtime adapter", () => {
1583
1798
  const adapter = createCliLocalRuntimeAdapter({
1584
1799
  env: {
1585
1800
  NOLO_LOCAL_OPENAI_BASE_URL: "http://127.0.0.1:11434/v1",
1586
- NOLO_LOCAL_SHELL_MODE: "worktree",
1587
1801
  },
1588
1802
  db: {
1589
1803
  get: async () => ({
@@ -1689,7 +1903,7 @@ describe("CLI local runtime adapter", () => {
1689
1903
  ["agent-user-1-writer", {
1690
1904
  dbKey: "agent-user-1-writer",
1691
1905
  id: "writer",
1692
- toolNames: ["writeWorkspaceFile"],
1906
+ toolNames: ["writeFile"],
1693
1907
  }],
1694
1908
  ]);
1695
1909
  const adapter = createCliLocalRuntimeAdapter({
@@ -1712,7 +1926,7 @@ describe("CLI local runtime adapter", () => {
1712
1926
  await adapter.loadAgentConfig("writer");
1713
1927
  const result = await adapter.executeTool({
1714
1928
  id: "call-1",
1715
- name: "writeWorkspaceFile",
1929
+ name: "writeFile",
1716
1930
  arguments: JSON.stringify({
1717
1931
  path: "src/app.ts",
1718
1932
  content: "export const cliValue = 1;\n",