nolo-cli 0.8.0-alpha.2 → 0.8.0-alpha.21

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 (188) hide show
  1. package/README.md +1 -1
  2. package/_executeModel-42U3VOVZ.js +205 -0
  3. package/action-TLI3V62L.js +28 -0
  4. package/addContentAction-57RSIIMR.js +26 -0
  5. package/addDialogAgentAction-G3VWEA6E.js +68 -0
  6. package/agentDeleteCommand-5DD2IM3J.js +327 -0
  7. package/agentEmailCommands-6FACJBU4.js +628 -0
  8. package/agentListCommands-I6KZYCIG.js +223 -0
  9. package/agentMachineCommands-VKLIGMZA.js +425 -0
  10. package/agentPullCommand-O2MTUAFR.js +122 -0
  11. package/agentRecordCommands-7TZICYDT.js +96 -0
  12. package/agentRunCommand-L4OM23KV.js +114 -0
  13. package/agentRunControl-K4VKNEHF.js +57 -0
  14. package/agentRuntimeLocal-ZYEIPTY4.js +104 -0
  15. package/agentSlice-BX7GXSNO.js +42 -0
  16. package/authCommand-EB5JSOX5.js +581 -0
  17. package/authCommands-XPEHTKSM.js +35 -0
  18. package/chunk-25LCXTML.js +175 -0
  19. package/chunk-2ECQG4YX.js +22296 -0
  20. package/chunk-2FTTDCD4.js +675 -0
  21. package/chunk-2JCXITPK.js +1078 -0
  22. package/chunk-3ASDTTEI.js +1774 -0
  23. package/chunk-3EUW3WEO.js +8 -0
  24. package/chunk-3LY4F7SV.js +9293 -0
  25. package/chunk-4CQLVGRV.js +50 -0
  26. package/chunk-4IJYA27C.js +342 -0
  27. package/chunk-4O3CARJ4.js +231 -0
  28. package/chunk-4QEWT7KD.js +933 -0
  29. package/chunk-4SN6J65J.js +38 -0
  30. package/chunk-4VNS5WPM.js +42 -0
  31. package/chunk-4XENYTF5.js +222 -0
  32. package/chunk-4ZDM73SD.js +34 -0
  33. package/chunk-5CS33IBL.js +301 -0
  34. package/chunk-5EFXE3O7.js +138 -0
  35. package/chunk-5KLGBAAR.js +386 -0
  36. package/chunk-5MIDPSSK.js +206 -0
  37. package/chunk-5MMAK75Q.js +15 -0
  38. package/chunk-63W5N6P3.js +150 -0
  39. package/chunk-6HYVJV7B.js +102 -0
  40. package/chunk-6KHNO3SK.js +1948 -0
  41. package/chunk-6WD3OOJS.js +20 -0
  42. package/chunk-7DAJ4AI4.js +191 -0
  43. package/chunk-7GNGZRLZ.js +1939 -0
  44. package/chunk-7KCUSYT2.js +354 -0
  45. package/chunk-7U44LYTR.js +238 -0
  46. package/chunk-AFON4QUU.js +112 -0
  47. package/chunk-AGFH73SK.js +239 -0
  48. package/chunk-AL2KDGR2.js +27339 -0
  49. package/chunk-AS4PVWA4.js +221 -0
  50. package/chunk-ATNTHIZI.js +13 -0
  51. package/chunk-AVMKZHBC.js +85 -0
  52. package/chunk-AZPCASRE.js +36 -0
  53. package/chunk-BBYVOSU2.js +792 -0
  54. package/chunk-C3RUNRHT.js +51 -0
  55. package/chunk-C4FTUXVF.js +146 -0
  56. package/chunk-CF2WZF4N.js +134 -0
  57. package/chunk-CF7PE763.js +10 -0
  58. package/chunk-CKOJQDKR.js +198 -0
  59. package/chunk-CMKUBIGW.js +1550 -0
  60. package/chunk-CWMSB67P.js +34 -0
  61. package/chunk-DCOA4QSN.js +105 -0
  62. package/chunk-DFFIZ25G.js +30 -0
  63. package/chunk-DSZUWUYB.js +478 -0
  64. package/chunk-DWLEOOGR.js +8 -0
  65. package/chunk-DZ3XJVET.js +231 -0
  66. package/chunk-EHLHSX7R.js +1433 -0
  67. package/chunk-ENOG22KJ.js +939 -0
  68. package/chunk-FSO5B7GH.js +171 -0
  69. package/chunk-FVYY6MCS.js +1447 -0
  70. package/chunk-G3SUCT4W.js +8 -0
  71. package/chunk-GAKEBQD6.js +30 -0
  72. package/chunk-GBRG75BQ.js +86 -0
  73. package/chunk-GU3PEVGZ.js +4723 -0
  74. package/chunk-H33743XH.js +25 -0
  75. package/chunk-HNMXYYJR.js +12 -0
  76. package/chunk-HNW7IJSK.js +71 -0
  77. package/chunk-I42VC5KR.js +15 -0
  78. package/chunk-I6XMPTMR.js +113 -0
  79. package/chunk-IDZTNRP2.js +85 -0
  80. package/chunk-ISNCLGUZ.js +146 -0
  81. package/chunk-IWX4UW2E.js +548 -0
  82. package/chunk-JBTJAPUF.js +35 -0
  83. package/chunk-JEXVIMYZ.js +55 -0
  84. package/chunk-JRKKFRAV.js +537 -0
  85. package/chunk-JZPBVBIY.js +94 -0
  86. package/chunk-KKY4B2Q2.js +21 -0
  87. package/chunk-KQHGZWSV.js +63 -0
  88. package/chunk-KUG52IAP.js +8 -0
  89. package/chunk-KX6YBIHG.js +8 -0
  90. package/chunk-LCBAMY2M.js +60 -0
  91. package/chunk-LM6IYQ3F.js +16 -0
  92. package/chunk-LTRXGFMS.js +83 -0
  93. package/chunk-M76ECQRD.js +13658 -0
  94. package/chunk-MRC4Q34M.js +188 -0
  95. package/chunk-MTU75CZ2.js +91 -0
  96. package/chunk-N54XAP77.js +19 -0
  97. package/chunk-O2ZNTTET.js +3272 -0
  98. package/chunk-O4BU24WZ.js +3212 -0
  99. package/chunk-OLZBQWZU.js +6 -0
  100. package/chunk-OOSFSFMA.js +271 -0
  101. package/chunk-OPZYGHUC.js +89 -0
  102. package/chunk-OWOHNGCN.js +50 -0
  103. package/chunk-P3PKED2I.js +962 -0
  104. package/chunk-QSJ3HFEF.js +8 -0
  105. package/chunk-RCSJFQPB.js +9036 -0
  106. package/chunk-RL776AGR.js +190 -0
  107. package/chunk-ROWQEJRP.js +139 -0
  108. package/chunk-S7Z2HMCN.js +25 -0
  109. package/chunk-SDJDLO5W.js +628 -0
  110. package/chunk-SOTZ6RDN.js +69 -0
  111. package/chunk-TILFE6LV.js +381 -0
  112. package/chunk-U4TRT5V4.js +246 -0
  113. package/chunk-U6VC4MU4.js +8 -0
  114. package/chunk-UAD2WT54.js +64 -0
  115. package/chunk-UB6SN4NJ.js +421 -0
  116. package/chunk-URUUZLPA.js +807 -0
  117. package/chunk-UTLZINAP.js +3066 -0
  118. package/chunk-VC6OZXO5.js +298 -0
  119. package/chunk-VF4K2QE6.js +21 -0
  120. package/chunk-VHBWHNVT.js +59 -0
  121. package/chunk-VIDPVFP3.js +20 -0
  122. package/chunk-VP4WJWKW.js +8882 -0
  123. package/chunk-VUW5FBDB.js +573 -0
  124. package/chunk-VVX233PH.js +482 -0
  125. package/chunk-VX3SXJ3N.js +2052 -0
  126. package/chunk-W4NVOSFF.js +37 -0
  127. package/chunk-WWC7I6TA.js +8 -0
  128. package/chunk-WZSRQNQG.js +2587 -0
  129. package/chunk-XBUBEFNX.js +34 -0
  130. package/chunk-XENYHRUE.js +104 -0
  131. package/chunk-Y5GCAMGP.js +9 -0
  132. package/chunk-YPRZSPF3.js +148 -0
  133. package/chunk-Z4NR32XR.js +50 -0
  134. package/chunk-ZNFJWEN4.js +56 -0
  135. package/cliExecutor-K3F7DMRO.js +36 -0
  136. package/clipboardy-BVE3LVEH.js +12001 -0
  137. package/createAgentAutomationAction-RJF3N2QY.js +866 -0
  138. package/createDialogAction-DRSPS6CE.js +55 -0
  139. package/createPageAction-6B2WMNO3.js +172 -0
  140. package/db-HCJ5PRB5.js +271 -0
  141. package/dbSlice-Q3TM2FJV.js +60 -0
  142. package/deleteFile-OW53A6BX.js +41 -0
  143. package/dialogCommands-4IX4XIZE.js +63 -0
  144. package/dialogSlice-3M7KX2TX.js +148 -0
  145. package/docCreateCommands-SIL3NPGT.js +220 -0
  146. package/docDeleteCommands-7IOMLUS4.js +181 -0
  147. package/docReadCommands-FNFXUA5L.js +134 -0
  148. package/docStore-SV7E34D4.js +98 -0
  149. package/docUpdateCommands-X2HNDVUC.js +318 -0
  150. package/fetchMessages-KTNM7QAR.js +17 -0
  151. package/getPricing-3E6UNPKL.js +30 -0
  152. package/handleSendMessageAction-JYETO5RZ.js +185 -0
  153. package/index.js +188 -112958
  154. package/lib-FYYBQIXS.js +19839 -0
  155. package/localDialogRead-2VRI24F4.js +26 -0
  156. package/localFirstLog-DHNOY2NA.js +19 -0
  157. package/localRuntimeAuthority-TEGCOWX4.js +471 -0
  158. package/localRuntimeDb-LGDF6FQP.js +12 -0
  159. package/machineCommands-RIO3RP5Q.js +781 -0
  160. package/machineInfo-M6KB6HZN.js +10 -0
  161. package/machineWsRunDispatch-W7UYLGB5.js +112 -0
  162. package/memoryCommands-O4MIPIWQ.js +476 -0
  163. package/models-4OPOOLFS.js +9 -0
  164. package/offlineMarxistsAgentCommand-BCPJITJL.js +242 -0
  165. package/package.json +4 -24
  166. package/read-GW7ZEI23.js +17 -0
  167. package/readDocTool-HUFU6OCT.js +16 -0
  168. package/readlineWorkspace-27JR7WPW.js +5682 -0
  169. package/removeDialogAgentAction-CXKR4NJI.js +73 -0
  170. package/runAgentClientLoop-HZFAPJHS.js +293 -0
  171. package/runtimeDoctorCommands-LRHLPDRC.js +289 -0
  172. package/setDialogExtraReferencesAction-6RKUSXHX.js +60 -0
  173. package/setPrimaryDialogAgentAction-T3UTBEFG.js +80 -0
  174. package/settingSlice-IVKXJXMG.js +199 -0
  175. package/skillDiscovery-UGSQGX2U.js +16 -0
  176. package/skillSummaryMarker-42HKSXYY.js +9 -0
  177. package/slateToRenderMarkdown-Y5IYN73U.js +7 -0
  178. package/slateUtils-2M7MUTWX.js +19 -0
  179. package/spaceCommands-E7VOF4LO.js +450 -0
  180. package/spaceSlice-TSVROA5U.js +149 -0
  181. package/streamAgentChatTurn-3C5RQZJF.js +4510 -0
  182. package/tableCommands-O7O2LBEG.js +1286 -0
  183. package/toolApiClient-QI3YBNWB.js +26 -0
  184. package/tools-EQDEKR6N.js +87 -0
  185. package/tuiSummaryLlmCaller-RV3THLZF.js +78 -0
  186. package/understanding-3CUQQ6SV.js +271 -0
  187. package/updateCommands-VOSPKXFF.js +31 -0
  188. package/updateDialogTitleAction-3XV7VWSZ.js +188 -0
@@ -0,0 +1,781 @@
1
+ import {
2
+ buildMachinePermissionPromptBlock,
3
+ handleConnectorRunMessage,
4
+ resolveMachineRunPermissionPolicy
5
+ } from "./chunk-2JCXITPK.js";
6
+ import {
7
+ isConnectorWebSocketAuthError,
8
+ isConnectorWebSocketRetryableError,
9
+ resolveConnectorWebSocketTarget
10
+ } from "./chunk-AVMKZHBC.js";
11
+ import {
12
+ detectMachineInfo
13
+ } from "./chunk-6HYVJV7B.js";
14
+ import "./chunk-RCSJFQPB.js";
15
+ import "./chunk-EHLHSX7R.js";
16
+ import "./chunk-N54XAP77.js";
17
+ import "./chunk-VHBWHNVT.js";
18
+ import "./chunk-4O3CARJ4.js";
19
+ import "./chunk-CMKUBIGW.js";
20
+ import "./chunk-JBTJAPUF.js";
21
+ import "./chunk-ATNTHIZI.js";
22
+ import "./chunk-FSO5B7GH.js";
23
+ import "./chunk-C3RUNRHT.js";
24
+ import "./chunk-AL2KDGR2.js";
25
+ import "./chunk-GAKEBQD6.js";
26
+ import "./chunk-KQHGZWSV.js";
27
+ import "./chunk-AS4PVWA4.js";
28
+ import "./chunk-3LY4F7SV.js";
29
+ import "./chunk-VP4WJWKW.js";
30
+ import "./chunk-63W5N6P3.js";
31
+ import "./chunk-VF4K2QE6.js";
32
+ import "./chunk-UB6SN4NJ.js";
33
+ import "./chunk-ENOG22KJ.js";
34
+ import "./chunk-VC6OZXO5.js";
35
+ import "./chunk-OWOHNGCN.js";
36
+ import "./chunk-25LCXTML.js";
37
+ import "./chunk-XENYHRUE.js";
38
+ import "./chunk-2ECQG4YX.js";
39
+ import "./chunk-4ZDM73SD.js";
40
+ import "./chunk-MRC4Q34M.js";
41
+ import "./chunk-MTU75CZ2.js";
42
+ import "./chunk-CWMSB67P.js";
43
+ import "./chunk-VUW5FBDB.js";
44
+ import "./chunk-5EFXE3O7.js";
45
+ import "./chunk-Z4NR32XR.js";
46
+ import "./chunk-M76ECQRD.js";
47
+ import "./chunk-SOTZ6RDN.js";
48
+ import "./chunk-I6XMPTMR.js";
49
+ import "./chunk-UAD2WT54.js";
50
+ import "./chunk-DCOA4QSN.js";
51
+ import "./chunk-IDZTNRP2.js";
52
+ import {
53
+ isCompiledBinary
54
+ } from "./chunk-ISNCLGUZ.js";
55
+ import {
56
+ DEFAULT_NOLO_SERVER_URL
57
+ } from "./chunk-OLZBQWZU.js";
58
+ import "./chunk-WZSRQNQG.js";
59
+ import "./chunk-O2ZNTTET.js";
60
+ import "./chunk-5KLGBAAR.js";
61
+ import "./chunk-ZNFJWEN4.js";
62
+ import "./chunk-TILFE6LV.js";
63
+ import "./chunk-4QEWT7KD.js";
64
+ import "./chunk-OPZYGHUC.js";
65
+ import "./chunk-AGFH73SK.js";
66
+ import "./chunk-JRKKFRAV.js";
67
+ import "./chunk-P3PKED2I.js";
68
+ import "./chunk-5MMAK75Q.js";
69
+ import "./chunk-BBYVOSU2.js";
70
+ import "./chunk-5CS33IBL.js";
71
+ import "./chunk-JZPBVBIY.js";
72
+ import "./chunk-IWX4UW2E.js";
73
+ import "./chunk-5MIDPSSK.js";
74
+ import "./chunk-DFFIZ25G.js";
75
+ import "./chunk-3ASDTTEI.js";
76
+ import "./chunk-DWLEOOGR.js";
77
+ import {
78
+ toErrorMessage
79
+ } from "./chunk-HNMXYYJR.js";
80
+ import "./chunk-H33743XH.js";
81
+ import "./chunk-LM6IYQ3F.js";
82
+ import "./chunk-VX3SXJ3N.js";
83
+ import {
84
+ parsePositiveFiniteNumberOrFallback
85
+ } from "./chunk-Y5GCAMGP.js";
86
+ import "./chunk-URUUZLPA.js";
87
+ import "./chunk-AZPCASRE.js";
88
+ import "./chunk-7U44LYTR.js";
89
+ import "./chunk-KX6YBIHG.js";
90
+ import "./chunk-O4BU24WZ.js";
91
+ import "./chunk-I42VC5KR.js";
92
+ import "./chunk-WWC7I6TA.js";
93
+ import "./chunk-QSJ3HFEF.js";
94
+ import "./chunk-DSZUWUYB.js";
95
+ import "./chunk-UTLZINAP.js";
96
+ import "./chunk-OOSFSFMA.js";
97
+ import "./chunk-GBRG75BQ.js";
98
+ import "./chunk-4SN6J65J.js";
99
+ import "./chunk-LCBAMY2M.js";
100
+ import {
101
+ asTrimmedString
102
+ } from "./chunk-3EUW3WEO.js";
103
+ import "./chunk-U6VC4MU4.js";
104
+ import {
105
+ normalizeServerOrigin
106
+ } from "./chunk-CF7PE763.js";
107
+ import "./chunk-G3SUCT4W.js";
108
+ import {
109
+ isRecord
110
+ } from "./chunk-KUG52IAP.js";
111
+ import "./chunk-4VNS5WPM.js";
112
+
113
+ // packages/connector-experimental/heartbeatLoop.ts
114
+ var defaultSleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
115
+ async function runHeartbeatLoop(options) {
116
+ const sleep = options.sleep ?? defaultSleep;
117
+ let beats = 0;
118
+ while (!options.signal?.aborted) {
119
+ await options.sendHeartbeat();
120
+ beats += 1;
121
+ if (options.maxBeats && beats >= options.maxBeats) return;
122
+ if (options.signal?.aborted) return;
123
+ await sleep(options.intervalMs);
124
+ }
125
+ }
126
+
127
+ // packages/cli/machineDaemonCommands.ts
128
+ import { spawn } from "node:child_process";
129
+ import { existsSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync } from "node:fs";
130
+ import { homedir } from "node:os";
131
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
132
+ import { fileURLToPath } from "node:url";
133
+ var CONNECTOR_RUNTIME_WORKSPACE_PACKAGES = /* @__PURE__ */ new Set([
134
+ "connector-experimental",
135
+ "ai"
136
+ ]);
137
+ function readJsonFile(path) {
138
+ try {
139
+ return JSON.parse(readFileSync(path, "utf8"));
140
+ } catch {
141
+ return null;
142
+ }
143
+ }
144
+ function getWorkspacePatterns(packageJson) {
145
+ if (Array.isArray(packageJson.workspaces)) return packageJson.workspaces;
146
+ return packageJson.workspaces?.packages ?? [];
147
+ }
148
+ function normalizePath(path) {
149
+ const resolved = resolve(path);
150
+ return process.platform === "win32" ? resolved.toLowerCase() : resolved;
151
+ }
152
+ function isInsideOrSame(path, parent) {
153
+ const relativePath = relative(parent, path);
154
+ return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute(relativePath);
155
+ }
156
+ function findWorkspaceRoot(startPath) {
157
+ let current = resolve(startPath);
158
+ while (true) {
159
+ const packageJsonPath = join(current, "package.json");
160
+ if (existsSync(packageJsonPath)) {
161
+ const packageJson = readJsonFile(packageJsonPath);
162
+ if (packageJson && getWorkspacePatterns(packageJson).length > 0) {
163
+ return current;
164
+ }
165
+ }
166
+ const parent = dirname(current);
167
+ if (parent === current) return null;
168
+ current = parent;
169
+ }
170
+ }
171
+ function listWorkspacePackageJsonFiles(workspaceParent) {
172
+ let entries;
173
+ try {
174
+ entries = readdirSync(workspaceParent, { withFileTypes: true });
175
+ } catch {
176
+ return [];
177
+ }
178
+ const results = [];
179
+ for (const entry of entries) {
180
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
181
+ const relativePath = `${entry.name}/package.json`;
182
+ if (existsSync(join(workspaceParent, relativePath))) {
183
+ results.push(relativePath);
184
+ }
185
+ }
186
+ return results;
187
+ }
188
+ function validateConnectorWorkspaceLinks(cwd) {
189
+ const repoRoot = findWorkspaceRoot(cwd);
190
+ if (!repoRoot) return [];
191
+ const rootPackageJson = readJsonFile(join(repoRoot, "package.json"));
192
+ if (!rootPackageJson) return [];
193
+ const normalizedRepoRoot = normalizePath(realpathSync(repoRoot));
194
+ const errors = [];
195
+ for (const pattern of getWorkspacePatterns(rootPackageJson)) {
196
+ if (!pattern.endsWith("/*")) continue;
197
+ const workspaceParent = join(repoRoot, pattern.slice(0, -2));
198
+ if (!existsSync(workspaceParent)) continue;
199
+ for (const entry of listWorkspacePackageJsonFiles(workspaceParent)) {
200
+ const packageDir = join(workspaceParent, dirname(entry));
201
+ const packageJson = readJsonFile(join(workspaceParent, entry));
202
+ if (!packageJson?.name || !CONNECTOR_RUNTIME_WORKSPACE_PACKAGES.has(packageJson.name)) {
203
+ continue;
204
+ }
205
+ const linkPath = join(repoRoot, "node_modules", ...packageJson.name.split("/"));
206
+ if (!existsSync(linkPath)) {
207
+ errors.push(`${linkPath} is missing. Run bun install in ${repoRoot}.`);
208
+ continue;
209
+ }
210
+ const actualPath = normalizePath(realpathSync(linkPath));
211
+ const expectedPath = normalizePath(realpathSync(packageDir));
212
+ if (!isInsideOrSame(actualPath, normalizedRepoRoot)) {
213
+ errors.push(
214
+ `${linkPath} points outside this checkout: ${actualPath}. Run bun install in ${repoRoot}.`
215
+ );
216
+ continue;
217
+ }
218
+ if (actualPath !== expectedPath) {
219
+ errors.push(
220
+ `${linkPath} points at ${actualPath}, expected ${expectedPath}. Run bun install in ${repoRoot}.`
221
+ );
222
+ }
223
+ }
224
+ }
225
+ return errors;
226
+ }
227
+ async function checkConnectorWorkspaceLinks(cwd, output, validateWorkspaceLinks) {
228
+ const errors = await validateWorkspaceLinks(cwd);
229
+ if (errors.length === 0) return true;
230
+ output.write(
231
+ [
232
+ "[nolo] Connector workspace package links are unsafe.",
233
+ "The connector would import workspace packages from a different checkout, so machine capabilities and runtime behavior may be stale.",
234
+ ...errors,
235
+ ""
236
+ ].join("\n")
237
+ );
238
+ return false;
239
+ }
240
+ function resolveDaemonLogPath(env) {
241
+ return env.NOLO_CONNECT_LOG || join(homedir(), ".nolo", "logs", "connector.log");
242
+ }
243
+ function buildDaemonCommand(cliEntrypointPath) {
244
+ const execPath = process.execPath;
245
+ const entrypoint = cliEntrypointPath || fileURLToPath(import.meta.url);
246
+ if (isCompiledBinary() || entrypoint === execPath) {
247
+ return [execPath, "connect", "--ws"];
248
+ }
249
+ return [execPath, entrypoint, "connect", "--ws"];
250
+ }
251
+ function defaultSpawnDaemon(args) {
252
+ mkdirSync(dirname(args.logPath), { recursive: true });
253
+ const out = openSync(args.logPath, "a");
254
+ const env = Object.fromEntries(
255
+ Object.entries(args.env).filter((entry) => typeof entry[1] === "string")
256
+ );
257
+ const proc = spawn(args.cmd[0], args.cmd.slice(1), {
258
+ cwd: args.cwd,
259
+ env,
260
+ detached: true,
261
+ stdio: ["ignore", out, out]
262
+ });
263
+ proc.unref();
264
+ return { pid: proc.pid };
265
+ }
266
+ async function runMachineDaemonCommand(deps = {}) {
267
+ const env = deps.env ?? process.env;
268
+ const output = deps.output ?? process.stdout;
269
+ const validateWorkspaceLinks = deps.validateWorkspaceLinks ?? validateConnectorWorkspaceLinks;
270
+ if (!await checkConnectorWorkspaceLinks(process.cwd(), output, validateWorkspaceLinks)) {
271
+ return 1;
272
+ }
273
+ const logPath = resolveDaemonLogPath(env);
274
+ const result = (deps.spawnDaemon ?? defaultSpawnDaemon)({
275
+ cmd: buildDaemonCommand(deps.cliEntrypointPath),
276
+ cwd: process.cwd(),
277
+ env,
278
+ logPath
279
+ });
280
+ output.write(`Connector daemon started${result.pid ? ` pid=${result.pid}` : ""}. Log: ${logPath}
281
+ `);
282
+ return 0;
283
+ }
284
+
285
+ // packages/cli/machineHeartbeatCommands.ts
286
+ async function runMachineHeartbeatConnectCommand(deps) {
287
+ const output = deps.output ?? process.stdout;
288
+ const machine = deps.machine;
289
+ try {
290
+ await deps.sendHeartbeat();
291
+ } catch (error) {
292
+ output.write(
293
+ `[nolo] Machine connect failed: ${toErrorMessage(error)}
294
+ `
295
+ );
296
+ return 1;
297
+ }
298
+ output.write(`Connected machine: ${machine.name} (${machine.platform}/${machine.arch})
299
+ `);
300
+ return 0;
301
+ }
302
+
303
+ // packages/cli/machineWatchCommands.ts
304
+ function resolveHeartbeatIntervalMs(env) {
305
+ return parsePositiveFiniteNumberOrFallback(
306
+ env.NOLO_CONNECT_HEARTBEAT_MS,
307
+ 3e4
308
+ );
309
+ }
310
+ async function runMachineWatchCommand(deps) {
311
+ const env = deps.env ?? process.env;
312
+ const output = deps.output ?? process.stdout;
313
+ const machine = deps.machine;
314
+ output.write(`Connecting machine heartbeat loop: ${machine.name} (${machine.platform}/${machine.arch})
315
+ `);
316
+ try {
317
+ await deps.runHeartbeatLoop({
318
+ intervalMs: resolveHeartbeatIntervalMs(env),
319
+ sendHeartbeat: deps.sendHeartbeat
320
+ });
321
+ return 0;
322
+ } catch (error) {
323
+ output.write(
324
+ `[nolo] Machine heartbeat loop failed: ${toErrorMessage(error)}
325
+ `
326
+ );
327
+ return 1;
328
+ }
329
+ }
330
+
331
+ // packages/cli/machineWsSession.ts
332
+ var CONNECTOR_WS_KEEPALIVE_MS = 25e3;
333
+ function buildConnectorKeepaliveMessage() {
334
+ return JSON.stringify({ type: "connector.keepalive", sentAt: Date.now() });
335
+ }
336
+ function resolveHeartbeatIntervalMs2(env) {
337
+ return parsePositiveFiniteNumberOrFallback(
338
+ env.NOLO_CONNECT_HEARTBEAT_MS,
339
+ 3e4
340
+ );
341
+ }
342
+ async function defaultConnectWebSocket(url, options) {
343
+ const WebSocketCtor = globalThis.WebSocket;
344
+ if (!WebSocketCtor) {
345
+ throw new Error("WebSocket is not available in this runtime");
346
+ }
347
+ await new Promise((resolve2, reject) => {
348
+ const ws = new WebSocketCtor(url, {
349
+ headers: options.headers
350
+ });
351
+ let opened = false;
352
+ let aborted = options.signal?.aborted ?? false;
353
+ let keepalive = null;
354
+ const clearKeepalive = () => {
355
+ if (keepalive) {
356
+ clearInterval(keepalive);
357
+ keepalive = null;
358
+ }
359
+ };
360
+ const handleAbort = () => {
361
+ aborted = true;
362
+ clearKeepalive();
363
+ try {
364
+ ws.close();
365
+ } catch {
366
+ resolve2();
367
+ }
368
+ };
369
+ options.signal?.addEventListener("abort", handleAbort, { once: true });
370
+ ws.addEventListener(
371
+ "open",
372
+ () => {
373
+ opened = true;
374
+ keepalive = setInterval(() => {
375
+ try {
376
+ ws.send(buildConnectorKeepaliveMessage());
377
+ } catch {
378
+ clearKeepalive();
379
+ }
380
+ }, CONNECTOR_WS_KEEPALIVE_MS);
381
+ },
382
+ { once: true }
383
+ );
384
+ ws.addEventListener("error", () => {
385
+ clearKeepalive();
386
+ if (aborted) {
387
+ resolve2();
388
+ return;
389
+ }
390
+ reject(new Error("connector websocket failed"));
391
+ });
392
+ ws.addEventListener(
393
+ "close",
394
+ () => {
395
+ clearKeepalive();
396
+ if (opened || aborted) resolve2();
397
+ else reject(new Error("connector websocket closed before opening"));
398
+ },
399
+ { once: true }
400
+ );
401
+ ws.addEventListener("message", (event) => {
402
+ const startIndex = options.sentMessages.length;
403
+ Promise.resolve(options.onMessage(String(event.data))).then(() => {
404
+ for (const message of options.sentMessages.slice(startIndex)) {
405
+ ws.send(message);
406
+ }
407
+ }).catch(() => void 0);
408
+ });
409
+ });
410
+ }
411
+ async function runMachineWsSession(options) {
412
+ const sentMessages = [];
413
+ const heartbeatAbort = new AbortController();
414
+ let heartbeatLoopPromise = null;
415
+ let websocketPromise = null;
416
+ try {
417
+ if (options.signal?.aborted) {
418
+ return { exitCode: 0 };
419
+ }
420
+ await options.sendHeartbeat();
421
+ options.output.write(
422
+ `Connector websocket connected: ${options.machine.name} (${options.machine.machineId})
423
+ `
424
+ );
425
+ heartbeatLoopPromise = options.runHeartbeatLoop({
426
+ intervalMs: resolveHeartbeatIntervalMs2(options.env),
427
+ sendHeartbeat: options.sendHeartbeat,
428
+ signal: heartbeatAbort.signal
429
+ });
430
+ const heartbeatMonitorPromise = heartbeatLoopPromise.then(() => {
431
+ if (!heartbeatAbort.signal.aborted) {
432
+ throw new Error("connector heartbeat loop ended unexpectedly");
433
+ }
434
+ });
435
+ const wsTarget = await options.resolveConnectorWebSocketTarget({
436
+ serverUrl: options.serverUrl,
437
+ machineId: options.machine.machineId,
438
+ connectorSurface: "cli",
439
+ headers: { Authorization: `Bearer ${options.authToken}` }
440
+ });
441
+ websocketPromise = options.connectWebSocket(wsTarget, {
442
+ headers: { Authorization: `Bearer ${options.authToken}` },
443
+ signal: options.signal,
444
+ sentMessages,
445
+ onMessage: (message) => options.onMessage(message, (response) => {
446
+ sentMessages.push(response);
447
+ })
448
+ });
449
+ const abortPromise = options.signal ? new Promise((resolve2) => {
450
+ if (options.signal?.aborted) {
451
+ resolve2("aborted");
452
+ return;
453
+ }
454
+ options.signal?.addEventListener("abort", () => resolve2("aborted"), { once: true });
455
+ }) : null;
456
+ const raceResult = await Promise.race(
457
+ [websocketPromise, heartbeatMonitorPromise, abortPromise].filter(Boolean)
458
+ );
459
+ heartbeatAbort.abort();
460
+ await Promise.allSettled([websocketPromise, heartbeatLoopPromise]);
461
+ if (raceResult === "aborted") {
462
+ return { exitCode: 0 };
463
+ }
464
+ return { exitCode: 0 };
465
+ } catch (error) {
466
+ heartbeatAbort.abort();
467
+ await Promise.allSettled(
468
+ [websocketPromise, heartbeatLoopPromise].filter(Boolean)
469
+ );
470
+ if (isConnectorWebSocketAuthError(error)) {
471
+ options.output.write(
472
+ `[nolo] Connector websocket auth failed: ${error.message}. Re-register this machine or update NOLO_MACHINE_API_KEY.
473
+ `
474
+ );
475
+ return { exitCode: 2 };
476
+ }
477
+ if (isConnectorWebSocketRetryableError(error)) {
478
+ const description = error.reason === "core_draining" ? "core draining" : error.reason;
479
+ options.output.write(
480
+ `[nolo] Connector websocket unavailable: ${description} (${error.message}).
481
+ `
482
+ );
483
+ return {
484
+ exitCode: 1,
485
+ retryAfterMs: error.retryAfterMs,
486
+ reconnectReason: error.reason
487
+ };
488
+ }
489
+ options.output.write(
490
+ `[nolo] Connector websocket failed: ${toErrorMessage(error)}
491
+ `
492
+ );
493
+ return { exitCode: 1 };
494
+ }
495
+ }
496
+
497
+ // packages/cli/machineStatusCommands.ts
498
+ function resolveServerUrl(env) {
499
+ return normalizeServerOrigin(
500
+ env.NOLO_SERVER || env.BASE_URL || DEFAULT_NOLO_SERVER_URL
501
+ );
502
+ }
503
+ function resolveAuthToken(env) {
504
+ return env.AUTH_TOKEN || env.AUTH || "";
505
+ }
506
+ function writeAuthMissing(output) {
507
+ output.write(
508
+ "[nolo] Machine commands require an auth token. Run `nolo login` or set AUTH_TOKEN.\n"
509
+ );
510
+ }
511
+ function formatMachineStatus(machines) {
512
+ if (machines.length === 0) {
513
+ return "No connected machines.\nRun `nolo connect` on this computer to register it once.\n";
514
+ }
515
+ return [
516
+ "Connected machines:",
517
+ ...machines.map((machine) => {
518
+ const caps = machine.capabilities.length ? machine.capabilities.join(", ") : "no capabilities";
519
+ const connector = machine.connectorStatus ? ` ws:${machine.connectorStatus}` : "";
520
+ return `- ${machine.name} ${machine.status}${connector} ${machine.platform}/${machine.arch} ${caps}`;
521
+ }),
522
+ ""
523
+ ].join("\n");
524
+ }
525
+ async function runMachineStatusCommand(_args, deps = {}) {
526
+ const env = deps.env ?? process.env;
527
+ const output = deps.output ?? process.stdout;
528
+ const authToken = resolveAuthToken(env);
529
+ if (!authToken) {
530
+ writeAuthMissing(output);
531
+ return 1;
532
+ }
533
+ const serverUrl = resolveServerUrl(env);
534
+ const fetchImpl = deps.fetchImpl ?? fetch;
535
+ let res;
536
+ try {
537
+ res = await fetchImpl(`${serverUrl}/api/machines`, {
538
+ method: "GET",
539
+ headers: {
540
+ Authorization: `Bearer ${authToken}`
541
+ }
542
+ });
543
+ } catch (error) {
544
+ output.write(
545
+ `[nolo] Machine status failed: ${toErrorMessage(error)}
546
+ `
547
+ );
548
+ return 1;
549
+ }
550
+ if (!res.ok) {
551
+ const text = await res.text().catch(() => "");
552
+ output.write(`[nolo] Machine status failed: HTTP ${res.status}
553
+ ${text}
554
+ `);
555
+ return 1;
556
+ }
557
+ const data = await res.json().catch(() => ({ machines: [] }));
558
+ const machines = Array.isArray(data?.machines) ? data.machines : [];
559
+ output.write(formatMachineStatus(machines));
560
+ return 0;
561
+ }
562
+
563
+ // packages/cli/machineCommands.ts
564
+ function resolveAuthToken2(env) {
565
+ return env.AUTH_TOKEN || env.AUTH || "";
566
+ }
567
+ function writeAuthMissing2(output) {
568
+ output.write(
569
+ "[nolo] Machine commands require an auth token. Run `nolo login` or set AUTH_TOKEN.\n"
570
+ );
571
+ }
572
+ function hasFlag(args, flag) {
573
+ return args.includes(flag);
574
+ }
575
+ function readOption(args, flag) {
576
+ for (let i = 0; i < args.length; i++) {
577
+ const arg = args[i];
578
+ if (arg === flag) {
579
+ const next = args[i + 1];
580
+ if (typeof next === "string" && !next.startsWith("-")) return next;
581
+ return "";
582
+ }
583
+ if (arg.startsWith(flag + "=")) {
584
+ return arg.slice(flag.length + 1);
585
+ }
586
+ }
587
+ return "";
588
+ }
589
+ function resolveConnectServerUrl(args, env) {
590
+ const fromFlag = readOption(args, "--server-url") || readOption(args, "--server");
591
+ const raw = fromFlag || env.NOLO_SERVER || env.BASE_URL || DEFAULT_NOLO_SERVER_URL;
592
+ return String(raw).replace(/\/+$|\s+$/g, "").replace(/\/+$/g, "").replace(/\s+$/g, "");
593
+ }
594
+ function resolveConnectAuthToken(args, env) {
595
+ return readOption(args, "--machine-key") || readOption(args, "--token") || resolveAuthToken2(env);
596
+ }
597
+ var defaultSleep2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
598
+ async function sleepWithAbort(ms, sleep, signal) {
599
+ if (!signal) {
600
+ await sleep(ms);
601
+ return;
602
+ }
603
+ if (signal.aborted) return;
604
+ await Promise.race([
605
+ sleep(ms),
606
+ new Promise((resolve2) => {
607
+ signal.addEventListener("abort", () => resolve2(), { once: true });
608
+ })
609
+ ]);
610
+ }
611
+ function resolveConnectorReconnectDelayMs(env) {
612
+ const raw = Number(env.NOLO_CONNECT_RECONNECT_MS ?? "");
613
+ return Number.isFinite(raw) && raw >= 0 ? raw : 5e3;
614
+ }
615
+ async function defaultExecuteCli(provider, prompt, options) {
616
+ const { executeCli } = await import("./cliExecutor-K3F7DMRO.js");
617
+ return executeCli(provider, prompt, options);
618
+ }
619
+ function detectLaunchableMachineInfo() {
620
+ return detectMachineInfo({ probeLaunchable: true });
621
+ }
622
+ function findTaskRowSubjectRef(runtimeContext) {
623
+ const subjectRefs = Array.isArray(runtimeContext?.subjectRefs) ? runtimeContext.subjectRefs : [];
624
+ for (const ref of subjectRefs) {
625
+ if (!isRecord(ref)) continue;
626
+ if (ref.kind !== "table-row") continue;
627
+ const id = asTrimmedString(ref.id);
628
+ if (id) return id;
629
+ }
630
+ return "";
631
+ }
632
+ function buildTaskEvidencePrompt(args) {
633
+ const rowDbKey = findTaskRowSubjectRef(args.runtimeContext);
634
+ if (!rowDbKey) return "";
635
+ return [
636
+ "--- Nolo task evidence context ---",
637
+ "This CLI runtime does not receive server-side function tools directly.",
638
+ "Use the task row subjectRef and linked dialog evidence as durable task evidence.",
639
+ "Run commands from the repository root. The runner already provides server URL and auth in the environment.",
640
+ "Release boundary: after review passes, AI/reviewer/Codex may advance alpha for verification. Do not merge, push, or release main/release unless the human owner explicitly authorizes it in the current request.",
641
+ "Handoff context: query dialog.subjectRefs first, then inspect dialog checkpoints, artifacts, commits, and test evidence. Treat row activityRefs/latestActivityRef as cache hints, not state truth.",
642
+ "Reviewer autonomy: if you are reviewing and find a concrete fix, you may directly dispatch the rework agent/dialog instead of sending the task back to PM first.",
643
+ "Rework evidence rule: every implementation, review, and rework dialog must preserve the same table-row subjectRef and report any child/rework dialog id it starts.",
644
+ `Read task row: bun packages/cli/index.ts table query --table meta-0e95801d90-01KWSK4Q4TESXQ06SW39JN2TTJ --row ${JSON.stringify(rowDbKey)} --include-activity --output json`,
645
+ `Query linked dialogs: bun packages/cli/index.ts dialog query --row-dbkey ${JSON.stringify(rowDbKey)} --json`,
646
+ "If this run already has a dialog id, exclude it from evidence queries: bun packages/cli/index.ts dialog query --row-dbkey <rowDbKey> --exclude-dialog <currentDialogId> --json",
647
+ "Then read exact dialog traces with: bun packages/cli/index.ts dialog read <dialogId>",
648
+ "Reviewers must end with exactly one line: Review decision: approved | needs_changes | blocked",
649
+ "Report progress, blockers, worktree, branch, commit/diff, tests, and unverified items in the dialog."
650
+ ].join("\n");
651
+ }
652
+ function buildConnectorCliPrompt(agentConfig, userInput, bridgeArgs, permissionPolicy) {
653
+ const policy = permissionPolicy ?? resolveMachineRunPermissionPolicy(agentConfig);
654
+ return [
655
+ asTrimmedString(agentConfig?.prompt),
656
+ bridgeArgs ? buildTaskEvidencePrompt({
657
+ agentKey: bridgeArgs.agentKey,
658
+ agentConfig,
659
+ runtimeContext: bridgeArgs.runtimeContext
660
+ }) : "",
661
+ buildMachinePermissionPromptBlock(policy),
662
+ `--- User task ---
663
+ ${userInput}`
664
+ ].filter(Boolean).join("\n\n");
665
+ }
666
+ async function runMachineConnectCommand(args, deps = {}) {
667
+ const env = deps.env ?? process.env;
668
+ const output = deps.output ?? process.stdout;
669
+ const authToken = resolveConnectAuthToken(args, env);
670
+ if (!authToken) {
671
+ writeAuthMissing2(output);
672
+ return 1;
673
+ }
674
+ const serverUrl = resolveConnectServerUrl(args, env);
675
+ const fetchImpl = deps.fetchImpl ?? fetch;
676
+ if (hasFlag(args, "--daemon") || hasFlag(args, "--background")) {
677
+ return runMachineDaemonCommand({
678
+ env,
679
+ output,
680
+ cliEntrypointPath: deps.cliEntrypointPath,
681
+ validateWorkspaceLinks: deps.validateWorkspaceLinks,
682
+ spawnDaemon: deps.spawnDaemon
683
+ });
684
+ }
685
+ const machine = (deps.machineInfo ?? detectLaunchableMachineInfo)();
686
+ const sendHeartbeat = async () => {
687
+ const res = await fetchImpl(`${serverUrl}/api/machines/heartbeat`, {
688
+ method: "POST",
689
+ headers: {
690
+ Authorization: `Bearer ${authToken}`,
691
+ "Content-Type": "application/json"
692
+ },
693
+ body: JSON.stringify(machine)
694
+ });
695
+ if (!res.ok) {
696
+ const text = await res.text().catch(() => "");
697
+ throw new Error(`HTTP ${res.status}
698
+ ${text}`);
699
+ }
700
+ };
701
+ if (hasFlag(args, "--ws")) {
702
+ const validateWorkspaceLinks = deps.validateWorkspaceLinks ?? (() => []);
703
+ if (!await checkConnectorWorkspaceLinks(process.cwd(), output, validateWorkspaceLinks)) {
704
+ return 1;
705
+ }
706
+ const maxAttempts = deps.maxConnectorAttempts ?? Infinity;
707
+ const sleep = deps.sleep ?? defaultSleep2;
708
+ const reconnectDelayMs = resolveConnectorReconnectDelayMs(env);
709
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
710
+ if (deps.signal?.aborted) {
711
+ return 0;
712
+ }
713
+ const runtimeServerUrl = env.NOLO_CONNECT_RUNTIME_SERVER_URL || env.NOLO_RUNTIME_SERVER_URL || serverUrl;
714
+ const sessionResult = await runMachineWsSession({
715
+ env,
716
+ output,
717
+ signal: deps.signal,
718
+ machine,
719
+ sendHeartbeat,
720
+ runHeartbeatLoop: deps.runHeartbeatLoop ?? runHeartbeatLoop,
721
+ connectWebSocket: deps.connectWebSocket ?? defaultConnectWebSocket,
722
+ serverUrl,
723
+ authToken,
724
+ resolveConnectorWebSocketTarget: (options) => resolveConnectorWebSocketTarget({
725
+ ...options,
726
+ fetchImpl
727
+ }),
728
+ onMessage: (message, send) => handleConnectorRunMessage(
729
+ message,
730
+ send,
731
+ deps.executeCli ?? defaultExecuteCli,
732
+ {
733
+ ...env,
734
+ NOLO_SERVER: runtimeServerUrl,
735
+ NOLO_SERVER_URL: runtimeServerUrl,
736
+ BASE_URL: runtimeServerUrl,
737
+ AUTH_TOKEN: authToken,
738
+ NOLO_MACHINE_API_KEY: authToken
739
+ },
740
+ fetchImpl,
741
+ {
742
+ buildConnectorCliPrompt
743
+ }
744
+ )
745
+ });
746
+ const exitCode = sessionResult.exitCode;
747
+ if (exitCode === 2) return 1;
748
+ if (deps.signal?.aborted) {
749
+ return 0;
750
+ }
751
+ if (attempt >= maxAttempts) return exitCode;
752
+ const retryDelayMs = sessionResult.retryAfterMs ?? reconnectDelayMs;
753
+ const reconnectContext = sessionResult.reconnectReason === "core_draining" ? " during core draining" : "";
754
+ output.write(
755
+ `[nolo] Connector websocket disconnected${reconnectContext}. Reconnecting in ${retryDelayMs}ms.
756
+ `
757
+ );
758
+ await sleepWithAbort(retryDelayMs, sleep, deps.signal);
759
+ }
760
+ return 0;
761
+ }
762
+ if (hasFlag(args, "--watch")) {
763
+ return runMachineWatchCommand({
764
+ env,
765
+ output,
766
+ machine,
767
+ sendHeartbeat,
768
+ runHeartbeatLoop: deps.runHeartbeatLoop ?? runHeartbeatLoop
769
+ });
770
+ }
771
+ return runMachineHeartbeatConnectCommand({
772
+ output,
773
+ machine,
774
+ sendHeartbeat
775
+ });
776
+ }
777
+ export {
778
+ formatMachineStatus,
779
+ runMachineConnectCommand,
780
+ runMachineStatusCommand
781
+ };