nolo-cli 0.1.32 → 0.1.33

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 (230) hide show
  1. package/README.md +0 -6
  2. package/agent-runtime/agentRecordConfig.ts +2 -0
  3. package/agent-runtime/hostAdapter.ts +1 -0
  4. package/agent-runtime/index.ts +0 -21
  5. package/agent-runtime/localToolPolicy.ts +6 -13
  6. package/agent-runtime/localWorkspaceTools.ts +30 -333
  7. package/agent-runtime/platformChatProvider.ts +1 -4
  8. package/agent-runtime/runtimeToolPolicy.ts +47 -32
  9. package/agentAliases.ts +14 -83
  10. package/agentCommandSupport.ts +3 -6
  11. package/agentInternalCommandEntries.ts +2 -13
  12. package/agentListCommands.ts +19 -28
  13. package/agentMachineCommands.ts +40 -336
  14. package/agentPullCommand.ts +36 -56
  15. package/agentRecordCommands.ts +3 -5
  16. package/agentRecordHelpers.ts +22 -189
  17. package/agentRunCommand.ts +438 -107
  18. package/agentRuntimeLocal.ts +0 -10
  19. package/ai/agent/cliExecutor.ts +19 -323
  20. package/authCommands.ts +2 -36
  21. package/cli/agentAliases.ts +14 -83
  22. package/cli/agentCommandSupport.ts +3 -6
  23. package/cli/agentInternalCommandEntries.ts +2 -13
  24. package/cli/agentListCommands.ts +19 -28
  25. package/cli/agentMachineCommands.ts +40 -336
  26. package/cli/agentPullCommand.ts +36 -56
  27. package/cli/agentRecordCommands.ts +3 -5
  28. package/cli/agentRecordHelpers.ts +22 -189
  29. package/cli/agentRunCommand.ts +438 -107
  30. package/cli/agentRuntimeLocal.ts +0 -10
  31. package/cli/authCommands.ts +2 -36
  32. package/cli/cliEnvHelpers.ts +21 -162
  33. package/cli/client/agentRun.ts +853 -57
  34. package/cli/client/localRuntimeAdapter.ts +22 -159
  35. package/cli/client/streamingOutput.ts +3 -1
  36. package/cli/client/taskRunPrompt.ts +24 -7
  37. package/cli/commandRegistry.ts +2 -3
  38. package/cli/connectorRunArtifact.ts +10 -34
  39. package/cli/connectorWebSocketTarget.ts +6 -10
  40. package/cli/internalCommandEntries.ts +0 -8
  41. package/cli/localRuntimeDb.ts +2 -39
  42. package/cli/machineCommands.ts +189 -190
  43. package/cli/machineDaemonCommands.ts +165 -9
  44. package/cli/machineHeartbeatCommands.ts +2 -1
  45. package/cli/machineStatusCommands.ts +13 -5
  46. package/cli/machineWatchCommands.ts +1 -1
  47. package/cli/machineWsRunDispatch.ts +14 -48
  48. package/cli/machineWsSession.ts +0 -2
  49. package/cli/offlineMarxistsAgentCommand.ts +314 -0
  50. package/cli/runtimeDoctorCommands.ts +69 -18
  51. package/cli/scriptCommandEntries.ts +45 -5
  52. package/cli/tableCommands.ts +133 -33
  53. package/cli/taskRunCommand.ts +211 -16
  54. package/cli/tui/session.ts +372 -43
  55. package/cli/workflowInternalCommandEntries.ts +0 -20
  56. package/cliEnvHelpers.ts +21 -162
  57. package/client/agentConfigResolver.test.ts +2 -0
  58. package/client/agentRun.test.ts +12 -208
  59. package/client/agentRun.ts +853 -57
  60. package/client/localRuntimeAdapter.test.ts +9 -168
  61. package/client/localRuntimeAdapter.ts +22 -159
  62. package/client/localToolPolicy.test.ts +4 -28
  63. package/client/streamingOutput.ts +3 -1
  64. package/client/taskRunPrompt.ts +24 -7
  65. package/commandRegistry.ts +2 -3
  66. package/connectorRunArtifact.ts +10 -34
  67. package/connectorWebSocketTarget.ts +6 -10
  68. package/database/server/db.ts +34 -15
  69. package/internalCommandEntries.ts +0 -8
  70. package/localRuntimeDb.ts +2 -39
  71. package/machineCommands.ts +189 -190
  72. package/machineDaemonCommands.ts +165 -9
  73. package/machineHeartbeatCommands.ts +2 -1
  74. package/machineStatusCommands.ts +13 -5
  75. package/machineWatchCommands.ts +1 -1
  76. package/machineWsRunDispatch.ts +14 -48
  77. package/machineWsSession.ts +0 -2
  78. package/offlineMarxistsAgentCommand.ts +314 -0
  79. package/package.json +49 -193
  80. package/runtimeDoctorCommands.ts +69 -18
  81. package/scriptCommandEntries.ts +45 -5
  82. package/tableCommands.ts +133 -33
  83. package/taskRunCommand.ts +211 -16
  84. package/tui/session.ts +372 -43
  85. package/workflowInternalCommandEntries.ts +0 -20
  86. package/agent-runtime/dialogStatus.ts +0 -139
  87. package/agent-runtime/hostRuntimeConfig.ts +0 -86
  88. package/agentCreateCustomCommands.ts +0 -278
  89. package/agentDialogsCommands.ts +0 -227
  90. package/agentDoctorCommands.ts +0 -203
  91. package/agentRunLocalWorkspace.ts +0 -182
  92. package/agentRunParsing.ts +0 -298
  93. package/agentSuperviseCommands.ts +0 -8
  94. package/agentUnpublishCommands.ts +0 -113
  95. package/ai/agent/agentRunDialogLineage.ts +0 -56
  96. package/ai/policy/types.ts +0 -64
  97. package/ai/skills/skillSummaryMarker.ts +0 -26
  98. package/app/types.ts +0 -358
  99. package/build.ts +0 -16
  100. package/buildPublish.ts +0 -138
  101. package/buildPublishArtifactAssembly.ts +0 -724
  102. package/buildPublishImportAnalysis.ts +0 -242
  103. package/chat/messages/fetchMessages.ts +0 -84
  104. package/chat/messages/types.ts +0 -185
  105. package/cli/agentCreateCustomCommands.ts +0 -278
  106. package/cli/agentDialogsCommands.ts +0 -227
  107. package/cli/agentDoctorCommands.ts +0 -203
  108. package/cli/agentRunLocalWorkspace.ts +0 -182
  109. package/cli/agentRunParsing.ts +0 -298
  110. package/cli/agentSuperviseCommands.ts +0 -8
  111. package/cli/agentUnpublishCommands.ts +0 -113
  112. package/cli/buildPublish.ts +0 -138
  113. package/cli/buildPublishArtifactAssembly.ts +0 -724
  114. package/cli/buildPublishImportAnalysis.ts +0 -242
  115. package/cli/cliIoTypes.ts +0 -3
  116. package/cli/cliRuntimeDoctorReport.ts +0 -193
  117. package/cli/client/agentRunInput.ts +0 -10
  118. package/cli/client/agentRunLocalExecution.ts +0 -124
  119. package/cli/client/agentRunLocalExecutor.ts +0 -179
  120. package/cli/client/agentRunRuntimeSelection.ts +0 -145
  121. package/cli/client/agentRunServerTransport.ts +0 -397
  122. package/cli/client/agentRunTaskRunRecorder.ts +0 -176
  123. package/cli/customCodingAgentFlow.ts +0 -208
  124. package/cli/customCodingAgentRecord.ts +0 -179
  125. package/cli/dialogDataAccess.ts +0 -186
  126. package/cli/dialogInternalCommandEntries.ts +0 -11
  127. package/cli/dialogReadCommands.ts +0 -180
  128. package/cli/dialogReadHelpers.ts +0 -226
  129. package/cli/dialogStatusCommands.ts +0 -123
  130. package/cli/docInternalCommandEntries.ts +0 -20
  131. package/cli/hybridReadHelpers.ts +0 -109
  132. package/cli/machineCommandPrompts.ts +0 -79
  133. package/cli/machineCommandResolution.ts +0 -43
  134. package/cli/noloReadBridgePrompt.ts +0 -16
  135. package/cli/pageCreateCommands.ts +0 -219
  136. package/cli/pageDeleteCommands.ts +0 -167
  137. package/cli/pageReadCommands.ts +0 -151
  138. package/cli/pageUpdateCommands.ts +0 -249
  139. package/cli/pageWriteHelpers.ts +0 -209
  140. package/cli/publishPackage.ts +0 -36
  141. package/cli/runtimeInternalCommandEntries.ts +0 -15
  142. package/cli/runtimePassthroughCommands.ts +0 -22
  143. package/cli/scriptPassthroughHelpers.ts +0 -28
  144. package/cli/secretScanHelpers.ts +0 -31
  145. package/cli/spaceAttachCommands.ts +0 -134
  146. package/cli/spaceCategoryCommands.ts +0 -263
  147. package/cli/spaceCommands.ts +0 -295
  148. package/cli/spaceDeleteCommands.ts +0 -312
  149. package/cli/spaceInternalCommandEntries.ts +0 -21
  150. package/cli/spaceMutationHelpers.ts +0 -135
  151. package/cli/spaceReadCommands.ts +0 -323
  152. package/cli/tableDataOutput.ts +0 -41
  153. package/cli/tableDataSafety.ts +0 -26
  154. package/cli/tableMetaCommands.ts +0 -307
  155. package/cli/tableMutationCommands.ts +0 -266
  156. package/cli/tableQueryParsing.ts +0 -90
  157. package/cli/tableQueryRequest.ts +0 -53
  158. package/cli/taskRunActions.ts +0 -122
  159. package/cli/taskRunParsing.ts +0 -86
  160. package/cli/taskRunPromptShared.ts +0 -55
  161. package/cli/tui/tuiCatalog.ts +0 -22
  162. package/cli/tui/tuiCommandInterpreter.ts +0 -253
  163. package/cli/tui/tuiPresentation.ts +0 -146
  164. package/cliIoTypes.ts +0 -3
  165. package/cliRuntimeDoctorReport.ts +0 -193
  166. package/client/agentRunInput.ts +0 -10
  167. package/client/agentRunLocalExecution.test.ts +0 -123
  168. package/client/agentRunLocalExecution.ts +0 -124
  169. package/client/agentRunLocalExecutor.ts +0 -179
  170. package/client/agentRunRuntimeSelection.test.ts +0 -159
  171. package/client/agentRunRuntimeSelection.ts +0 -145
  172. package/client/agentRunServerTransport.ts +0 -397
  173. package/client/agentRunTaskRunRecorder.ts +0 -176
  174. package/connector-experimental/daemonLauncher.ts +0 -223
  175. package/create/space/spaceKeys.ts +0 -65
  176. package/create/types.ts +0 -21
  177. package/customCodingAgentFlow.ts +0 -208
  178. package/customCodingAgentRecord.ts +0 -179
  179. package/database/keys.ts +0 -765
  180. package/database/server/authorityStoreTypes.ts +0 -31
  181. package/database/server/legacyServerDb.ts +0 -58
  182. package/database/server/levelAuthorityStore.ts +0 -75
  183. package/database/server/memoryAuthorityStore.ts +0 -133
  184. package/database/server/serverStoreFactory.ts +0 -124
  185. package/database/tombstones.ts +0 -52
  186. package/database/utils/ulid.ts +0 -1
  187. package/dialogDataAccess.ts +0 -186
  188. package/dialogInternalCommandEntries.ts +0 -11
  189. package/dialogReadCommands.ts +0 -180
  190. package/dialogReadHelpers.ts +0 -226
  191. package/dialogStatusCommands.ts +0 -123
  192. package/docInternalCommandEntries.ts +0 -20
  193. package/hybridReadHelpers.ts +0 -109
  194. package/machineCommandPrompts.ts +0 -79
  195. package/machineCommandResolution.ts +0 -43
  196. package/noloReadBridgePrompt.ts +0 -16
  197. package/pageCreateCommands.ts +0 -219
  198. package/pageDeleteCommands.ts +0 -167
  199. package/pageReadCommands.ts +0 -151
  200. package/pageUpdateCommands.ts +0 -249
  201. package/pageWriteHelpers.ts +0 -209
  202. package/publishPackage.ts +0 -36
  203. package/runtimeInternalCommandEntries.ts +0 -15
  204. package/runtimePassthroughCommands.ts +0 -22
  205. package/scriptPassthroughHelpers.ts +0 -28
  206. package/secretScanHelpers.ts +0 -31
  207. package/share/helpers.ts +0 -302
  208. package/share/keys.ts +0 -243
  209. package/share/types.ts +0 -100
  210. package/spaceAttachCommands.ts +0 -134
  211. package/spaceCategoryCommands.ts +0 -263
  212. package/spaceCommands.ts +0 -295
  213. package/spaceDeleteCommands.ts +0 -312
  214. package/spaceInternalCommandEntries.ts +0 -21
  215. package/spaceMutationHelpers.ts +0 -135
  216. package/spaceReadCommands.ts +0 -323
  217. package/tableDataOutput.ts +0 -41
  218. package/tableDataSafety.ts +0 -26
  219. package/tableMetaCommands.ts +0 -307
  220. package/tableMutationCommands.ts +0 -266
  221. package/tableQueryParsing.ts +0 -90
  222. package/tableQueryRequest.ts +0 -53
  223. package/taskRunActions.ts +0 -122
  224. package/taskRunParsing.ts +0 -86
  225. package/taskRunPromptShared.ts +0 -55
  226. package/tui/tuiCatalog.ts +0 -22
  227. package/tui/tuiCommandInterpreter.test.ts +0 -169
  228. package/tui/tuiCommandInterpreter.ts +0 -253
  229. package/tui/tuiPresentation.test.ts +0 -154
  230. package/tui/tuiPresentation.ts +0 -146
@@ -1,8 +1,8 @@
1
1
  import type { MachineHeartbeat } from "./connector-experimental/protocol";
2
2
  import type { HeartbeatLoopOptions } from "./connector-experimental/heartbeatLoop";
3
- import type { OutputLike } from "./cliIoTypes";
4
3
 
5
4
  type EnvLike = Record<string, string | undefined>;
5
+ type OutputLike = { write(chunk: string): unknown };
6
6
 
7
7
  function resolveHeartbeatIntervalMs(env: EnvLike) {
8
8
  const raw = Number(env.NOLO_CONNECT_HEARTBEAT_MS ?? "");
@@ -1,6 +1,4 @@
1
1
  import { runLocalAgentTurn, type LocalAgentToolEvent } from "./agent-runtime/localLoop";
2
- import { resolveHostRuntimeConfigFromEnv } from "./agent-runtime/hostRuntimeConfig";
3
- import { normalizeAgentRunDialogLineage } from "./ai/agent/agentRunDialogLineage";
4
2
  import {
5
3
  assertMachineRunAllowed as defaultAssertMachineRunAllowed,
6
4
  resolveMachineRunPermissionPolicy as defaultResolveMachineRunPermissionPolicy,
@@ -58,7 +56,7 @@ type ConnectorRunProgress = {
58
56
 
59
57
  type PermissionPolicy = ReturnType<typeof defaultResolveMachineRunPermissionPolicy>;
60
58
 
61
- export type MachineWsRunDispatchDeps = {
59
+ type MachineWsRunDispatchDeps = {
62
60
  assertMachineRunAllowed?: typeof defaultAssertMachineRunAllowed;
63
61
  resolveMachineRunPermissionPolicy?: typeof defaultResolveMachineRunPermissionPolicy;
64
62
  resolveConnectorRunCwd?: typeof defaultResolveConnectorRunCwd;
@@ -150,7 +148,6 @@ function hasExplicitMachinePermissions(agentConfig: any) {
150
148
 
151
149
  function runtimeWorkspacePermissionPolicy(
152
150
  runtimePolicy: ConnectorRuntimePolicy | undefined,
153
- hostRuntimeConfig: { capabilities: { allowShell: boolean } },
154
151
  cwd: string
155
152
  ): PermissionPolicy | null {
156
153
  if (!requestsTaskWorktree(runtimePolicy)) return null;
@@ -158,10 +155,7 @@ function runtimeWorkspacePermissionPolicy(
158
155
  mode: "full_access",
159
156
  allowFilesystemRead: true,
160
157
  allowFilesystemWrite: true,
161
- allowShell:
162
- hostRuntimeConfig.capabilities.allowShell &&
163
- Array.isArray(runtimePolicy?.runtimeTools) &&
164
- runtimePolicy.runtimeTools.includes("execShell"),
158
+ allowShell: runtimePolicy?.shell?.enabled !== false,
165
159
  writableRoots: [cwd],
166
160
  };
167
161
  }
@@ -199,6 +193,9 @@ function mergeToolNames(...values: unknown[]) {
199
193
  function localRuntimeEnvFromPolicy(runtimeEnv: EnvLike, policy?: ConnectorRuntimePolicy): EnvLike {
200
194
  return {
201
195
  ...runtimeEnv,
196
+ ...(policy?.shell?.enabled && policy.shell.mode === "worktree"
197
+ ? { NOLO_LOCAL_SHELL_MODE: "worktree" }
198
+ : {}),
202
199
  ...(policy?.workspace?.cwd ? { NOLO_LOCAL_WORKTREE: policy.workspace.cwd } : {}),
203
200
  };
204
201
  }
@@ -272,12 +269,6 @@ async function defaultRunConnectorLocalRuntimeAgent(args: {
272
269
  ? args.parsed.payload.agentConfig
273
270
  : {};
274
271
  const policy = runtimePolicyFromConnectorPayload(args.parsed);
275
- const wantsTaskWorktree = requestsTaskWorktree(policy);
276
- const hostRuntimeConfig = resolveHostRuntimeConfigFromEnv({
277
- env: args.runtimeEnv,
278
- surface: "connector-local",
279
- workspaceBinding: wantsTaskWorktree ? "default-cwd" : "explicit-cwd",
280
- });
281
272
  const agentRecord = {
282
273
  ...payloadAgentConfig,
283
274
  dbKey: agentKey,
@@ -303,10 +294,11 @@ async function defaultRunConnectorLocalRuntimeAgent(args: {
303
294
  withForwardedUserAuthToken(args.runtimeEnv, args.parsed),
304
295
  policy
305
296
  );
297
+ const wantsTaskWorktree = requestsTaskWorktree(policy);
306
298
  const adapter = createCliLocalRuntimeAdapter({
307
299
  env,
308
- hostRuntimeConfig,
309
300
  cwd: args.cwd,
301
+ useCwdAsTaskWorkspaceBase: wantsTaskWorktree,
310
302
  ...(wantsTaskWorktree
311
303
  ? {
312
304
  prepareTaskWorktree: (input) => prepareTaskWorktree({
@@ -389,20 +381,6 @@ function normalizeConnectorRunTimeoutMs(value: unknown): number | undefined {
389
381
  return Math.floor(value);
390
382
  }
391
383
 
392
- function normalizeConnectorRunPayloadContinueDialogId(payload: unknown) {
393
- if (!isRecord(payload)) return payload;
394
- const dialogLineage = normalizeAgentRunDialogLineage({
395
- continueDialogId: payload.continueDialogId,
396
- });
397
- const normalizedPayload = { ...payload };
398
- if (dialogLineage.continueDialogId) {
399
- normalizedPayload.continueDialogId = dialogLineage.continueDialogId;
400
- } else {
401
- delete normalizedPayload.continueDialogId;
402
- }
403
- return normalizedPayload;
404
- }
405
-
406
384
  export async function handleConnectorRunMessage(
407
385
  message: string,
408
386
  send: (message: string) => void,
@@ -418,12 +396,6 @@ export async function handleConnectorRunMessage(
418
396
  return;
419
397
  }
420
398
  if (parsed?.type !== "agent.run" || typeof parsed.requestId !== "string") return;
421
- if (isRecord(parsed)) {
422
- parsed = {
423
- ...parsed,
424
- payload: normalizeConnectorRunPayloadContinueDialogId(parsed.payload),
425
- };
426
- }
427
399
  const agentConfig = parsed.payload?.agentConfig ?? {};
428
400
  const sendProgress = (progress: ConnectorRunProgress) => {
429
401
  send(JSON.stringify({
@@ -451,11 +423,6 @@ export async function handleConnectorRunMessage(
451
423
  try {
452
424
  const machinePermissionPolicy = resolveMachineRunPermissionPolicy(agentConfig);
453
425
  const runtimePolicy = runtimePolicyFromConnectorPayload(parsed);
454
- const hostRuntimeConfig = resolveHostRuntimeConfigFromEnv({
455
- env: runtimeEnv,
456
- surface: agentConfig.apiSource === "cli" ? "connector-cli" : "connector-local",
457
- workspaceBinding: requestsTaskWorktree(runtimePolicy) ? "default-cwd" : "explicit-cwd",
458
- });
459
426
  const userInput = String(parsed.payload?.userInput ?? "");
460
427
  const timeout = normalizeConnectorRunTimeoutMs(parsed.payload?.timeoutMs);
461
428
  let cwd = resolveConnectorRunCwd({ env: runtimeEnv, policy: machinePermissionPolicy });
@@ -478,7 +445,7 @@ export async function handleConnectorRunMessage(
478
445
  artifactCwd = prepared.path;
479
446
  }
480
447
  const runtimePermissionPolicy = !hasExplicitMachinePermissions(agentConfig)
481
- ? runtimeWorkspacePermissionPolicy(runtimePolicy, hostRuntimeConfig, cwd)
448
+ ? runtimeWorkspacePermissionPolicy(runtimePolicy, cwd)
482
449
  : null;
483
450
  const effectivePermissionPolicy = scopePermissionPolicyToRuntimeWorkspace(
484
451
  runtimePermissionPolicy ?? machinePermissionPolicy,
@@ -536,18 +503,17 @@ export async function handleConnectorRunMessage(
536
503
  updatedAt: Date.now(),
537
504
  });
538
505
  }, 15_000);
539
- const effectiveRuntimeEnv = withForwardedUserAuthToken(runtimeEnv, parsed);
540
506
  const result = await executeCli(provider, materializedPrompt.prompt, {
541
507
  model: agentConfig.model || undefined,
542
508
  timeout,
543
509
  cwd,
544
510
  yolo: true,
545
511
  env: {
546
- NOLO_SERVER: effectiveRuntimeEnv.NOLO_SERVER || effectiveRuntimeEnv.NOLO_SERVER_URL || effectiveRuntimeEnv.BASE_URL,
547
- NOLO_SERVER_URL: effectiveRuntimeEnv.NOLO_SERVER_URL || effectiveRuntimeEnv.NOLO_SERVER || effectiveRuntimeEnv.BASE_URL,
548
- BASE_URL: effectiveRuntimeEnv.BASE_URL || effectiveRuntimeEnv.NOLO_SERVER || effectiveRuntimeEnv.NOLO_SERVER_URL,
549
- AUTH_TOKEN: effectiveRuntimeEnv.AUTH_TOKEN || effectiveRuntimeEnv.AUTH || effectiveRuntimeEnv.NOLO_MACHINE_API_KEY,
550
- NOLO_MACHINE_API_KEY: effectiveRuntimeEnv.NOLO_MACHINE_API_KEY || effectiveRuntimeEnv.AUTH_TOKEN || effectiveRuntimeEnv.AUTH,
512
+ NOLO_SERVER: runtimeEnv.NOLO_SERVER || runtimeEnv.NOLO_SERVER_URL || runtimeEnv.BASE_URL,
513
+ NOLO_SERVER_URL: runtimeEnv.NOLO_SERVER_URL || runtimeEnv.NOLO_SERVER || runtimeEnv.BASE_URL,
514
+ BASE_URL: runtimeEnv.BASE_URL || runtimeEnv.NOLO_SERVER || runtimeEnv.NOLO_SERVER_URL,
515
+ AUTH_TOKEN: runtimeEnv.AUTH_TOKEN || runtimeEnv.AUTH || runtimeEnv.NOLO_MACHINE_API_KEY,
516
+ NOLO_MACHINE_API_KEY: runtimeEnv.NOLO_MACHINE_API_KEY || runtimeEnv.AUTH_TOKEN || runtimeEnv.AUTH,
551
517
  },
552
518
  }).finally(() => clearInterval(heartbeat));
553
519
  logConnectorRun("agent.run.cli.result", {
@@ -589,7 +555,7 @@ export async function handleConnectorRunMessage(
589
555
  baseSha = await readConnectorGitHead(cwd);
590
556
  const result = await runConnectorLocalRuntimeAgent({
591
557
  parsed,
592
- runtimeEnv: withForwardedUserAuthToken(runtimeEnv, parsed),
558
+ runtimeEnv,
593
559
  cwd,
594
560
  fetchImpl,
595
561
  onProgress: sendProgress,
@@ -119,7 +119,6 @@ export async function runMachineWsSession(options: {
119
119
  resolveConnectorWebSocketTarget: (args: {
120
120
  serverUrl: string;
121
121
  machineId: string;
122
- connectorSurface?: string;
123
122
  headers: Record<string, string>;
124
123
  }) => Promise<string>;
125
124
  connectWebSocket: (url: string, options: ConnectorWebSocketOptions) => Promise<void>;
@@ -150,7 +149,6 @@ export async function runMachineWsSession(options: {
150
149
  const wsTarget = await options.resolveConnectorWebSocketTarget({
151
150
  serverUrl: options.serverUrl,
152
151
  machineId: options.machine.machineId,
153
- connectorSurface: "cli",
154
152
  headers: { Authorization: `Bearer ${options.authToken}` },
155
153
  });
156
154
  websocketPromise = options.connectWebSocket(wsTarget, {
@@ -0,0 +1,314 @@
1
+ import { DEFAULT_NOLO_SERVER_URL } from "./defaultServer";
2
+
3
+ type EnvLike = Record<string, string | undefined>;
4
+
5
+ type OutputLike = {
6
+ write(chunk: string): unknown;
7
+ };
8
+
9
+ type SetupOfflineMarxistsAgentDeps = {
10
+ env?: EnvLike;
11
+ output?: OutputLike;
12
+ fetchImpl?: typeof fetch;
13
+ now?: () => number;
14
+ };
15
+
16
+ type ParsedArgs = {
17
+ serverUrl: string;
18
+ authToken: string;
19
+ userId: string;
20
+ sourceAgentKey: string;
21
+ targetAgentId: string;
22
+ targetAgentKey: string;
23
+ spaceId: string;
24
+ name: string;
25
+ publicAgent: boolean;
26
+ json: boolean;
27
+ };
28
+
29
+ const DEFAULT_USER_ID = "b2e06f801f";
30
+ const DEFAULT_SPACE_ID = "01KKY77TT0DA9NY7TNW3R7255N";
31
+ const DEFAULT_SOURCE_AGENT_ID = "01MIMO25MONTH00000001PGT4X";
32
+ const DEFAULT_TARGET_AGENT_ID = "01OFFMARXBOOK000000010AHL1";
33
+ const DEFAULT_AGENT_NAME = "离线马克思主义文库书籍转换助手";
34
+ const TOOL_NAME = "convertMarxistsBookToOfflineHtml";
35
+ const AGENT_TOOLS = [TOOL_NAME];
36
+
37
+ function readFlagValue(args: string[], flag: string) {
38
+ const index = args.indexOf(flag);
39
+ return index >= 0 ? args[index + 1] : undefined;
40
+ }
41
+
42
+ function parseUserIdFromToken(token: string) {
43
+ const payload = token.split(".")[0];
44
+ if (!payload) return "";
45
+ try {
46
+ const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
47
+ const padded = normalized + "=".repeat((4 - (normalized.length % 4)) % 4);
48
+ const parsed = JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
49
+ return typeof parsed?.userId === "string" ? parsed.userId : "";
50
+ } catch {
51
+ return "";
52
+ }
53
+ }
54
+
55
+ function normalizeBaseUrl(value: string) {
56
+ return value.trim().replace(/\/+$/, "");
57
+ }
58
+
59
+ function parseArgs(args: string[], env: EnvLike): ParsedArgs | null {
60
+ if (args.includes("--help") || args.includes("-h")) return null;
61
+ const serverUrl = normalizeBaseUrl(
62
+ readFlagValue(args, "--server") ??
63
+ readFlagValue(args, "--server-url") ??
64
+ env.NOLO_SERVER ??
65
+ env.BASE_URL ??
66
+ DEFAULT_NOLO_SERVER_URL
67
+ );
68
+ const authToken = readFlagValue(args, "--token") ?? env.AUTH_TOKEN ?? env.NOLO_AUTH_TOKEN ?? "";
69
+ const userId =
70
+ readFlagValue(args, "--user-id") ??
71
+ env.NOLO_USER_ID ??
72
+ parseUserIdFromToken(authToken) ??
73
+ DEFAULT_USER_ID;
74
+ const sourceAgentKey =
75
+ readFlagValue(args, "--source-agent") ??
76
+ env.NOLO_MIMO_SOURCE_AGENT_KEY ??
77
+ `agent-${userId}-${DEFAULT_SOURCE_AGENT_ID}`;
78
+ const targetAgentId =
79
+ readFlagValue(args, "--target-agent-id") ??
80
+ env.NOLO_OFFLINE_MARXISTS_AGENT_ID ??
81
+ DEFAULT_TARGET_AGENT_ID;
82
+ const targetAgentKey =
83
+ readFlagValue(args, "--target-agent") ??
84
+ env.NOLO_OFFLINE_MARXISTS_AGENT_KEY ??
85
+ `agent-${userId}-${targetAgentId}`;
86
+ const spaceId =
87
+ readFlagValue(args, "--space") ??
88
+ env.NOLO_OFFLINE_MARXISTS_SPACE_ID ??
89
+ DEFAULT_SPACE_ID;
90
+
91
+ if (!authToken.trim()) return null;
92
+ return {
93
+ serverUrl,
94
+ authToken,
95
+ userId,
96
+ sourceAgentKey,
97
+ targetAgentId,
98
+ targetAgentKey,
99
+ spaceId,
100
+ name: readFlagValue(args, "--name") ?? DEFAULT_AGENT_NAME,
101
+ publicAgent: args.includes("--public"),
102
+ json: args.includes("--json"),
103
+ };
104
+ }
105
+
106
+ async function readDbRecord(args: {
107
+ fetchImpl: typeof fetch;
108
+ serverUrl: string;
109
+ authToken: string;
110
+ dbKey: string;
111
+ }) {
112
+ const res = await args.fetchImpl(
113
+ `${args.serverUrl}/api/v1/db/read/${encodeURIComponent(args.dbKey)}`,
114
+ { headers: { Authorization: `Bearer ${args.authToken}` } }
115
+ );
116
+ const data = await res.json().catch(() => ({}));
117
+ if (!res.ok) {
118
+ throw new Error(`read ${args.dbKey} failed (${res.status}): ${JSON.stringify(data)}`);
119
+ }
120
+ return (data as any)?.data ?? data;
121
+ }
122
+
123
+ async function writeDbRecord(args: {
124
+ fetchImpl: typeof fetch;
125
+ serverUrl: string;
126
+ authToken: string;
127
+ userId: string;
128
+ dbKey: string;
129
+ data: Record<string, any>;
130
+ }) {
131
+ const res = await args.fetchImpl(`${args.serverUrl}/api/v1/db/write/`, {
132
+ method: "POST",
133
+ headers: {
134
+ "Content-Type": "application/json",
135
+ Authorization: `Bearer ${args.authToken}`,
136
+ },
137
+ body: JSON.stringify({
138
+ customKey: args.dbKey,
139
+ userId: args.userId,
140
+ data: { ...args.data, dbKey: args.dbKey },
141
+ }),
142
+ });
143
+ const data = await res.json().catch(() => ({}));
144
+ if (!res.ok) {
145
+ throw new Error(`write ${args.dbKey} failed (${res.status}): ${JSON.stringify(data)}`);
146
+ }
147
+ }
148
+
149
+ function buildTargetAgent(args: {
150
+ parsed: ParsedArgs;
151
+ source: Record<string, any>;
152
+ now: number;
153
+ }) {
154
+ const { parsed, source, now } = args;
155
+ if (!source.apiKey) {
156
+ throw new Error(`source agent ${parsed.sourceAgentKey} has no apiKey`);
157
+ }
158
+ if (!source.customProviderUrl) {
159
+ throw new Error(`source agent ${parsed.sourceAgentKey} has no customProviderUrl`);
160
+ }
161
+ return {
162
+ id: parsed.targetAgentId,
163
+ type: "agent",
164
+ name: parsed.name,
165
+ description:
166
+ "把 Marxists.org 中文旧式书籍页面转换为可离线打开的单文件 HTML,保留原 CSS、表格排版和背景纹理。",
167
+ prompt:
168
+ "你是离线书籍转换助手。用户给出 Marxists.org 中文书籍页面或要求保存离线书籍时,只能调用 convertMarxistsBookToOfflineHtml,不要使用普通网页抓取流程。最终回答必须逐字给出 rawData.fileUrl、rawData.pageCount、rawData.hasNetworkUrls、rawData.byteLength。",
169
+ isPublic: parsed.publicAgent,
170
+ model: source.model ?? "mimo-v2.5-pro",
171
+ provider: source.provider ?? "custom",
172
+ apiSource: source.apiSource ?? "custom",
173
+ apiKey: source.apiKey,
174
+ customProviderUrl: source.customProviderUrl,
175
+ apiKeyHeader: source.apiKeyHeader ?? "api-key",
176
+ tools: AGENT_TOOLS,
177
+ temperature: source.temperature ?? 0.2,
178
+ maxTokens: source.maxTokens ?? 4096,
179
+ category: "document-tools",
180
+ tags: ["offline-book", "marxists", "mimo"],
181
+ userId: parsed.userId,
182
+ createdAt: source.createdAt ?? now,
183
+ updatedAt: now,
184
+ };
185
+ }
186
+
187
+ async function attachAgentToSpace(args: {
188
+ fetchImpl: typeof fetch;
189
+ parsed: ParsedArgs;
190
+ contentKey: string;
191
+ title: string;
192
+ now: number;
193
+ }) {
194
+ const spaceKey = `space-${args.parsed.spaceId}`;
195
+ const space = await readDbRecord({
196
+ fetchImpl: args.fetchImpl,
197
+ serverUrl: args.parsed.serverUrl,
198
+ authToken: args.parsed.authToken,
199
+ dbKey: spaceKey,
200
+ });
201
+ await writeDbRecord({
202
+ fetchImpl: args.fetchImpl,
203
+ serverUrl: args.parsed.serverUrl,
204
+ authToken: args.parsed.authToken,
205
+ userId: args.parsed.userId,
206
+ dbKey: spaceKey,
207
+ data: {
208
+ ...space,
209
+ contents: {
210
+ ...(space.contents ?? {}),
211
+ [args.contentKey]: {
212
+ ...(space.contents?.[args.contentKey] ?? {}),
213
+ title: args.title,
214
+ type: "agent",
215
+ contentKey: args.contentKey,
216
+ createdAt: space.contents?.[args.contentKey]?.createdAt ?? args.now,
217
+ updatedAt: args.now,
218
+ },
219
+ },
220
+ updatedAt: args.now,
221
+ },
222
+ });
223
+ }
224
+
225
+ function writeUsage(output: OutputLike) {
226
+ output.write(
227
+ "Usage: nolo agent setup-offline-marxists [--server https://nolo.chat] [--source-agent <key>] [--space <spaceId>] [--target-agent-id <id>] [--json]\n" +
228
+ "Requires AUTH_TOKEN from `nolo login` or --token.\n"
229
+ );
230
+ }
231
+
232
+ export async function runSetupOfflineMarxistsAgentCommand(
233
+ args: string[],
234
+ deps: SetupOfflineMarxistsAgentDeps = {}
235
+ ) {
236
+ const env = deps.env ?? process.env;
237
+ const output = deps.output ?? process.stdout;
238
+ const parsed = parseArgs(args, env);
239
+ if (!parsed) {
240
+ writeUsage(output);
241
+ return 1;
242
+ }
243
+ const fetchImpl = deps.fetchImpl ?? fetch;
244
+ const now = deps.now?.() ?? Date.now();
245
+
246
+ try {
247
+ const source = await readDbRecord({
248
+ fetchImpl,
249
+ serverUrl: parsed.serverUrl,
250
+ authToken: parsed.authToken,
251
+ dbKey: parsed.sourceAgentKey,
252
+ });
253
+ const target = buildTargetAgent({ parsed, source, now });
254
+ await writeDbRecord({
255
+ fetchImpl,
256
+ serverUrl: parsed.serverUrl,
257
+ authToken: parsed.authToken,
258
+ userId: parsed.userId,
259
+ dbKey: parsed.targetAgentKey,
260
+ data: target,
261
+ });
262
+ const publicKey = `agent-pub-${parsed.targetAgentId}`;
263
+ if (parsed.publicAgent) {
264
+ await writeDbRecord({
265
+ fetchImpl,
266
+ serverUrl: parsed.serverUrl,
267
+ authToken: parsed.authToken,
268
+ userId: parsed.userId,
269
+ dbKey: publicKey,
270
+ data: target,
271
+ });
272
+ }
273
+ await attachAgentToSpace({
274
+ fetchImpl,
275
+ parsed,
276
+ contentKey: parsed.publicAgent ? publicKey : parsed.targetAgentKey,
277
+ title: parsed.name,
278
+ now,
279
+ });
280
+
281
+ const result = {
282
+ serverUrl: parsed.serverUrl,
283
+ sourceAgentKey: parsed.sourceAgentKey,
284
+ agentKey: parsed.targetAgentKey,
285
+ agentUrl: `${parsed.serverUrl}/${parsed.targetAgentKey}`,
286
+ publicKey: parsed.publicAgent ? publicKey : null,
287
+ spaceId: parsed.spaceId,
288
+ model: target.model,
289
+ provider: target.provider,
290
+ customProviderUrl: target.customProviderUrl,
291
+ tools: target.tools,
292
+ };
293
+ if (parsed.json) {
294
+ output.write(`${JSON.stringify(result, null, 2)}\n`);
295
+ } else {
296
+ output.write(
297
+ [
298
+ `created/updated: ${result.agentKey}`,
299
+ `url: ${result.agentUrl}`,
300
+ `space: ${result.spaceId}`,
301
+ `model: ${result.model}`,
302
+ `tools: ${result.tools.join(", ")}`,
303
+ "",
304
+ ].join("\n")
305
+ );
306
+ }
307
+ return 0;
308
+ } catch (error) {
309
+ output.write(
310
+ `setup-offline-marxists failed: ${error instanceof Error ? error.message : String(error)}\n`
311
+ );
312
+ return 1;
313
+ }
314
+ }