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,581 @@
1
+ import {
2
+ defaultOpenBrowser
3
+ } from "./chunk-VVX233PH.js";
4
+ import "./chunk-6HYVJV7B.js";
5
+ import {
6
+ generateCloudflareEmailRoutingToken,
7
+ parseFlagWithOptionalValue,
8
+ runCloudflareOAuthLogin,
9
+ upsertEnvVariable
10
+ } from "./chunk-4IJYA27C.js";
11
+ import {
12
+ generatePkcePair,
13
+ runAntigravityOAuthLogin,
14
+ runCursorOAuthLogin,
15
+ runOpenAiCodexBrowserPkce,
16
+ runOpenAiCodexDeviceCode,
17
+ runXaiOAuthDeviceCode,
18
+ runXaiOAuthLogin,
19
+ startCallbackServer
20
+ } from "./chunk-EHLHSX7R.js";
21
+ import "./chunk-JBTJAPUF.js";
22
+ import {
23
+ buildEnvFromProfile,
24
+ loadProfileConfig
25
+ } from "./chunk-ROWQEJRP.js";
26
+ import "./chunk-ISNCLGUZ.js";
27
+ import "./chunk-OLZBQWZU.js";
28
+ import {
29
+ createOAuthTokenStore
30
+ } from "./chunk-JZPBVBIY.js";
31
+ import {
32
+ toErrorMessage
33
+ } from "./chunk-HNMXYYJR.js";
34
+ import "./chunk-H33743XH.js";
35
+ import "./chunk-LM6IYQ3F.js";
36
+ import "./chunk-O4BU24WZ.js";
37
+ import "./chunk-I42VC5KR.js";
38
+ import "./chunk-WWC7I6TA.js";
39
+ import "./chunk-4SN6J65J.js";
40
+ import "./chunk-LCBAMY2M.js";
41
+ import "./chunk-3EUW3WEO.js";
42
+ import "./chunk-U6VC4MU4.js";
43
+ import "./chunk-CF7PE763.js";
44
+ import "./chunk-G3SUCT4W.js";
45
+ import "./chunk-KUG52IAP.js";
46
+ import "./chunk-4VNS5WPM.js";
47
+
48
+ // packages/cli/oauth/flows/anthropic.ts
49
+ import { randomBytes } from "node:crypto";
50
+ import { createInterface } from "node:readline/promises";
51
+ var ANTHROPIC_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
52
+ var ANTHROPIC_OAUTH_AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
53
+ var ANTHROPIC_OAUTH_TOKEN_URL = "https://api.anthropic.com/v1/oauth/token";
54
+ var ANTHROPIC_OAUTH_CALLBACK_PORT = 54545;
55
+ var ANTHROPIC_OAUTH_REDIRECT_URI = `http://localhost:${ANTHROPIC_OAUTH_CALLBACK_PORT}/callback`;
56
+ var ANTHROPIC_OAUTH_SCOPES = [
57
+ "org:create_api_key",
58
+ "user:profile",
59
+ "user:inference",
60
+ "user:sessions:claude_code",
61
+ "user:mcp_servers",
62
+ "user:file_upload"
63
+ ];
64
+ var ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
65
+ function buildAnthropicAuthorizeUrl(args) {
66
+ const params = new URLSearchParams({
67
+ code: "true",
68
+ client_id: ANTHROPIC_OAUTH_CLIENT_ID,
69
+ response_type: "code",
70
+ redirect_uri: args.redirectUri ?? ANTHROPIC_OAUTH_REDIRECT_URI,
71
+ scope: ANTHROPIC_OAUTH_SCOPES.join(" "),
72
+ code_challenge: args.challenge,
73
+ code_challenge_method: "S256",
74
+ state: args.state
75
+ });
76
+ return `${ANTHROPIC_OAUTH_AUTHORIZE_URL}?${params.toString()}`;
77
+ }
78
+ function parseManualAuthorization(raw, expectedState) {
79
+ const value = raw.trim();
80
+ if (!value) throw new Error("No authorization code was provided.");
81
+ try {
82
+ const url = new URL(value);
83
+ const code2 = url.searchParams.get("code")?.trim();
84
+ const state = url.searchParams.get("state")?.trim();
85
+ if (code2 && state === expectedState) return { code: code2, state };
86
+ throw new Error("Claude OAuth state verification failed.");
87
+ } catch (error) {
88
+ if (error instanceof Error && error.message.includes("state verification")) {
89
+ throw error;
90
+ }
91
+ }
92
+ const separator = value.lastIndexOf("#");
93
+ if (separator < 0) return { code: value, state: expectedState };
94
+ const code = value.slice(0, separator).trim();
95
+ const returnedState = value.slice(separator + 1).trim();
96
+ if (!code || returnedState !== expectedState) {
97
+ throw new Error("Claude OAuth state verification failed.");
98
+ }
99
+ return { code, state: returnedState };
100
+ }
101
+ function tokenError(payload, status) {
102
+ const detail = typeof payload.error_description === "string" ? payload.error_description : typeof payload.error === "string" ? payload.error : `HTTP ${status}`;
103
+ return `Claude OAuth token exchange failed: ${detail}`;
104
+ }
105
+ async function exchangeAnthropicAuthorizationCode(args) {
106
+ const fetchImpl = args.fetchImpl ?? fetch;
107
+ const response = await fetchImpl(ANTHROPIC_OAUTH_TOKEN_URL, {
108
+ method: "POST",
109
+ headers: { "Content-Type": "application/json" },
110
+ body: JSON.stringify({
111
+ grant_type: "authorization_code",
112
+ client_id: ANTHROPIC_OAUTH_CLIENT_ID,
113
+ code: args.code,
114
+ state: args.state,
115
+ redirect_uri: args.redirectUri ?? ANTHROPIC_OAUTH_REDIRECT_URI,
116
+ code_verifier: args.verifier
117
+ }),
118
+ signal: AbortSignal.timeout(3e4)
119
+ });
120
+ const payload = await response.json().catch(() => ({}));
121
+ if (!response.ok) throw new Error(tokenError(payload, response.status));
122
+ if (typeof payload.access_token !== "string" || !payload.access_token) {
123
+ throw new Error("Claude OAuth token exchange response missing access_token.");
124
+ }
125
+ const now = args.now?.() ?? Date.now();
126
+ const expiresIn = typeof payload.expires_in === "number" && Number.isFinite(payload.expires_in) ? payload.expires_in : void 0;
127
+ const accountId = typeof payload.account?.uuid === "string" ? payload.account.uuid : void 0;
128
+ const email = typeof payload.account?.email_address === "string" ? payload.account.email_address : void 0;
129
+ const organizationId = typeof payload.organization?.uuid === "string" ? payload.organization.uuid : void 0;
130
+ const organizationName = typeof payload.organization?.name === "string" ? payload.organization.name : void 0;
131
+ return {
132
+ provider: "claude",
133
+ accessToken: payload.access_token,
134
+ ...typeof payload.refresh_token === "string" && payload.refresh_token ? { refreshToken: payload.refresh_token } : {},
135
+ ...expiresIn !== void 0 ? { expiresAt: now + expiresIn * 1e3 - ACCESS_TOKEN_CLIENT_SKEW_MS } : {},
136
+ ...typeof payload.scope === "string" ? { scope: payload.scope } : {},
137
+ ...accountId ? { accountId } : {},
138
+ ...email || organizationId || organizationName ? { metadata: { email, organizationId, organizationName } } : {},
139
+ obtainedAt: now
140
+ };
141
+ }
142
+ async function defaultReadLine(prompt) {
143
+ const terminal = createInterface({ input: process.stdin, output: process.stdout });
144
+ try {
145
+ return await terminal.question(prompt);
146
+ } finally {
147
+ terminal.close();
148
+ }
149
+ }
150
+ async function runAnthropicOAuthLogin(deps = {}) {
151
+ const output = deps.output ?? console;
152
+ const error = deps.error ?? console;
153
+ const state = randomBytes(24).toString("base64url");
154
+ const pkce = generatePkcePair();
155
+ const preferredCallbackPort = deps.callbackPort ?? ANTHROPIC_OAUTH_CALLBACK_PORT;
156
+ const callbackServerFactory = deps.callbackServerFactory ?? startCallbackServer;
157
+ const callback = deps.manualCode ? null : await callbackServerFactory({
158
+ port: preferredCallbackPort,
159
+ hostname: "127.0.0.1",
160
+ timeoutMs: 5 * 6e4,
161
+ fallbackToRandomPort: true
162
+ });
163
+ const redirectUri = callback ? `http://localhost:${callback.port}/callback` : `http://localhost:${preferredCallbackPort}/callback`;
164
+ const authUrl = buildAnthropicAuthorizeUrl({
165
+ state,
166
+ challenge: pkce.challenge,
167
+ redirectUri
168
+ });
169
+ output.log(
170
+ `Open this URL to authorize Claude Pro/Max:
171
+ ${authUrl}`
172
+ );
173
+ if (callback && callback.port !== preferredCallbackPort) {
174
+ output.log(
175
+ `Port ${preferredCallbackPort} is busy; using callback port ${callback.port}.`
176
+ );
177
+ }
178
+ if (deps.openBrowser) {
179
+ try {
180
+ await deps.openBrowser(authUrl);
181
+ } catch (cause) {
182
+ error.error(`Could not open the browser automatically: ${String(cause)}`);
183
+ }
184
+ }
185
+ let code = "";
186
+ let returnedState = state;
187
+ if (deps.manualCode) {
188
+ const raw = await (deps.readLine ?? defaultReadLine)(
189
+ "Paste the final callback URL or authorization code: "
190
+ );
191
+ ({ code, state: returnedState } = parseManualAuthorization(raw, state));
192
+ } else {
193
+ if (!callback) throw new Error("Claude OAuth callback server did not start.");
194
+ try {
195
+ const result = await callback.waitForCode();
196
+ if (result.state !== state) {
197
+ throw new Error("Claude OAuth state verification failed.");
198
+ }
199
+ code = result.code;
200
+ returnedState = result.state;
201
+ } finally {
202
+ await callback.close().catch(() => void 0);
203
+ }
204
+ }
205
+ return exchangeAnthropicAuthorizationCode({
206
+ code,
207
+ state: returnedState,
208
+ verifier: pkce.verifier,
209
+ redirectUri,
210
+ ...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {},
211
+ ...deps.now ? { now: deps.now } : {}
212
+ });
213
+ }
214
+
215
+ // packages/cli/oauth/authCommand.ts
216
+ var SYNC_HELP_LINE = ` --sync-to-server After local save, push the credential to your nolo server.
217
+ --sync-only Push ~/.nolo/credentials/<provider>.json to the server without re-login.`;
218
+ var CHATGPT_HELP_TEXT = `Authorize nolo-cli to call the OpenAI Codex / ChatGPT Plus API on your behalf.
219
+
220
+ This authorizes model API access only. It does NOT log you into the Nolo platform.
221
+ To manage agents, docs, spaces, and other Nolo resources, run "nolo login" first.
222
+
223
+ Usage:
224
+ nolo auth chatgpt [--browser] [--no-browser] [--sync-to-server] [--help]
225
+
226
+ Options:
227
+ --browser Use the local browser PKCE flow instead of the device-code flow.
228
+ --no-browser Print the authorization URL only (device-code flow).
229
+ ${SYNC_HELP_LINE}
230
+ --help, -h Show this help and exit.
231
+
232
+ The default flow is device-code, which works headless: open the printed URL on any
233
+ machine with a browser where you are already logged into ChatGPT. After approval, the
234
+ access and refresh tokens are stored in ~/.nolo/credentials/chatgpt.json.
235
+
236
+ Agents can reference the stored token by setting apiKeyRef: "chatgpt" with
237
+ apiSource: "custom" and provider: "openai".
238
+ `;
239
+ var XAI_HELP_TEXT = `Authorize nolo-cli to call the xAI Grok API via your SuperGrok subscription.
240
+
241
+ This authorizes model API access only. It does NOT log you into the Nolo platform.
242
+ To manage agents, docs, spaces, and other Nolo resources, run "nolo login" first.
243
+
244
+ Usage:
245
+ nolo auth xai [--browser] [--device-code] [--no-browser] [--sync-to-server] [--help]
246
+
247
+ Default (interactive desktop): OIDC PKCE loopback on 127.0.0.1:56121.
248
+ Headless / SSH / Docker: use --device-code or --no-browser (RFC 8628 device
249
+ authorization; no localhost callback). After approval, tokens are stored in
250
+ ~/.nolo/credentials/xai.json.
251
+
252
+ The OAuth client_id is the same fixed value used by NousResearch/hermes-agent
253
+ (MIT), oh-my-pi, and OpenClaw; xAI does not publish a public client registration flow.
254
+
255
+ Options:
256
+ --browser Use the browser PKCE loopback flow (default for xAI).
257
+ --device-code Use RFC 8628 device authorization (headless-friendly).
258
+ --no-browser Same as --device-code for xAI (no loopback listener).
259
+ ${SYNC_HELP_LINE}
260
+ --help, -h Show this help and exit.
261
+
262
+ Agents can reference the stored token by setting apiKeyRef: "xai" with
263
+ apiSource: "custom" and provider: "xai".
264
+ `;
265
+ var ANTIGRAVITY_HELP_TEXT = `Authorize nolo-cli to call Google Antigravity (Gemini 3, Claude, GPT-OSS) via your Google account.
266
+
267
+ This authorizes model API access only. It does NOT log you into the Nolo platform.
268
+ To manage agents, docs, spaces, and other Nolo resources, run "nolo login" first.
269
+
270
+ Usage:
271
+ nolo auth antigravity [--browser] [--no-browser] [--sync-to-server] [--help]
272
+
273
+ Opens a browser to https://accounts.google.com (OIDC PKCE loopback on 127.0.0.1:51121).
274
+ After approval, the flow provisions a Cloud Code Assist project and stores the
275
+ access and refresh tokens in ~/.nolo/credentials/antigravity.json.
276
+
277
+ The OAuth client_id/secret are the same base64-decoded values used by
278
+ oh-my-pi; Google does not publish a public Cloud Code Assist client registration.
279
+
280
+ Options:
281
+ --browser Use the browser PKCE flow (default for antigravity).
282
+ --no-browser Print the authorization URL only.
283
+ ${SYNC_HELP_LINE}
284
+ --help, -h Show this help and exit.
285
+
286
+ Agents can reference the stored token by setting apiKeyRef: "antigravity" with
287
+ apiSource: "custom" and provider: "google-antigravity".
288
+ `;
289
+ var CLAUDE_HELP_TEXT = `Authorize nolo-cli to call Anthropic Claude with your Claude Pro/Max subscription.
290
+
291
+ This authorizes model API access only. It does NOT log you into the Nolo platform.
292
+ To manage agents, docs, spaces, and other Nolo resources, run "nolo login" first.
293
+
294
+ Usage:
295
+ nolo auth claude [--browser] [--no-browser] [--sync-to-server] [--help]
296
+
297
+ The default flow returns to a loopback callback on localhost:54545. With
298
+ --no-browser, paste the final callback URL or authorization code into the
299
+ terminal. Tokens are stored in ~/.nolo/credentials/claude.json.
300
+
301
+ Options:
302
+ --browser Open the Anthropic authorization page (default).
303
+ --no-browser Print the authorization URL without opening a browser.
304
+ ${SYNC_HELP_LINE}
305
+ --help, -h Show this help and exit.
306
+
307
+ Agents can reference the stored token with apiKeyRef: "claude", provider:
308
+ "anthropic", and model such as "claude-sonnet-5".
309
+ `;
310
+ var CURSOR_HELP_TEXT = `Authorize nolo-cli to call Cursor models via your Cursor Pro subscription.
311
+
312
+ This authorizes model API access only. It does NOT log you into the Nolo
313
+ platform. To manage agents, docs, spaces, and other Nolo resources, run
314
+ "nolo login" first.
315
+
316
+ Usage: nolo auth cursor [--no-browser] [--sync-to-server] [--help]
317
+
318
+ The flow opens https://cursor.com/loginDeepControl in your browser and polls
319
+ https://api2.cursor.sh/auth/poll until you approve. There is no loopback
320
+ callback \u2014 this is a poll-based device flow, so it works in headless / SSH /
321
+ Docker environments too.
322
+
323
+ After approval, tokens are stored in ~/.nolo/credentials/cursor.json.
324
+ Agents can reference the stored token with apiKeyRef: "cursor".
325
+
326
+ Options:
327
+ --no-browser Print the authorization URL without opening a browser.
328
+ ${SYNC_HELP_LINE}
329
+ --help, -h Show this help and exit.
330
+ `;
331
+ var CLOUDFLARE_HELP_TEXT = `Authorize nolo-cli to manage Cloudflare resources on your behalf.
332
+
333
+ This authorizes Cloudflare API access only. It does NOT log you into the Nolo platform.
334
+ To manage agents, docs, spaces, and other Nolo resources, run "nolo login" first.
335
+
336
+ Usage:
337
+ nolo auth cloudflare [--client-id <id>] [--scope <scopes>] [--generate-token] [--zone-name <domain>] [--token-name <label>] [--browser] [--no-browser] [--sync-to-server] [--help]
338
+
339
+ Opens a browser to https://dash.cloudflare.com (OAuth 2.0 PKCE loopback on
340
+ 127.0.0.1:56122). After approval, the OAuth access token is stored locally in
341
+ ~/.nolo/credentials/cloudflare.json.
342
+
343
+ To use this flow you must first create a Cloudflare OAuth client in the
344
+ Cloudflare Dashboard (Manage Account > OAuth clients) and obtain a client_id.
345
+ You can also create the client via the Cloudflare API:
346
+ POST /accounts/{account_id}/oauth_clients
347
+
348
+ Set the client ID via the environment variable:
349
+ CLOUDFLARE_OAUTH_CLIENT_ID
350
+
351
+ Override requested scopes via:
352
+ CLOUDFLARE_OAUTH_SCOPE
353
+
354
+ Default scopes: account:read zone:read zone:edit user:read user:edit
355
+
356
+ With --generate-token, the command will also use the OAuth access token to
357
+ programmatically create a long-lived Cloudflare API token scoped to the
358
+ specified zone with the Email Routing Edit permission.
359
+
360
+ Options:
361
+ --client-id <id> Use this OAuth client ID for this run.
362
+ --scope <scopes> Space-separated scopes (overrides env var for this run).
363
+ --generate-token Also create a Zone:Email Routing:Edit API token.
364
+ --zone-name <domain> Zone domain for token generation (default: nolo.chat).
365
+ --token-name <label> Name for the generated API token.
366
+ --write-to-env [path] Append or update CLOUDFLARE_EMAIL_ROUTING_API_TOKEN in the env file (default: .env).
367
+ --browser Use the browser PKCE flow (default for cloudflare).
368
+ --no-browser Print the authorization URL only.
369
+ ${SYNC_HELP_LINE}
370
+ --help, -h Show this help and exit.
371
+ `;
372
+ var HELP_BY_PROVIDER = {
373
+ chatgpt: CHATGPT_HELP_TEXT,
374
+ xai: XAI_HELP_TEXT,
375
+ antigravity: ANTIGRAVITY_HELP_TEXT,
376
+ claude: CLAUDE_HELP_TEXT,
377
+ cloudflare: CLOUDFLARE_HELP_TEXT,
378
+ cursor: CURSOR_HELP_TEXT
379
+ };
380
+ function resolveServerSyncConfig() {
381
+ const envServer = process.env.NOLO_SERVER?.trim() || process.env.NOLO_SERVER_URL?.trim() || process.env.BASE_URL?.trim() || "";
382
+ const envToken = process.env.AUTH_TOKEN?.trim() || process.env.NOLO_AUTH_TOKEN?.trim() || "";
383
+ if (envServer && envToken) {
384
+ return { serverOrigin: envServer.replace(/\/+$/, ""), authToken: envToken };
385
+ }
386
+ let profileServer = "";
387
+ let profileToken = "";
388
+ try {
389
+ const config = loadProfileConfig();
390
+ const profileEnv = buildEnvFromProfile(config);
391
+ profileServer = profileEnv.NOLO_SERVER?.trim() || "";
392
+ profileToken = profileEnv.AUTH_TOKEN?.trim() || "";
393
+ } catch {
394
+ }
395
+ const serverOrigin = (envServer || profileServer).replace(/\/+$/, "");
396
+ const authToken = envToken || profileToken;
397
+ if (serverOrigin && authToken) {
398
+ return { serverOrigin, authToken };
399
+ }
400
+ return null;
401
+ }
402
+ async function syncCredentialToServer(provider, credential, deps) {
403
+ const output = deps.output ?? console;
404
+ const fetchImpl = deps.fetchImpl ?? fetch;
405
+ const syncConfig = (deps.resolveServerSyncConfig ?? resolveServerSyncConfig)();
406
+ if (!syncConfig) {
407
+ output.log(
408
+ `[nolo] Warning: --sync-to-server requires NOLO_SERVER and AUTH_TOKEN env vars, or a configured profile. Skipping server sync.`
409
+ );
410
+ return;
411
+ }
412
+ const { serverOrigin, authToken } = syncConfig;
413
+ const url = `${serverOrigin}/api/oauth/${provider}/sync`;
414
+ try {
415
+ const res = await fetchImpl(url, {
416
+ method: "POST",
417
+ headers: {
418
+ "Content-Type": "application/json",
419
+ Authorization: `Bearer ${authToken}`
420
+ },
421
+ body: JSON.stringify({
422
+ accessToken: credential.accessToken,
423
+ refreshToken: credential.refreshToken,
424
+ expiresAt: credential.expiresAt,
425
+ scope: credential.scope,
426
+ idToken: credential.idToken,
427
+ accountId: credential.accountId,
428
+ email: credential.metadata?.email,
429
+ metadata: credential.metadata
430
+ })
431
+ });
432
+ if (res.ok) {
433
+ output.log(`[nolo] Synced to ${serverOrigin}`);
434
+ } else {
435
+ let errorDetail = "";
436
+ try {
437
+ const body = await res.json();
438
+ errorDetail = body?.error || "";
439
+ } catch {
440
+ }
441
+ output.log(
442
+ `[nolo] Warning: server sync failed (${res.status}${errorDetail ? `: ${errorDetail}` : ""}). Token saved locally.`
443
+ );
444
+ }
445
+ } catch (err) {
446
+ output.log(
447
+ `[nolo] Warning: server sync failed (${err?.message ?? "network error"}). Token saved locally.`
448
+ );
449
+ }
450
+ }
451
+ async function runAuthProviderCommand(provider, args, _ctx, deps = {}) {
452
+ const output = deps.output ?? console;
453
+ const error = deps.error ?? console;
454
+ const tokenStore = deps.tokenStore ?? createOAuthTokenStore();
455
+ if (args.includes("--help") || args.includes("-h")) {
456
+ output.log(HELP_BY_PROVIDER[provider]);
457
+ return 0;
458
+ }
459
+ const useBrowser = args.includes("--browser");
460
+ const noBrowser = args.includes("--no-browser") || deps.noBrowserByDefault;
461
+ const syncOnly = args.includes("--sync-only");
462
+ const syncToServer = args.includes("--sync-to-server") || syncOnly;
463
+ const generateToken = args.includes("--generate-token");
464
+ const writeToEnvRaw = parseFlagWithOptionalValue(args, "--write-to-env");
465
+ const writeToEnvPath = typeof writeToEnvRaw === "string" ? writeToEnvRaw : writeToEnvRaw === true ? ".env" : void 0;
466
+ const openBrowser = noBrowser ? void 0 : deps.openBrowser ?? defaultOpenBrowser;
467
+ if (syncOnly) {
468
+ const credential = tokenStore.read(provider);
469
+ if (!credential) {
470
+ error.error(
471
+ `[nolo] No local ${provider} credential. Run: nolo auth ${provider}`
472
+ );
473
+ return 1;
474
+ }
475
+ await syncCredentialToServer(provider, credential, deps);
476
+ return 0;
477
+ }
478
+ const flowDeps = {
479
+ ...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {},
480
+ ...deps.sleep ? { sleep: deps.sleep } : {},
481
+ ...deps.now ? { now: deps.now } : {},
482
+ ...deps.readLine ? { readLine: deps.readLine } : {},
483
+ ...noBrowser ? { manualCode: true } : {},
484
+ openBrowser,
485
+ output,
486
+ error
487
+ };
488
+ const clientIdFlag = args.find((arg, index) => arg === "--client-id" && index + 1 < args.length) ? args[args.indexOf("--client-id") + 1] : void 0;
489
+ const scopeFlag = args.find((arg, index) => arg === "--scope" && index + 1 < args.length) ? args[args.indexOf("--scope") + 1] : void 0;
490
+ const zoneNameFlag = args.find((arg, index) => arg === "--zone-name" && index + 1 < args.length) ? args[args.indexOf("--zone-name") + 1] : void 0;
491
+ const tokenNameFlag = args.find((arg, index) => arg === "--token-name" && index + 1 < args.length) ? args[args.indexOf("--token-name") + 1] : void 0;
492
+ try {
493
+ let credential;
494
+ if (provider === "chatgpt") {
495
+ credential = useBrowser ? await runOpenAiCodexBrowserPkce(flowDeps) : await runOpenAiCodexDeviceCode(flowDeps);
496
+ } else if (provider === "xai") {
497
+ const useDeviceCode = !useBrowser && (args.includes("--device-code") || noBrowser);
498
+ credential = useDeviceCode ? await runXaiOAuthDeviceCode(flowDeps) : await runXaiOAuthLogin(flowDeps);
499
+ } else if (provider === "claude") {
500
+ credential = await runAnthropicOAuthLogin(flowDeps);
501
+ } else if (provider === "cursor") {
502
+ credential = await runCursorOAuthLogin(flowDeps);
503
+ } else if (provider === "cloudflare") {
504
+ credential = await runCloudflareOAuthLogin({
505
+ ...flowDeps,
506
+ ...clientIdFlag ? { clientId: clientIdFlag } : {},
507
+ ...scopeFlag ? { scope: scopeFlag } : {}
508
+ });
509
+ if (generateToken) {
510
+ const zoneName = zoneNameFlag ?? process.env.CLOUDFLARE_ZONE_NAME ?? "nolo.chat";
511
+ const tokenName = tokenNameFlag ?? `nolo-email-routing-${zoneName}`;
512
+ const { token, zoneId } = await generateCloudflareEmailRoutingToken({
513
+ accessToken: credential.accessToken,
514
+ zoneName,
515
+ tokenName,
516
+ fetchImpl: deps.fetchImpl ?? fetch
517
+ });
518
+ output.log(
519
+ `[nolo] Generated Cloudflare API token for zone ${zoneName} (${zoneId}).
520
+ Store it as CLOUDFLARE_EMAIL_ROUTING_API_TOKEN:
521
+ ${token}
522
+ `
523
+ );
524
+ if (writeToEnvPath) {
525
+ upsertEnvVariable(
526
+ writeToEnvPath,
527
+ "CLOUDFLARE_EMAIL_ROUTING_API_TOKEN",
528
+ token
529
+ );
530
+ output.log(
531
+ `[nolo] Updated ${writeToEnvPath} with CLOUDFLARE_EMAIL_ROUTING_API_TOKEN.`
532
+ );
533
+ }
534
+ }
535
+ } else {
536
+ credential = await runAntigravityOAuthLogin(flowDeps);
537
+ }
538
+ tokenStore.write(provider, credential);
539
+ const accountLabel = credential.metadata?.email ?? credential.accountId ?? "";
540
+ output.log(
541
+ `[nolo] ${provider} authorization saved` + (accountLabel ? ` for ${accountLabel}` : "") + `.`
542
+ );
543
+ if (syncToServer) {
544
+ await syncCredentialToServer(provider, credential, deps);
545
+ }
546
+ return 0;
547
+ } catch (err) {
548
+ error.error(
549
+ `nolo auth ${provider} failed: ${toErrorMessage(err)}`
550
+ );
551
+ return 1;
552
+ }
553
+ }
554
+ async function runAuthChatgptCommand(args, ctx, deps) {
555
+ return runAuthProviderCommand("chatgpt", args, ctx, deps);
556
+ }
557
+ async function runAuthXaiCommand(args, ctx, deps) {
558
+ return runAuthProviderCommand("xai", args, ctx, deps);
559
+ }
560
+ async function runAuthAntigravityCommand(args, ctx, deps) {
561
+ return runAuthProviderCommand("antigravity", args, ctx, deps);
562
+ }
563
+ async function runAuthCloudflareCommand(args, ctx, deps) {
564
+ return runAuthProviderCommand("cloudflare", args, ctx, deps);
565
+ }
566
+ async function runAuthClaudeCommand(args, ctx, deps) {
567
+ return runAuthProviderCommand("claude", args, ctx, deps);
568
+ }
569
+ async function runAuthCursorCommand(args, ctx, deps) {
570
+ return runAuthProviderCommand("cursor", args, ctx, deps);
571
+ }
572
+ export {
573
+ resolveServerSyncConfig,
574
+ runAuthAntigravityCommand,
575
+ runAuthChatgptCommand,
576
+ runAuthClaudeCommand,
577
+ runAuthCloudflareCommand,
578
+ runAuthCursorCommand,
579
+ runAuthProviderCommand,
580
+ runAuthXaiCommand
581
+ };
@@ -0,0 +1,35 @@
1
+ import {
2
+ LOGIN_HELP_TEXT,
3
+ LOGOUT_HELP_TEXT,
4
+ WHOAMI_HELP_TEXT,
5
+ defaultOpenBrowser,
6
+ runLoginCommand,
7
+ runLogoutCommand,
8
+ runWhoamiCommand
9
+ } from "./chunk-VVX233PH.js";
10
+ import "./chunk-6HYVJV7B.js";
11
+ import "./chunk-JBTJAPUF.js";
12
+ import "./chunk-ROWQEJRP.js";
13
+ import "./chunk-ISNCLGUZ.js";
14
+ import "./chunk-OLZBQWZU.js";
15
+ import "./chunk-H33743XH.js";
16
+ import "./chunk-LM6IYQ3F.js";
17
+ import "./chunk-O4BU24WZ.js";
18
+ import "./chunk-I42VC5KR.js";
19
+ import "./chunk-WWC7I6TA.js";
20
+ import "./chunk-4SN6J65J.js";
21
+ import "./chunk-LCBAMY2M.js";
22
+ import "./chunk-3EUW3WEO.js";
23
+ import "./chunk-U6VC4MU4.js";
24
+ import "./chunk-CF7PE763.js";
25
+ import "./chunk-G3SUCT4W.js";
26
+ import "./chunk-4VNS5WPM.js";
27
+ export {
28
+ LOGIN_HELP_TEXT,
29
+ LOGOUT_HELP_TEXT,
30
+ WHOAMI_HELP_TEXT,
31
+ defaultOpenBrowser,
32
+ runLoginCommand,
33
+ runLogoutCommand,
34
+ runWhoamiCommand
35
+ };