deepline 0.1.143 → 0.1.145
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.
- package/README.md +2 -2
- package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +36 -4
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +5 -2
- package/dist/bundling-sources/sdk/src/client.ts +5 -0
- package/dist/bundling-sources/sdk/src/config.ts +310 -13
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/shared_libs/temporal/constants.ts +4 -3
- package/dist/cli/index.js +865 -82
- package/dist/cli/index.mjs +889 -98
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +151 -14
- package/dist/index.mjs +160 -15
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -164,7 +164,15 @@ import { tmpdir as tmpdir4 } from "os";
|
|
|
164
164
|
import { Command as Command3 } from "commander";
|
|
165
165
|
|
|
166
166
|
// src/config.ts
|
|
167
|
-
import {
|
|
167
|
+
import {
|
|
168
|
+
existsSync,
|
|
169
|
+
mkdirSync,
|
|
170
|
+
readdirSync,
|
|
171
|
+
realpathSync,
|
|
172
|
+
readFileSync,
|
|
173
|
+
statSync,
|
|
174
|
+
writeFileSync
|
|
175
|
+
} from "fs";
|
|
168
176
|
import { homedir } from "os";
|
|
169
177
|
import { dirname, join, resolve } from "path";
|
|
170
178
|
|
|
@@ -214,6 +222,22 @@ var PROD_URL = "https://code.deepline.com";
|
|
|
214
222
|
var DEFAULT_TIMEOUT = 6e4;
|
|
215
223
|
var DEFAULT_MAX_RETRIES = 3;
|
|
216
224
|
var PROJECT_DEEPLINE_ENV_FILE = ".env.deepline";
|
|
225
|
+
var COWORK_IGNORED_WORKSPACE_DIRS = /* @__PURE__ */ new Set([
|
|
226
|
+
".auto-memory",
|
|
227
|
+
".claude",
|
|
228
|
+
".remote-plugins",
|
|
229
|
+
"outputs",
|
|
230
|
+
"plugins",
|
|
231
|
+
"uploads"
|
|
232
|
+
]);
|
|
233
|
+
var COWORK_PROJECT_MARKERS = [
|
|
234
|
+
".deepline",
|
|
235
|
+
".env.deepline",
|
|
236
|
+
".git",
|
|
237
|
+
"AGENTS.md",
|
|
238
|
+
"package.json",
|
|
239
|
+
"pyproject.toml"
|
|
240
|
+
];
|
|
217
241
|
function baseUrlSlug(baseUrl) {
|
|
218
242
|
let url;
|
|
219
243
|
try {
|
|
@@ -259,9 +283,124 @@ function findNearestEnvFile(name, startDir = process.cwd()) {
|
|
|
259
283
|
current = parent;
|
|
260
284
|
}
|
|
261
285
|
}
|
|
262
|
-
function
|
|
263
|
-
|
|
264
|
-
|
|
286
|
+
function isDirectory(path) {
|
|
287
|
+
try {
|
|
288
|
+
return statSync(path).isDirectory();
|
|
289
|
+
} catch {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function canonicalPath(path) {
|
|
294
|
+
try {
|
|
295
|
+
return realpathSync(path);
|
|
296
|
+
} catch {
|
|
297
|
+
return resolve(path);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function isTruthy(value) {
|
|
301
|
+
return /^(1|true|yes|on)$/i.test(value?.trim() ?? "");
|
|
302
|
+
}
|
|
303
|
+
function sessionRootFromPath(path) {
|
|
304
|
+
const trimmed = path?.trim();
|
|
305
|
+
if (!trimmed) return null;
|
|
306
|
+
const match = /^\/sessions\/[^/]+(?=\/|$)/.exec(trimmed);
|
|
307
|
+
return match?.[0] ?? null;
|
|
308
|
+
}
|
|
309
|
+
function coworkSessionRoot() {
|
|
310
|
+
const home = process.env.HOME?.trim();
|
|
311
|
+
const homeSessionRoot = sessionRootFromPath(home);
|
|
312
|
+
if (homeSessionRoot && isDirectory(join(homeSessionRoot, "mnt"))) {
|
|
313
|
+
return homeSessionRoot;
|
|
314
|
+
}
|
|
315
|
+
const cwdSessionRoot = sessionRootFromPath(process.cwd());
|
|
316
|
+
if (cwdSessionRoot && isDirectory(join(cwdSessionRoot, "mnt"))) {
|
|
317
|
+
return cwdSessionRoot;
|
|
318
|
+
}
|
|
319
|
+
if (isTruthy(process.env.CLAUDE_CODE_REMOTE) && home) {
|
|
320
|
+
const mountedRoot = join(home, "mnt");
|
|
321
|
+
if (isDirectory(mountedRoot)) return resolve(home);
|
|
322
|
+
}
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
function isCoworkLikeSandbox() {
|
|
326
|
+
const home = process.env.HOME?.trim();
|
|
327
|
+
return isTruthy(process.env.CLAUDE_CODE_REMOTE) || sessionRootFromPath(home) !== null || sessionRootFromPath(process.cwd()) !== null;
|
|
328
|
+
}
|
|
329
|
+
function coworkProjectScore(path) {
|
|
330
|
+
let score = 0;
|
|
331
|
+
for (const marker of COWORK_PROJECT_MARKERS) {
|
|
332
|
+
if (existsSync(join(path, marker))) score += 1;
|
|
333
|
+
}
|
|
334
|
+
return score;
|
|
335
|
+
}
|
|
336
|
+
function listCoworkWorkspaceDirCandidates() {
|
|
337
|
+
if (!isCoworkLikeSandbox()) {
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
340
|
+
const explicitProjectDir = process.env.CLAUDE_PROJECT_DIR?.trim();
|
|
341
|
+
if (explicitProjectDir && isDirectory(explicitProjectDir)) {
|
|
342
|
+
return [resolve(explicitProjectDir)];
|
|
343
|
+
}
|
|
344
|
+
const sessionRoot = coworkSessionRoot();
|
|
345
|
+
if (!sessionRoot) return [];
|
|
346
|
+
const mountedRoot = join(sessionRoot, "mnt");
|
|
347
|
+
if (!isDirectory(mountedRoot)) return [];
|
|
348
|
+
let names;
|
|
349
|
+
try {
|
|
350
|
+
names = readdirSync(mountedRoot).sort();
|
|
351
|
+
} catch {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
354
|
+
const candidates = [];
|
|
355
|
+
for (const name of names) {
|
|
356
|
+
if (name.startsWith(".") || COWORK_IGNORED_WORKSPACE_DIRS.has(name)) {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
const candidate = join(mountedRoot, name);
|
|
360
|
+
if (isDirectory(candidate)) candidates.push(candidate);
|
|
361
|
+
}
|
|
362
|
+
if (candidates.length <= 1) return candidates;
|
|
363
|
+
const projectLike = candidates.filter(
|
|
364
|
+
(candidate) => coworkProjectScore(candidate) > 0
|
|
365
|
+
);
|
|
366
|
+
return projectLike.length > 0 ? projectLike : candidates;
|
|
367
|
+
}
|
|
368
|
+
function isInIgnoredCoworkMount(path) {
|
|
369
|
+
const sessionRoot = coworkSessionRoot();
|
|
370
|
+
if (!sessionRoot) return false;
|
|
371
|
+
const mountedRoot = canonicalPath(join(sessionRoot, "mnt"));
|
|
372
|
+
const resolvedPath = canonicalPath(path);
|
|
373
|
+
const prefix = `${mountedRoot}/`;
|
|
374
|
+
if (!resolvedPath.startsWith(prefix)) return false;
|
|
375
|
+
const relativePath = resolvedPath.slice(prefix.length);
|
|
376
|
+
const mountName = relativePath.split("/")[0];
|
|
377
|
+
return mountName.startsWith(".") || COWORK_IGNORED_WORKSPACE_DIRS.has(mountName);
|
|
378
|
+
}
|
|
379
|
+
function detectCoworkWorkspaceDir() {
|
|
380
|
+
const candidates = listCoworkWorkspaceDirCandidates();
|
|
381
|
+
return candidates.length === 1 ? candidates[0] : null;
|
|
382
|
+
}
|
|
383
|
+
function loadProjectEnvCandidates(startDir = process.cwd()) {
|
|
384
|
+
const filePaths = [];
|
|
385
|
+
const sources = /* @__PURE__ */ new Map();
|
|
386
|
+
const nearestFile = findNearestEnvFile(PROJECT_DEEPLINE_ENV_FILE, startDir);
|
|
387
|
+
if (nearestFile && !isInIgnoredCoworkMount(nearestFile)) {
|
|
388
|
+
filePaths.push(nearestFile);
|
|
389
|
+
sources.set(resolve(nearestFile), "nearest");
|
|
390
|
+
}
|
|
391
|
+
const coworkWorkspaceDir = detectCoworkWorkspaceDir();
|
|
392
|
+
if (coworkWorkspaceDir) {
|
|
393
|
+
const coworkFile = join(coworkWorkspaceDir, PROJECT_DEEPLINE_ENV_FILE);
|
|
394
|
+
if (existsSync(coworkFile) && !filePaths.some((filePath) => resolve(filePath) === resolve(coworkFile))) {
|
|
395
|
+
filePaths.push(coworkFile);
|
|
396
|
+
sources.set(resolve(coworkFile), "cowork");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return filePaths.map((filePath) => ({
|
|
400
|
+
filePath,
|
|
401
|
+
env: parseEnvFile(filePath),
|
|
402
|
+
source: sources.get(resolve(filePath)) ?? "nearest"
|
|
403
|
+
}));
|
|
265
404
|
}
|
|
266
405
|
function normalizeBaseUrl(baseUrl) {
|
|
267
406
|
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
@@ -325,23 +464,35 @@ function loadGlobalCliEnv() {
|
|
|
325
464
|
return loadCliEnv(PROD_URL);
|
|
326
465
|
}
|
|
327
466
|
function autoDetectBaseUrl() {
|
|
328
|
-
const
|
|
467
|
+
const projectEnvs = loadProjectEnvCandidates();
|
|
329
468
|
const globalEnv = loadGlobalCliEnv();
|
|
330
|
-
return normalizeBaseUrl(process.env[HOST_URL_ENV] ?? "") ||
|
|
469
|
+
return normalizeBaseUrl(process.env[HOST_URL_ENV] ?? "") || firstNonEmpty(
|
|
470
|
+
...projectEnvs.map(({ env }) => normalizeBaseUrl(env[HOST_URL_ENV]))
|
|
471
|
+
) || normalizeBaseUrl(globalEnv[HOST_URL_ENV] ?? "") || PROD_URL;
|
|
331
472
|
}
|
|
332
473
|
function resolveApiKeyForBaseUrl(baseUrl, explicitApiKey) {
|
|
333
474
|
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
334
|
-
const
|
|
475
|
+
const projectEnvs = loadProjectEnvCandidates();
|
|
335
476
|
const cliEnv = loadCliEnv(normalizedBaseUrl || baseUrl);
|
|
336
|
-
const projectBaseUrl = normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "");
|
|
337
|
-
const projectKeyApplies = projectBaseUrl === normalizedBaseUrl;
|
|
338
477
|
return firstNonEmpty(
|
|
339
478
|
explicitApiKey,
|
|
340
479
|
process.env[API_KEY_ENV],
|
|
341
|
-
|
|
480
|
+
...projectEnvs.map(({ env }) => {
|
|
481
|
+
const projectBaseUrl = normalizeBaseUrl(env[HOST_URL_ENV] ?? "");
|
|
482
|
+
return projectBaseUrl === normalizedBaseUrl ? env[API_KEY_ENV] : "";
|
|
483
|
+
}),
|
|
342
484
|
cliEnv[API_KEY_ENV]
|
|
343
485
|
);
|
|
344
486
|
}
|
|
487
|
+
function getResolvedProjectAuthSource(baseUrl, apiKey, startDir = process.cwd()) {
|
|
488
|
+
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
489
|
+
const normalizedApiKey = apiKey.trim();
|
|
490
|
+
if (!normalizedBaseUrl || !normalizedApiKey) return null;
|
|
491
|
+
return loadProjectEnvCandidates(startDir).find(({ env }) => {
|
|
492
|
+
const projectBaseUrl = normalizeBaseUrl(env[HOST_URL_ENV] ?? "");
|
|
493
|
+
return projectBaseUrl === normalizedBaseUrl && (env[API_KEY_ENV] ?? "").trim() === normalizedApiKey;
|
|
494
|
+
}) ?? null;
|
|
495
|
+
}
|
|
345
496
|
function resolveConfig(options) {
|
|
346
497
|
const baseUrl = normalizeBaseUrl(
|
|
347
498
|
options?.baseUrl?.trim() || autoDetectBaseUrl()
|
|
@@ -364,6 +515,69 @@ function resolveConfig(options) {
|
|
|
364
515
|
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES
|
|
365
516
|
};
|
|
366
517
|
}
|
|
518
|
+
function mergeProjectEnvFile(filePath, values) {
|
|
519
|
+
const existing = parseEnvFile(filePath);
|
|
520
|
+
const merged = { ...existing, ...values };
|
|
521
|
+
const dir = dirname(filePath);
|
|
522
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
523
|
+
ensureProjectEnvIsIgnored(dir);
|
|
524
|
+
const allowedKeys = /* @__PURE__ */ new Set([HOST_URL_ENV, API_KEY_ENV]);
|
|
525
|
+
const lines = Object.entries(merged).filter(([key, value]) => allowedKeys.has(key) && value !== "").map(([key, value]) => `${key}=${value}`);
|
|
526
|
+
writeFileSync(filePath, `${lines.join("\n")}
|
|
527
|
+
`, "utf-8");
|
|
528
|
+
}
|
|
529
|
+
function ensureProjectEnvIsIgnored(dir) {
|
|
530
|
+
const gitignorePath = join(dir, ".gitignore");
|
|
531
|
+
const entry = PROJECT_DEEPLINE_ENV_FILE;
|
|
532
|
+
const existing = existsSync(gitignorePath) ? readFileSync(gitignorePath, "utf-8") : "";
|
|
533
|
+
const alreadyIgnored = existing.split(/\r?\n/).map((line) => line.trim()).some((line) => line === entry || line === `/${entry}`);
|
|
534
|
+
if (alreadyIgnored) return;
|
|
535
|
+
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
536
|
+
writeFileSync(gitignorePath, `${existing}${prefix}${entry}
|
|
537
|
+
`, "utf-8");
|
|
538
|
+
}
|
|
539
|
+
function saveProjectDeeplineEnvValues(values, startDir = process.cwd()) {
|
|
540
|
+
const target = resolveProjectPinTarget(startDir);
|
|
541
|
+
if (!target.ok) {
|
|
542
|
+
throw new ConfigError(
|
|
543
|
+
`Cowork project folder is ambiguous. Candidate folders: ${target.candidates.join(
|
|
544
|
+
", "
|
|
545
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder before running this command.`
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
const filePath = join(target.dir, PROJECT_DEEPLINE_ENV_FILE);
|
|
549
|
+
mergeProjectEnvFile(filePath, values);
|
|
550
|
+
return [filePath];
|
|
551
|
+
}
|
|
552
|
+
function resolveProjectPinTarget(startDir = process.cwd()) {
|
|
553
|
+
const nearestFile = findNearestEnvFile(PROJECT_DEEPLINE_ENV_FILE, startDir);
|
|
554
|
+
if (nearestFile && !isInIgnoredCoworkMount(nearestFile)) {
|
|
555
|
+
return { ok: true, dir: dirname(nearestFile), source: "nearest" };
|
|
556
|
+
}
|
|
557
|
+
const coworkCandidates = listCoworkWorkspaceDirCandidates();
|
|
558
|
+
if (coworkCandidates.length === 1) {
|
|
559
|
+
return { ok: true, dir: coworkCandidates[0], source: "cowork" };
|
|
560
|
+
}
|
|
561
|
+
if (coworkCandidates.length > 1) {
|
|
562
|
+
const resolvedStartDir = canonicalPath(startDir);
|
|
563
|
+
const cwdCandidate = coworkCandidates.find((candidate) => {
|
|
564
|
+
const resolvedCandidate = canonicalPath(candidate);
|
|
565
|
+
return resolvedStartDir === resolvedCandidate || resolvedStartDir.startsWith(`${resolvedCandidate}/`);
|
|
566
|
+
});
|
|
567
|
+
if (cwdCandidate) {
|
|
568
|
+
return { ok: true, dir: cwdCandidate, source: "cowork" };
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
ok: false,
|
|
572
|
+
reason: "ambiguous_cowork_project",
|
|
573
|
+
candidates: coworkCandidates
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
return { ok: true, dir: resolve(startDir), source: "cwd" };
|
|
577
|
+
}
|
|
578
|
+
function getActiveProjectAuthSource(startDir = process.cwd()) {
|
|
579
|
+
return loadProjectEnvCandidates(startDir)[0] ?? null;
|
|
580
|
+
}
|
|
367
581
|
|
|
368
582
|
// src/http.ts
|
|
369
583
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
@@ -390,10 +604,10 @@ var SDK_RELEASE = {
|
|
|
390
604
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
391
605
|
// the SDK enrich generator's one-second stale policy.
|
|
392
606
|
// 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
|
|
393
|
-
version: "0.1.
|
|
607
|
+
version: "0.1.145",
|
|
394
608
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
395
609
|
supportPolicy: {
|
|
396
|
-
latest: "0.1.
|
|
610
|
+
latest: "0.1.145",
|
|
397
611
|
minimumSupported: "0.1.53",
|
|
398
612
|
deprecatedBelow: "0.1.53",
|
|
399
613
|
commandMinimumSupported: [
|
|
@@ -484,7 +698,7 @@ function normalizeAgentRuntime(value) {
|
|
|
484
698
|
if (explicit === "gemini_cli") return "gemini";
|
|
485
699
|
return EXPLICIT_AGENT_RUNTIMES.has(explicit) ? explicit : null;
|
|
486
700
|
}
|
|
487
|
-
function
|
|
701
|
+
function isCoworkLikeSandbox2() {
|
|
488
702
|
const pluginMode = truthyEnv("DEEPLINE_PLUGIN_MODE");
|
|
489
703
|
const claudeRemote = truthyEnv("CLAUDE_CODE_REMOTE");
|
|
490
704
|
const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
|
|
@@ -497,7 +711,7 @@ function detectAgentRuntime(options = {}) {
|
|
|
497
711
|
const explicit = normalizeAgentRuntime(process.env.DEEPLINE_AGENT_RUNTIME);
|
|
498
712
|
if (explicit) return explicit;
|
|
499
713
|
if (process.env.CODEX_THREAD_ID?.trim()) return "codex";
|
|
500
|
-
if (options.detectCowork !== false &&
|
|
714
|
+
if (options.detectCowork !== false && isCoworkLikeSandbox2()) {
|
|
501
715
|
return "claude_cowork";
|
|
502
716
|
}
|
|
503
717
|
if (process.env.CLAUDECODE?.trim() === "1") return "claude_code";
|
|
@@ -963,7 +1177,7 @@ function sleep(ms) {
|
|
|
963
1177
|
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
964
1178
|
}
|
|
965
1179
|
function withCoworkNetworkHint(message) {
|
|
966
|
-
if (!
|
|
1180
|
+
if (!isCoworkLikeSandbox2() || message.includes(COWORK_NETWORK_HINT)) {
|
|
967
1181
|
return message;
|
|
968
1182
|
}
|
|
969
1183
|
return `${message}
|
|
@@ -3270,6 +3484,9 @@ var DeeplineClient = class {
|
|
|
3270
3484
|
if (input2.runId?.trim()) {
|
|
3271
3485
|
params.set("runId", input2.runId.trim());
|
|
3272
3486
|
}
|
|
3487
|
+
if (input2.rowMode === "all") {
|
|
3488
|
+
params.set("rowMode", "all");
|
|
3489
|
+
}
|
|
3273
3490
|
return await this.http.get(
|
|
3274
3491
|
`/api/v2/plays/${encodeURIComponent(input2.playName)}/sheet?${params.toString()}`
|
|
3275
3492
|
);
|
|
@@ -7017,9 +7234,9 @@ import { createHash as createHash2 } from "crypto";
|
|
|
7017
7234
|
import {
|
|
7018
7235
|
existsSync as existsSync6,
|
|
7019
7236
|
readFileSync as readFileSync6,
|
|
7020
|
-
readdirSync,
|
|
7021
|
-
realpathSync,
|
|
7022
|
-
statSync as
|
|
7237
|
+
readdirSync as readdirSync2,
|
|
7238
|
+
realpathSync as realpathSync2,
|
|
7239
|
+
statSync as statSync3,
|
|
7023
7240
|
writeFileSync as writeFileSync8
|
|
7024
7241
|
} from "fs";
|
|
7025
7242
|
import { basename, dirname as dirname6, join as join5, resolve as resolve7 } from "path";
|
|
@@ -7030,7 +7247,7 @@ import {
|
|
|
7030
7247
|
closeSync,
|
|
7031
7248
|
openSync,
|
|
7032
7249
|
readSync,
|
|
7033
|
-
statSync,
|
|
7250
|
+
statSync as statSync2,
|
|
7034
7251
|
writeFileSync as writeFileSync7
|
|
7035
7252
|
} from "fs";
|
|
7036
7253
|
import { isAbsolute, relative, resolve as resolve6 } from "path";
|
|
@@ -7463,7 +7680,7 @@ function inferCsvColumnSpecs(headers, rows) {
|
|
|
7463
7680
|
}
|
|
7464
7681
|
function readCsvSample(csvPath) {
|
|
7465
7682
|
const resolvedPath = resolve6(csvPath);
|
|
7466
|
-
const size =
|
|
7683
|
+
const size = statSync2(resolvedPath).size;
|
|
7467
7684
|
const fd = openSync(resolvedPath, "r");
|
|
7468
7685
|
const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
|
|
7469
7686
|
const buffer = Buffer.alloc(byteLength);
|
|
@@ -9499,7 +9716,7 @@ function preflightLocalFileInputs(runtimeInput) {
|
|
|
9499
9716
|
}
|
|
9500
9717
|
let stat2;
|
|
9501
9718
|
try {
|
|
9502
|
-
stat2 =
|
|
9719
|
+
stat2 = statSync3(absolutePath);
|
|
9503
9720
|
} catch (error) {
|
|
9504
9721
|
throw new DeeplineError(
|
|
9505
9722
|
`Input ${ref.inputPath} references a local file that is not readable: ${ref.value} (${error instanceof Error ? error.message : String(error)}). No run was created.`,
|
|
@@ -9651,7 +9868,7 @@ function stageFile(logicalPath, absolutePath) {
|
|
|
9651
9868
|
}
|
|
9652
9869
|
function normalizePlayPath(filePath) {
|
|
9653
9870
|
try {
|
|
9654
|
-
return
|
|
9871
|
+
return realpathSync2.native(resolve7(filePath));
|
|
9655
9872
|
} catch {
|
|
9656
9873
|
return resolve7(filePath);
|
|
9657
9874
|
}
|
|
@@ -11749,7 +11966,8 @@ async function fetchBackingDatasetRows(input2) {
|
|
|
11749
11966
|
tableNamespace,
|
|
11750
11967
|
runId: input2.status.runId,
|
|
11751
11968
|
limit: RUN_EXPORT_PAGE_SIZE,
|
|
11752
|
-
offset
|
|
11969
|
+
offset,
|
|
11970
|
+
rowMode: "all"
|
|
11753
11971
|
});
|
|
11754
11972
|
sheetRows.push(...page.rows);
|
|
11755
11973
|
const summaryTotal = page.summary?.stats?.total;
|
|
@@ -12913,7 +13131,7 @@ async function handlePlayRun(args) {
|
|
|
12913
13131
|
if (existsSync6(dir)) {
|
|
12914
13132
|
const base = basename(resolved);
|
|
12915
13133
|
try {
|
|
12916
|
-
const siblings =
|
|
13134
|
+
const siblings = readdirSync2(dir).filter(
|
|
12917
13135
|
(f) => f.includes(base.replace(/\.(play\.)?ts$/, "")) || f.endsWith(".play.ts")
|
|
12918
13136
|
);
|
|
12919
13137
|
if (siblings.length > 0) {
|
|
@@ -16089,8 +16307,10 @@ function helperSource() {
|
|
|
16089
16307
|
|
|
16090
16308
|
// src/cli/commands/enrich.ts
|
|
16091
16309
|
var ENRICH_EXPORT_PAGE_SIZE = 5e3;
|
|
16310
|
+
var ENRICH_AUTO_BATCH_ROWS = 250;
|
|
16092
16311
|
var EXIT_SERVER2 = 5;
|
|
16093
16312
|
var ENRICH_DEBUG_T0 = Date.now();
|
|
16313
|
+
var GENERATED_ENRICH_ROWS_TABLE_NAMESPACE = "deepline_enrich_rows";
|
|
16094
16314
|
var PLAN_SHAPING_OPTION_NAMES = [
|
|
16095
16315
|
"with",
|
|
16096
16316
|
"withWaterfall",
|
|
@@ -16754,7 +16974,12 @@ async function runGeneratedEnrichPlay(runArgs, options = {}) {
|
|
|
16754
16974
|
async function writeOutputCsv(outputPath, status, options) {
|
|
16755
16975
|
let rowsInfo = extractCanonicalRowsInfo(status);
|
|
16756
16976
|
if (!rowsInfo) {
|
|
16757
|
-
|
|
16977
|
+
rowsInfo = fallbackRowsInfoForGeneratedEnrichExport(status, options);
|
|
16978
|
+
}
|
|
16979
|
+
if (!rowsInfo) {
|
|
16980
|
+
throw new Error(
|
|
16981
|
+
"The generated play did not return row-shaped output, and no durable enrich rows were available to export."
|
|
16982
|
+
);
|
|
16758
16983
|
}
|
|
16759
16984
|
if (options?.client) {
|
|
16760
16985
|
rowsInfo = await fetchBackingRowsForCsvExport({
|
|
@@ -16817,6 +17042,98 @@ function extractPlayName2(status) {
|
|
|
16817
17042
|
}
|
|
16818
17043
|
return null;
|
|
16819
17044
|
}
|
|
17045
|
+
function selectedSourceCsvRange(sourceCsvPath, rows) {
|
|
17046
|
+
const sourceRows = readCsvRows(sourceCsvPath).length;
|
|
17047
|
+
if (sourceRows === 0) {
|
|
17048
|
+
return { start: 0, end: -1, count: 0, sourceRows };
|
|
17049
|
+
}
|
|
17050
|
+
const start = Math.max(0, rows?.rowStart ?? 0);
|
|
17051
|
+
if (start >= sourceRows) {
|
|
17052
|
+
return { start, end: start - 1, count: 0, sourceRows };
|
|
17053
|
+
}
|
|
17054
|
+
const maxEnd = sourceRows - 1;
|
|
17055
|
+
const end = rows?.rowEnd === null || rows?.rowEnd === void 0 ? maxEnd : Math.min(maxEnd, rows.rowEnd);
|
|
17056
|
+
return {
|
|
17057
|
+
start,
|
|
17058
|
+
end,
|
|
17059
|
+
count: Math.max(0, end - start + 1),
|
|
17060
|
+
sourceRows
|
|
17061
|
+
};
|
|
17062
|
+
}
|
|
17063
|
+
function selectedSourceCsvRowCount(options) {
|
|
17064
|
+
if (!options?.sourceCsvPath) {
|
|
17065
|
+
return null;
|
|
17066
|
+
}
|
|
17067
|
+
return selectedSourceCsvRange(options.sourceCsvPath, options.rows).count;
|
|
17068
|
+
}
|
|
17069
|
+
function collectStringFields(value, key, output2, depth = 0) {
|
|
17070
|
+
if (depth > 12 || !value || typeof value !== "object") {
|
|
17071
|
+
return;
|
|
17072
|
+
}
|
|
17073
|
+
if (Array.isArray(value)) {
|
|
17074
|
+
for (const item of value.slice(0, 50)) {
|
|
17075
|
+
collectStringFields(item, key, output2, depth + 1);
|
|
17076
|
+
}
|
|
17077
|
+
return;
|
|
17078
|
+
}
|
|
17079
|
+
const record = value;
|
|
17080
|
+
const direct = record[key];
|
|
17081
|
+
if (typeof direct === "string" && direct.trim()) {
|
|
17082
|
+
output2.add(direct.trim());
|
|
17083
|
+
}
|
|
17084
|
+
for (const child of Object.values(record)) {
|
|
17085
|
+
collectStringFields(child, key, output2, depth + 1);
|
|
17086
|
+
}
|
|
17087
|
+
}
|
|
17088
|
+
function fallbackRowsInfoForGeneratedEnrichExport(status, options) {
|
|
17089
|
+
if (!extractRunId(status) || !extractPlayName2(status)) {
|
|
17090
|
+
return null;
|
|
17091
|
+
}
|
|
17092
|
+
const totalRows = selectedSourceCsvRowCount(options);
|
|
17093
|
+
if (totalRows === null) {
|
|
17094
|
+
return null;
|
|
17095
|
+
}
|
|
17096
|
+
const tableNamespaces = /* @__PURE__ */ new Set();
|
|
17097
|
+
collectStringFields(status, "tableNamespace", tableNamespaces);
|
|
17098
|
+
collectStringFields(status, "artifactTableNamespace", tableNamespaces);
|
|
17099
|
+
const tableNamespace = tableNamespaces.values().next().value ?? GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
|
|
17100
|
+
return {
|
|
17101
|
+
rows: [],
|
|
17102
|
+
totalRows,
|
|
17103
|
+
columns: [],
|
|
17104
|
+
columnsExplicit: false,
|
|
17105
|
+
complete: false,
|
|
17106
|
+
source: tableNamespace,
|
|
17107
|
+
tableNamespace
|
|
17108
|
+
};
|
|
17109
|
+
}
|
|
17110
|
+
function firstCollectedStringField(value, key) {
|
|
17111
|
+
const fields = /* @__PURE__ */ new Set();
|
|
17112
|
+
collectStringFields(value, key, fields);
|
|
17113
|
+
return fields.values().next().value ?? null;
|
|
17114
|
+
}
|
|
17115
|
+
function emitPlainBatchRunFailure(input2) {
|
|
17116
|
+
process.stderr.write(
|
|
17117
|
+
`Batch ${input2.chunkIndex + 1}/${input2.chunkCount} failed for rows ${input2.rows.rowStart}:${input2.rows.rowEnd}.
|
|
17118
|
+
`
|
|
17119
|
+
);
|
|
17120
|
+
const runId = extractRunId(input2.status);
|
|
17121
|
+
const error = firstCollectedStringField(input2.status, "error") ?? firstCollectedStringField(input2.status, "message");
|
|
17122
|
+
if (runId) {
|
|
17123
|
+
process.stderr.write(`Run id: ${runId}
|
|
17124
|
+
`);
|
|
17125
|
+
}
|
|
17126
|
+
if (error) {
|
|
17127
|
+
process.stderr.write(`Error: ${error}
|
|
17128
|
+
`);
|
|
17129
|
+
}
|
|
17130
|
+
if (runId) {
|
|
17131
|
+
process.stderr.write(
|
|
17132
|
+
`Inspect run output: deepline runs get ${runId} --full --json
|
|
17133
|
+
`
|
|
17134
|
+
);
|
|
17135
|
+
}
|
|
17136
|
+
}
|
|
16820
17137
|
function exportableSheetRow2(row) {
|
|
16821
17138
|
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
16822
17139
|
return null;
|
|
@@ -17184,7 +17501,8 @@ async function fetchBackingRowsForCsvExport(input2) {
|
|
|
17184
17501
|
tableNamespace,
|
|
17185
17502
|
runId,
|
|
17186
17503
|
limit: ENRICH_EXPORT_PAGE_SIZE,
|
|
17187
|
-
offset
|
|
17504
|
+
offset,
|
|
17505
|
+
rowMode: "all"
|
|
17188
17506
|
});
|
|
17189
17507
|
sheetRows.push(...page.rows);
|
|
17190
17508
|
const summaryTotal = page.summary?.stats?.total;
|
|
@@ -17552,41 +17870,177 @@ function registerEnrichCommand(program) {
|
|
|
17552
17870
|
const tempPlay = join6(tempDir, "deepline-enrich.play.ts");
|
|
17553
17871
|
try {
|
|
17554
17872
|
await writeFile3(tempPlay, playSource, "utf8");
|
|
17555
|
-
const
|
|
17556
|
-
|
|
17557
|
-
|
|
17558
|
-
|
|
17873
|
+
const runOne = async (input2) => {
|
|
17874
|
+
const runtimeInput = {
|
|
17875
|
+
file: resolve8(input2.sourceCsvPath),
|
|
17876
|
+
...input2.rows.rowStart !== null ? { rowStart: input2.rows.rowStart } : {},
|
|
17877
|
+
...input2.rows.rowEnd !== null ? { rowEnd: input2.rows.rowEnd } : {}
|
|
17878
|
+
};
|
|
17879
|
+
const runArgs = [
|
|
17880
|
+
"--file",
|
|
17881
|
+
tempPlay,
|
|
17882
|
+
"--input",
|
|
17883
|
+
JSON.stringify(runtimeInput),
|
|
17884
|
+
"--watch"
|
|
17885
|
+
];
|
|
17886
|
+
if (options.profile) {
|
|
17887
|
+
runArgs.push("--profile", options.profile);
|
|
17888
|
+
}
|
|
17889
|
+
if (options.noOpen || input2.suppressOpen) {
|
|
17890
|
+
runArgs.push("--no-open");
|
|
17891
|
+
}
|
|
17892
|
+
if (input2.json) {
|
|
17893
|
+
runArgs.push("--json");
|
|
17894
|
+
} else {
|
|
17895
|
+
runArgs.push("--logs");
|
|
17896
|
+
}
|
|
17897
|
+
const timeoutSeconds = options.timeout ? Number.parseInt(options.timeout, 10) : null;
|
|
17898
|
+
if (timeoutSeconds !== null && Number.isFinite(timeoutSeconds) && timeoutSeconds > 0) {
|
|
17899
|
+
runArgs.push("--tail-timeout-ms", String(timeoutSeconds * 1e3));
|
|
17900
|
+
}
|
|
17901
|
+
const captured2 = await runGeneratedEnrichPlay(runArgs, {
|
|
17902
|
+
passthroughStdout: input2.passthroughStdout
|
|
17903
|
+
});
|
|
17904
|
+
const status2 = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
|
|
17905
|
+
client: client2,
|
|
17906
|
+
stdout: captured2.stdout,
|
|
17907
|
+
exitCode: captured2.result
|
|
17908
|
+
});
|
|
17909
|
+
const exportResult2 = captured2.result === 0 && outputPath ? await writeOutputCsv(outputPath, status2, {
|
|
17910
|
+
client: client2,
|
|
17911
|
+
config,
|
|
17912
|
+
sourceCsvPath: input2.sourceCsvPath,
|
|
17913
|
+
rows: input2.rows,
|
|
17914
|
+
inPlace: Boolean(options.inPlace)
|
|
17915
|
+
}) : null;
|
|
17916
|
+
return { captured: captured2, status: status2, exportResult: exportResult2 };
|
|
17559
17917
|
};
|
|
17560
|
-
const
|
|
17561
|
-
|
|
17562
|
-
|
|
17563
|
-
|
|
17564
|
-
|
|
17565
|
-
|
|
17566
|
-
|
|
17567
|
-
|
|
17568
|
-
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
17573
|
-
|
|
17574
|
-
|
|
17575
|
-
|
|
17576
|
-
|
|
17577
|
-
|
|
17578
|
-
|
|
17579
|
-
|
|
17580
|
-
|
|
17918
|
+
const selectedRange = selectedSourceCsvRange(sourceCsvPath, rows);
|
|
17919
|
+
if (outputPath && selectedRange.count > ENRICH_AUTO_BATCH_ROWS) {
|
|
17920
|
+
const chunkCount = Math.ceil(
|
|
17921
|
+
selectedRange.count / ENRICH_AUTO_BATCH_ROWS
|
|
17922
|
+
);
|
|
17923
|
+
if (!options.json) {
|
|
17924
|
+
process.stderr.write(
|
|
17925
|
+
`Large enrich input selected ${selectedRange.count.toLocaleString()} rows. Running ${chunkCount.toLocaleString()} sequential batch runs of up to ${ENRICH_AUTO_BATCH_ROWS.toLocaleString()} rows and merging ${resolve8(outputPath)}.
|
|
17926
|
+
`
|
|
17927
|
+
);
|
|
17928
|
+
}
|
|
17929
|
+
let workingSourceCsvPath = sourceCsvPath;
|
|
17930
|
+
let lastStatus = null;
|
|
17931
|
+
let finalExportResult = null;
|
|
17932
|
+
let totalEnrichedRows = 0;
|
|
17933
|
+
const batchFailureRows = [];
|
|
17934
|
+
for (let chunkStart = selectedRange.start, chunkIndex = 0; chunkStart <= selectedRange.end; chunkStart += ENRICH_AUTO_BATCH_ROWS, chunkIndex += 1) {
|
|
17935
|
+
const chunkRows = {
|
|
17936
|
+
rowStart: chunkStart,
|
|
17937
|
+
rowEnd: Math.min(
|
|
17938
|
+
selectedRange.end,
|
|
17939
|
+
chunkStart + ENRICH_AUTO_BATCH_ROWS - 1
|
|
17940
|
+
)
|
|
17941
|
+
};
|
|
17942
|
+
if (!options.json) {
|
|
17943
|
+
process.stderr.write(
|
|
17944
|
+
`Batch ${chunkIndex + 1}/${chunkCount}: rows ${chunkRows.rowStart}:${chunkRows.rowEnd}
|
|
17945
|
+
`
|
|
17946
|
+
);
|
|
17947
|
+
}
|
|
17948
|
+
const chunk = await runOne({
|
|
17949
|
+
sourceCsvPath: workingSourceCsvPath,
|
|
17950
|
+
rows: chunkRows,
|
|
17951
|
+
json: true,
|
|
17952
|
+
passthroughStdout: false,
|
|
17953
|
+
suppressOpen: true
|
|
17954
|
+
});
|
|
17955
|
+
lastStatus = chunk.status;
|
|
17956
|
+
if (chunk.captured.result !== 0) {
|
|
17957
|
+
if (options.json) {
|
|
17958
|
+
printJson({
|
|
17959
|
+
ok: false,
|
|
17960
|
+
batch: {
|
|
17961
|
+
chunk: chunkIndex + 1,
|
|
17962
|
+
chunks: chunkCount,
|
|
17963
|
+
rows: chunkRows
|
|
17964
|
+
},
|
|
17965
|
+
result: chunk.status
|
|
17966
|
+
});
|
|
17967
|
+
} else {
|
|
17968
|
+
emitPlainBatchRunFailure({
|
|
17969
|
+
chunkIndex,
|
|
17970
|
+
chunkCount,
|
|
17971
|
+
rows: chunkRows,
|
|
17972
|
+
status: chunk.status
|
|
17973
|
+
});
|
|
17974
|
+
}
|
|
17975
|
+
process.exitCode = chunk.captured.result;
|
|
17976
|
+
return;
|
|
17977
|
+
}
|
|
17978
|
+
if (chunk.exportResult) {
|
|
17979
|
+
finalExportResult = chunk.exportResult;
|
|
17980
|
+
totalEnrichedRows += chunk.exportResult.enrichedRows;
|
|
17981
|
+
batchFailureRows.push(...chunk.exportResult.enrichedDataRows);
|
|
17982
|
+
workingSourceCsvPath = outputPath;
|
|
17983
|
+
}
|
|
17984
|
+
}
|
|
17985
|
+
const outputRows = readCsvRows(outputPath);
|
|
17986
|
+
const failureReport2 = await maybeEmitEnrichFailureReport({
|
|
17987
|
+
config,
|
|
17988
|
+
rows: batchFailureRows,
|
|
17989
|
+
rowRange: {
|
|
17990
|
+
rowStart: selectedRange.start,
|
|
17991
|
+
rowEnd: selectedRange.end
|
|
17992
|
+
},
|
|
17993
|
+
client: client2,
|
|
17994
|
+
outputPath
|
|
17995
|
+
});
|
|
17996
|
+
if (options.json) {
|
|
17997
|
+
const run = rewriteEnrichJsonStatus({
|
|
17998
|
+
status: lastStatus,
|
|
17999
|
+
config,
|
|
18000
|
+
forceAliases,
|
|
18001
|
+
output: finalExportResult ? {
|
|
18002
|
+
...finalExportResult,
|
|
18003
|
+
sourceCsvRows: selectedRange.sourceRows,
|
|
18004
|
+
selectedRows: selectedRange.count,
|
|
18005
|
+
enrichedRows: totalEnrichedRows,
|
|
18006
|
+
rows: outputRows.length,
|
|
18007
|
+
enrichedDataRows: outputRows
|
|
18008
|
+
} : null,
|
|
18009
|
+
failureReport: failureReport2
|
|
18010
|
+
});
|
|
18011
|
+
printJson({
|
|
18012
|
+
ok: !failureReport2,
|
|
18013
|
+
run,
|
|
18014
|
+
batch: {
|
|
18015
|
+
chunks: chunkCount,
|
|
18016
|
+
chunkRows: ENRICH_AUTO_BATCH_ROWS,
|
|
18017
|
+
selectedRows: selectedRange.count
|
|
18018
|
+
},
|
|
18019
|
+
output: finalExportResult ? {
|
|
18020
|
+
sourceCsvRows: selectedRange.sourceRows,
|
|
18021
|
+
selectedRows: selectedRange.count,
|
|
18022
|
+
enrichedRows: totalEnrichedRows,
|
|
18023
|
+
path: finalExportResult.path
|
|
18024
|
+
} : null,
|
|
18025
|
+
...failureReport2 ? {
|
|
18026
|
+
failure_report: {
|
|
18027
|
+
path: failureReport2.path,
|
|
18028
|
+
jobs: failureReport2.jobs.length
|
|
18029
|
+
}
|
|
18030
|
+
} : {}
|
|
18031
|
+
});
|
|
18032
|
+
}
|
|
18033
|
+
if (failureReport2) {
|
|
18034
|
+
process.exitCode = EXIT_SERVER2;
|
|
18035
|
+
}
|
|
18036
|
+
return;
|
|
17581
18037
|
}
|
|
17582
|
-
const captured = await
|
|
18038
|
+
const { captured, status, exportResult } = await runOne({
|
|
18039
|
+
sourceCsvPath,
|
|
18040
|
+
rows,
|
|
18041
|
+
json: Boolean(options.json),
|
|
17583
18042
|
passthroughStdout: !options.json
|
|
17584
18043
|
});
|
|
17585
|
-
const status = options.json ? parseJsonOutput(captured.stdout) : await resolveWatchedGeneratedPlayStatus({
|
|
17586
|
-
client: client2,
|
|
17587
|
-
stdout: captured.stdout,
|
|
17588
|
-
exitCode: captured.result
|
|
17589
|
-
});
|
|
17590
18044
|
if (captured.result !== 0) {
|
|
17591
18045
|
if (options.json) {
|
|
17592
18046
|
printJson({
|
|
@@ -17596,13 +18050,6 @@ function registerEnrichCommand(program) {
|
|
|
17596
18050
|
process.exitCode = captured.result;
|
|
17597
18051
|
return;
|
|
17598
18052
|
}
|
|
17599
|
-
const exportResult = outputPath ? await writeOutputCsv(outputPath, status, {
|
|
17600
|
-
client: client2,
|
|
17601
|
-
config,
|
|
17602
|
-
sourceCsvPath,
|
|
17603
|
-
rows,
|
|
17604
|
-
inPlace: Boolean(options.inPlace)
|
|
17605
|
-
}) : null;
|
|
17606
18053
|
const rowsForFailureReport = exportResult?.enrichedDataRows ?? extractCanonicalRowsInfo(status)?.rows ?? [];
|
|
17607
18054
|
if (options.json) {
|
|
17608
18055
|
const failureReport2 = await maybeEmitEnrichFailureReport({
|
|
@@ -17718,9 +18165,9 @@ Examples:
|
|
|
17718
18165
|
import {
|
|
17719
18166
|
existsSync as existsSync7,
|
|
17720
18167
|
mkdirSync as mkdirSync5,
|
|
17721
|
-
readdirSync as
|
|
18168
|
+
readdirSync as readdirSync3,
|
|
17722
18169
|
readFileSync as readFileSync7,
|
|
17723
|
-
statSync as
|
|
18170
|
+
statSync as statSync4,
|
|
17724
18171
|
writeFileSync as writeFileSync9
|
|
17725
18172
|
} from "fs";
|
|
17726
18173
|
import { homedir as homedir7, platform } from "os";
|
|
@@ -17805,7 +18252,7 @@ function listSessionFiles(agent) {
|
|
|
17805
18252
|
}
|
|
17806
18253
|
function readDirectoryNames(dir) {
|
|
17807
18254
|
try {
|
|
17808
|
-
return
|
|
18255
|
+
return readdirSync3(dir);
|
|
17809
18256
|
} catch {
|
|
17810
18257
|
return [];
|
|
17811
18258
|
}
|
|
@@ -17816,7 +18263,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
|
|
|
17816
18263
|
if (depth > maxDepth) return;
|
|
17817
18264
|
let entries;
|
|
17818
18265
|
try {
|
|
17819
|
-
entries =
|
|
18266
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
17820
18267
|
} catch {
|
|
17821
18268
|
return;
|
|
17822
18269
|
}
|
|
@@ -17834,7 +18281,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
|
|
|
17834
18281
|
}
|
|
17835
18282
|
function statIfReadable(filePath) {
|
|
17836
18283
|
try {
|
|
17837
|
-
return
|
|
18284
|
+
return statSync4(filePath);
|
|
17838
18285
|
} catch {
|
|
17839
18286
|
return null;
|
|
17840
18287
|
}
|
|
@@ -18527,6 +18974,15 @@ Examples:
|
|
|
18527
18974
|
async function fetchOrganizations(http, apiKey) {
|
|
18528
18975
|
return http.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
|
|
18529
18976
|
}
|
|
18977
|
+
function normalizeAuthScope(value) {
|
|
18978
|
+
if (!value) return "auto";
|
|
18979
|
+
if (value === "auto" || value === "folder" || value === "global") {
|
|
18980
|
+
return value;
|
|
18981
|
+
}
|
|
18982
|
+
throw new Error(
|
|
18983
|
+
`Invalid --auth-scope "${value}". Expected one of: auto, folder, global.`
|
|
18984
|
+
);
|
|
18985
|
+
}
|
|
18530
18986
|
function orgListLines(orgs) {
|
|
18531
18987
|
return orgs.map((org, index) => {
|
|
18532
18988
|
const current = org.is_current ? " (current)" : "";
|
|
@@ -18534,6 +18990,90 @@ function orgListLines(orgs) {
|
|
|
18534
18990
|
return `${index + 1}. ${org.name}${role}${current}`;
|
|
18535
18991
|
});
|
|
18536
18992
|
}
|
|
18993
|
+
function redactApiKey(value) {
|
|
18994
|
+
if (!value) return null;
|
|
18995
|
+
if (value.length <= 10) return `${value.slice(0, 3)}...`;
|
|
18996
|
+
return `${value.slice(0, 8)}...${value.slice(-4)}`;
|
|
18997
|
+
}
|
|
18998
|
+
function processEnvValue(name) {
|
|
18999
|
+
return process.env[name]?.trim() ?? "";
|
|
19000
|
+
}
|
|
19001
|
+
function resolveOrgSwitchAuthTarget(scope, config) {
|
|
19002
|
+
const activeProject = getResolvedProjectAuthSource(
|
|
19003
|
+
config.baseUrl,
|
|
19004
|
+
config.apiKey
|
|
19005
|
+
);
|
|
19006
|
+
const folderTarget = resolveProjectPinTarget();
|
|
19007
|
+
const globalOverrideWarning = activeProject && scope === "global" ? [
|
|
19008
|
+
`Folder auth in ${activeProject.filePath} overrides global auth for commands run here.`
|
|
19009
|
+
] : [];
|
|
19010
|
+
if (scope === "folder") {
|
|
19011
|
+
if (!folderTarget.ok) {
|
|
19012
|
+
throw new Error(
|
|
19013
|
+
`Cowork project folder is ambiguous. Candidate folders: ${folderTarget.candidates.join(
|
|
19014
|
+
", "
|
|
19015
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder before running this command.`
|
|
19016
|
+
);
|
|
19017
|
+
}
|
|
19018
|
+
return {
|
|
19019
|
+
kind: "folder",
|
|
19020
|
+
requested_scope: scope,
|
|
19021
|
+
effective_scope: "folder",
|
|
19022
|
+
reason: "explicit_folder",
|
|
19023
|
+
source: folderTarget.source,
|
|
19024
|
+
warnings: []
|
|
19025
|
+
};
|
|
19026
|
+
}
|
|
19027
|
+
if (scope === "global") {
|
|
19028
|
+
return {
|
|
19029
|
+
kind: "global",
|
|
19030
|
+
requested_scope: scope,
|
|
19031
|
+
effective_scope: "global",
|
|
19032
|
+
reason: "explicit_global",
|
|
19033
|
+
warnings: globalOverrideWarning
|
|
19034
|
+
};
|
|
19035
|
+
}
|
|
19036
|
+
if (activeProject) {
|
|
19037
|
+
return {
|
|
19038
|
+
kind: "folder",
|
|
19039
|
+
requested_scope: scope,
|
|
19040
|
+
effective_scope: "folder",
|
|
19041
|
+
reason: "existing_folder_auth",
|
|
19042
|
+
source: activeProject.source,
|
|
19043
|
+
warnings: []
|
|
19044
|
+
};
|
|
19045
|
+
}
|
|
19046
|
+
if (folderTarget.ok && folderTarget.source === "cowork") {
|
|
19047
|
+
return {
|
|
19048
|
+
kind: "folder",
|
|
19049
|
+
requested_scope: scope,
|
|
19050
|
+
effective_scope: "folder",
|
|
19051
|
+
reason: "detected_cowork_project",
|
|
19052
|
+
source: "cowork",
|
|
19053
|
+
warnings: []
|
|
19054
|
+
};
|
|
19055
|
+
}
|
|
19056
|
+
if (!folderTarget.ok) {
|
|
19057
|
+
return {
|
|
19058
|
+
kind: "global",
|
|
19059
|
+
requested_scope: scope,
|
|
19060
|
+
effective_scope: "global",
|
|
19061
|
+
reason: "ambiguous_cowork_fell_back_global",
|
|
19062
|
+
warnings: [
|
|
19063
|
+
`Cowork project folder is ambiguous, so global auth was updated. Candidate folders: ${folderTarget.candidates.join(
|
|
19064
|
+
", "
|
|
19065
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder to update folder auth.`
|
|
19066
|
+
]
|
|
19067
|
+
};
|
|
19068
|
+
}
|
|
19069
|
+
return {
|
|
19070
|
+
kind: "global",
|
|
19071
|
+
requested_scope: scope,
|
|
19072
|
+
effective_scope: "global",
|
|
19073
|
+
reason: "default_global",
|
|
19074
|
+
warnings: []
|
|
19075
|
+
};
|
|
19076
|
+
}
|
|
18537
19077
|
async function handleOrgList(options) {
|
|
18538
19078
|
const config = resolveConfig();
|
|
18539
19079
|
const http = new HttpClient(config);
|
|
@@ -18553,7 +19093,89 @@ async function handleOrgList(options) {
|
|
|
18553
19093
|
{ json: options.json }
|
|
18554
19094
|
);
|
|
18555
19095
|
}
|
|
19096
|
+
async function handleOrgStatus(options) {
|
|
19097
|
+
const config = resolveConfig();
|
|
19098
|
+
const http = new HttpClient(config);
|
|
19099
|
+
const payload = await fetchOrganizations(http, config.apiKey);
|
|
19100
|
+
const current = payload.organizations.find((org) => org.is_current) ?? payload.organizations.find((org) => org.org_id === payload.current_org_id) ?? null;
|
|
19101
|
+
const projectCandidate = getActiveProjectAuthSource();
|
|
19102
|
+
const activeProject = getResolvedProjectAuthSource(
|
|
19103
|
+
config.baseUrl,
|
|
19104
|
+
config.apiKey
|
|
19105
|
+
);
|
|
19106
|
+
const folderTarget = resolveProjectPinTarget();
|
|
19107
|
+
const hostPath = hostEnvFilePath(config.baseUrl);
|
|
19108
|
+
const envApiKey = processEnvValue(API_KEY_ENV);
|
|
19109
|
+
const envHostUrl = processEnvValue(HOST_URL_ENV);
|
|
19110
|
+
const authSource = envApiKey ? {
|
|
19111
|
+
scope: "env",
|
|
19112
|
+
source: "process",
|
|
19113
|
+
path: null,
|
|
19114
|
+
api_key: redactApiKey(envApiKey),
|
|
19115
|
+
host: envHostUrl || null,
|
|
19116
|
+
overrides_global: true,
|
|
19117
|
+
overrides_folder: Boolean(projectCandidate)
|
|
19118
|
+
} : activeProject ? {
|
|
19119
|
+
scope: "folder",
|
|
19120
|
+
source: activeProject.source,
|
|
19121
|
+
path: activeProject.filePath,
|
|
19122
|
+
api_key: redactApiKey(activeProject.env.DEEPLINE_API_KEY),
|
|
19123
|
+
overrides_global: true
|
|
19124
|
+
} : {
|
|
19125
|
+
scope: "global",
|
|
19126
|
+
source: "host",
|
|
19127
|
+
path: hostPath,
|
|
19128
|
+
api_key: redactApiKey(config.apiKey),
|
|
19129
|
+
overrides_global: false
|
|
19130
|
+
};
|
|
19131
|
+
const folderTargetPayload = folderTarget.ok ? {
|
|
19132
|
+
ok: true,
|
|
19133
|
+
source: folderTarget.source,
|
|
19134
|
+
dir: folderTarget.dir,
|
|
19135
|
+
env_path: `${folderTarget.dir}/.env.deepline`
|
|
19136
|
+
} : {
|
|
19137
|
+
ok: false,
|
|
19138
|
+
reason: folderTarget.reason,
|
|
19139
|
+
candidates: folderTarget.candidates
|
|
19140
|
+
};
|
|
19141
|
+
const lines = [
|
|
19142
|
+
`Organization: ${current?.name ?? "(unknown)"}`,
|
|
19143
|
+
`Host: ${config.baseUrl}`,
|
|
19144
|
+
`Auth scope: ${authSource.scope}`
|
|
19145
|
+
];
|
|
19146
|
+
if (authSource.path) {
|
|
19147
|
+
lines.push(`Auth file: ${authSource.path}`);
|
|
19148
|
+
} else {
|
|
19149
|
+
lines.push(`Auth source: ${API_KEY_ENV} process environment`);
|
|
19150
|
+
}
|
|
19151
|
+
if (envApiKey) {
|
|
19152
|
+
lines.push(`${API_KEY_ENV} overrides saved auth for this process.`);
|
|
19153
|
+
} else if (activeProject) {
|
|
19154
|
+
lines.push("Global auth is overridden in this folder.");
|
|
19155
|
+
}
|
|
19156
|
+
printCommandEnvelope(
|
|
19157
|
+
{
|
|
19158
|
+
ok: true,
|
|
19159
|
+
host: config.baseUrl,
|
|
19160
|
+
organization: current,
|
|
19161
|
+
current_org_id: payload.current_org_id,
|
|
19162
|
+
auth_source: authSource,
|
|
19163
|
+
host_env_path: hostPath,
|
|
19164
|
+
folder_target: folderTargetPayload,
|
|
19165
|
+
next: {
|
|
19166
|
+
set_auto: "deepline org set <org>",
|
|
19167
|
+
set_folder: "deepline org set <org> --auth-scope folder",
|
|
19168
|
+
set_global: "deepline org set <org> --auth-scope global"
|
|
19169
|
+
},
|
|
19170
|
+
render: {
|
|
19171
|
+
sections: [{ title: "org status", lines }]
|
|
19172
|
+
}
|
|
19173
|
+
},
|
|
19174
|
+
{ json: options.json }
|
|
19175
|
+
);
|
|
19176
|
+
}
|
|
18556
19177
|
async function handleOrgSwitch(selection, options) {
|
|
19178
|
+
const authScope = normalizeAuthScope(options.authScope);
|
|
18557
19179
|
const config = resolveConfig();
|
|
18558
19180
|
const http = new HttpClient(config);
|
|
18559
19181
|
const payload = await fetchOrganizations(http, config.apiKey);
|
|
@@ -18561,7 +19183,10 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18561
19183
|
printCommandEnvelope(
|
|
18562
19184
|
{
|
|
18563
19185
|
...payload,
|
|
18564
|
-
next: {
|
|
19186
|
+
next: { set: "deepline org set <number>" },
|
|
19187
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
19188
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
19189
|
+
warnings: options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
18565
19190
|
render: {
|
|
18566
19191
|
sections: [
|
|
18567
19192
|
{
|
|
@@ -18569,7 +19194,7 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18569
19194
|
lines: orgListLines(payload.organizations)
|
|
18570
19195
|
}
|
|
18571
19196
|
],
|
|
18572
|
-
actions: [{ label: "Run", command: "deepline org
|
|
19197
|
+
actions: [{ label: "Run", command: "deepline org set <number>" }]
|
|
18573
19198
|
}
|
|
18574
19199
|
},
|
|
18575
19200
|
{ json: options.json }
|
|
@@ -18592,16 +19217,56 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18592
19217
|
if (!target) {
|
|
18593
19218
|
throw new Error("Could not resolve the selected organization.");
|
|
18594
19219
|
}
|
|
19220
|
+
const authTarget = resolveOrgSwitchAuthTarget(authScope, config);
|
|
18595
19221
|
if (target.is_current) {
|
|
19222
|
+
let project_env_paths2 = [];
|
|
19223
|
+
if (authTarget.kind === "folder") {
|
|
19224
|
+
project_env_paths2 = saveProjectDeeplineEnvValues({
|
|
19225
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
19226
|
+
DEEPLINE_API_KEY: config.apiKey
|
|
19227
|
+
});
|
|
19228
|
+
} else {
|
|
19229
|
+
saveHostEnvValues(config.baseUrl, {
|
|
19230
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
19231
|
+
DEEPLINE_API_KEY: config.apiKey
|
|
19232
|
+
});
|
|
19233
|
+
}
|
|
19234
|
+
const renderLines2 = [`Already on ${target.name}.`];
|
|
19235
|
+
for (const projectPath of project_env_paths2) {
|
|
19236
|
+
renderLines2.push(`Saved folder auth in ${projectPath}`);
|
|
19237
|
+
}
|
|
19238
|
+
if (authTarget.kind === "global") {
|
|
19239
|
+
renderLines2.push(`Saved global auth in ${hostEnvFilePath(config.baseUrl)}`);
|
|
19240
|
+
}
|
|
19241
|
+
renderLines2.push(
|
|
19242
|
+
`Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
|
|
19243
|
+
);
|
|
19244
|
+
if (options.deprecatedSwitch) {
|
|
19245
|
+
renderLines2.push("Warning: org switch is deprecated; use org set.");
|
|
19246
|
+
}
|
|
19247
|
+
for (const warning of authTarget.warnings) {
|
|
19248
|
+
renderLines2.push(`Warning: ${warning}`);
|
|
19249
|
+
}
|
|
19250
|
+
const warnings2 = [
|
|
19251
|
+
...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
19252
|
+
...authTarget.warnings
|
|
19253
|
+
];
|
|
18596
19254
|
printCommandEnvelope(
|
|
18597
19255
|
{
|
|
18598
19256
|
ok: true,
|
|
18599
19257
|
unchanged: true,
|
|
18600
19258
|
organization: target,
|
|
19259
|
+
requested_auth_scope: authTarget.requested_scope,
|
|
19260
|
+
effective_auth_scope: authTarget.effective_scope,
|
|
19261
|
+
auth_scope_reason: authTarget.reason,
|
|
19262
|
+
auth_scope: authTarget.effective_scope,
|
|
19263
|
+
host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
|
|
19264
|
+
project_env_paths: project_env_paths2,
|
|
19265
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
19266
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
19267
|
+
warnings: warnings2,
|
|
18601
19268
|
render: {
|
|
18602
|
-
sections: [
|
|
18603
|
-
{ title: "org switch", lines: [`Already on ${target.name}.`] }
|
|
18604
|
-
]
|
|
19269
|
+
sections: [{ title: "org set", lines: renderLines2 }]
|
|
18605
19270
|
}
|
|
18606
19271
|
},
|
|
18607
19272
|
{ json: options.json }
|
|
@@ -18612,26 +19277,61 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18612
19277
|
api_key: config.apiKey,
|
|
18613
19278
|
org_id: target.org_id
|
|
18614
19279
|
});
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
19280
|
+
let project_env_paths = [];
|
|
19281
|
+
if (authTarget.kind === "folder") {
|
|
19282
|
+
project_env_paths = saveProjectDeeplineEnvValues({
|
|
19283
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
19284
|
+
DEEPLINE_API_KEY: switched.api_key
|
|
19285
|
+
});
|
|
19286
|
+
} else {
|
|
19287
|
+
saveHostEnvValues(config.baseUrl, {
|
|
19288
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
19289
|
+
DEEPLINE_API_KEY: switched.api_key,
|
|
19290
|
+
DEEPLINE_ACTIVE_ORG_ID: switched.org_id,
|
|
19291
|
+
DEEPLINE_ACTIVE_ORG_NAME: switched.org_name
|
|
19292
|
+
});
|
|
19293
|
+
}
|
|
18620
19294
|
const { api_key: _apiKey, ...publicSwitched } = switched;
|
|
19295
|
+
const renderLines = [`Switched to ${switched.org_name}.`];
|
|
19296
|
+
if (authTarget.kind === "folder") {
|
|
19297
|
+
for (const projectPath of project_env_paths) {
|
|
19298
|
+
renderLines.push(`Saved folder auth in ${projectPath}`);
|
|
19299
|
+
}
|
|
19300
|
+
} else {
|
|
19301
|
+
renderLines.push(`Saved global auth in ${hostEnvFilePath(config.baseUrl)}`);
|
|
19302
|
+
}
|
|
19303
|
+
renderLines.push(
|
|
19304
|
+
`Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
|
|
19305
|
+
);
|
|
19306
|
+
if (options.deprecatedSwitch) {
|
|
19307
|
+
renderLines.push("Warning: org switch is deprecated; use org set.");
|
|
19308
|
+
}
|
|
19309
|
+
for (const warning of authTarget.warnings) {
|
|
19310
|
+
renderLines.push(`Warning: ${warning}`);
|
|
19311
|
+
}
|
|
19312
|
+
const warnings = [
|
|
19313
|
+
...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
19314
|
+
...authTarget.warnings
|
|
19315
|
+
];
|
|
18621
19316
|
printCommandEnvelope(
|
|
18622
19317
|
{
|
|
18623
19318
|
ok: true,
|
|
18624
|
-
host_env_path: hostEnvFilePath(config.baseUrl),
|
|
19319
|
+
host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
|
|
19320
|
+
project_env_paths,
|
|
18625
19321
|
...publicSwitched,
|
|
18626
19322
|
api_key_saved: true,
|
|
19323
|
+
requested_auth_scope: authTarget.requested_scope,
|
|
19324
|
+
effective_auth_scope: authTarget.effective_scope,
|
|
19325
|
+
auth_scope_reason: authTarget.reason,
|
|
19326
|
+
auth_scope: authTarget.effective_scope,
|
|
19327
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
19328
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
19329
|
+
warnings,
|
|
18627
19330
|
render: {
|
|
18628
19331
|
sections: [
|
|
18629
19332
|
{
|
|
18630
|
-
title: "org
|
|
18631
|
-
lines:
|
|
18632
|
-
`Switched to ${switched.org_name}.`,
|
|
18633
|
-
`Saved host auth in ${hostEnvFilePath(config.baseUrl)}`
|
|
18634
|
-
]
|
|
19333
|
+
title: "org set",
|
|
19334
|
+
lines: renderLines
|
|
18635
19335
|
}
|
|
18636
19336
|
]
|
|
18637
19337
|
}
|
|
@@ -18647,6 +19347,7 @@ async function handleOrgCreate(name, options) {
|
|
|
18647
19347
|
name
|
|
18648
19348
|
});
|
|
18649
19349
|
saveHostEnvValues(config.baseUrl, {
|
|
19350
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18650
19351
|
DEEPLINE_API_KEY: created.api_key,
|
|
18651
19352
|
DEEPLINE_ACTIVE_ORG_ID: created.org_id,
|
|
18652
19353
|
DEEPLINE_ACTIVE_ORG_NAME: created.org_name
|
|
@@ -18676,18 +19377,41 @@ async function handleOrgCreate(name, options) {
|
|
|
18676
19377
|
);
|
|
18677
19378
|
}
|
|
18678
19379
|
function registerOrgCommands(program) {
|
|
18679
|
-
const org = program.command("org").description("List, create, and
|
|
19380
|
+
const org = program.command("org").description("List, create, and set organizations.").addHelpText(
|
|
18680
19381
|
"after",
|
|
18681
19382
|
`
|
|
18682
19383
|
Notes:
|
|
18683
|
-
Organizations are workspaces.
|
|
18684
|
-
|
|
19384
|
+
Organizations are workspaces. Auth is stored as an API key scoped to one
|
|
19385
|
+
organization, so setting an org saves a key for the selected auth scope.
|
|
19386
|
+
|
|
19387
|
+
Auth scopes:
|
|
19388
|
+
auto Update the folder pin that already controls this command; in
|
|
19389
|
+
Cowork, write the mounted project folder; otherwise update global
|
|
19390
|
+
host auth.
|
|
19391
|
+
folder Write .env.deepline in the current project/Cowork project and make
|
|
19392
|
+
sure .env.deepline is gitignored. Commands below that folder use
|
|
19393
|
+
this org; sibling folders can pin different orgs.
|
|
19394
|
+
global Write ~/.local/deepline/<host>/.env. Commands outside folder pins
|
|
19395
|
+
use this org. Existing folder pins still override global auth.
|
|
19396
|
+
|
|
19397
|
+
Process env DEEPLINE_API_KEY overrides saved auth for that command only.
|
|
19398
|
+
|
|
19399
|
+
Agent loop:
|
|
19400
|
+
deepline org list --json
|
|
19401
|
+
deepline org set <number-or-org-id> --auth-scope folder --json
|
|
19402
|
+
deepline org status --json
|
|
19403
|
+
deepline auth status --json
|
|
18685
19404
|
|
|
18686
19405
|
Examples:
|
|
18687
19406
|
deepline org list --json
|
|
19407
|
+
deepline org status --json
|
|
18688
19408
|
deepline org create Acme --json
|
|
18689
|
-
deepline org
|
|
18690
|
-
deepline org
|
|
19409
|
+
deepline org set 2
|
|
19410
|
+
deepline org set 2 --auth-scope folder
|
|
19411
|
+
deepline org set --org-id org_123 --json
|
|
19412
|
+
cd path/to/project-a && deepline org set Prove --auth-scope folder --json
|
|
19413
|
+
cd path/to/project-b && deepline org set Mixmax --auth-scope folder --json
|
|
19414
|
+
cd .. && deepline org status --json
|
|
18691
19415
|
`
|
|
18692
19416
|
);
|
|
18693
19417
|
org.command("list").description("List your organizations.").addHelpText(
|
|
@@ -18714,21 +19438,88 @@ Examples:
|
|
|
18714
19438
|
deepline org create "Acme Sales" --json
|
|
18715
19439
|
`
|
|
18716
19440
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgCreate);
|
|
18717
|
-
org.command("
|
|
18718
|
-
"Switch to another organization and save the new API key in the host auth file."
|
|
18719
|
-
).addHelpText(
|
|
19441
|
+
org.command("status").description("Show the current organization and auth source.").addHelpText(
|
|
18720
19442
|
"after",
|
|
18721
19443
|
`
|
|
18722
19444
|
Notes:
|
|
18723
|
-
|
|
18724
|
-
|
|
19445
|
+
Read-only. Shows the current org plus auth_source.scope, auth_source.path,
|
|
19446
|
+
folder_target, host_env_path, and next commands.
|
|
19447
|
+
|
|
19448
|
+
Scopes are env, folder, or global. env means DEEPLINE_API_KEY/
|
|
19449
|
+
DEEPLINE_HOST_URL in process env wins. folder means nearest/Cowork
|
|
19450
|
+
.env.deepline wins. global means host config wins.
|
|
19451
|
+
|
|
19452
|
+
Run before and after org set to verify what future commands will use.
|
|
19453
|
+
|
|
19454
|
+
Examples:
|
|
19455
|
+
deepline org status
|
|
19456
|
+
deepline org status --json
|
|
19457
|
+
`
|
|
19458
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgStatus);
|
|
19459
|
+
const addOrgSetOptions = (command) => command.option("--org-id <id>", "Set using an explicit organization id").option(
|
|
19460
|
+
"--auth-scope <scope>",
|
|
19461
|
+
"Where to save auth: auto, folder, or global",
|
|
19462
|
+
"auto"
|
|
19463
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped");
|
|
19464
|
+
addOrgSetOptions(
|
|
19465
|
+
org.command("set [selection]").description("Set the organization for the selected auth scope.").addHelpText(
|
|
19466
|
+
"after",
|
|
19467
|
+
`
|
|
19468
|
+
Notes:
|
|
19469
|
+
Selection can be a list number, exact organization name, or organization id.
|
|
19470
|
+
Without a selection, prints choices.
|
|
19471
|
+
|
|
19472
|
+
Mutates local auth state and asks Deepline for an org-scoped API key. It
|
|
19473
|
+
writes only the selected scope:
|
|
19474
|
+
auto Update the folder pin that already controls this command; in
|
|
19475
|
+
Cowork, write the mounted project folder; otherwise update global
|
|
19476
|
+
host auth.
|
|
19477
|
+
folder Write .env.deepline in the current project/Cowork project and make
|
|
19478
|
+
sure .env.deepline is gitignored.
|
|
19479
|
+
global Write ~/.local/deepline/<host>/.env.
|
|
19480
|
+
|
|
19481
|
+
Folder auth shadows global auth. If you set --auth-scope global from a pinned
|
|
19482
|
+
folder, commands in that folder still use the folder pin until it is changed
|
|
19483
|
+
or removed.
|
|
19484
|
+
|
|
19485
|
+
Use --json for stable fields including effective_auth_scope,
|
|
19486
|
+
auth_scope_reason, host_env_path, project_env_paths, warnings, org_id, and
|
|
19487
|
+
org_name.
|
|
19488
|
+
|
|
19489
|
+
Examples:
|
|
19490
|
+
deepline org set
|
|
19491
|
+
deepline org set 2
|
|
19492
|
+
deepline org set 2 --auth-scope folder
|
|
19493
|
+
deepline org set 2 --auth-scope global
|
|
19494
|
+
deepline org set --org-id org_123 --json
|
|
19495
|
+
deepline org status --json
|
|
19496
|
+
`
|
|
19497
|
+
)
|
|
19498
|
+
).action(handleOrgSwitch);
|
|
19499
|
+
addOrgSetOptions(
|
|
19500
|
+
org.command("switch [selection]").description(
|
|
19501
|
+
"Deprecated alias for org set. Set the organization for the selected auth scope."
|
|
19502
|
+
).addHelpText(
|
|
19503
|
+
"after",
|
|
19504
|
+
`
|
|
19505
|
+
Notes:
|
|
19506
|
+
Deprecated alias. Use deepline org set instead. The command still mutates
|
|
19507
|
+
local auth state with the same --auth-scope behavior as org set.
|
|
19508
|
+
|
|
19509
|
+
Run deepline org set --help for scope definitions and the agent verification
|
|
19510
|
+
loop.
|
|
18725
19511
|
|
|
18726
19512
|
Examples:
|
|
18727
19513
|
deepline org switch
|
|
18728
19514
|
deepline org switch 2
|
|
19515
|
+
deepline org switch 2 --auth-scope folder
|
|
19516
|
+
deepline org switch 2 --auth-scope global
|
|
18729
19517
|
deepline org switch --org-id org_123 --json
|
|
18730
19518
|
`
|
|
18731
|
-
|
|
19519
|
+
)
|
|
19520
|
+
).action(
|
|
19521
|
+
(selection, options) => handleOrgSwitch(selection, { ...options, deprecatedSwitch: true })
|
|
19522
|
+
);
|
|
18732
19523
|
}
|
|
18733
19524
|
|
|
18734
19525
|
// src/cli/commands/quickstart.ts
|
|
@@ -21595,7 +22386,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
21595
22386
|
import {
|
|
21596
22387
|
existsSync as existsSync11,
|
|
21597
22388
|
mkdirSync as mkdirSync9,
|
|
21598
|
-
realpathSync as
|
|
22389
|
+
realpathSync as realpathSync3,
|
|
21599
22390
|
readFileSync as readFileSync11,
|
|
21600
22391
|
renameSync,
|
|
21601
22392
|
rmSync as rmSync3,
|
|
@@ -22094,7 +22885,7 @@ function findRepoBackedSdkRoot(startPath) {
|
|
|
22094
22885
|
function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
|
|
22095
22886
|
const normalized = (() => {
|
|
22096
22887
|
try {
|
|
22097
|
-
return
|
|
22888
|
+
return realpathSync3(entrypoint);
|
|
22098
22889
|
} catch {
|
|
22099
22890
|
return resolve12(entrypoint);
|
|
22100
22891
|
}
|