nolo-cli 0.6.1 → 0.8.0-alpha.10

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 (175) hide show
  1. package/_executeModel-CPDNUUQV.js +198 -0
  2. package/action-PAXRPJJF.js +27 -0
  3. package/addContentAction-CZVWF3QZ.js +25 -0
  4. package/addDialogAgentAction-CCIDTPHC.js +67 -0
  5. package/agentDeleteCommand-OSUMJMZM.js +323 -0
  6. package/agentEmailCommands-OQTJIPQU.js +621 -0
  7. package/agentListCommands-FATQEUYT.js +219 -0
  8. package/agentMachineCommands-6LZWF4GL.js +421 -0
  9. package/agentPullCommand-O2MTUAFR.js +122 -0
  10. package/agentRecordCommands-TIHFU65Z.js +89 -0
  11. package/agentRunCommand-R64Y3HCH.js +102 -0
  12. package/agentRunControl-K4VKNEHF.js +57 -0
  13. package/agentRuntimeLocal-6PIWAHLQ.js +99 -0
  14. package/agentSlice-TP4VARJF.js +41 -0
  15. package/authCommand-WXMD3IPR.js +574 -0
  16. package/authCommands-X74AFDTC.js +26 -0
  17. package/chunk-2EISRLRC.js +238 -0
  18. package/chunk-2FTTDCD4.js +675 -0
  19. package/chunk-2MALU52L.js +51 -0
  20. package/chunk-2TPUKEU7.js +1078 -0
  21. package/chunk-3ASDTTEI.js +1774 -0
  22. package/chunk-3EUW3WEO.js +8 -0
  23. package/chunk-3LY4F7SV.js +9293 -0
  24. package/chunk-4CQLVGRV.js +50 -0
  25. package/chunk-4IJYA27C.js +342 -0
  26. package/chunk-4SN6J65J.js +38 -0
  27. package/chunk-4VNS5WPM.js +42 -0
  28. package/chunk-572EKYLF.js +792 -0
  29. package/chunk-5MIDPSSK.js +206 -0
  30. package/chunk-5MMAK75Q.js +15 -0
  31. package/chunk-5VV37AT4.js +222 -0
  32. package/chunk-63W5N6P3.js +150 -0
  33. package/chunk-6A5EF6IR.js +929 -0
  34. package/chunk-6HYVJV7B.js +102 -0
  35. package/chunk-6P2WX5IA.js +3631 -0
  36. package/chunk-6WD3OOJS.js +20 -0
  37. package/chunk-ATNTHIZI.js +13 -0
  38. package/chunk-AUGHVUFE.js +69 -0
  39. package/chunk-AVMKZHBC.js +85 -0
  40. package/chunk-AZPCASRE.js +36 -0
  41. package/chunk-BNMT7YY5.js +34 -0
  42. package/chunk-BR2WP3DF.js +548 -0
  43. package/chunk-BSTNFPHD.js +231 -0
  44. package/chunk-BU4OPIXC.js +171 -0
  45. package/chunk-CF2WZF4N.js +134 -0
  46. package/chunk-CF7PE763.js +10 -0
  47. package/chunk-CKOJQDKR.js +198 -0
  48. package/chunk-CM54RSSA.js +206 -0
  49. package/chunk-CWMSB67P.js +34 -0
  50. package/chunk-DA2OEKS6.js +27 -0
  51. package/chunk-DFFIZ25G.js +30 -0
  52. package/chunk-DWLEOOGR.js +8 -0
  53. package/chunk-DZ3XJVET.js +231 -0
  54. package/chunk-EHLHSX7R.js +1433 -0
  55. package/chunk-ELRRLDWI.js +478 -0
  56. package/chunk-EYEEHCU4.js +3066 -0
  57. package/chunk-FQZWM5YX.js +628 -0
  58. package/chunk-G3SUCT4W.js +8 -0
  59. package/chunk-G5H7RNFL.js +807 -0
  60. package/chunk-GAKEBQD6.js +30 -0
  61. package/chunk-GBRG75BQ.js +86 -0
  62. package/chunk-H2RMRZJE.js +113 -0
  63. package/chunk-H33743XH.js +25 -0
  64. package/chunk-HD63YREL.js +19 -0
  65. package/chunk-HEIIIZBX.js +104 -0
  66. package/chunk-HNMXYYJR.js +12 -0
  67. package/chunk-HOMYP7GZ.js +2152 -0
  68. package/chunk-HZFOMJRA.js +4300 -0
  69. package/chunk-IAXBCTTE.js +175 -0
  70. package/chunk-IDZTNRP2.js +85 -0
  71. package/chunk-IHHA5Y2S.js +9013 -0
  72. package/chunk-ISNCLGUZ.js +146 -0
  73. package/chunk-IYQV26RA.js +138 -0
  74. package/chunk-J4576WMJ.js +91 -0
  75. package/chunk-JBTJAPUF.js +35 -0
  76. package/chunk-JZPBVBIY.js +94 -0
  77. package/chunk-KQHGZWSV.js +63 -0
  78. package/chunk-KUG52IAP.js +8 -0
  79. package/chunk-KX6YBIHG.js +8 -0
  80. package/chunk-LCBAMY2M.js +60 -0
  81. package/chunk-LM25IZBJ.js +902 -0
  82. package/chunk-LM6IYQ3F.js +16 -0
  83. package/chunk-M76ECQRD.js +13658 -0
  84. package/chunk-MRC4Q34M.js +188 -0
  85. package/chunk-NEMRK4EK.js +944 -0
  86. package/chunk-NXZGF7F7.js +2878 -0
  87. package/chunk-OF5H3QWS.js +300 -0
  88. package/chunk-OLZBQWZU.js +6 -0
  89. package/chunk-OOYVBFM7.js +191 -0
  90. package/chunk-OWOHNGCN.js +50 -0
  91. package/chunk-PN7AFLOK.js +3401 -0
  92. package/chunk-POCFIDGQ.js +562 -0
  93. package/chunk-Q6WACBKB.js +1949 -0
  94. package/chunk-QFV2OAIM.js +421 -0
  95. package/chunk-QJ6V2NIN.js +1447 -0
  96. package/chunk-QSJ3HFEF.js +8 -0
  97. package/chunk-QUWDTOUP.js +190 -0
  98. package/chunk-QYXLLLGL.js +4519 -0
  99. package/chunk-ROWQEJRP.js +139 -0
  100. package/chunk-S7Z2HMCN.js +25 -0
  101. package/chunk-TDIQFT2F.js +301 -0
  102. package/chunk-TILFE6LV.js +381 -0
  103. package/chunk-TKOUBWBO.js +24674 -0
  104. package/chunk-TYH5JE6N.js +27158 -0
  105. package/chunk-U4TRT5V4.js +246 -0
  106. package/chunk-U6VC4MU4.js +8 -0
  107. package/chunk-UAD2WT54.js +64 -0
  108. package/chunk-USZMK5UT.js +105 -0
  109. package/chunk-VEJLAVTC.js +2052 -0
  110. package/chunk-VF4K2QE6.js +21 -0
  111. package/chunk-VHBWHNVT.js +59 -0
  112. package/chunk-VIDPVFP3.js +20 -0
  113. package/chunk-VP4WJWKW.js +8882 -0
  114. package/chunk-VQ2AJRGD.js +148 -0
  115. package/chunk-W4NVOSFF.js +37 -0
  116. package/chunk-WWC7I6TA.js +8 -0
  117. package/chunk-X7W4TNB4.js +1550 -0
  118. package/chunk-XDVAYP26.js +537 -0
  119. package/chunk-XKIMRZO2.js +221 -0
  120. package/chunk-Y5GCAMGP.js +9 -0
  121. package/chunk-YWPXYBY7.js +360 -0
  122. package/chunk-Z4NR32XR.js +50 -0
  123. package/chunk-ZNFJWEN4.js +56 -0
  124. package/cliExecutor-DNE7TCC4.js +36 -0
  125. package/clipboardy-BVE3LVEH.js +12001 -0
  126. package/createAgentAutomationAction-KLKS2HGU.js +864 -0
  127. package/createDialogAction-Z33JMBF5.js +52 -0
  128. package/createPageAction-AQVNOAAI.js +169 -0
  129. package/db-HCJ5PRB5.js +271 -0
  130. package/dbSlice-C4UJLRZP.js +59 -0
  131. package/deleteFile-4SKGPHOZ.js +41 -0
  132. package/dialogCommands-W5PD6MZU.js +59 -0
  133. package/dialogSlice-RBJYVSAR.js +146 -0
  134. package/docCreateCommands-MM34S4Z3.js +215 -0
  135. package/docDeleteCommands-JJTU722V.js +176 -0
  136. package/docReadCommands-GLYDMCTU.js +129 -0
  137. package/docStore-5TYME4DO.js +96 -0
  138. package/docUpdateCommands-ZCGQ7URR.js +313 -0
  139. package/fetchMessages-JOCYIFKL.js +16 -0
  140. package/getPricing-PWPJ6MNV.js +30 -0
  141. package/handleSendMessageAction-KA2MRW6E.js +183 -0
  142. package/index.js +184 -112254
  143. package/lib-FYYBQIXS.js +19839 -0
  144. package/localDialogRead-D3BELSTF.js +26 -0
  145. package/localFirstLog-DHNOY2NA.js +19 -0
  146. package/localRuntimeAuthority-TEGCOWX4.js +471 -0
  147. package/localRuntimeDb-LGDF6FQP.js +12 -0
  148. package/machineCommands-ZB5WUSPF.js +774 -0
  149. package/machineInfo-M6KB6HZN.js +10 -0
  150. package/machineWsRunDispatch-GWCAPPCM.js +105 -0
  151. package/memoryCommands-O4MIPIWQ.js +476 -0
  152. package/models-XLEOET3E.js +9 -0
  153. package/offlineMarxistsAgentCommand-BCPJITJL.js +242 -0
  154. package/package.json +3 -25
  155. package/read-RIJCIVKX.js +17 -0
  156. package/readDocTool-GZD2N3LO.js +16 -0
  157. package/readlineWorkspace-FEDY44AA.js +5357 -0
  158. package/removeDialogAgentAction-CXLST3N6.js +72 -0
  159. package/runAgentClientLoop-W4NKE64V.js +288 -0
  160. package/runtimeDoctorCommands-LRHLPDRC.js +289 -0
  161. package/setDialogExtraReferencesAction-LP6VYGU7.js +59 -0
  162. package/setPrimaryDialogAgentAction-D3GGH23T.js +79 -0
  163. package/settingSlice-J4I3Z5H7.js +198 -0
  164. package/skillSummaryMarker-42HKSXYY.js +9 -0
  165. package/slateToRenderMarkdown-Y5IYN73U.js +7 -0
  166. package/slateUtils-2M7MUTWX.js +19 -0
  167. package/spaceCommands-LC4FDAKE.js +450 -0
  168. package/spaceSlice-32XOGBEF.js +145 -0
  169. package/streamAgentChatTurn-YQW32AQH.js +4503 -0
  170. package/tableCommands-GOFP7QKA.js +1286 -0
  171. package/toolApiClient-QI3YBNWB.js +26 -0
  172. package/tools-XGTFRYD7.js +83 -0
  173. package/understanding-HCSFPE7R.js +318 -0
  174. package/updateCommands-VOSPKXFF.js +31 -0
  175. package/updateDialogTitleAction-4LHQDNHQ.js +185 -0
@@ -0,0 +1,219 @@
1
+ import {
2
+ decorateAgentsWithPublicStatusAcrossServers,
3
+ listLocalCachedAgents,
4
+ listRemoteAgents,
5
+ listRemoteAgentsAcrossServers,
6
+ parseAgentListArgs
7
+ } from "./chunk-OOYVBFM7.js";
8
+ import {
9
+ buildSpaceLookup,
10
+ getSpaceContentKeys
11
+ } from "./chunk-4CQLVGRV.js";
12
+ import {
13
+ readLiveDbRecordAfterTombstoneMerge
14
+ } from "./chunk-QUWDTOUP.js";
15
+ import {
16
+ getReadableCliDb
17
+ } from "./chunk-W4NVOSFF.js";
18
+ import {
19
+ queryUserRecords,
20
+ readDbRecord
21
+ } from "./chunk-FQZWM5YX.js";
22
+ import "./chunk-HD63YREL.js";
23
+ import "./chunk-VHBWHNVT.js";
24
+ import "./chunk-KQHGZWSV.js";
25
+ import "./chunk-IDZTNRP2.js";
26
+ import {
27
+ parseUserIdFromAuthToken,
28
+ readOption,
29
+ resolveAuthToken,
30
+ resolveServerCandidates,
31
+ resolveServerUrl
32
+ } from "./chunk-ISNCLGUZ.js";
33
+ import "./chunk-OLZBQWZU.js";
34
+ import "./chunk-6P2WX5IA.js";
35
+ import "./chunk-ZNFJWEN4.js";
36
+ import "./chunk-TILFE6LV.js";
37
+ import "./chunk-NEMRK4EK.js";
38
+ import "./chunk-XDVAYP26.js";
39
+ import "./chunk-LM25IZBJ.js";
40
+ import "./chunk-5MMAK75Q.js";
41
+ import "./chunk-572EKYLF.js";
42
+ import "./chunk-TDIQFT2F.js";
43
+ import "./chunk-JZPBVBIY.js";
44
+ import "./chunk-BR2WP3DF.js";
45
+ import "./chunk-DWLEOOGR.js";
46
+ import {
47
+ toErrorMessage
48
+ } from "./chunk-HNMXYYJR.js";
49
+ import "./chunk-KX6YBIHG.js";
50
+ import "./chunk-PN7AFLOK.js";
51
+ import "./chunk-WWC7I6TA.js";
52
+ import "./chunk-QSJ3HFEF.js";
53
+ import "./chunk-GBRG75BQ.js";
54
+ import "./chunk-4SN6J65J.js";
55
+ import "./chunk-LCBAMY2M.js";
56
+ import "./chunk-3EUW3WEO.js";
57
+ import "./chunk-U6VC4MU4.js";
58
+ import "./chunk-CF7PE763.js";
59
+ import "./chunk-G3SUCT4W.js";
60
+ import "./chunk-KUG52IAP.js";
61
+ import "./chunk-4VNS5WPM.js";
62
+
63
+ // packages/cli/agentListCommands.ts
64
+ async function runAgentListCommand(args, deps = {}) {
65
+ const env = deps.env ?? process.env;
66
+ const output = deps.output ?? process.stdout;
67
+ const { wantJson, publicOnly, idsOnly } = parseAgentListArgs(args);
68
+ const spaceInput = readOption(args, "--space") ?? readOption(args, "--space-id");
69
+ const authToken = resolveAuthToken(args, env);
70
+ if (!authToken) {
71
+ output.write("[nolo] agent list requires an auth token. Run `nolo login` or set AUTH_TOKEN.\n");
72
+ return 1;
73
+ }
74
+ const userId = parseUserIdFromAuthToken(authToken);
75
+ if (!userId) {
76
+ output.write("[nolo] agent list could not read userId from AUTH_TOKEN.\n");
77
+ return 1;
78
+ }
79
+ const fetchImpl = deps.fetchImpl ?? fetch;
80
+ const fallbackFetchImpl = deps.fallbackFetchImpl;
81
+ const serverUrl = resolveServerUrl(args, env);
82
+ const serverUrls = resolveServerCandidates(args, env, serverUrl);
83
+ try {
84
+ let agents;
85
+ let source;
86
+ let serverFailures = [];
87
+ try {
88
+ const remoteResult = await listRemoteAgentsAcrossServers({
89
+ authToken,
90
+ fallbackFetchImpl,
91
+ fetchImpl,
92
+ serverUrls,
93
+ userId
94
+ });
95
+ agents = remoteResult.agents;
96
+ serverFailures = remoteResult.failures;
97
+ source = "global-cache";
98
+ } catch {
99
+ try {
100
+ const db = deps.db ?? await getReadableCliDb(output);
101
+ agents = await listLocalCachedAgents({ db, userId });
102
+ source = "local-cache";
103
+ } catch {
104
+ agents = await listRemoteAgents({
105
+ authToken,
106
+ fallbackFetchImpl,
107
+ fetchImpl,
108
+ serverUrl,
109
+ userId,
110
+ queryUserRecords,
111
+ readDbRecord
112
+ });
113
+ source = "remote-cache";
114
+ }
115
+ }
116
+ agents = agents.filter((agent) => agent.privateKey.startsWith("agent-"));
117
+ let resolvedSpaceId = null;
118
+ if (spaceInput) {
119
+ const { spaceId, spaceKey } = buildSpaceLookup(spaceInput);
120
+ resolvedSpaceId = spaceId;
121
+ const spaceRead = await readLiveDbRecordAfterTombstoneMerge({
122
+ authToken,
123
+ dbKey: spaceKey,
124
+ fallbackFetchImpl,
125
+ fetchImpl,
126
+ serverUrls
127
+ });
128
+ serverFailures = [...serverFailures, ...spaceRead.failures];
129
+ const spaceRecord = spaceRead.record;
130
+ const spaceContentKeys = getSpaceContentKeys(spaceRecord);
131
+ agents = agents.filter(
132
+ (agent) => spaceContentKeys.has(agent.privateKey) || spaceContentKeys.has(agent.publicKey) || spaceContentKeys.has(agent.id)
133
+ );
134
+ }
135
+ if (source === "global-cache") {
136
+ await decorateAgentsWithPublicStatusAcrossServers({
137
+ agents,
138
+ authToken,
139
+ fallbackFetchImpl,
140
+ fetchImpl,
141
+ serverUrls
142
+ });
143
+ }
144
+ if (publicOnly) {
145
+ agents = agents.filter((agent) => agent.publicRecordExists);
146
+ }
147
+ if (idsOnly) {
148
+ output.write(`${agents.map((agent) => agent.id).join("\n")}
149
+ `);
150
+ return 0;
151
+ }
152
+ if (wantJson) {
153
+ output.write(JSON.stringify({
154
+ userId,
155
+ ...resolvedSpaceId ? { spaceId: resolvedSpaceId } : {},
156
+ targetServers: serverUrls,
157
+ ...serverFailures.length ? { serverFailures } : {},
158
+ total: agents.length,
159
+ publicCount: agents.filter((agent) => agent.publicRecordExists).length,
160
+ source,
161
+ agents
162
+ }, null, 2));
163
+ output.write("\n");
164
+ return 0;
165
+ }
166
+ output.write(`userId: ${userId}
167
+ `);
168
+ if (resolvedSpaceId) {
169
+ output.write(`spaceId: ${resolvedSpaceId}
170
+ `);
171
+ }
172
+ output.write(`targetServers: ${serverUrls.join(", ")}
173
+ `);
174
+ if (serverFailures.length) {
175
+ output.write(`serverFailures: ${serverFailures.length}
176
+ `);
177
+ }
178
+ output.write(`total agents: ${agents.length}
179
+ `);
180
+ output.write(`public agents: ${agents.filter((agent) => agent.publicRecordExists).length}
181
+ `);
182
+ output.write(`source: ${source}
183
+ `);
184
+ if (agents.length === 0) {
185
+ output.write("\n(no agents found)\n");
186
+ return 0;
187
+ }
188
+ for (const agent of agents) {
189
+ const status = agent.publicRecordExists ? "public" : "private";
190
+ const flagMismatch = agent.isPublicFlag !== agent.publicRecordExists ? ` flag=${agent.isPublicFlag}` : "";
191
+ const credentialLine = agent.credentialConfigured ? `credentialConfigured=true${agent.credentialRef ? ` credentialRef=${agent.credentialRef}` : ""}${agent.apiKeyRef ? ` apiKeyRef=${agent.apiKeyRef}` : ""}` : "credentialConfigured=false";
192
+ output.write(
193
+ [
194
+ `
195
+ [${status}] ${agent.name}`,
196
+ `id=${agent.id}`,
197
+ `type=${agent.type ?? "-"}`,
198
+ `model=${agent.model}`,
199
+ `updatedAt=${agent.updatedAt ?? "-"}`,
200
+ `privateKey=${agent.privateKey}`,
201
+ `publicKey=${agent.publicKey}${flagMismatch}`,
202
+ `tools=${agent.tools.join(", ") || "-"}`,
203
+ credentialLine
204
+ ].join("\n")
205
+ );
206
+ output.write("\n");
207
+ }
208
+ return 0;
209
+ } catch (error) {
210
+ output.write(
211
+ `[nolo] agent list failed: ${toErrorMessage(error)}
212
+ `
213
+ );
214
+ return 1;
215
+ }
216
+ }
217
+ export {
218
+ runAgentListCommand
219
+ };
@@ -0,0 +1,421 @@
1
+ import {
2
+ resolveConnectorWebSocketTarget
3
+ } from "./chunk-AVMKZHBC.js";
4
+ import {
5
+ getReadableCliDb
6
+ } from "./chunk-W4NVOSFF.js";
7
+ import {
8
+ readAgentRecord,
9
+ resolveAgentRecordFromHybridStore,
10
+ writeAgentRecord
11
+ } from "./chunk-FQZWM5YX.js";
12
+ import "./chunk-HD63YREL.js";
13
+ import {
14
+ resolveCliAgentKeyInput
15
+ } from "./chunk-VHBWHNVT.js";
16
+ import "./chunk-GAKEBQD6.js";
17
+ import "./chunk-IDZTNRP2.js";
18
+ import {
19
+ parseUserIdFromAuthToken,
20
+ readOption,
21
+ resolveAuthToken,
22
+ resolveServerUrl
23
+ } from "./chunk-ISNCLGUZ.js";
24
+ import "./chunk-OLZBQWZU.js";
25
+ import "./chunk-6P2WX5IA.js";
26
+ import "./chunk-ZNFJWEN4.js";
27
+ import "./chunk-TILFE6LV.js";
28
+ import "./chunk-NEMRK4EK.js";
29
+ import "./chunk-XDVAYP26.js";
30
+ import "./chunk-LM25IZBJ.js";
31
+ import "./chunk-5MMAK75Q.js";
32
+ import "./chunk-572EKYLF.js";
33
+ import "./chunk-TDIQFT2F.js";
34
+ import "./chunk-JZPBVBIY.js";
35
+ import "./chunk-BR2WP3DF.js";
36
+ import "./chunk-DWLEOOGR.js";
37
+ import {
38
+ toErrorMessage
39
+ } from "./chunk-HNMXYYJR.js";
40
+ import {
41
+ asRecordOrEmpty
42
+ } from "./chunk-KX6YBIHG.js";
43
+ import "./chunk-PN7AFLOK.js";
44
+ import "./chunk-WWC7I6TA.js";
45
+ import {
46
+ asTrimmedLowercaseString
47
+ } from "./chunk-QSJ3HFEF.js";
48
+ import "./chunk-4SN6J65J.js";
49
+ import "./chunk-LCBAMY2M.js";
50
+ import "./chunk-3EUW3WEO.js";
51
+ import "./chunk-U6VC4MU4.js";
52
+ import "./chunk-CF7PE763.js";
53
+ import "./chunk-G3SUCT4W.js";
54
+ import "./chunk-KUG52IAP.js";
55
+ import "./chunk-4VNS5WPM.js";
56
+
57
+ // packages/cli/agentMachineCommands.ts
58
+ async function defaultExecuteCli(provider, prompt, options) {
59
+ const { executeCli } = await import("./cliExecutor-DNE7TCC4.js");
60
+ return executeCli(provider, prompt, options);
61
+ }
62
+ async function forwardConnectorRunMessage(machine, message, pushMessage, executeCli, env, fetchImpl) {
63
+ const { handleConnectorRunMessage } = await import("./machineWsRunDispatch-GWCAPPCM.js");
64
+ return handleConnectorRunMessage(message, pushMessage, executeCli, env, fetchImpl);
65
+ }
66
+ async function detectLaunchableMachineInfo() {
67
+ const { detectMachineInfo } = await import("./machineInfo-M6KB6HZN.js");
68
+ return detectMachineInfo({ probeLaunchable: true });
69
+ }
70
+ function requiredCapabilityForAgent(agent) {
71
+ if (agent?.apiSource !== "cli") return "";
72
+ const cliProvider = asTrimmedLowercaseString(agent?.cliProvider || agent?.provider);
73
+ const capabilityByProvider = {
74
+ codex: "codex-cli",
75
+ claude: "claude-code",
76
+ copilot: "copilot-cli",
77
+ gemini: "gemini-cli",
78
+ kimi: "kimi-cli",
79
+ agy: "agy-cli",
80
+ qoder: "qoder-cli",
81
+ opencode: "opencode-cli",
82
+ grok: "grok-cli"
83
+ };
84
+ return capabilityByProvider[cliProvider] ?? "";
85
+ }
86
+ function resolveAgentCliProvider(agent) {
87
+ return asTrimmedLowercaseString(agent?.cliProvider || agent?.provider);
88
+ }
89
+ function classifyAgentRuntime(agent) {
90
+ if (agent?.apiSource === "cli") return "cli-machine";
91
+ if (agent?.apiSource === "platform" || agent?.useServerProxy) return "platform-local-loop";
92
+ if (agent?.apiSource === "local") return "local-provider-loop";
93
+ return "unknown";
94
+ }
95
+ function shouldRuntimeDoctorPass(args) {
96
+ if (args.runtimeClass !== "cli-machine") return args.runtimeClass !== "unknown";
97
+ return Boolean(args.requiredCapability && args.hasCapability);
98
+ }
99
+ function assertSmokeCompatible(agent, machine) {
100
+ if (agent?.apiSource !== "cli") {
101
+ throw new Error(`Agent ${agent?.name ?? agent?.dbKey ?? "unknown"} is not a CLI agent.`);
102
+ }
103
+ const requiredCapability = requiredCapabilityForAgent(agent);
104
+ if (!requiredCapability) {
105
+ throw new Error(`Agent ${agent?.name ?? agent?.dbKey ?? "unknown"} has unsupported cliProvider: ${agent?.cliProvider ?? "missing"}.`);
106
+ }
107
+ if (!machine.capabilities.includes(requiredCapability)) {
108
+ const currentCapabilities = machine.capabilities.length ? machine.capabilities.join(", ") : "none";
109
+ throw new Error(
110
+ `Agent ${agent?.name ?? agent?.dbKey ?? "unknown"} requires ${requiredCapability}; current machine capabilities: ${currentCapabilities}.`
111
+ );
112
+ }
113
+ }
114
+ var CONNECTOR_WS_KEEPALIVE_MS = 25e3;
115
+ function buildConnectorKeepaliveMessage() {
116
+ return JSON.stringify({ type: "connector.keepalive", sentAt: Date.now() });
117
+ }
118
+ async function defaultConnectWebSocket(url, options) {
119
+ const WebSocketCtor = globalThis.WebSocket;
120
+ if (!WebSocketCtor) {
121
+ throw new Error("WebSocket is not available in this runtime");
122
+ }
123
+ await new Promise((resolve, reject) => {
124
+ const ws = new WebSocketCtor(url, { headers: options.headers });
125
+ let keepalive = null;
126
+ const clearKeepalive = () => {
127
+ if (keepalive) {
128
+ clearInterval(keepalive);
129
+ keepalive = null;
130
+ }
131
+ };
132
+ ws.addEventListener("open", () => {
133
+ keepalive = setInterval(() => {
134
+ try {
135
+ ws.send(buildConnectorKeepaliveMessage());
136
+ } catch {
137
+ clearKeepalive();
138
+ }
139
+ }, CONNECTOR_WS_KEEPALIVE_MS);
140
+ Promise.resolve(options.onOpen()).then(() => ws.close()).catch((error) => {
141
+ ws.close();
142
+ reject(error);
143
+ });
144
+ }, { once: true });
145
+ ws.addEventListener("error", () => {
146
+ clearKeepalive();
147
+ reject(new Error("connector websocket failed"));
148
+ });
149
+ ws.addEventListener("close", () => {
150
+ clearKeepalive();
151
+ resolve();
152
+ }, { once: true });
153
+ ws.addEventListener("message", (event) => {
154
+ const startIndex = options.sentMessages.length;
155
+ Promise.resolve(options.onMessage(String(event.data))).then(() => {
156
+ for (const message of options.sentMessages.slice(startIndex)) {
157
+ ws.send(message);
158
+ }
159
+ }).catch(reject);
160
+ });
161
+ });
162
+ }
163
+ async function heartbeatCurrentMachine(args) {
164
+ const res = await args.fetchImpl(`${args.serverUrl}/api/machines/heartbeat`, {
165
+ method: "POST",
166
+ headers: {
167
+ Authorization: `Bearer ${args.authToken}`,
168
+ "Content-Type": "application/json"
169
+ },
170
+ body: JSON.stringify(args.machine)
171
+ });
172
+ const text = await res.text().catch(() => "");
173
+ if (!res.ok) {
174
+ throw new Error(`heartbeat failed: HTTP ${res.status} ${text}`);
175
+ }
176
+ }
177
+ async function runAgentBindCurrentCommand(args, deps = {}) {
178
+ const env = deps.env ?? process.env;
179
+ const output = deps.output ?? process.stdout;
180
+ const agentInput = args[0]?.trim();
181
+ if (!agentInput || agentInput === "--help" || agentInput === "-h") {
182
+ output.write("Usage: nolo agent bind-current <agentKey|handle>\n");
183
+ return agentInput ? 0 : 1;
184
+ }
185
+ const authToken = resolveAuthToken(env);
186
+ if (!authToken) {
187
+ output.write("[nolo] agent bind-current requires an auth token. Run `nolo login` or set AUTH_TOKEN.\n");
188
+ return 1;
189
+ }
190
+ const userId = parseUserIdFromAuthToken(authToken);
191
+ if (!userId) {
192
+ output.write("[nolo] agent bind-current could not read userId from AUTH_TOKEN.\n");
193
+ return 1;
194
+ }
195
+ const serverUrl = resolveServerUrl(env);
196
+ const fetchImpl = deps.fetchImpl ?? fetch;
197
+ const fallbackFetchImpl = deps.fallbackFetchImpl;
198
+ const machine = await (deps.machineInfo ?? detectLaunchableMachineInfo)();
199
+ let boundAgentKey = "";
200
+ try {
201
+ await heartbeatCurrentMachine({ authToken, fetchImpl, machine, serverUrl });
202
+ const db = deps.db ?? await getReadableCliDb(output);
203
+ const resolved = await resolveAgentRecordFromHybridStore({
204
+ agentInput,
205
+ env,
206
+ db,
207
+ fetchImpl,
208
+ fallbackFetchImpl
209
+ });
210
+ if (!resolved) {
211
+ throw new Error(`agent not found: ${resolveCliAgentKeyInput(agentInput)}`);
212
+ }
213
+ const agentKey = resolved.agentKey;
214
+ boundAgentKey = agentKey;
215
+ const existing = resolved.record;
216
+ const updated = {
217
+ ...existing,
218
+ runtimeBinding: {
219
+ ...asRecordOrEmpty(existing?.runtimeBinding),
220
+ machineId: machine.machineId,
221
+ ownerUserId: userId
222
+ },
223
+ updatedAt: Date.now()
224
+ };
225
+ await writeAgentRecord({
226
+ agentKey,
227
+ authToken,
228
+ fallbackFetchImpl,
229
+ fetchImpl,
230
+ serverUrl,
231
+ userId,
232
+ record: updated
233
+ });
234
+ } catch (error) {
235
+ output.write(
236
+ `[nolo] agent bind-current failed: ${toErrorMessage(error)}
237
+ `
238
+ );
239
+ return 1;
240
+ }
241
+ output.write(`Bound agent ${boundAgentKey} to this machine: ${machine.name} (${machine.machineId})
242
+ `);
243
+ return 0;
244
+ }
245
+ async function runAgentSmokeCurrentCommand(args, deps = {}) {
246
+ const env = deps.env ?? process.env;
247
+ const output = deps.output ?? process.stdout;
248
+ const agentInput = args[0]?.trim();
249
+ if (!agentInput || agentInput === "--help" || agentInput === "-h") {
250
+ output.write('Usage: nolo agent smoke-current <agent> --msg "hello"\n');
251
+ return agentInput ? 0 : 1;
252
+ }
253
+ const agentKey = resolveCliAgentKeyInput(agentInput);
254
+ const authToken = resolveAuthToken(env);
255
+ if (!authToken) {
256
+ output.write("[nolo] agent smoke-current requires an auth token. Run `nolo login` or set AUTH_TOKEN.\n");
257
+ return 1;
258
+ }
259
+ const userId = parseUserIdFromAuthToken(authToken);
260
+ if (!userId) {
261
+ output.write("[nolo] agent smoke-current could not read userId from AUTH_TOKEN.\n");
262
+ return 1;
263
+ }
264
+ const userInput = readOption(args, "--msg") ?? "Smoke test from nolo connector.";
265
+ const serverUrl = resolveServerUrl(env);
266
+ const fetchImpl = deps.fetchImpl ?? fetch;
267
+ const fallbackFetchImpl = deps.fallbackFetchImpl;
268
+ const machine = await (deps.machineInfo ?? detectLaunchableMachineInfo)();
269
+ const sentMessages = [];
270
+ try {
271
+ await heartbeatCurrentMachine({ authToken, fetchImpl, machine, serverUrl });
272
+ const existing = await readAgentRecord({ agentKey, authToken, fallbackFetchImpl, fetchImpl, serverUrl });
273
+ assertSmokeCompatible(existing, machine);
274
+ await writeAgentRecord({
275
+ agentKey,
276
+ authToken,
277
+ fallbackFetchImpl,
278
+ fetchImpl,
279
+ serverUrl,
280
+ userId,
281
+ record: {
282
+ ...existing,
283
+ runtimeBinding: {
284
+ ...asRecordOrEmpty(existing?.runtimeBinding),
285
+ machineId: machine.machineId,
286
+ ownerUserId: userId
287
+ },
288
+ updatedAt: Date.now()
289
+ }
290
+ });
291
+ let runResponse = null;
292
+ const wsTarget = await resolveConnectorWebSocketTarget({
293
+ serverUrl,
294
+ machineId: machine.machineId,
295
+ headers: { Authorization: `Bearer ${authToken}` },
296
+ fetchImpl
297
+ });
298
+ await (deps.connectWebSocket ?? defaultConnectWebSocket)(
299
+ wsTarget,
300
+ {
301
+ headers: { Authorization: `Bearer ${authToken}` },
302
+ sentMessages,
303
+ onMessage: (message) => (deps.connectorRunMessageHandler ?? forwardConnectorRunMessage)(
304
+ machine,
305
+ message,
306
+ (response) => sentMessages.push(response),
307
+ deps.executeCli ?? defaultExecuteCli,
308
+ {
309
+ ...env,
310
+ NOLO_SERVER: serverUrl,
311
+ NOLO_SERVER_URL: serverUrl,
312
+ BASE_URL: serverUrl,
313
+ AUTH_TOKEN: authToken,
314
+ NOLO_MACHINE_API_KEY: authToken
315
+ },
316
+ fetchImpl
317
+ ),
318
+ onOpen: async () => {
319
+ const res = await fetchImpl(`${serverUrl}/api/agent/run`, {
320
+ method: "POST",
321
+ headers: {
322
+ Authorization: `Bearer ${authToken}`,
323
+ "Content-Type": "application/json"
324
+ },
325
+ body: JSON.stringify({
326
+ agentKey,
327
+ userInput,
328
+ stream: false
329
+ })
330
+ });
331
+ runResponse = await res.json().catch(() => ({}));
332
+ if (!res.ok) {
333
+ throw new Error(`agent run failed: HTTP ${res.status} ${JSON.stringify(runResponse)}`);
334
+ }
335
+ }
336
+ }
337
+ );
338
+ output.write(`Smoke OK: ${runResponse?.dialogId ?? "no-dialog"}
339
+ `);
340
+ if (runResponse?.content) output.write(`${runResponse.content}
341
+ `);
342
+ return 0;
343
+ } catch (error) {
344
+ output.write(
345
+ `[nolo] agent smoke-current failed: ${toErrorMessage(error)}
346
+ `
347
+ );
348
+ return 1;
349
+ }
350
+ }
351
+ async function runAgentRuntimeDoctorCommand(args, deps = {}) {
352
+ const env = deps.env ?? process.env;
353
+ const output = deps.output ?? process.stdout;
354
+ const agentInput = args[0]?.trim();
355
+ if (!agentInput || agentInput === "--help" || agentInput === "-h") {
356
+ output.write("Usage: nolo agent runtime-doctor <agentKey>\n");
357
+ return agentInput ? 0 : 1;
358
+ }
359
+ const authToken = resolveAuthToken(env);
360
+ if (!authToken) {
361
+ output.write("[nolo] agent runtime-doctor requires an auth token. Run `nolo login` or set AUTH_TOKEN.\n");
362
+ return 1;
363
+ }
364
+ const serverUrl = resolveServerUrl(env);
365
+ const fetchImpl = deps.fetchImpl ?? fetch;
366
+ const fallbackFetchImpl = deps.fallbackFetchImpl;
367
+ const machine = await (deps.machineInfo ?? detectLaunchableMachineInfo)();
368
+ try {
369
+ const db = deps.db ?? await getReadableCliDb(output);
370
+ const resolved = await resolveAgentRecordFromHybridStore({
371
+ agentInput,
372
+ env,
373
+ db,
374
+ fetchImpl,
375
+ fallbackFetchImpl
376
+ });
377
+ if (!resolved) {
378
+ throw new Error(`agent not found: ${resolveCliAgentKeyInput(agentInput)}`);
379
+ }
380
+ const agentKey = resolved.agentKey;
381
+ const agent = resolved.record;
382
+ const requiredCapability = requiredCapabilityForAgent(agent);
383
+ const runtimeClass = classifyAgentRuntime(agent);
384
+ const isBoundToCurrent = agent?.runtimeBinding?.machineId === machine.machineId;
385
+ const hasCapability = requiredCapability ? machine.capabilities.includes(requiredCapability) : false;
386
+ output.write(`Agent runtime doctor: ${agent?.name ?? agentKey}
387
+ `);
388
+ if (agentInput !== agentKey) output.write(`Agent input: ${agentInput}
389
+ `);
390
+ output.write(`Agent key: ${agentKey}
391
+ `);
392
+ output.write(`Runtime class: ${runtimeClass}
393
+ `);
394
+ output.write(`API source: ${agent?.apiSource ?? "unknown"}
395
+ `);
396
+ output.write(`CLI provider: ${resolveAgentCliProvider(agent) || "none"}
397
+ `);
398
+ output.write(`Required capability: ${requiredCapability || "none"}
399
+ `);
400
+ output.write(`Current machine: ${machine.name} (${machine.machineId})
401
+ `);
402
+ output.write(`Current machine capabilities: ${machine.capabilities.length ? machine.capabilities.join(", ") : "none"}
403
+ `);
404
+ output.write(`Current machine binding: ${runtimeClass === "cli-machine" ? isBoundToCurrent ? "yes" : "no" : "not required"}
405
+ `);
406
+ output.write(`Current machine has required capability: ${requiredCapability ? hasCapability ? "yes" : "no" : "not required"}
407
+ `);
408
+ return shouldRuntimeDoctorPass({ runtimeClass, requiredCapability, hasCapability }) ? 0 : 1;
409
+ } catch (error) {
410
+ output.write(
411
+ `[nolo] agent runtime-doctor failed: ${toErrorMessage(error)}
412
+ `
413
+ );
414
+ return 1;
415
+ }
416
+ }
417
+ export {
418
+ runAgentBindCurrentCommand,
419
+ runAgentRuntimeDoctorCommand,
420
+ runAgentSmokeCurrentCommand
421
+ };