nolo-cli 0.1.32 → 0.1.34

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 (234) hide show
  1. package/README.md +4 -10
  2. package/agent-runtime/agentRecordConfig.ts +10 -0
  3. package/agent-runtime/hostAdapter.ts +10 -1
  4. package/agent-runtime/index.ts +9 -20
  5. package/agent-runtime/localLoop.ts +49 -2
  6. package/agent-runtime/localToolPolicy.ts +76 -34
  7. package/agent-runtime/localWorkspaceTools.ts +30 -333
  8. package/agent-runtime/openAiCompatibleProvider.ts +7 -3
  9. package/agent-runtime/openAiCompatibleProviderConfig.ts +15 -26
  10. package/agent-runtime/platformChatProvider.ts +47 -73
  11. package/agent-runtime/providerResolution.ts +244 -0
  12. package/agent-runtime/runtimeToolPolicy.ts +77 -29
  13. package/agent-runtime/shellCommandPolicy.ts +120 -0
  14. package/agentAliases.ts +14 -83
  15. package/agentCommandSupport.ts +3 -6
  16. package/agentInternalCommandEntries.ts +4 -13
  17. package/agentListCommands.ts +18 -27
  18. package/agentMachineCommands.ts +40 -336
  19. package/agentPullCommand.ts +30 -55
  20. package/agentRecordCommands.ts +84 -1
  21. package/agentRecordHelpers.ts +102 -186
  22. package/agentRunCommand.ts +438 -107
  23. package/agentRuntimeLocal.ts +2 -9
  24. package/ai/agent/cliExecutor.ts +19 -323
  25. package/ai/tools/toolNameAliases.ts +70 -0
  26. package/authCommands.ts +2 -36
  27. package/cli/agentAliases.ts +14 -83
  28. package/cli/agentCommandSupport.ts +3 -6
  29. package/cli/agentInternalCommandEntries.ts +4 -13
  30. package/cli/agentListCommands.ts +18 -27
  31. package/cli/agentMachineCommands.ts +40 -336
  32. package/cli/agentPullCommand.ts +30 -55
  33. package/cli/agentRecordCommands.ts +84 -1
  34. package/cli/agentRecordHelpers.ts +102 -186
  35. package/cli/agentRunCommand.ts +438 -107
  36. package/cli/agentRuntimeLocal.ts +2 -9
  37. package/cli/authCommands.ts +2 -36
  38. package/cli/cliCommandDispatch.ts +2 -2
  39. package/cli/cliEnvHelpers.ts +34 -107
  40. package/cli/client/agentRun.ts +854 -57
  41. package/cli/client/localRuntimeAdapter.ts +59 -159
  42. package/cli/client/streamingOutput.ts +3 -1
  43. package/cli/client/taskRunPrompt.ts +24 -7
  44. package/cli/commandRegistry.ts +4 -5
  45. package/cli/connectorRunArtifact.ts +10 -34
  46. package/cli/connectorWebSocketTarget.ts +6 -10
  47. package/cli/internalCommandEntries.ts +0 -8
  48. package/cli/localRuntimeDb.ts +2 -39
  49. package/cli/machineCommands.ts +189 -190
  50. package/cli/machineDaemonCommands.ts +165 -9
  51. package/cli/machineHeartbeatCommands.ts +2 -1
  52. package/cli/machineStatusCommands.ts +13 -5
  53. package/cli/machineWatchCommands.ts +1 -1
  54. package/cli/machineWsRunDispatch.ts +30 -44
  55. package/cli/machineWsSession.ts +0 -2
  56. package/cli/offlineMarxistsAgentCommand.ts +314 -0
  57. package/cli/runtimeDoctorCommands.ts +72 -15
  58. package/cli/scriptCommandEntries.ts +45 -5
  59. package/cli/tableCommands.ts +133 -33
  60. package/cli/taskRunCommand.ts +211 -16
  61. package/cli/tui/session.ts +372 -43
  62. package/cli/workflowInternalCommandEntries.ts +0 -20
  63. package/cliCommandDispatch.ts +2 -2
  64. package/cliEnvHelpers.ts +34 -107
  65. package/client/agentConfigResolver.test.ts +2 -0
  66. package/client/agentRun.test.ts +12 -208
  67. package/client/agentRun.ts +854 -57
  68. package/client/localProviderResolver.test.ts +26 -2
  69. package/client/localRuntimeAdapter.test.ts +296 -171
  70. package/client/localRuntimeAdapter.ts +59 -159
  71. package/client/localToolPolicy.test.ts +4 -28
  72. package/client/streamingOutput.ts +3 -1
  73. package/client/taskRunPrompt.ts +24 -7
  74. package/commandRegistry.ts +4 -5
  75. package/connectorRunArtifact.ts +10 -34
  76. package/connectorWebSocketTarget.ts +6 -10
  77. package/database/server/serverStoreFactory.ts +2 -8
  78. package/internalCommandEntries.ts +0 -8
  79. package/localRuntimeDb.ts +2 -39
  80. package/machineCommands.ts +189 -190
  81. package/machineDaemonCommands.ts +165 -9
  82. package/machineHeartbeatCommands.ts +2 -1
  83. package/machineStatusCommands.ts +13 -5
  84. package/machineWatchCommands.ts +1 -1
  85. package/machineWsRunDispatch.ts +30 -44
  86. package/machineWsSession.ts +0 -2
  87. package/offlineMarxistsAgentCommand.ts +314 -0
  88. package/package.json +52 -188
  89. package/runtimeDoctorCommands.ts +72 -15
  90. package/scriptCommandEntries.ts +45 -5
  91. package/tableCommands.ts +133 -33
  92. package/taskRunCommand.ts +211 -16
  93. package/tui/session.ts +372 -43
  94. package/workflowInternalCommandEntries.ts +0 -20
  95. package/agent-runtime/dialogStatus.ts +0 -139
  96. package/agent-runtime/hostRuntimeConfig.ts +0 -86
  97. package/agentCreateCustomCommands.ts +0 -278
  98. package/agentDialogsCommands.ts +0 -227
  99. package/agentDoctorCommands.ts +0 -203
  100. package/agentRunLocalWorkspace.ts +0 -182
  101. package/agentRunParsing.ts +0 -298
  102. package/agentSuperviseCommands.ts +0 -8
  103. package/agentUnpublishCommands.ts +0 -113
  104. package/ai/agent/agentRunDialogLineage.ts +0 -56
  105. package/ai/policy/types.ts +0 -64
  106. package/ai/skills/skillSummaryMarker.ts +0 -26
  107. package/app/types.ts +0 -358
  108. package/build.ts +0 -16
  109. package/buildPublish.ts +0 -138
  110. package/buildPublishArtifactAssembly.ts +0 -724
  111. package/buildPublishImportAnalysis.ts +0 -242
  112. package/chat/messages/fetchMessages.ts +0 -84
  113. package/chat/messages/types.ts +0 -185
  114. package/cli/agentCreateCustomCommands.ts +0 -278
  115. package/cli/agentDialogsCommands.ts +0 -227
  116. package/cli/agentDoctorCommands.ts +0 -203
  117. package/cli/agentRunLocalWorkspace.ts +0 -182
  118. package/cli/agentRunParsing.ts +0 -298
  119. package/cli/agentSuperviseCommands.ts +0 -8
  120. package/cli/agentUnpublishCommands.ts +0 -113
  121. package/cli/buildPublish.ts +0 -138
  122. package/cli/buildPublishArtifactAssembly.ts +0 -724
  123. package/cli/buildPublishImportAnalysis.ts +0 -242
  124. package/cli/cliIoTypes.ts +0 -3
  125. package/cli/cliRuntimeDoctorReport.ts +0 -193
  126. package/cli/client/agentRunInput.ts +0 -10
  127. package/cli/client/agentRunLocalExecution.ts +0 -124
  128. package/cli/client/agentRunLocalExecutor.ts +0 -179
  129. package/cli/client/agentRunRuntimeSelection.ts +0 -145
  130. package/cli/client/agentRunServerTransport.ts +0 -397
  131. package/cli/client/agentRunTaskRunRecorder.ts +0 -176
  132. package/cli/customCodingAgentFlow.ts +0 -208
  133. package/cli/customCodingAgentRecord.ts +0 -179
  134. package/cli/dialogDataAccess.ts +0 -186
  135. package/cli/dialogInternalCommandEntries.ts +0 -11
  136. package/cli/dialogReadCommands.ts +0 -180
  137. package/cli/dialogReadHelpers.ts +0 -226
  138. package/cli/dialogStatusCommands.ts +0 -123
  139. package/cli/docInternalCommandEntries.ts +0 -20
  140. package/cli/hybridReadHelpers.ts +0 -109
  141. package/cli/machineCommandPrompts.ts +0 -79
  142. package/cli/machineCommandResolution.ts +0 -43
  143. package/cli/noloReadBridgePrompt.ts +0 -16
  144. package/cli/pageCreateCommands.ts +0 -219
  145. package/cli/pageDeleteCommands.ts +0 -167
  146. package/cli/pageReadCommands.ts +0 -151
  147. package/cli/pageUpdateCommands.ts +0 -249
  148. package/cli/pageWriteHelpers.ts +0 -209
  149. package/cli/publishPackage.ts +0 -36
  150. package/cli/runtimeInternalCommandEntries.ts +0 -15
  151. package/cli/runtimePassthroughCommands.ts +0 -22
  152. package/cli/scriptPassthroughHelpers.ts +0 -28
  153. package/cli/secretScanHelpers.ts +0 -31
  154. package/cli/spaceAttachCommands.ts +0 -134
  155. package/cli/spaceCategoryCommands.ts +0 -263
  156. package/cli/spaceCommands.ts +0 -295
  157. package/cli/spaceDeleteCommands.ts +0 -312
  158. package/cli/spaceInternalCommandEntries.ts +0 -21
  159. package/cli/spaceMutationHelpers.ts +0 -135
  160. package/cli/spaceReadCommands.ts +0 -323
  161. package/cli/tableDataOutput.ts +0 -41
  162. package/cli/tableDataSafety.ts +0 -26
  163. package/cli/tableMetaCommands.ts +0 -307
  164. package/cli/tableMutationCommands.ts +0 -266
  165. package/cli/tableQueryParsing.ts +0 -90
  166. package/cli/tableQueryRequest.ts +0 -53
  167. package/cli/taskRunActions.ts +0 -122
  168. package/cli/taskRunParsing.ts +0 -86
  169. package/cli/taskRunPromptShared.ts +0 -55
  170. package/cli/tui/tuiCatalog.ts +0 -22
  171. package/cli/tui/tuiCommandInterpreter.ts +0 -253
  172. package/cli/tui/tuiPresentation.ts +0 -146
  173. package/cliIoTypes.ts +0 -3
  174. package/cliRuntimeDoctorReport.ts +0 -193
  175. package/client/agentRunInput.ts +0 -10
  176. package/client/agentRunLocalExecution.test.ts +0 -123
  177. package/client/agentRunLocalExecution.ts +0 -124
  178. package/client/agentRunLocalExecutor.ts +0 -179
  179. package/client/agentRunRuntimeSelection.test.ts +0 -159
  180. package/client/agentRunRuntimeSelection.ts +0 -145
  181. package/client/agentRunServerTransport.ts +0 -397
  182. package/client/agentRunTaskRunRecorder.ts +0 -176
  183. package/connector-experimental/daemonLauncher.ts +0 -223
  184. package/create/space/spaceKeys.ts +0 -65
  185. package/create/types.ts +0 -21
  186. package/customCodingAgentFlow.ts +0 -208
  187. package/customCodingAgentRecord.ts +0 -179
  188. package/database/keys.ts +0 -765
  189. package/database/tombstones.ts +0 -52
  190. package/database/utils/ulid.ts +0 -1
  191. package/dialogDataAccess.ts +0 -186
  192. package/dialogInternalCommandEntries.ts +0 -11
  193. package/dialogReadCommands.ts +0 -180
  194. package/dialogReadHelpers.ts +0 -226
  195. package/dialogStatusCommands.ts +0 -123
  196. package/docInternalCommandEntries.ts +0 -20
  197. package/hybridReadHelpers.ts +0 -109
  198. package/machineCommandPrompts.ts +0 -79
  199. package/machineCommandResolution.ts +0 -43
  200. package/noloReadBridgePrompt.ts +0 -16
  201. package/pageCreateCommands.ts +0 -219
  202. package/pageDeleteCommands.ts +0 -167
  203. package/pageReadCommands.ts +0 -151
  204. package/pageUpdateCommands.ts +0 -249
  205. package/pageWriteHelpers.ts +0 -209
  206. package/publishPackage.ts +0 -36
  207. package/runtimeInternalCommandEntries.ts +0 -15
  208. package/runtimePassthroughCommands.ts +0 -22
  209. package/scriptPassthroughHelpers.ts +0 -28
  210. package/secretScanHelpers.ts +0 -31
  211. package/share/helpers.ts +0 -302
  212. package/share/keys.ts +0 -243
  213. package/share/types.ts +0 -100
  214. package/spaceAttachCommands.ts +0 -134
  215. package/spaceCategoryCommands.ts +0 -263
  216. package/spaceCommands.ts +0 -295
  217. package/spaceDeleteCommands.ts +0 -312
  218. package/spaceInternalCommandEntries.ts +0 -21
  219. package/spaceMutationHelpers.ts +0 -135
  220. package/spaceReadCommands.ts +0 -323
  221. package/tableDataOutput.ts +0 -41
  222. package/tableDataSafety.ts +0 -26
  223. package/tableMetaCommands.ts +0 -307
  224. package/tableMutationCommands.ts +0 -266
  225. package/tableQueryParsing.ts +0 -90
  226. package/tableQueryRequest.ts +0 -53
  227. package/taskRunActions.ts +0 -122
  228. package/taskRunParsing.ts +0 -86
  229. package/taskRunPromptShared.ts +0 -55
  230. package/tui/tuiCatalog.ts +0 -22
  231. package/tui/tuiCommandInterpreter.test.ts +0 -169
  232. package/tui/tuiCommandInterpreter.ts +0 -253
  233. package/tui/tuiPresentation.test.ts +0 -154
  234. package/tui/tuiPresentation.ts +0 -146
@@ -7,7 +7,6 @@ import { request as httpRequest } from "node:http";
7
7
  import { request as httpsRequest } from "node:https";
8
8
  import {
9
9
  buildLocalWorkspacePolicyToolNames,
10
- resolveLocalWorkspaceShellToolExposure,
11
10
  buildLocalWorkspaceToolset,
12
11
  buildLocalWorkspaceOpenAiTools,
13
12
  buildOpenAiCompatibleChatCompletionRequest,
@@ -16,11 +15,9 @@ import {
16
15
  parseOpenAiCompatibleChatCompletionResponse,
17
16
  parsePlatformChatCompletionData,
18
17
  parsePlatformChatCompletionResponse,
19
- resolveHostRuntimeConfigFromEnv,
20
18
  resolvePlatformChatProviderConfig,
21
19
  resolveRequestedRuntimeToolNames,
22
20
  shouldUsePlatformChatProvider,
23
- type HostRuntimeConfig,
24
21
  } from "../agentRuntimeLocal";
25
22
  import type { AgentRuntimeChatMessage } from "../agent-runtime";
26
23
  import { getDefaultCliLocalRuntimeDb } from "../localRuntimeDb";
@@ -52,29 +49,6 @@ import {
52
49
  type EnvLike = Record<string, string | undefined>;
53
50
  type FetchInput = Parameters<typeof fetch>[0];
54
51
  type FetchInit = Parameters<typeof fetch>[1];
55
- type CliLocalRuntimeCliExecution = {
56
- text: string;
57
- raw?: string;
58
- elapsed?: number;
59
- warnings?: string[];
60
- };
61
- type CliLocalRuntimeCliExecutor = (
62
- provider: string,
63
- prompt: string,
64
- options: {
65
- model?: string;
66
- timeout?: number;
67
- cwd?: string;
68
- yolo?: boolean;
69
- env?: EnvLike;
70
- systemPrompt?: string;
71
- reasoningEffort?: "low" | "medium" | "high" | "xhigh" | "max";
72
- temperature?: number;
73
- topP?: number;
74
- frequencyPenalty?: number;
75
- maxTokens?: number;
76
- }
77
- ) => Promise<CliLocalRuntimeCliExecution>;
78
52
  const TRANSIENT_FETCH_MAX_ATTEMPTS = 8;
79
53
  const TRANSIENT_FETCH_RETRY_BASE_DELAY_MS = 250;
80
54
 
@@ -82,17 +56,16 @@ export type CliLocalRuntimeDb = CliKvDb;
82
56
 
83
57
  export type CliLocalRuntimeAdapterDeps = {
84
58
  env: EnvLike;
85
- hostRuntimeConfig?: HostRuntimeConfig;
86
59
  db?: CliLocalRuntimeDb;
87
60
  store?: HybridRecordStore;
88
61
  now?: () => number;
89
62
  createId?: () => string;
90
63
  fetchImpl?: typeof fetch;
91
64
  cwd?: string;
65
+ useCwdAsTaskWorkspaceBase?: boolean;
92
66
  output?: { write(chunk: string): unknown };
93
67
  prepareTaskWorktree?: typeof prepareTaskWorktree;
94
68
  localToolExecutors?: Record<string, (call: any) => Promise<{ content: string; metadata?: Record<string, unknown> }>>;
95
- executeCli?: CliLocalRuntimeCliExecutor;
96
69
  sleep?: (ms: number) => Promise<void>;
97
70
  loopbackRequest?: (input: FetchInput, init?: FetchInit) => Promise<Response>;
98
71
  };
@@ -101,15 +74,6 @@ async function defaultLocalRuntimeDb(): Promise<CliLocalRuntimeDb> {
101
74
  return getDefaultCliLocalRuntimeDb();
102
75
  }
103
76
 
104
- async function defaultExecuteCli(
105
- provider: string,
106
- prompt: string,
107
- options: Parameters<CliLocalRuntimeCliExecutor>[2]
108
- ) {
109
- const { executeCli } = await import("../ai/agent/cliExecutor");
110
- return executeCli(provider as any, prompt, options);
111
- }
112
-
113
77
  function createFallbackId() {
114
78
  return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`.toUpperCase();
115
79
  }
@@ -118,6 +82,10 @@ function resolveLocalUserId(env: EnvLike) {
118
82
  return env.NOLO_LOCAL_USER_ID || env.NOLO_USER_ID || "local";
119
83
  }
120
84
 
85
+ function shellModeEnabled(env: EnvLike) {
86
+ return ["worktree", "dangerous", "1", "true"].includes(env.NOLO_LOCAL_SHELL_MODE || "");
87
+ }
88
+
121
89
  function parseLocalToolBudgets(env: EnvLike) {
122
90
  const raw = env.NOLO_LOCAL_TOOL_BUDGETS?.trim();
123
91
  if (!raw) return {};
@@ -202,6 +170,12 @@ async function defaultLoopbackRequest(input: FetchInput, init?: FetchInit) {
202
170
  });
203
171
  });
204
172
  req.on("error", reject);
173
+ init?.signal?.addEventListener("abort", () => {
174
+ req.destroy(
175
+ init.signal?.reason instanceof Error ? init.signal.reason : new Error("request aborted")
176
+ );
177
+ reject(init.signal?.reason ?? new Error("request aborted"));
178
+ }, { once: true });
205
179
  if (body) req.write(body);
206
180
  req.end();
207
181
  });
@@ -224,6 +198,7 @@ async function fetchWithTransientRetry(
224
198
  }
225
199
  return await fetchImpl(input, init);
226
200
  } catch (error) {
201
+ if (init?.signal?.aborted) throw error;
227
202
  if (!isTransientFetchError(error)) throw error;
228
203
  lastError = error;
229
204
  if (attempt < TRANSIENT_FETCH_MAX_ATTEMPTS) {
@@ -234,52 +209,44 @@ async function fetchWithTransientRetry(
234
209
  throw lastError;
235
210
  }
236
211
 
237
- function buildOpenAiTools(args: {
238
- requestedToolNames?: string[];
239
- platformToolNames?: string[];
240
- hostRuntimeConfig: HostRuntimeConfig;
241
- }) {
242
- const toolset = buildLocalWorkspaceToolsetForHost(args);
212
+ function buildRequestTimeoutSignal(timeoutMs?: number) {
213
+ if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
214
+ return undefined;
215
+ }
216
+ if (typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function") {
217
+ return AbortSignal.timeout(timeoutMs);
218
+ }
219
+ const controller = new AbortController();
220
+ setTimeout(() => controller.abort(new Error(`request timed out after ${timeoutMs}ms`)), timeoutMs);
221
+ return controller.signal;
222
+ }
223
+
224
+ function buildOpenAiTools(args: { toolNames?: string[]; env: EnvLike }) {
225
+ const toolset = buildLocalWorkspaceToolsetForEnv(args);
243
226
  return [
244
227
  ...buildLocalWorkspaceOpenAiTools({
245
228
  toolNames: toolset.toolNames,
246
229
  exposeShellTools: toolset.exposeShellTools,
247
230
  }),
248
- ...buildServerPlatformOpenAiTools({ toolNames: args.platformToolNames }),
231
+ ...buildServerPlatformOpenAiTools({ toolNames: args.toolNames }),
249
232
  ];
250
233
  }
251
234
 
252
- function buildLocalWorkspaceToolsetForHost(args: {
253
- requestedToolNames?: string[];
254
- hostRuntimeConfig: HostRuntimeConfig;
255
- }) {
256
- const requestedToolNames = args.requestedToolNames ?? [];
257
- const exposeShellTools = resolveLocalWorkspaceShellToolExposure({
258
- declaredToolNames: requestedToolNames,
259
- hostRuntimeConfig: args.hostRuntimeConfig,
260
- });
235
+ function buildLocalWorkspaceToolsetForEnv(args: { toolNames?: string[]; env: EnvLike }) {
261
236
  const toolset = buildLocalWorkspaceToolset({
262
- declaredToolNames: requestedToolNames,
263
- exposeShellTools,
237
+ declaredToolNames: args.toolNames,
238
+ exposeShellTools: shellModeEnabled(args.env),
264
239
  });
265
240
  return toolset;
266
241
  }
267
242
 
268
- function buildLocalPolicyToolNames(args: {
269
- requestedToolNames?: string[];
270
- platformToolNames?: string[];
271
- hostRuntimeConfig: HostRuntimeConfig;
272
- }) {
273
- const exposeShellTools = resolveLocalWorkspaceShellToolExposure({
274
- declaredToolNames: args.requestedToolNames,
275
- hostRuntimeConfig: args.hostRuntimeConfig,
276
- });
243
+ function buildLocalPolicyToolNames(args: { toolNames?: string[]; env: EnvLike }) {
277
244
  return [
278
245
  ...buildLocalWorkspacePolicyToolNames({
279
- declaredToolNames: args.requestedToolNames,
280
- exposeShellTools,
246
+ declaredToolNames: args.toolNames,
247
+ exposeShellTools: shellModeEnabled(args.env),
281
248
  }),
282
- ...((args.platformToolNames ?? []).includes("taskRun") ? ["taskRun"] : []),
249
+ ...((args.toolNames ?? []).includes("taskRun") ? ["taskRun"] : []),
283
250
  ];
284
251
  }
285
252
 
@@ -365,33 +332,6 @@ function readLocalWorkspaceMode(agentConfig: AgentRuntimeAgentConfig | null) {
365
332
  return value === "task-worktree" ? "task-worktree" : "current";
366
333
  }
367
334
 
368
- function extractRuntimeMessageText(content: AgentRuntimeChatMessage["content"]) {
369
- if (typeof content === "string") return content;
370
- if (!Array.isArray(content)) return "";
371
- return content
372
- .filter((part): part is Extract<typeof part, { type: "text" }> => part?.type === "text")
373
- .map((part) => part.text ?? "")
374
- .join("");
375
- }
376
-
377
- function buildCliTaskPromptFromMessages(messages: AgentRuntimeChatMessage[]) {
378
- const history = messages
379
- .filter((message) => message.role === "user" || message.role === "assistant")
380
- .map((message) => {
381
- const text = extractRuntimeMessageText(message.content).trim();
382
- if (!text) return null;
383
- return `[${message.role === "user" ? "用户" : "助手"}]\n${text}`;
384
- })
385
- .filter((message): message is string => Boolean(message))
386
- .slice(-6);
387
-
388
- if (history.length === 0) return "";
389
- if (history.length === 1 && history[0]?.startsWith("[用户]\n")) {
390
- return history[0].slice("[用户]\n".length);
391
- }
392
- return `请基于以下最近对话继续完成当前任务。\n\n${history.join("\n\n")}`;
393
- }
394
-
395
335
  async function resolveStore(deps: CliLocalRuntimeAdapterDeps) {
396
336
  if (deps.store) return deps.store;
397
337
  return createCliHybridRecordStore({
@@ -462,18 +402,12 @@ export function createCliLocalRuntimeAdapter(
462
402
  const createId = deps.createId ?? createFallbackId;
463
403
  const fetchImpl = deps.fetchImpl ?? fetch;
464
404
  const loopbackRequest = deps.loopbackRequest ?? (deps.fetchImpl ? undefined : defaultLoopbackRequest);
465
- const executeCli = deps.executeCli ?? defaultExecuteCli;
466
405
  const userId = resolveLocalUserId(deps.env);
467
- const hostRuntimeConfig = deps.hostRuntimeConfig ?? resolveHostRuntimeConfigFromEnv({
468
- env: deps.env,
469
- surface: "cli-local",
470
- workspaceBinding: "explicit-cwd",
471
- });
472
406
  const localToolBudgets = parseLocalToolBudgets(deps.env);
473
407
  const localToolUsage = new Map<string, number>();
474
408
  let activeAgentToolNames: string[] = [];
475
409
  let workspaceSession: WorkspaceSession = createWorkspaceSession(
476
- hostRuntimeConfig.workspaceBinding === "default-cwd"
410
+ deps.useCwdAsTaskWorkspaceBase
477
411
  ? { defaultCwd: deps.cwd }
478
412
  : { cwd: deps.cwd }
479
413
  );
@@ -518,9 +452,8 @@ export function createCliLocalRuntimeAdapter(
518
452
  ? resolveRequestedRuntimeToolNames({ agentConfig })
519
453
  : [];
520
454
  activeAgentToolNames = buildLocalPolicyToolNames({
521
- requestedToolNames,
522
- platformToolNames: agentConfig?.toolNames,
523
- hostRuntimeConfig,
455
+ toolNames: requestedToolNames,
456
+ env: deps.env,
524
457
  });
525
458
  await activateAgentWorkspaceSession({ agentRef, agentConfig });
526
459
  return agentConfig;
@@ -538,48 +471,6 @@ export function createCliLocalRuntimeAdapter(
538
471
  cwd: workspaceSession.workspaceRoot,
539
472
  }),
540
473
  resolveProvider: async (agentConfig) => {
541
- if (agentConfig.apiSource === "cli") {
542
- const cliProvider = String(agentConfig.cliProvider || "copilot").trim() || "copilot";
543
- return {
544
- model: agentConfig.model || cliProvider,
545
- complete: async (messages) => {
546
- const [firstMessage, ...remainingMessages] = messages;
547
- const systemPrompt = firstMessage?.role === "system"
548
- ? extractRuntimeMessageText(firstMessage.content).trim()
549
- : "";
550
- const taskPrompt = buildCliTaskPromptFromMessages(
551
- firstMessage?.role === "system" ? remainingMessages : messages
552
- );
553
- const result = await executeCli(cliProvider, taskPrompt, {
554
- ...(agentConfig.model ? { model: agentConfig.model } : {}),
555
- cwd: workspaceSession.workspaceRoot,
556
- yolo: true,
557
- env: deps.env,
558
- ...(systemPrompt ? { systemPrompt } : {}),
559
- ...(typeof agentConfig.reasoning_effort === "string"
560
- ? { reasoningEffort: agentConfig.reasoning_effort as "low" | "medium" | "high" | "xhigh" | "max" }
561
- : {}),
562
- ...(typeof agentConfig.temperature === "number"
563
- ? { temperature: agentConfig.temperature }
564
- : {}),
565
- ...(typeof agentConfig.top_p === "number" ? { topP: agentConfig.top_p } : {}),
566
- ...(typeof agentConfig.frequency_penalty === "number"
567
- ? { frequencyPenalty: agentConfig.frequency_penalty }
568
- : {}),
569
- ...(typeof agentConfig.max_tokens === "number"
570
- ? { maxTokens: agentConfig.max_tokens }
571
- : {}),
572
- });
573
- return {
574
- content: result.text,
575
- model: agentConfig.model || cliProvider,
576
- provider: cliProvider,
577
- trace: messages,
578
- };
579
- },
580
- };
581
- }
582
-
583
474
  if (shouldUsePlatformChatProvider(deps.env, agentConfig)) {
584
475
  const providerConfig = resolvePlatformChatProviderConfig({
585
476
  agentConfig,
@@ -587,19 +478,24 @@ export function createCliLocalRuntimeAdapter(
587
478
  });
588
479
  return {
589
480
  model: providerConfig.model,
590
- complete: async (messages) => {
591
- const requestedToolNames = resolveRequestedRuntimeToolNames({ agentConfig });
481
+ complete: async (messages, options) => {
482
+ const requestedToolNames = resolveRequestedRuntimeToolNames({
483
+ agentConfig,
484
+ });
592
485
  const tools = buildOpenAiTools({
593
- requestedToolNames,
594
- platformToolNames: agentConfig.toolNames,
595
- hostRuntimeConfig,
486
+ toolNames: requestedToolNames,
487
+ env: deps.env,
596
488
  });
597
489
  const request = buildPlatformChatCompletionRequest({
598
490
  providerConfig,
599
491
  messages,
600
492
  tools,
601
493
  });
602
- const res = await fetchWithTransientRetry(fetchImpl, request.url, request.init, {
494
+ const signal = buildRequestTimeoutSignal(options?.timeoutMs);
495
+ const res = await fetchWithTransientRetry(fetchImpl, request.url, {
496
+ ...request.init,
497
+ ...(signal ? { signal } : {}),
498
+ }, {
603
499
  sleep: deps.sleep,
604
500
  loopbackRequest,
605
501
  });
@@ -622,19 +518,24 @@ export function createCliLocalRuntimeAdapter(
622
518
  });
623
519
  return {
624
520
  model: providerConfig.model,
625
- complete: async (messages) => {
626
- const requestedToolNames = resolveRequestedRuntimeToolNames({ agentConfig });
521
+ complete: async (messages, options) => {
522
+ const requestedToolNames = resolveRequestedRuntimeToolNames({
523
+ agentConfig,
524
+ });
627
525
  const tools = buildOpenAiTools({
628
- requestedToolNames,
629
- platformToolNames: agentConfig.toolNames,
630
- hostRuntimeConfig,
526
+ toolNames: requestedToolNames,
527
+ env: deps.env,
631
528
  });
632
529
  const request = buildOpenAiCompatibleChatCompletionRequest({
633
530
  providerConfig,
634
531
  messages,
635
532
  tools,
636
533
  });
637
- const res = await fetchWithTransientRetry(fetchImpl, request.url, request.init, {
534
+ const signal = buildRequestTimeoutSignal(options?.timeoutMs);
535
+ const res = await fetchWithTransientRetry(fetchImpl, request.url, {
536
+ ...request.init,
537
+ ...(signal ? { signal } : {}),
538
+ }, {
638
539
  sleep: deps.sleep,
639
540
  loopbackRequest,
640
541
  });
@@ -658,7 +559,6 @@ export function createCliLocalRuntimeAdapter(
658
559
  });
659
560
  const result = await executeLocalToolWithPolicy({
660
561
  env: deps.env,
661
- hostRuntimeConfig,
662
562
  agentToolNames: activeAgentToolNames,
663
563
  call,
664
564
  executors: localToolExecutors,
@@ -1,47 +1,24 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import { executeLocalToolWithPolicy, resolveLocalToolPolicy } from "./localToolPolicy";
4
- import { createHostRuntimeConfig } from "../agent-runtime";
5
-
6
- function createCliHostRuntimeConfig(allowShell = false) {
7
- return createHostRuntimeConfig({
8
- surface: "cli-local",
9
- workspaceBinding: "explicit-cwd",
10
- allowShell,
11
- });
12
- }
13
4
 
14
5
  describe("CLI local tool policy", () => {
15
- test("allows execShell when the host grants shell capability", () => {
6
+ test("allows execShell in explicit worktree shell mode", () => {
16
7
  expect(resolveLocalToolPolicy({
17
- env: {},
18
- hostRuntimeConfig: createCliHostRuntimeConfig(true),
19
- agentToolNames: ["execShell"],
8
+ env: { NOLO_LOCAL_SHELL_MODE: "worktree" },
9
+ agentToolNames: [],
20
10
  toolName: "execShell",
21
11
  })).toEqual({ allowed: true, toolName: "execShell" });
22
12
  });
23
13
 
24
- test("blocks execShell unless the host grants shell capability", () => {
14
+ test("blocks execShell unless explicit shell mode is enabled", () => {
25
15
  expect(resolveLocalToolPolicy({
26
16
  env: { NOLO_LOCAL_ALLOWED_TOOLS: "execShell" },
27
- hostRuntimeConfig: createCliHostRuntimeConfig(),
28
17
  agentToolNames: ["execShell"],
29
18
  toolName: "execShell",
30
19
  })).toMatchObject({ allowed: false });
31
20
  });
32
21
 
33
- test("blocks execShell when shell was not requested by the runtime", () => {
34
- expect(resolveLocalToolPolicy({
35
- env: {},
36
- hostRuntimeConfig: createCliHostRuntimeConfig(true),
37
- agentToolNames: [],
38
- toolName: "execShell",
39
- })).toMatchObject({
40
- allowed: false,
41
- reason: "execShell is not requested by this agent runtime.",
42
- });
43
- });
44
-
45
22
  test("requires both env allowlist and agent declaration", () => {
46
23
  expect(resolveLocalToolPolicy({
47
24
  env: { NOLO_LOCAL_ALLOWED_TOOLS: "readFile" },
@@ -59,7 +36,6 @@ describe("CLI local tool policy", () => {
59
36
  test("executes only registered tools after policy allows them", async () => {
60
37
  const result = await executeLocalToolWithPolicy({
61
38
  env: { NOLO_LOCAL_ALLOWED_TOOLS: "readFile" },
62
- hostRuntimeConfig: createCliHostRuntimeConfig(),
63
39
  agentToolNames: ["readFile"],
64
40
  call: { id: "call-1", name: "readFile", arguments: "{\"path\":\"README.md\"}" },
65
41
  executors: {
@@ -1,4 +1,6 @@
1
- import type { OutputLike } from "../cliIoTypes";
1
+ type OutputLike = {
2
+ write(chunk: string): unknown;
3
+ };
2
4
 
3
5
  export function splitStreamingText(content: string): string[] {
4
6
  const Segmenter = Intl.Segmenter;
@@ -1,10 +1,27 @@
1
- import {
2
- prependTaskRunPromptForRuntime,
3
- type TaskRunPromptContext,
4
- } from "../taskRunPromptShared";
5
-
6
- export type { TaskRunPromptContext };
1
+ export type TaskRunPromptContext = {
2
+ rowDbKey: string;
3
+ taskRunId?: string;
4
+ workItemId?: string;
5
+ artifactIds?: string[];
6
+ };
7
7
 
8
8
  export function prependTaskRunPrompt(message: string, context?: TaskRunPromptContext): string {
9
- return prependTaskRunPromptForRuntime(message, context, "cli");
9
+ if (!context?.rowDbKey) return message;
10
+ const artifactIds = context.artifactIds?.filter(Boolean) ?? [];
11
+ return [
12
+ "AI-native task-run context:",
13
+ "- This system is AI-native. The current task board is only the present observation and validation use case; different users, companies, and workflows may use different task owners later.",
14
+ "- Treat the task row meta as the durable execution context. Do not infer branch, runner, handoff, review, or blocker state from chat history alone.",
15
+ `- rowDbKey: ${context.rowDbKey}`,
16
+ ...(context.taskRunId ? [`- taskRunId: ${context.taskRunId}`] : []),
17
+ ...(context.workItemId ? [`- workItemId: ${context.workItemId}`] : []),
18
+ ...(artifactIds.length ? [`- artifactIds: ${artifactIds.join(",")}`] : []),
19
+ "- Handoff rule: start from the durable task context, then inspect existing refs such as workItems.dialogIds, workItems.outcome, review.dialogId, activityRefs, agentRuns.dialogId/resultSummary, and artifactRefs. Use dialog read/search for exact evidence.",
20
+ "- When you create, update, hand off, block, or review work, update the task context with `bun run task:run -- ...`.",
21
+ "- If this turn already includes a server TaskRun preflight snapshot, use that snapshot directly for read-only reporting or planning.",
22
+ "- Keep long reasoning and logs in the dialog; record only resumable references in task row meta.",
23
+ "",
24
+ "User task:",
25
+ message,
26
+ ].join("\n");
10
27
  }
@@ -49,14 +49,14 @@ export function renderHelpText() {
49
49
  " nolo connect",
50
50
  " nolo connect --watch",
51
51
  " nolo connect --ws",
52
- " nolo connect --ws --server-url https://api.nolo.chat --api-key sk_machine_xxx",
53
- " nolo connect --daemon --server-url https://api.nolo.chat --api-key sk_machine_xxx",
52
+ " nolo connect --ws --server-url https://api.nolo.chat --machine-key sk_machine_xxx",
53
+ " nolo connect --daemon --server-url https://api.nolo.chat --machine-key sk_machine_xxx",
54
54
  " nolo machine status",
55
55
  " nolo doctor",
56
56
  " nolo doctor runtime",
57
57
  " nolo update",
58
- ' nolo doc create --title "Trip Notes" --body "hello" --space 01SPACEID --dry-run',
59
- ' nolo skill-doc create --title "Agent Query Skill" --description "Inspect recent agent dialogs" --space 01SPACEID',
58
+ ' nolo doc create --title "Trip Notes" --body "hello" --sync local,us --dry-run',
59
+ ' nolo skill-doc create --title "Agent Query Skill" --description "Inspect recent agent dialogs" --sync local,main,us',
60
60
  " nolo agent list --json",
61
61
  " nolo space list --json",
62
62
  " nolo agent pull agent-pub-01APPBUILDER00000001YAII3I",
@@ -64,7 +64,6 @@ export function renderHelpText() {
64
64
  ' nolo agent run frontend-implementer --msg "polish notifications"',
65
65
  " nolo agent bind-current agent-user-1-agent-1",
66
66
  " nolo agent runtime-doctor agent-user-1-agent-1",
67
- ' nolo agent smoke-bound agent-user-1-agent-1 --msg "ping"',
68
67
  ' nolo agent smoke-current agent-user-1-agent-1 --msg "ping"',
69
68
  ' nolo chat --agent agent-pub-01APPBUILDER00000001YAII3I --msg "你好"',
70
69
  " nolo space read 01KKY77TT0DA9NY7TNW3R7255N --content-key page-user-id --brief",
@@ -24,46 +24,22 @@ function normalizePath(value: string) {
24
24
  return resolve(value.trim());
25
25
  }
26
26
 
27
- function resolveExistingCandidate(
28
- value: string | undefined,
29
- checked: string[],
30
- label: string
31
- ) {
32
- const trimmed = value?.trim();
33
- if (!trimmed) return null;
34
- const normalized = normalizePath(trimmed);
35
- if (existsSync(normalized)) return normalized;
36
- checked.push(`${label}=${normalized}`);
37
- return null;
38
- }
39
-
40
27
  export function resolveConnectorRunCwd(args: {
41
28
  env?: EnvLike;
42
29
  policy: MachineRunPermissionPolicy;
43
30
  fallbackCwd?: string;
44
31
  }) {
45
- const checked: string[] = [];
46
- const candidates: Array<[string | undefined, string]> = [
47
- [args.env?.NOLO_CONNECTOR_WORKDIR, "NOLO_CONNECTOR_WORKDIR"],
48
- [args.env?.NOLO_AGENT_WORKDIR, "NOLO_AGENT_WORKDIR"],
49
- [args.env?.NOLO_LOCAL_WORKTREE, "NOLO_LOCAL_WORKTREE"],
50
- [args.policy.writableRoots[0], "writableRoots[0]"],
51
- [args.fallbackCwd, "fallbackCwd"],
52
- [process.env.PWD, "PWD"],
53
- [process.cwd(), "process.cwd()"],
54
- ];
55
-
56
- for (const [value, label] of candidates) {
57
- const resolved = resolveExistingCandidate(value, checked, label);
58
- if (resolved) return resolved;
59
- }
60
-
61
- if (checked.length > 0) {
62
- throw new Error(
63
- `Connector run cwd does not exist. Checked: ${checked.join(", ")}`
64
- );
32
+ const explicit =
33
+ args.env?.NOLO_CONNECTOR_WORKDIR ||
34
+ args.env?.NOLO_AGENT_WORKDIR ||
35
+ args.env?.NOLO_LOCAL_WORKTREE ||
36
+ "";
37
+ const candidate = explicit || args.policy.writableRoots[0] || args.fallbackCwd || process.cwd();
38
+ const cwd = normalizePath(candidate);
39
+ if (!existsSync(cwd)) {
40
+ throw new Error(`Connector run cwd does not exist: ${cwd}`);
65
41
  }
66
- throw new Error("Connector run cwd could not be resolved.");
42
+ return cwd;
67
43
  }
68
44
 
69
45
  async function runGit(
@@ -49,18 +49,14 @@ function parseRetryAfterMs(response: Response, bodyRetryAfterMs?: unknown) {
49
49
  export async function resolveConnectorWebSocketTarget(input: {
50
50
  serverUrl: string;
51
51
  machineId: string;
52
- connectorSurface?: string;
53
52
  headers: Record<string, string>;
54
53
  fetchImpl?: typeof fetch;
55
54
  }) {
56
55
  const directWsUrl = new URL(input.serverUrl);
57
56
  directWsUrl.protocol = directWsUrl.protocol === "https:" ? "wss:" : "ws:";
58
57
  directWsUrl.pathname = "/api/connector/ws";
59
- directWsUrl.search = "";
60
- directWsUrl.searchParams.set("machineId", input.machineId);
61
- if (input.connectorSurface?.trim()) {
62
- directWsUrl.searchParams.set("connectorSurface", input.connectorSurface.trim().toLowerCase());
63
- }
58
+ directWsUrl.search = "";
59
+ directWsUrl.searchParams.set("machineId", input.machineId);
64
60
 
65
61
  const probeUrl = new URL(input.serverUrl);
66
62
  probeUrl.pathname = "/api/connector/ws";
@@ -103,7 +99,7 @@ export async function resolveConnectorWebSocketTarget(input: {
103
99
  }
104
100
 
105
101
  const json = await response.json().catch(() => null);
106
- return typeof json?.wsUrl === "string" && json.wsUrl
107
- ? json.wsUrl
108
- : directWsUrl.toString();
109
- }
102
+ return typeof json?.wsUrl === "string" && json.wsUrl
103
+ ? json.wsUrl
104
+ : directWsUrl.toString();
105
+ }
@@ -7,8 +7,6 @@ import { createLegacyServerDb, type LegacyServerDb } from "./legacyServerDb";
7
7
  import { createLevelAuthorityStore } from "./levelAuthorityStore";
8
8
  import { createMemoryAuthorityStore } from "./memoryAuthorityStore";
9
9
 
10
- // Keep the storage seam local-first. Cross-process sharing stays in the
11
- // existing core/proxy runtime layer; this factory is only for embedded drivers.
12
10
  export type ServerStoreDriver = "level" | "memory";
13
11
 
14
12
  export type ServerStoreFactoryEnv = {
@@ -66,15 +64,12 @@ export function resolveServerStoreDriver(
66
64
 
67
65
  export function createAuthorityStoreForDriver(
68
66
  driver: ServerStoreDriver,
69
- dbPath: string,
70
- env: ServerStoreFactoryEnv = process.env
67
+ dbPath: string
71
68
  ): AuthorityStore {
72
69
  switch (driver) {
73
70
  case "level":
74
71
  return createLevelBackedAuthorityStore(dbPath);
75
72
  case "memory":
76
- // Test/dev-only driver that exercises the seam without changing the
77
- // production single-writer runtime model.
78
73
  return createMemoryAuthorityStore(dbPath);
79
74
  }
80
75
  }
@@ -103,8 +98,7 @@ export function getOrCreateServerStoreRuntime(
103
98
  if (!globalScope.__serverAuthorityStore) {
104
99
  globalScope.__serverAuthorityStore = createAuthorityStoreForDriver(
105
100
  driver,
106
- dbPath,
107
- options.env
101
+ dbPath
108
102
  );
109
103
  globalScope.__serverAuthorityStoreDriver = driver;
110
104
  } else if (!cachedDriver) {
@@ -1,20 +1,12 @@
1
1
  import { getAgentInternalCommandEntries } from "./agentInternalCommandEntries";
2
2
  import type { CommandEntry } from "./cliCommandTypes";
3
- import { getDialogInternalCommandEntries } from "./dialogInternalCommandEntries";
4
- import { getDocInternalCommandEntries } from "./docInternalCommandEntries";
5
- import { getRuntimeInternalCommandEntries } from "./runtimeInternalCommandEntries";
6
- import { getSpaceInternalCommandEntries } from "./spaceInternalCommandEntries";
7
3
  import { getSystemInternalCommandEntries } from "./systemInternalCommandEntries";
8
4
  import { getWorkflowInternalCommandEntries } from "./workflowInternalCommandEntries";
9
5
 
10
6
  export function getInternalCommandEntries(renderHelpText: () => string): CommandEntry[] {
11
7
  return [
12
8
  ...getAgentInternalCommandEntries(),
13
- ...getDialogInternalCommandEntries(),
14
- ...getDocInternalCommandEntries(),
15
- ...getSpaceInternalCommandEntries(),
16
9
  ...getWorkflowInternalCommandEntries(),
17
- ...getRuntimeInternalCommandEntries(),
18
10
  ...getSystemInternalCommandEntries(renderHelpText),
19
11
  ];
20
12
  }