deepline 0.3.294 → 0.3.295

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 (136) hide show
  1. package/dist/bundling-sources/sdk/src/compat.ts +35 -7
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +14 -1
  4. package/dist/cli/auth-EDTRERZP.mjs +31 -0
  5. package/dist/cli/auth-TDHKB277.js +31 -0
  6. package/dist/cli/billing-ELIDPILY.js +1749 -0
  7. package/dist/cli/billing-EXGXJVAU.mjs +1749 -0
  8. package/dist/cli/chunk-2S5Y3TZP.js +5688 -0
  9. package/dist/cli/chunk-3KC45UVF.js +150 -0
  10. package/dist/cli/chunk-3XX5TEA4.js +15 -0
  11. package/dist/cli/chunk-4MBOJQPL.mjs +0 -0
  12. package/dist/cli/chunk-4NEFYBF7.js +2240 -0
  13. package/dist/cli/chunk-5JLQPVNX.js +3056 -0
  14. package/dist/cli/chunk-5KDKFHZI.js +1269 -0
  15. package/dist/cli/chunk-6A3TJUWC.js +76 -0
  16. package/dist/cli/chunk-6O5YZOVN.mjs +890 -0
  17. package/dist/cli/chunk-7P5AA3SN.js +344 -0
  18. package/dist/cli/chunk-AYHLUHE5.js +52 -0
  19. package/dist/cli/chunk-CBVIJSHF.mjs +560 -0
  20. package/dist/cli/chunk-CFVVCN4A.js +735 -0
  21. package/dist/cli/chunk-COGTRVWW.js +30 -0
  22. package/dist/cli/chunk-D4AZUZO4.js +190 -0
  23. package/dist/cli/chunk-DLIRSHV6.mjs +28 -0
  24. package/dist/cli/chunk-EACVZI6N.mjs +1995 -0
  25. package/dist/cli/chunk-EDWJY6T4.mjs +3056 -0
  26. package/dist/cli/chunk-EXMLR72R.mjs +0 -0
  27. package/dist/cli/chunk-F35VOIQL.js +890 -0
  28. package/dist/cli/chunk-GAMFK2ZP.mjs +148 -0
  29. package/dist/cli/chunk-GHRQQPW2.mjs +2240 -0
  30. package/dist/cli/chunk-GONRLVV3.js +3440 -0
  31. package/dist/cli/chunk-GVUJJJ5G.mjs +76 -0
  32. package/dist/cli/chunk-H7HIDGZ7.mjs +150 -0
  33. package/dist/cli/chunk-HUZXWOSK.mjs +503 -0
  34. package/dist/cli/chunk-I5YZLGMG.js +1 -0
  35. package/dist/cli/chunk-ITOFSXIU.mjs +15 -0
  36. package/dist/cli/chunk-J5NA2TTX.js +503 -0
  37. package/dist/cli/chunk-JCS5TPNY.mjs +3440 -0
  38. package/dist/cli/chunk-JNNOCMQY.js +47 -0
  39. package/dist/cli/chunk-KRD6H754.mjs +30 -0
  40. package/dist/cli/chunk-LA46MMTL.js +560 -0
  41. package/dist/cli/chunk-LDWT7RJK.mjs +190 -0
  42. package/dist/cli/chunk-M2V26OR5.js +499 -0
  43. package/dist/cli/chunk-MIMASXO4.mjs +389 -0
  44. package/dist/cli/chunk-MROPCKW2.mjs +190 -0
  45. package/dist/cli/chunk-NXDRDJ4K.js +389 -0
  46. package/dist/cli/chunk-NXGCO4JB.mjs +344 -0
  47. package/dist/cli/chunk-OG64RBAC.js +6 -0
  48. package/dist/cli/chunk-OQYEC4GL.mjs +34 -0
  49. package/dist/cli/chunk-OWJZUE3Y.mjs +103 -0
  50. package/dist/cli/chunk-SDK3ZA2C.js +103 -0
  51. package/dist/cli/chunk-SFLARO4Y.mjs +47 -0
  52. package/dist/cli/chunk-SVIIIYIQ.js +923 -0
  53. package/dist/cli/chunk-TAC3JIFE.mjs +354 -0
  54. package/dist/cli/chunk-U3PI7HBM.js +34 -0
  55. package/dist/cli/chunk-UFS752TU.mjs +52 -0
  56. package/dist/cli/chunk-UI37DQE7.mjs +499 -0
  57. package/dist/cli/chunk-UNEMDKXN.js +1 -0
  58. package/dist/cli/chunk-WB6Z2Q44.mjs +1622 -0
  59. package/dist/cli/chunk-WJYPBHTE.js +148 -0
  60. package/dist/cli/chunk-WOHBA5PV.js +354 -0
  61. package/dist/cli/chunk-WQICC2B3.js +190 -0
  62. package/dist/cli/chunk-WZYKRD7T.mjs +6 -0
  63. package/dist/cli/chunk-XL2FO6CW.mjs +5688 -0
  64. package/dist/cli/chunk-XNYIZMNQ.js +28 -0
  65. package/dist/cli/chunk-XRK2TZT5.js +1995 -0
  66. package/dist/cli/chunk-YJYPL5OK.mjs +1269 -0
  67. package/dist/cli/chunk-YWNDYCXR.mjs +735 -0
  68. package/dist/cli/chunk-YWWAF7KZ.mjs +923 -0
  69. package/dist/cli/chunk-ZDO3TO3M.js +1622 -0
  70. package/dist/cli/client-4JVOYVC5.js +20 -0
  71. package/dist/cli/client-EEN2IJN2.mjs +20 -0
  72. package/dist/cli/csv-BOHBEP2I.mjs +585 -0
  73. package/dist/cli/csv-S5NYRUEX.js +585 -0
  74. package/dist/cli/db-CLODWCOB.mjs +486 -0
  75. package/dist/cli/db-F6PKFOOV.js +486 -0
  76. package/dist/cli/executions-5TQAKLJU.js +28 -0
  77. package/dist/cli/executions-MAKW6QOY.mjs +28 -0
  78. package/dist/cli/feedback-GV4QJFEN.js +107 -0
  79. package/dist/cli/feedback-XY24TW7H.mjs +107 -0
  80. package/dist/cli/getting-started.js +18 -76
  81. package/dist/cli/getting-started.mjs +10 -37
  82. package/dist/cli/git-6S2C22T5.js +23 -0
  83. package/dist/cli/git-OZLBD5HH.mjs +23 -0
  84. package/dist/cli/index.js +291 -54294
  85. package/dist/cli/index.mjs +209 -54352
  86. package/dist/cli/legacy-noops-LLCGDPQE.js +157 -0
  87. package/dist/cli/legacy-noops-TYH3TW2D.mjs +157 -0
  88. package/dist/cli/monitors-CABMB4DW.js +3251 -0
  89. package/dist/cli/monitors-TTD55HMK.mjs +3251 -0
  90. package/dist/cli/org-MSF3RG76.js +849 -0
  91. package/dist/cli/org-SFJ77MWY.mjs +849 -0
  92. package/dist/cli/play-NXHJSCKL.mjs +18439 -0
  93. package/dist/cli/play-OKSFNNO4.js +18439 -0
  94. package/dist/cli/providers-QC2ERERL.js +95 -0
  95. package/dist/cli/providers-TIIAZEUA.mjs +95 -0
  96. package/dist/cli/proxy-env-EBANZHPV.js +161 -0
  97. package/dist/cli/proxy-env-M4ZHXHRL.mjs +161 -0
  98. package/dist/cli/quickstart-ICANHLMI.js +69 -0
  99. package/dist/cli/quickstart-KWUOP3FI.mjs +69 -0
  100. package/dist/cli/search-U5H2FDOO.mjs +18 -0
  101. package/dist/cli/search-XQRQOLWS.js +18 -0
  102. package/dist/cli/secrets-3J6YTWFA.mjs +400 -0
  103. package/dist/cli/secrets-YNMNZNOM.js +400 -0
  104. package/dist/cli/sessions-CLEES4L6.mjs +15 -0
  105. package/dist/cli/sessions-J6VR47FG.js +15 -0
  106. package/dist/cli/settings-EEKZMTY4.js +846 -0
  107. package/dist/cli/settings-UVLOQZRH.mjs +846 -0
  108. package/dist/cli/setup-DLMDXPGJ.mjs +1257 -0
  109. package/dist/cli/setup-HC4Q7QM4.js +1257 -0
  110. package/dist/cli/skills-33PHFBSB.mjs +28 -0
  111. package/dist/cli/skills-LFRY3KPX.js +28 -0
  112. package/dist/cli/tools-3COEPKML.mjs +2955 -0
  113. package/dist/cli/tools-QXEVCN45.js +2955 -0
  114. package/dist/cli/update-LSAC4FF5.mjs +28 -0
  115. package/dist/cli/update-NXHSPYXA.js +28 -0
  116. package/dist/cli/workflow-7S44OECF.mjs +1936 -0
  117. package/dist/cli/workflow-QPZWYSZE.js +1936 -0
  118. package/dist/helpers.js +6 -32
  119. package/dist/helpers.mjs +2 -0
  120. package/dist/index.js +1972 -12825
  121. package/dist/index.mjs +1910 -12672
  122. package/dist/install-integrity.json +110 -0
  123. package/dist/monitor-fleet-contract.js +31 -730
  124. package/dist/monitor-fleet-contract.mjs +18 -667
  125. package/dist/monitor-input-contract.js +10 -390
  126. package/dist/monitor-input-contract.mjs +7 -348
  127. package/dist/plays/bundle-play-file.mjs +13 -5178
  128. package/dist/plays/csv-data-input.js +5 -3132
  129. package/dist/plays/csv-data-input.mjs +5 -3105
  130. package/dist/plays/run-request.js +56 -664
  131. package/dist/plays/run-request.mjs +30 -588
  132. package/dist/release.d.mts +1 -1
  133. package/dist/release.d.ts +1 -1
  134. package/dist/release.js +5 -212
  135. package/dist/release.mjs +5 -185
  136. package/package.json +1 -1
@@ -0,0 +1,849 @@
1
+ import {
2
+ DeeplineClient
3
+ } from "./chunk-XL2FO6CW.mjs";
4
+ import "./chunk-CBVIJSHF.mjs";
5
+ import {
6
+ printCommandEnvelope
7
+ } from "./chunk-6O5YZOVN.mjs";
8
+ import {
9
+ ACTIVE_ORG_ID_ENV,
10
+ ACTIVE_ORG_NAME_ENV,
11
+ API_KEY_ENV,
12
+ FEATURES_ENV,
13
+ HOST_URL_ENV,
14
+ HttpClient,
15
+ detectAgentRuntime,
16
+ featureEnvValues,
17
+ getActiveProjectAuthSource,
18
+ getResolvedProjectAuthSource,
19
+ hostEnvFilePath,
20
+ resolveCliAuthProvenance,
21
+ resolveCliCommandContext,
22
+ resolveConfig,
23
+ resolveProjectPinTarget,
24
+ saveHostEnvValues,
25
+ saveProjectDeeplineEnvValues,
26
+ sdkCliStateDirPath,
27
+ storedHostFeatures
28
+ } from "./chunk-EACVZI6N.mjs";
29
+ import "./chunk-DLIRSHV6.mjs";
30
+ import "./chunk-LDWT7RJK.mjs";
31
+ import "./chunk-GVUJJJ5G.mjs";
32
+ import "./chunk-NXGCO4JB.mjs";
33
+ import "./chunk-WZYKRD7T.mjs";
34
+ import "./chunk-KRD6H754.mjs";
35
+
36
+ // src/cli/commands/org.ts
37
+ import { createHash, randomUUID } from "crypto";
38
+ import {
39
+ existsSync,
40
+ mkdirSync,
41
+ readFileSync,
42
+ unlinkSync,
43
+ writeFileSync
44
+ } from "fs";
45
+ import { join } from "path";
46
+ function pendingOrgCreatePath(baseUrl, accountId, sourceOrgId, name) {
47
+ const intent = createHash("sha256").update(accountId).update("\0").update(sourceOrgId).update("\0").update(name).digest("hex");
48
+ return join(sdkCliStateDirPath(baseUrl), `pending-org-create-${intent}.json`);
49
+ }
50
+ function readPendingOrgCreate(path, accountId, sourceOrgId, name) {
51
+ let value;
52
+ try {
53
+ value = JSON.parse(readFileSync(path, "utf8"));
54
+ } catch (error) {
55
+ throw new Error(
56
+ `Cannot resume the pending workspace creation recorded at ${path}: ${error instanceof Error ? error.message : String(error)}`
57
+ );
58
+ }
59
+ if (typeof value !== "object" || value === null || value.accountId !== accountId || value.sourceOrgId !== sourceOrgId || value.name !== name || typeof value.idempotencyKey !== "string" || !value.idempotencyKey.trim()) {
60
+ throw new Error(
61
+ `Cannot resume the pending workspace creation recorded at ${path}: the saved intent is invalid.`
62
+ );
63
+ }
64
+ return value;
65
+ }
66
+ function loadOrCreatePendingOrgCreate(input) {
67
+ const stateDir = sdkCliStateDirPath(input.baseUrl);
68
+ const path = pendingOrgCreatePath(
69
+ input.baseUrl,
70
+ input.accountId,
71
+ input.sourceOrgId,
72
+ input.name
73
+ );
74
+ mkdirSync(stateDir, { recursive: true });
75
+ if (existsSync(path)) {
76
+ return {
77
+ ...readPendingOrgCreate(
78
+ path,
79
+ input.accountId,
80
+ input.sourceOrgId,
81
+ input.name
82
+ ),
83
+ path
84
+ };
85
+ }
86
+ const pending = {
87
+ accountId: input.accountId,
88
+ sourceOrgId: input.sourceOrgId,
89
+ name: input.name,
90
+ idempotencyKey: randomUUID()
91
+ };
92
+ try {
93
+ writeFileSync(path, `${JSON.stringify(pending)}
94
+ `, {
95
+ encoding: "utf8",
96
+ flag: "wx",
97
+ mode: 384
98
+ });
99
+ return { ...pending, path };
100
+ } catch (error) {
101
+ if (error.code !== "EEXIST") throw error;
102
+ return {
103
+ ...readPendingOrgCreate(
104
+ path,
105
+ input.accountId,
106
+ input.sourceOrgId,
107
+ input.name
108
+ ),
109
+ path
110
+ };
111
+ }
112
+ }
113
+ async function fetchWorkspaceCreationIdentity(http, apiKey) {
114
+ const status = await http.post("/api/v2/auth/cli/status", { api_key: apiKey });
115
+ const accountId = status.user_id?.trim();
116
+ if (!accountId) {
117
+ throw new Error(
118
+ "Workspace creation requires an API key linked to a user account."
119
+ );
120
+ }
121
+ return { accountId, orgId: status.org_id?.trim() || null };
122
+ }
123
+ async function fetchOrganizations(http, apiKey) {
124
+ return http.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
125
+ }
126
+ function normalizeAuthScope(value) {
127
+ if (!value) return "auto";
128
+ if (value === "auto" || value === "folder" || value === "global") {
129
+ return value;
130
+ }
131
+ throw new Error(
132
+ `Invalid --auth-scope "${value}". Expected one of: auto, folder, global.`
133
+ );
134
+ }
135
+ function orgListLines(orgs) {
136
+ return orgs.map((org, index) => {
137
+ const current = org.is_current ? " (current)" : "";
138
+ const role = org.role ? ` [${org.role}]` : "";
139
+ return `${index + 1}. ${org.name}${role}${current}`;
140
+ });
141
+ }
142
+ function redactApiKey(value) {
143
+ if (!value) return null;
144
+ if (value.length <= 10) return `${value.slice(0, 3)}...`;
145
+ return `${value.slice(0, 8)}...${value.slice(-4)}`;
146
+ }
147
+ function processEnvValue(name) {
148
+ return process.env[name]?.trim() ?? "";
149
+ }
150
+ function organizationAuthValues(input) {
151
+ return {
152
+ [HOST_URL_ENV]: input.baseUrl,
153
+ [API_KEY_ENV]: input.apiKey,
154
+ [ACTIVE_ORG_ID_ENV]: input.orgId,
155
+ [ACTIVE_ORG_NAME_ENV]: input.orgName,
156
+ ...featureEnvValues(input)
157
+ };
158
+ }
159
+ function organizationCommandContext(input) {
160
+ return {
161
+ active_organization: {
162
+ org_id: input.orgId,
163
+ org_name: input.orgName
164
+ },
165
+ auth_scope: input.authScope,
166
+ metadata_source: input.authScope === "folder" ? "folder_env" : "host_env"
167
+ };
168
+ }
169
+ function agentCommandContext(commandContext) {
170
+ return detectAgentRuntime() !== "unknown" ? { command_context: commandContext } : {};
171
+ }
172
+ function resolveOrgSwitchAuthTarget(scope, config) {
173
+ const activeProject = getResolvedProjectAuthSource(
174
+ config.baseUrl,
175
+ config.apiKey
176
+ );
177
+ const folderTarget = resolveProjectPinTarget();
178
+ const globalOverrideWarning = activeProject && scope === "global" ? [
179
+ `Folder auth in ${activeProject.filePath} overrides global auth for commands run here.`
180
+ ] : [];
181
+ if (scope === "folder") {
182
+ if (!folderTarget.ok) {
183
+ throw new Error(
184
+ `Cowork project folder is ambiguous. Candidate folders: ${folderTarget.candidates.join(
185
+ ", "
186
+ )}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder before running this command.`
187
+ );
188
+ }
189
+ return {
190
+ kind: "folder",
191
+ requested_scope: scope,
192
+ effective_scope: "folder",
193
+ reason: "explicit_folder",
194
+ source: folderTarget.source,
195
+ warnings: []
196
+ };
197
+ }
198
+ if (scope === "global") {
199
+ return {
200
+ kind: "global",
201
+ requested_scope: scope,
202
+ effective_scope: "global",
203
+ reason: "explicit_global",
204
+ warnings: globalOverrideWarning
205
+ };
206
+ }
207
+ if (activeProject) {
208
+ return {
209
+ kind: "folder",
210
+ requested_scope: scope,
211
+ effective_scope: "folder",
212
+ reason: "existing_folder_auth",
213
+ source: activeProject.source,
214
+ warnings: []
215
+ };
216
+ }
217
+ if (folderTarget.ok && folderTarget.source === "cowork") {
218
+ return {
219
+ kind: "folder",
220
+ requested_scope: scope,
221
+ effective_scope: "folder",
222
+ reason: "detected_cowork_project",
223
+ source: "cowork",
224
+ warnings: []
225
+ };
226
+ }
227
+ if (!folderTarget.ok) {
228
+ return {
229
+ kind: "global",
230
+ requested_scope: scope,
231
+ effective_scope: "global",
232
+ reason: "ambiguous_cowork_fell_back_global",
233
+ warnings: [
234
+ `Cowork project folder is ambiguous, so global auth was updated. Candidate folders: ${folderTarget.candidates.join(
235
+ ", "
236
+ )}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder to update folder auth.`
237
+ ]
238
+ };
239
+ }
240
+ return {
241
+ kind: "global",
242
+ requested_scope: scope,
243
+ effective_scope: "global",
244
+ reason: "default_global",
245
+ warnings: []
246
+ };
247
+ }
248
+ async function handleOrgList(options) {
249
+ const config = resolveConfig();
250
+ const http = new HttpClient(config);
251
+ const payload = await fetchOrganizations(http, config.apiKey);
252
+ printCommandEnvelope(
253
+ {
254
+ ...payload,
255
+ render: {
256
+ sections: [
257
+ {
258
+ title: "Your organizations:",
259
+ lines: orgListLines(payload.organizations)
260
+ }
261
+ ]
262
+ }
263
+ },
264
+ { json: options.json }
265
+ );
266
+ }
267
+ async function handleOrgStatus(options) {
268
+ const config = resolveConfig();
269
+ const http = new HttpClient(config);
270
+ const payload = await fetchOrganizations(http, config.apiKey);
271
+ const current = payload.organizations.find((org) => org.is_current) ?? payload.organizations.find(
272
+ (org) => org.org_id === payload.current_org_id
273
+ ) ?? null;
274
+ const projectCandidate = getActiveProjectAuthSource();
275
+ const activeProject = getResolvedProjectAuthSource(
276
+ config.baseUrl,
277
+ config.apiKey
278
+ );
279
+ const folderTarget = resolveProjectPinTarget();
280
+ const provenance = resolveCliAuthProvenance(config);
281
+ const hostPath = hostEnvFilePath(config.baseUrl);
282
+ const envApiKey = processEnvValue(API_KEY_ENV);
283
+ const envHostUrl = processEnvValue(HOST_URL_ENV);
284
+ const authSource = envApiKey ? {
285
+ scope: "env",
286
+ source: "process",
287
+ path: null,
288
+ api_key: redactApiKey(envApiKey),
289
+ host: envHostUrl || null,
290
+ overrides_global: true,
291
+ overrides_folder: Boolean(projectCandidate)
292
+ } : activeProject ? {
293
+ scope: "folder",
294
+ source: activeProject.source,
295
+ path: activeProject.filePath,
296
+ api_key: redactApiKey(activeProject.env.DEEPLINE_API_KEY),
297
+ overrides_global: true
298
+ } : {
299
+ scope: "global",
300
+ source: "host",
301
+ path: hostPath,
302
+ api_key: redactApiKey(config.apiKey),
303
+ overrides_global: false
304
+ };
305
+ const folderTargetPayload = folderTarget.ok ? {
306
+ ok: true,
307
+ source: folderTarget.source,
308
+ dir: folderTarget.dir,
309
+ env_path: `${folderTarget.dir}/.env.deepline`
310
+ } : {
311
+ ok: false,
312
+ reason: folderTarget.reason,
313
+ candidates: folderTarget.candidates
314
+ };
315
+ const lines = [
316
+ `Organization: ${current?.name ?? "(unknown)"}`,
317
+ `Host: ${config.baseUrl}`,
318
+ `Auth scope: ${authSource.scope}`
319
+ ];
320
+ if (authSource.path) {
321
+ lines.push(`Auth file: ${authSource.path}`);
322
+ } else {
323
+ lines.push(`Auth source: ${API_KEY_ENV} process environment`);
324
+ }
325
+ if (envApiKey) {
326
+ lines.push(`${API_KEY_ENV} overrides saved auth for this process.`);
327
+ } else if (activeProject) {
328
+ lines.push("Global auth is overridden in this folder.");
329
+ } else if (provenance.scope === "global" && provenance.project.state === "project") {
330
+ lines.push("Cloud mutations are blocked until this project is pinned.");
331
+ lines.push("Pin it: deepline org set --auth-scope folder");
332
+ }
333
+ printCommandEnvelope(
334
+ {
335
+ ok: true,
336
+ host: config.baseUrl,
337
+ organization: current,
338
+ current_org_id: payload.current_org_id,
339
+ auth_source: authSource,
340
+ host_env_path: hostPath,
341
+ folder_target: folderTargetPayload,
342
+ project_pin: provenance.scope === "global" && provenance.project.state === "project" ? {
343
+ available: true,
344
+ required: false,
345
+ path: provenance.project.pinPath,
346
+ cloud_mutations_blocked: false,
347
+ command: "deepline org set --auth-scope folder"
348
+ } : {
349
+ available: false,
350
+ required: false,
351
+ cloud_mutations_blocked: false
352
+ },
353
+ next: {
354
+ set_auto: "deepline org set <org>",
355
+ set_folder: "deepline org set <org> --auth-scope folder",
356
+ set_global: "deepline org set <org> --auth-scope global"
357
+ },
358
+ render: {
359
+ sections: [{ title: "org status", lines }]
360
+ }
361
+ },
362
+ { json: options.json }
363
+ );
364
+ }
365
+ async function handleOrgSwitch(selection, options) {
366
+ const authScope = normalizeAuthScope(options.authScope);
367
+ const config = resolveConfig();
368
+ const provenance = resolveCliAuthProvenance(config);
369
+ if (!selection && !options.orgId && authScope === "folder" && provenance.scope === "global" && provenance.project.state === "project") {
370
+ const commandContext = resolveCliCommandContext(config);
371
+ const activeOrganization = commandContext.active_organization;
372
+ const pinnedFeatures = storedHostFeatures(config.baseUrl);
373
+ const project_env_paths2 = saveProjectDeeplineEnvValues(
374
+ {
375
+ [HOST_URL_ENV]: config.baseUrl,
376
+ [API_KEY_ENV]: config.apiKey,
377
+ ...activeOrganization ? {
378
+ [ACTIVE_ORG_ID_ENV]: activeOrganization.org_id,
379
+ [ACTIVE_ORG_NAME_ENV]: activeOrganization.org_name ?? ""
380
+ } : {},
381
+ ...pinnedFeatures !== void 0 ? { [FEATURES_ENV]: pinnedFeatures } : {}
382
+ },
383
+ provenance.project.dir
384
+ );
385
+ printCommandEnvelope(
386
+ {
387
+ ok: true,
388
+ unchanged: true,
389
+ requested_auth_scope: "folder",
390
+ effective_auth_scope: "folder",
391
+ auth_scope: "folder",
392
+ ...agentCommandContext(
393
+ activeOrganization ? organizationCommandContext({
394
+ orgId: activeOrganization.org_id,
395
+ orgName: activeOrganization.org_name,
396
+ authScope: "folder"
397
+ }) : resolveCliCommandContext(config, "folder")
398
+ ),
399
+ project_env_paths: project_env_paths2,
400
+ next: { status: "deepline org status --json" },
401
+ render: {
402
+ sections: [
403
+ {
404
+ title: "org set",
405
+ lines: [
406
+ "\u2713 Pinned this project to the current target.",
407
+ `Saved folder auth in ${project_env_paths2[0]}.`,
408
+ "Global host auth was not changed."
409
+ ]
410
+ }
411
+ ]
412
+ }
413
+ },
414
+ { json: options.json }
415
+ );
416
+ return;
417
+ }
418
+ const http = new HttpClient(config);
419
+ const payload = await fetchOrganizations(http, config.apiKey);
420
+ if (!selection && !options.orgId) {
421
+ printCommandEnvelope(
422
+ {
423
+ ...payload,
424
+ next: { set: "deepline org set <number>" },
425
+ deprecated_command: options.deprecatedSwitch ? "org switch" : null,
426
+ replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
427
+ warnings: options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
428
+ render: {
429
+ sections: [
430
+ {
431
+ title: "Your organizations:",
432
+ lines: orgListLines(payload.organizations)
433
+ }
434
+ ],
435
+ actions: [{ label: "Run", command: "deepline org set <number>" }]
436
+ }
437
+ },
438
+ { json: options.json }
439
+ );
440
+ return;
441
+ }
442
+ let target = payload.organizations.find(
443
+ (org) => org.org_id === options.orgId
444
+ );
445
+ if (!target && selection) {
446
+ const index = Number.parseInt(selection, 10);
447
+ if (Number.isFinite(index) && index >= 1 && index <= payload.organizations.length) {
448
+ target = payload.organizations[index - 1];
449
+ } else {
450
+ target = payload.organizations.find(
451
+ (org) => org.name === selection || org.org_id === selection
452
+ );
453
+ }
454
+ }
455
+ if (!target) {
456
+ throw new Error("Could not resolve the selected organization.");
457
+ }
458
+ const authTarget = resolveOrgSwitchAuthTarget(authScope, config);
459
+ if (target.is_current) {
460
+ let project_env_paths2 = [];
461
+ const features = await http.post("/api/v2/auth/cli/status", {
462
+ api_key: config.apiKey
463
+ }).then((status) => status.features).catch(() => void 0);
464
+ const authValues2 = organizationAuthValues({
465
+ baseUrl: config.baseUrl,
466
+ apiKey: config.apiKey,
467
+ orgId: target.org_id,
468
+ orgName: target.name,
469
+ features
470
+ });
471
+ if (authTarget.kind === "folder") {
472
+ project_env_paths2 = saveProjectDeeplineEnvValues(authValues2);
473
+ } else {
474
+ saveHostEnvValues(config.baseUrl, authValues2);
475
+ }
476
+ const renderLines2 = [`Already on ${target.name}.`];
477
+ for (const projectPath of project_env_paths2) {
478
+ renderLines2.push(`Saved folder auth in ${projectPath}`);
479
+ }
480
+ if (authTarget.kind === "global") {
481
+ renderLines2.push(
482
+ `Saved global auth in ${hostEnvFilePath(config.baseUrl)}`
483
+ );
484
+ }
485
+ renderLines2.push(
486
+ `Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
487
+ );
488
+ if (options.deprecatedSwitch) {
489
+ renderLines2.push("Warning: org switch is deprecated; use org set.");
490
+ }
491
+ for (const warning of authTarget.warnings) {
492
+ renderLines2.push(`Warning: ${warning}`);
493
+ }
494
+ const warnings2 = [
495
+ ...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
496
+ ...authTarget.warnings
497
+ ];
498
+ printCommandEnvelope(
499
+ {
500
+ ok: true,
501
+ unchanged: true,
502
+ organization: target,
503
+ requested_auth_scope: authTarget.requested_scope,
504
+ effective_auth_scope: authTarget.effective_scope,
505
+ auth_scope_reason: authTarget.reason,
506
+ auth_scope: authTarget.effective_scope,
507
+ ...agentCommandContext(
508
+ organizationCommandContext({
509
+ orgId: target.org_id,
510
+ orgName: target.name,
511
+ authScope: authTarget.effective_scope
512
+ })
513
+ ),
514
+ host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
515
+ project_env_paths: project_env_paths2,
516
+ deprecated_command: options.deprecatedSwitch ? "org switch" : null,
517
+ replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
518
+ warnings: warnings2,
519
+ render: {
520
+ sections: [{ title: "org set", lines: renderLines2 }]
521
+ }
522
+ },
523
+ { json: options.json }
524
+ );
525
+ return;
526
+ }
527
+ const switched = await http.post("/api/v2/auth/cli/switch", {
528
+ api_key: config.apiKey,
529
+ org_id: target.org_id
530
+ });
531
+ let project_env_paths = [];
532
+ const authValues = organizationAuthValues({
533
+ baseUrl: config.baseUrl,
534
+ apiKey: switched.api_key,
535
+ orgId: switched.org_id,
536
+ orgName: switched.org_name,
537
+ features: switched.features
538
+ });
539
+ if (authTarget.kind === "folder") {
540
+ project_env_paths = saveProjectDeeplineEnvValues(authValues);
541
+ } else {
542
+ saveHostEnvValues(config.baseUrl, authValues);
543
+ }
544
+ const { api_key: _apiKey, ...publicSwitched } = switched;
545
+ const renderLines = [`Switched to ${switched.org_name}.`];
546
+ if (authTarget.kind === "folder") {
547
+ for (const projectPath of project_env_paths) {
548
+ renderLines.push(`Saved folder auth in ${projectPath}`);
549
+ }
550
+ } else {
551
+ renderLines.push(`Saved global auth in ${hostEnvFilePath(config.baseUrl)}`);
552
+ }
553
+ renderLines.push(
554
+ `Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
555
+ );
556
+ if (options.deprecatedSwitch) {
557
+ renderLines.push("Warning: org switch is deprecated; use org set.");
558
+ }
559
+ for (const warning of authTarget.warnings) {
560
+ renderLines.push(`Warning: ${warning}`);
561
+ }
562
+ const warnings = [
563
+ ...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
564
+ ...authTarget.warnings
565
+ ];
566
+ printCommandEnvelope(
567
+ {
568
+ ok: true,
569
+ host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
570
+ project_env_paths,
571
+ ...publicSwitched,
572
+ api_key_saved: true,
573
+ requested_auth_scope: authTarget.requested_scope,
574
+ effective_auth_scope: authTarget.effective_scope,
575
+ auth_scope_reason: authTarget.reason,
576
+ auth_scope: authTarget.effective_scope,
577
+ ...agentCommandContext(
578
+ organizationCommandContext({
579
+ orgId: switched.org_id,
580
+ orgName: switched.org_name,
581
+ authScope: authTarget.effective_scope
582
+ })
583
+ ),
584
+ deprecated_command: options.deprecatedSwitch ? "org switch" : null,
585
+ replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
586
+ warnings,
587
+ render: {
588
+ sections: [
589
+ {
590
+ title: "org set",
591
+ lines: renderLines
592
+ }
593
+ ]
594
+ }
595
+ },
596
+ { json: options.json }
597
+ );
598
+ }
599
+ async function handleOrgCreate(name, options) {
600
+ const config = resolveConfig();
601
+ const normalizedName = name.trim();
602
+ if (!normalizedName) {
603
+ throw new Error("Workspace name is required.");
604
+ }
605
+ const http = new HttpClient(config);
606
+ const identity = await fetchWorkspaceCreationIdentity(http, config.apiKey);
607
+ let created;
608
+ let workspaceApiKey;
609
+ let workspaceFeatures;
610
+ let pendingIntentPath = null;
611
+ if (!identity.orgId) {
612
+ const firstWorkspace = await http.post("/api/v2/auth/cli/org-create", {
613
+ api_key: config.apiKey,
614
+ name: normalizedName
615
+ });
616
+ const {
617
+ api_key: apiKey,
618
+ features,
619
+ ...publicFirstWorkspace
620
+ } = firstWorkspace;
621
+ workspaceApiKey = apiKey;
622
+ workspaceFeatures = features;
623
+ created = publicFirstWorkspace;
624
+ } else {
625
+ const pending = loadOrCreatePendingOrgCreate({
626
+ baseUrl: config.baseUrl,
627
+ accountId: identity.accountId,
628
+ sourceOrgId: identity.orgId,
629
+ name: normalizedName
630
+ });
631
+ const workspace = await new DeeplineClient({
632
+ apiKey: config.apiKey,
633
+ baseUrl: config.baseUrl
634
+ }).workspaces.create({
635
+ name: normalizedName,
636
+ idempotencyKey: pending.idempotencyKey
637
+ });
638
+ const switched = await http.post("/api/v2/auth/cli/switch", {
639
+ api_key: config.apiKey,
640
+ org_id: workspace.org_id
641
+ });
642
+ workspaceApiKey = switched.api_key;
643
+ workspaceFeatures = switched.features;
644
+ created = { ...workspace };
645
+ pendingIntentPath = pending.path;
646
+ }
647
+ const authValues = organizationAuthValues({
648
+ baseUrl: config.baseUrl,
649
+ apiKey: workspaceApiKey,
650
+ orgId: created.org_id,
651
+ orgName: created.org_name,
652
+ features: workspaceFeatures
653
+ });
654
+ saveHostEnvValues(config.baseUrl, authValues);
655
+ if (pendingIntentPath) unlinkSync(pendingIntentPath);
656
+ printCommandEnvelope(
657
+ {
658
+ ok: true,
659
+ ...created,
660
+ initial_credits: typeof created.initial_credits === "number" ? created.initial_credits : 0,
661
+ api_key_saved: true,
662
+ switched: true,
663
+ host_env_path: hostEnvFilePath(config.baseUrl),
664
+ ...agentCommandContext(
665
+ organizationCommandContext({
666
+ orgId: created.org_id,
667
+ orgName: created.org_name,
668
+ authScope: "global"
669
+ })
670
+ ),
671
+ render: {
672
+ sections: [
673
+ {
674
+ title: "org create",
675
+ lines: [
676
+ `Created organization: ${created.org_name}.`,
677
+ `Switched to ${created.org_name}.`,
678
+ `Saved host auth in ${hostEnvFilePath(config.baseUrl)}`
679
+ ]
680
+ }
681
+ ]
682
+ }
683
+ },
684
+ { json: options.json }
685
+ );
686
+ }
687
+ function registerOrgCommands(program) {
688
+ const org = program.command("org").description("List, create, and set organizations.").addHelpText(
689
+ "after",
690
+ `
691
+ Notes:
692
+ Organizations are workspaces. Auth is stored as an API key scoped to one
693
+ organization, so setting an org saves a key for the selected auth scope.
694
+
695
+ Auth scopes:
696
+ auto Update the folder pin that already controls this command; in
697
+ Cowork, write the mounted project folder; otherwise update global
698
+ host auth.
699
+ folder Write .env.deepline in the current project/Cowork project and make
700
+ sure .env.deepline is gitignored. Commands below that folder use
701
+ this org; sibling folders can pin different orgs.
702
+ global Write ~/.local/deepline/<host>/.env. Commands outside folder pins
703
+ use this org. Existing folder pins still override global auth.
704
+
705
+ Process env DEEPLINE_API_KEY overrides saved auth for that command only.
706
+ For projects, agents, CI, and multiple customer workspaces, prefer folder
707
+ scope or a per-command DEEPLINE_API_KEY. Global scope is machine-wide and
708
+ can make an unrelated terminal target the last-selected organization.
709
+
710
+ Agent loop:
711
+ deepline org list --json
712
+ deepline org set <number-or-org-id> --auth-scope folder --json
713
+ deepline org status --json
714
+ deepline auth status --json
715
+
716
+ Examples:
717
+ deepline org list --json
718
+ deepline org status --json
719
+ deepline org create Acme --json
720
+ deepline org set 2
721
+ deepline org set 2 --auth-scope folder
722
+ deepline org set --org-id org_123 --json
723
+ cd path/to/project-a && deepline org set Prove --auth-scope folder --json
724
+ cd path/to/project-b && deepline org set Mixmax --auth-scope folder --json
725
+ cd .. && deepline org status --json
726
+ `
727
+ );
728
+ org.command("list").description("List your organizations.").addHelpText(
729
+ "after",
730
+ `
731
+ Notes:
732
+ Read-only. Marks the active organization when the server returns that metadata.
733
+
734
+ Examples:
735
+ deepline org list
736
+ deepline org list --json
737
+ `
738
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgList);
739
+ org.command("create <name>").description("Create a new organization and switch this CLI to it.").addHelpText(
740
+ "after",
741
+ `
742
+ Notes:
743
+ Mutates workspace and billing state. The new organization is created for the
744
+ current authenticated user and provisioned on the active PAYG offer before
745
+ this CLI switches to it. Interrupted requests resume automatically.
746
+
747
+ Examples:
748
+ deepline org create Acme
749
+ deepline org create "Acme Sales" --json
750
+ `
751
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgCreate);
752
+ org.command("status").description("Show the current organization and auth source.").addHelpText(
753
+ "after",
754
+ `
755
+ Notes:
756
+ Read-only. Shows the current org plus auth_source.scope, auth_source.path,
757
+ folder_target, host_env_path, and next commands.
758
+
759
+ Scopes are env, folder, or global. env means DEEPLINE_API_KEY/
760
+ DEEPLINE_HOST_URL in process env wins. folder means nearest/Cowork
761
+ .env.deepline wins. global means host config wins.
762
+
763
+ Run before and after org set to verify what future commands will use.
764
+
765
+ Examples:
766
+ deepline org status
767
+ deepline org status --json
768
+ `
769
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgStatus);
770
+ const addOrgSetOptions = (command) => command.option("--org-id <id>", "Set using an explicit organization id").option(
771
+ "--auth-scope <scope>",
772
+ "Where to save auth: auto, folder, or global",
773
+ "auto"
774
+ ).option(
775
+ "--json",
776
+ "Emit JSON output. Also automatic when stdout is piped"
777
+ );
778
+ addOrgSetOptions(
779
+ org.command("set [selection]").description("Set the organization for the selected auth scope.").addHelpText(
780
+ "after",
781
+ `
782
+ Notes:
783
+ Selection can be a list number, exact organization name, or organization id.
784
+ Without a selection, prints choices. With --auth-scope folder while this
785
+ project is using global host auth, it pins the current target directly
786
+ without an additional organization lookup.
787
+
788
+ Mutates local auth state and asks Deepline for an org-scoped API key. It
789
+ writes only the selected scope:
790
+ auto Update the folder pin that already controls this command; in
791
+ Cowork, write the mounted project folder; otherwise update global
792
+ host auth.
793
+ folder Write .env.deepline in the current project/Cowork project and make
794
+ sure .env.deepline is gitignored.
795
+ global Write ~/.local/deepline/<host>/.env.
796
+
797
+ Folder auth shadows global auth. If you set --auth-scope global from a pinned
798
+ folder, commands in that folder still use the folder pin until it is changed
799
+ or removed.
800
+
801
+ Prefer --auth-scope folder for a repository or customer workspace. Use
802
+ --auth-scope global only for deliberate host-wide interactive defaults; it
803
+ is shared by every unpinned CLI on this machine. Global auth remains
804
+ supported in projects; use a folder pin when you want a project-specific
805
+ default. For automation, pass
806
+ DEEPLINE_API_KEY only to that invocation and confirm with org status --json.
807
+
808
+ Use --json for stable fields including effective_auth_scope,
809
+ auth_scope_reason, host_env_path, project_env_paths, warnings, org_id, and
810
+ org_name.
811
+
812
+ Examples:
813
+ deepline org set
814
+ deepline org set 2
815
+ deepline org set 2 --auth-scope folder
816
+ deepline org set 2 --auth-scope global
817
+ deepline org set --org-id org_123 --json
818
+ deepline org status --json
819
+ `
820
+ )
821
+ ).action(handleOrgSwitch);
822
+ addOrgSetOptions(
823
+ org.command("switch [selection]", { hidden: true }).description(
824
+ "Deprecated alias for org set. Set the organization for the selected auth scope."
825
+ ).addHelpText(
826
+ "after",
827
+ `
828
+ Notes:
829
+ Deprecated alias. Use deepline org set instead. The command still mutates
830
+ local auth state with the same --auth-scope behavior as org set.
831
+
832
+ Run deepline org set --help for scope definitions and the agent verification
833
+ loop.
834
+
835
+ Examples:
836
+ deepline org switch
837
+ deepline org switch 2
838
+ deepline org switch 2 --auth-scope folder
839
+ deepline org switch 2 --auth-scope global
840
+ deepline org switch --org-id org_123 --json
841
+ `
842
+ )
843
+ ).action(
844
+ (selection, options) => handleOrgSwitch(selection, { ...options, deprecatedSwitch: true })
845
+ );
846
+ }
847
+ export {
848
+ registerOrgCommands
849
+ };