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.
- package/README.md +4 -4
- package/agent-runtime/dialogWritePlan.ts +39 -0
- package/agent-runtime/hostAdapter.ts +4 -0
- package/agent-runtime/hybridRecordStore.ts +1 -1
- package/agent-runtime/index.ts +15 -0
- package/agent-runtime/localLoop.ts +87 -7
- package/agent-runtime/localToolPolicy.ts +2 -13
- package/agent-runtime/localWorkspaceTools.ts +42 -110
- package/agent-runtime/runtimeToolPolicy.ts +2 -11
- package/agent-runtime/runtimeToolSurface.ts +198 -0
- package/agent-runtime/types.ts +1 -0
- package/agentAliases.ts +2 -1
- package/agentRunCommand.ts +10 -32
- package/agentRuntimeLocal.ts +1 -0
- package/ai/agent/cliExecutor.ts +249 -34
- package/cli/agentAliases.ts +2 -1
- package/cli/agentRunCommand.ts +10 -32
- package/cli/agentRuntimeLocal.ts +1 -0
- package/cli/client/agentRun.ts +40 -87
- package/cli/client/localRuntimeAdapter.ts +179 -26
- package/cli/commandRegistry.ts +2 -2
- package/cli/machineWsRunDispatch.ts +51 -6
- package/cli/offlineMarxistsAgentCommand.ts +6 -4
- package/client/agentConfigResolver.test.ts +2 -2
- package/client/agentRun.test.ts +123 -57
- package/client/agentRun.ts +40 -87
- package/client/localRuntimeAdapter.test.ts +245 -31
- package/client/localRuntimeAdapter.ts +179 -26
- package/client/localRuntimeDryRun.test.ts +23 -9
- package/client/localToolPolicy.test.ts +4 -4
- package/commandRegistry.ts +2 -2
- package/database/server/levelAuthorityStore.ts +20 -1
- package/machineWsRunDispatch.ts +51 -6
- package/offlineMarxistsAgentCommand.ts +6 -4
- 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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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: ["
|
|
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(
|
|
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: ["
|
|
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: ["
|
|
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: "
|
|
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
|
-
|
|
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: "
|
|
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("
|
|
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
|
|
1217
|
+
const result = await adapter.executeTool({
|
|
1056
1218
|
id: "call-1",
|
|
1057
1219
|
name: "execShell",
|
|
1058
1220
|
arguments: "{\"cmd\":\"pwd\"}",
|
|
1059
|
-
})
|
|
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
|
|
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
|
|
1577
|
+
test("runs execShell locally by default", async () => {
|
|
1360
1578
|
const adapter = createCliLocalRuntimeAdapter({
|
|
1361
|
-
env: {
|
|
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
|
|
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'
|
|
1430
|
-
: "
|
|
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("
|
|
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: ["
|
|
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: "
|
|
1929
|
+
name: "writeFile",
|
|
1716
1930
|
arguments: JSON.stringify({
|
|
1717
1931
|
path: "src/app.ts",
|
|
1718
1932
|
content: "export const cliValue = 1;\n",
|