deepline 0.1.136 → 0.1.137
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/sdk/src/config.ts +310 -13
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/cli/index.js +547 -41
- package/dist/cli/index.mjs +571 -57
- package/dist/index.js +148 -14
- package/dist/index.mjs +157 -15
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -237,6 +237,22 @@ var PROD_URL = "https://code.deepline.com";
|
|
|
237
237
|
var DEFAULT_TIMEOUT = 6e4;
|
|
238
238
|
var DEFAULT_MAX_RETRIES = 3;
|
|
239
239
|
var PROJECT_DEEPLINE_ENV_FILE = ".env.deepline";
|
|
240
|
+
var COWORK_IGNORED_WORKSPACE_DIRS = /* @__PURE__ */ new Set([
|
|
241
|
+
".auto-memory",
|
|
242
|
+
".claude",
|
|
243
|
+
".remote-plugins",
|
|
244
|
+
"outputs",
|
|
245
|
+
"plugins",
|
|
246
|
+
"uploads"
|
|
247
|
+
]);
|
|
248
|
+
var COWORK_PROJECT_MARKERS = [
|
|
249
|
+
".deepline",
|
|
250
|
+
".env.deepline",
|
|
251
|
+
".git",
|
|
252
|
+
"AGENTS.md",
|
|
253
|
+
"package.json",
|
|
254
|
+
"pyproject.toml"
|
|
255
|
+
];
|
|
240
256
|
function baseUrlSlug(baseUrl) {
|
|
241
257
|
let url;
|
|
242
258
|
try {
|
|
@@ -282,9 +298,124 @@ function findNearestEnvFile(name, startDir = process.cwd()) {
|
|
|
282
298
|
current = parent;
|
|
283
299
|
}
|
|
284
300
|
}
|
|
285
|
-
function
|
|
286
|
-
|
|
287
|
-
|
|
301
|
+
function isDirectory(path) {
|
|
302
|
+
try {
|
|
303
|
+
return (0, import_node_fs.statSync)(path).isDirectory();
|
|
304
|
+
} catch {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function canonicalPath(path) {
|
|
309
|
+
try {
|
|
310
|
+
return (0, import_node_fs.realpathSync)(path);
|
|
311
|
+
} catch {
|
|
312
|
+
return (0, import_node_path.resolve)(path);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function isTruthy(value) {
|
|
316
|
+
return /^(1|true|yes|on)$/i.test(value?.trim() ?? "");
|
|
317
|
+
}
|
|
318
|
+
function sessionRootFromPath(path) {
|
|
319
|
+
const trimmed = path?.trim();
|
|
320
|
+
if (!trimmed) return null;
|
|
321
|
+
const match = /^\/sessions\/[^/]+(?=\/|$)/.exec(trimmed);
|
|
322
|
+
return match?.[0] ?? null;
|
|
323
|
+
}
|
|
324
|
+
function coworkSessionRoot() {
|
|
325
|
+
const home = process.env.HOME?.trim();
|
|
326
|
+
const homeSessionRoot = sessionRootFromPath(home);
|
|
327
|
+
if (homeSessionRoot && isDirectory((0, import_node_path.join)(homeSessionRoot, "mnt"))) {
|
|
328
|
+
return homeSessionRoot;
|
|
329
|
+
}
|
|
330
|
+
const cwdSessionRoot = sessionRootFromPath(process.cwd());
|
|
331
|
+
if (cwdSessionRoot && isDirectory((0, import_node_path.join)(cwdSessionRoot, "mnt"))) {
|
|
332
|
+
return cwdSessionRoot;
|
|
333
|
+
}
|
|
334
|
+
if (isTruthy(process.env.CLAUDE_CODE_REMOTE) && home) {
|
|
335
|
+
const mountedRoot = (0, import_node_path.join)(home, "mnt");
|
|
336
|
+
if (isDirectory(mountedRoot)) return (0, import_node_path.resolve)(home);
|
|
337
|
+
}
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
function isCoworkLikeSandbox() {
|
|
341
|
+
const home = process.env.HOME?.trim();
|
|
342
|
+
return isTruthy(process.env.CLAUDE_CODE_REMOTE) || sessionRootFromPath(home) !== null || sessionRootFromPath(process.cwd()) !== null;
|
|
343
|
+
}
|
|
344
|
+
function coworkProjectScore(path) {
|
|
345
|
+
let score = 0;
|
|
346
|
+
for (const marker of COWORK_PROJECT_MARKERS) {
|
|
347
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(path, marker))) score += 1;
|
|
348
|
+
}
|
|
349
|
+
return score;
|
|
350
|
+
}
|
|
351
|
+
function listCoworkWorkspaceDirCandidates() {
|
|
352
|
+
if (!isCoworkLikeSandbox()) {
|
|
353
|
+
return [];
|
|
354
|
+
}
|
|
355
|
+
const explicitProjectDir = process.env.CLAUDE_PROJECT_DIR?.trim();
|
|
356
|
+
if (explicitProjectDir && isDirectory(explicitProjectDir)) {
|
|
357
|
+
return [(0, import_node_path.resolve)(explicitProjectDir)];
|
|
358
|
+
}
|
|
359
|
+
const sessionRoot = coworkSessionRoot();
|
|
360
|
+
if (!sessionRoot) return [];
|
|
361
|
+
const mountedRoot = (0, import_node_path.join)(sessionRoot, "mnt");
|
|
362
|
+
if (!isDirectory(mountedRoot)) return [];
|
|
363
|
+
let names;
|
|
364
|
+
try {
|
|
365
|
+
names = (0, import_node_fs.readdirSync)(mountedRoot).sort();
|
|
366
|
+
} catch {
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
const candidates = [];
|
|
370
|
+
for (const name of names) {
|
|
371
|
+
if (name.startsWith(".") || COWORK_IGNORED_WORKSPACE_DIRS.has(name)) {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
const candidate = (0, import_node_path.join)(mountedRoot, name);
|
|
375
|
+
if (isDirectory(candidate)) candidates.push(candidate);
|
|
376
|
+
}
|
|
377
|
+
if (candidates.length <= 1) return candidates;
|
|
378
|
+
const projectLike = candidates.filter(
|
|
379
|
+
(candidate) => coworkProjectScore(candidate) > 0
|
|
380
|
+
);
|
|
381
|
+
return projectLike.length > 0 ? projectLike : candidates;
|
|
382
|
+
}
|
|
383
|
+
function isInIgnoredCoworkMount(path) {
|
|
384
|
+
const sessionRoot = coworkSessionRoot();
|
|
385
|
+
if (!sessionRoot) return false;
|
|
386
|
+
const mountedRoot = canonicalPath((0, import_node_path.join)(sessionRoot, "mnt"));
|
|
387
|
+
const resolvedPath = canonicalPath(path);
|
|
388
|
+
const prefix = `${mountedRoot}/`;
|
|
389
|
+
if (!resolvedPath.startsWith(prefix)) return false;
|
|
390
|
+
const relativePath = resolvedPath.slice(prefix.length);
|
|
391
|
+
const mountName = relativePath.split("/")[0];
|
|
392
|
+
return mountName.startsWith(".") || COWORK_IGNORED_WORKSPACE_DIRS.has(mountName);
|
|
393
|
+
}
|
|
394
|
+
function detectCoworkWorkspaceDir() {
|
|
395
|
+
const candidates = listCoworkWorkspaceDirCandidates();
|
|
396
|
+
return candidates.length === 1 ? candidates[0] : null;
|
|
397
|
+
}
|
|
398
|
+
function loadProjectEnvCandidates(startDir = process.cwd()) {
|
|
399
|
+
const filePaths = [];
|
|
400
|
+
const sources = /* @__PURE__ */ new Map();
|
|
401
|
+
const nearestFile = findNearestEnvFile(PROJECT_DEEPLINE_ENV_FILE, startDir);
|
|
402
|
+
if (nearestFile && !isInIgnoredCoworkMount(nearestFile)) {
|
|
403
|
+
filePaths.push(nearestFile);
|
|
404
|
+
sources.set((0, import_node_path.resolve)(nearestFile), "nearest");
|
|
405
|
+
}
|
|
406
|
+
const coworkWorkspaceDir = detectCoworkWorkspaceDir();
|
|
407
|
+
if (coworkWorkspaceDir) {
|
|
408
|
+
const coworkFile = (0, import_node_path.join)(coworkWorkspaceDir, PROJECT_DEEPLINE_ENV_FILE);
|
|
409
|
+
if ((0, import_node_fs.existsSync)(coworkFile) && !filePaths.some((filePath) => (0, import_node_path.resolve)(filePath) === (0, import_node_path.resolve)(coworkFile))) {
|
|
410
|
+
filePaths.push(coworkFile);
|
|
411
|
+
sources.set((0, import_node_path.resolve)(coworkFile), "cowork");
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return filePaths.map((filePath) => ({
|
|
415
|
+
filePath,
|
|
416
|
+
env: parseEnvFile(filePath),
|
|
417
|
+
source: sources.get((0, import_node_path.resolve)(filePath)) ?? "nearest"
|
|
418
|
+
}));
|
|
288
419
|
}
|
|
289
420
|
function normalizeBaseUrl(baseUrl) {
|
|
290
421
|
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
@@ -348,23 +479,35 @@ function loadGlobalCliEnv() {
|
|
|
348
479
|
return loadCliEnv(PROD_URL);
|
|
349
480
|
}
|
|
350
481
|
function autoDetectBaseUrl() {
|
|
351
|
-
const
|
|
482
|
+
const projectEnvs = loadProjectEnvCandidates();
|
|
352
483
|
const globalEnv = loadGlobalCliEnv();
|
|
353
|
-
return normalizeBaseUrl(process.env[HOST_URL_ENV] ?? "") ||
|
|
484
|
+
return normalizeBaseUrl(process.env[HOST_URL_ENV] ?? "") || firstNonEmpty(
|
|
485
|
+
...projectEnvs.map(({ env }) => normalizeBaseUrl(env[HOST_URL_ENV]))
|
|
486
|
+
) || normalizeBaseUrl(globalEnv[HOST_URL_ENV] ?? "") || PROD_URL;
|
|
354
487
|
}
|
|
355
488
|
function resolveApiKeyForBaseUrl(baseUrl, explicitApiKey) {
|
|
356
489
|
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
357
|
-
const
|
|
490
|
+
const projectEnvs = loadProjectEnvCandidates();
|
|
358
491
|
const cliEnv = loadCliEnv(normalizedBaseUrl || baseUrl);
|
|
359
|
-
const projectBaseUrl = normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "");
|
|
360
|
-
const projectKeyApplies = projectBaseUrl === normalizedBaseUrl;
|
|
361
492
|
return firstNonEmpty(
|
|
362
493
|
explicitApiKey,
|
|
363
494
|
process.env[API_KEY_ENV],
|
|
364
|
-
|
|
495
|
+
...projectEnvs.map(({ env }) => {
|
|
496
|
+
const projectBaseUrl = normalizeBaseUrl(env[HOST_URL_ENV] ?? "");
|
|
497
|
+
return projectBaseUrl === normalizedBaseUrl ? env[API_KEY_ENV] : "";
|
|
498
|
+
}),
|
|
365
499
|
cliEnv[API_KEY_ENV]
|
|
366
500
|
);
|
|
367
501
|
}
|
|
502
|
+
function getResolvedProjectAuthSource(baseUrl, apiKey, startDir = process.cwd()) {
|
|
503
|
+
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
504
|
+
const normalizedApiKey = apiKey.trim();
|
|
505
|
+
if (!normalizedBaseUrl || !normalizedApiKey) return null;
|
|
506
|
+
return loadProjectEnvCandidates(startDir).find(({ env }) => {
|
|
507
|
+
const projectBaseUrl = normalizeBaseUrl(env[HOST_URL_ENV] ?? "");
|
|
508
|
+
return projectBaseUrl === normalizedBaseUrl && (env[API_KEY_ENV] ?? "").trim() === normalizedApiKey;
|
|
509
|
+
}) ?? null;
|
|
510
|
+
}
|
|
368
511
|
function resolveConfig(options) {
|
|
369
512
|
const baseUrl = normalizeBaseUrl(
|
|
370
513
|
options?.baseUrl?.trim() || autoDetectBaseUrl()
|
|
@@ -387,6 +530,69 @@ function resolveConfig(options) {
|
|
|
387
530
|
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES
|
|
388
531
|
};
|
|
389
532
|
}
|
|
533
|
+
function mergeProjectEnvFile(filePath, values) {
|
|
534
|
+
const existing = parseEnvFile(filePath);
|
|
535
|
+
const merged = { ...existing, ...values };
|
|
536
|
+
const dir = (0, import_node_path.dirname)(filePath);
|
|
537
|
+
if (!(0, import_node_fs.existsSync)(dir)) (0, import_node_fs.mkdirSync)(dir, { recursive: true });
|
|
538
|
+
ensureProjectEnvIsIgnored(dir);
|
|
539
|
+
const allowedKeys = /* @__PURE__ */ new Set([HOST_URL_ENV, API_KEY_ENV]);
|
|
540
|
+
const lines = Object.entries(merged).filter(([key, value]) => allowedKeys.has(key) && value !== "").map(([key, value]) => `${key}=${value}`);
|
|
541
|
+
(0, import_node_fs.writeFileSync)(filePath, `${lines.join("\n")}
|
|
542
|
+
`, "utf-8");
|
|
543
|
+
}
|
|
544
|
+
function ensureProjectEnvIsIgnored(dir) {
|
|
545
|
+
const gitignorePath = (0, import_node_path.join)(dir, ".gitignore");
|
|
546
|
+
const entry = PROJECT_DEEPLINE_ENV_FILE;
|
|
547
|
+
const existing = (0, import_node_fs.existsSync)(gitignorePath) ? (0, import_node_fs.readFileSync)(gitignorePath, "utf-8") : "";
|
|
548
|
+
const alreadyIgnored = existing.split(/\r?\n/).map((line) => line.trim()).some((line) => line === entry || line === `/${entry}`);
|
|
549
|
+
if (alreadyIgnored) return;
|
|
550
|
+
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
551
|
+
(0, import_node_fs.writeFileSync)(gitignorePath, `${existing}${prefix}${entry}
|
|
552
|
+
`, "utf-8");
|
|
553
|
+
}
|
|
554
|
+
function saveProjectDeeplineEnvValues(values, startDir = process.cwd()) {
|
|
555
|
+
const target = resolveProjectPinTarget(startDir);
|
|
556
|
+
if (!target.ok) {
|
|
557
|
+
throw new ConfigError(
|
|
558
|
+
`Cowork project folder is ambiguous. Candidate folders: ${target.candidates.join(
|
|
559
|
+
", "
|
|
560
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder before running this command.`
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
const filePath = (0, import_node_path.join)(target.dir, PROJECT_DEEPLINE_ENV_FILE);
|
|
564
|
+
mergeProjectEnvFile(filePath, values);
|
|
565
|
+
return [filePath];
|
|
566
|
+
}
|
|
567
|
+
function resolveProjectPinTarget(startDir = process.cwd()) {
|
|
568
|
+
const nearestFile = findNearestEnvFile(PROJECT_DEEPLINE_ENV_FILE, startDir);
|
|
569
|
+
if (nearestFile && !isInIgnoredCoworkMount(nearestFile)) {
|
|
570
|
+
return { ok: true, dir: (0, import_node_path.dirname)(nearestFile), source: "nearest" };
|
|
571
|
+
}
|
|
572
|
+
const coworkCandidates = listCoworkWorkspaceDirCandidates();
|
|
573
|
+
if (coworkCandidates.length === 1) {
|
|
574
|
+
return { ok: true, dir: coworkCandidates[0], source: "cowork" };
|
|
575
|
+
}
|
|
576
|
+
if (coworkCandidates.length > 1) {
|
|
577
|
+
const resolvedStartDir = canonicalPath(startDir);
|
|
578
|
+
const cwdCandidate = coworkCandidates.find((candidate) => {
|
|
579
|
+
const resolvedCandidate = canonicalPath(candidate);
|
|
580
|
+
return resolvedStartDir === resolvedCandidate || resolvedStartDir.startsWith(`${resolvedCandidate}/`);
|
|
581
|
+
});
|
|
582
|
+
if (cwdCandidate) {
|
|
583
|
+
return { ok: true, dir: cwdCandidate, source: "cowork" };
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
ok: false,
|
|
587
|
+
reason: "ambiguous_cowork_project",
|
|
588
|
+
candidates: coworkCandidates
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
return { ok: true, dir: (0, import_node_path.resolve)(startDir), source: "cwd" };
|
|
592
|
+
}
|
|
593
|
+
function getActiveProjectAuthSource(startDir = process.cwd()) {
|
|
594
|
+
return loadProjectEnvCandidates(startDir)[0] ?? null;
|
|
595
|
+
}
|
|
390
596
|
|
|
391
597
|
// src/http.ts
|
|
392
598
|
var import_node_fs2 = require("fs");
|
|
@@ -413,10 +619,10 @@ var SDK_RELEASE = {
|
|
|
413
619
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
414
620
|
// the SDK enrich generator's one-second stale policy.
|
|
415
621
|
// 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
|
|
416
|
-
version: "0.1.
|
|
622
|
+
version: "0.1.137",
|
|
417
623
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
418
624
|
supportPolicy: {
|
|
419
|
-
latest: "0.1.
|
|
625
|
+
latest: "0.1.137",
|
|
420
626
|
minimumSupported: "0.1.53",
|
|
421
627
|
deprecatedBelow: "0.1.53",
|
|
422
628
|
commandMinimumSupported: [
|
|
@@ -507,7 +713,7 @@ function normalizeAgentRuntime(value) {
|
|
|
507
713
|
if (explicit === "gemini_cli") return "gemini";
|
|
508
714
|
return EXPLICIT_AGENT_RUNTIMES.has(explicit) ? explicit : null;
|
|
509
715
|
}
|
|
510
|
-
function
|
|
716
|
+
function isCoworkLikeSandbox2() {
|
|
511
717
|
const pluginMode = truthyEnv("DEEPLINE_PLUGIN_MODE");
|
|
512
718
|
const claudeRemote = truthyEnv("CLAUDE_CODE_REMOTE");
|
|
513
719
|
const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
|
|
@@ -520,7 +726,7 @@ function detectAgentRuntime(options = {}) {
|
|
|
520
726
|
const explicit = normalizeAgentRuntime(process.env.DEEPLINE_AGENT_RUNTIME);
|
|
521
727
|
if (explicit) return explicit;
|
|
522
728
|
if (process.env.CODEX_THREAD_ID?.trim()) return "codex";
|
|
523
|
-
if (options.detectCowork !== false &&
|
|
729
|
+
if (options.detectCowork !== false && isCoworkLikeSandbox2()) {
|
|
524
730
|
return "claude_cowork";
|
|
525
731
|
}
|
|
526
732
|
if (process.env.CLAUDECODE?.trim() === "1") return "claude_code";
|
|
@@ -986,7 +1192,7 @@ function sleep(ms) {
|
|
|
986
1192
|
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
987
1193
|
}
|
|
988
1194
|
function withCoworkNetworkHint(message) {
|
|
989
|
-
if (!
|
|
1195
|
+
if (!isCoworkLikeSandbox2() || message.includes(COWORK_NETWORK_HINT)) {
|
|
990
1196
|
return message;
|
|
991
1197
|
}
|
|
992
1198
|
return `${message}
|
|
@@ -18465,6 +18671,15 @@ Examples:
|
|
|
18465
18671
|
async function fetchOrganizations(http, apiKey) {
|
|
18466
18672
|
return http.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
|
|
18467
18673
|
}
|
|
18674
|
+
function normalizeAuthScope(value) {
|
|
18675
|
+
if (!value) return "auto";
|
|
18676
|
+
if (value === "auto" || value === "folder" || value === "global") {
|
|
18677
|
+
return value;
|
|
18678
|
+
}
|
|
18679
|
+
throw new Error(
|
|
18680
|
+
`Invalid --auth-scope "${value}". Expected one of: auto, folder, global.`
|
|
18681
|
+
);
|
|
18682
|
+
}
|
|
18468
18683
|
function orgListLines(orgs) {
|
|
18469
18684
|
return orgs.map((org, index) => {
|
|
18470
18685
|
const current = org.is_current ? " (current)" : "";
|
|
@@ -18472,6 +18687,90 @@ function orgListLines(orgs) {
|
|
|
18472
18687
|
return `${index + 1}. ${org.name}${role}${current}`;
|
|
18473
18688
|
});
|
|
18474
18689
|
}
|
|
18690
|
+
function redactApiKey(value) {
|
|
18691
|
+
if (!value) return null;
|
|
18692
|
+
if (value.length <= 10) return `${value.slice(0, 3)}...`;
|
|
18693
|
+
return `${value.slice(0, 8)}...${value.slice(-4)}`;
|
|
18694
|
+
}
|
|
18695
|
+
function processEnvValue(name) {
|
|
18696
|
+
return process.env[name]?.trim() ?? "";
|
|
18697
|
+
}
|
|
18698
|
+
function resolveOrgSwitchAuthTarget(scope, config) {
|
|
18699
|
+
const activeProject = getResolvedProjectAuthSource(
|
|
18700
|
+
config.baseUrl,
|
|
18701
|
+
config.apiKey
|
|
18702
|
+
);
|
|
18703
|
+
const folderTarget = resolveProjectPinTarget();
|
|
18704
|
+
const globalOverrideWarning = activeProject && scope === "global" ? [
|
|
18705
|
+
`Folder auth in ${activeProject.filePath} overrides global auth for commands run here.`
|
|
18706
|
+
] : [];
|
|
18707
|
+
if (scope === "folder") {
|
|
18708
|
+
if (!folderTarget.ok) {
|
|
18709
|
+
throw new Error(
|
|
18710
|
+
`Cowork project folder is ambiguous. Candidate folders: ${folderTarget.candidates.join(
|
|
18711
|
+
", "
|
|
18712
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder before running this command.`
|
|
18713
|
+
);
|
|
18714
|
+
}
|
|
18715
|
+
return {
|
|
18716
|
+
kind: "folder",
|
|
18717
|
+
requested_scope: scope,
|
|
18718
|
+
effective_scope: "folder",
|
|
18719
|
+
reason: "explicit_folder",
|
|
18720
|
+
source: folderTarget.source,
|
|
18721
|
+
warnings: []
|
|
18722
|
+
};
|
|
18723
|
+
}
|
|
18724
|
+
if (scope === "global") {
|
|
18725
|
+
return {
|
|
18726
|
+
kind: "global",
|
|
18727
|
+
requested_scope: scope,
|
|
18728
|
+
effective_scope: "global",
|
|
18729
|
+
reason: "explicit_global",
|
|
18730
|
+
warnings: globalOverrideWarning
|
|
18731
|
+
};
|
|
18732
|
+
}
|
|
18733
|
+
if (activeProject) {
|
|
18734
|
+
return {
|
|
18735
|
+
kind: "folder",
|
|
18736
|
+
requested_scope: scope,
|
|
18737
|
+
effective_scope: "folder",
|
|
18738
|
+
reason: "existing_folder_auth",
|
|
18739
|
+
source: activeProject.source,
|
|
18740
|
+
warnings: []
|
|
18741
|
+
};
|
|
18742
|
+
}
|
|
18743
|
+
if (folderTarget.ok && folderTarget.source === "cowork") {
|
|
18744
|
+
return {
|
|
18745
|
+
kind: "folder",
|
|
18746
|
+
requested_scope: scope,
|
|
18747
|
+
effective_scope: "folder",
|
|
18748
|
+
reason: "detected_cowork_project",
|
|
18749
|
+
source: "cowork",
|
|
18750
|
+
warnings: []
|
|
18751
|
+
};
|
|
18752
|
+
}
|
|
18753
|
+
if (!folderTarget.ok) {
|
|
18754
|
+
return {
|
|
18755
|
+
kind: "global",
|
|
18756
|
+
requested_scope: scope,
|
|
18757
|
+
effective_scope: "global",
|
|
18758
|
+
reason: "ambiguous_cowork_fell_back_global",
|
|
18759
|
+
warnings: [
|
|
18760
|
+
`Cowork project folder is ambiguous, so global auth was updated. Candidate folders: ${folderTarget.candidates.join(
|
|
18761
|
+
", "
|
|
18762
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder to update folder auth.`
|
|
18763
|
+
]
|
|
18764
|
+
};
|
|
18765
|
+
}
|
|
18766
|
+
return {
|
|
18767
|
+
kind: "global",
|
|
18768
|
+
requested_scope: scope,
|
|
18769
|
+
effective_scope: "global",
|
|
18770
|
+
reason: "default_global",
|
|
18771
|
+
warnings: []
|
|
18772
|
+
};
|
|
18773
|
+
}
|
|
18475
18774
|
async function handleOrgList(options) {
|
|
18476
18775
|
const config = resolveConfig();
|
|
18477
18776
|
const http = new HttpClient(config);
|
|
@@ -18491,7 +18790,89 @@ async function handleOrgList(options) {
|
|
|
18491
18790
|
{ json: options.json }
|
|
18492
18791
|
);
|
|
18493
18792
|
}
|
|
18793
|
+
async function handleOrgStatus(options) {
|
|
18794
|
+
const config = resolveConfig();
|
|
18795
|
+
const http = new HttpClient(config);
|
|
18796
|
+
const payload = await fetchOrganizations(http, config.apiKey);
|
|
18797
|
+
const current = payload.organizations.find((org) => org.is_current) ?? payload.organizations.find((org) => org.org_id === payload.current_org_id) ?? null;
|
|
18798
|
+
const projectCandidate = getActiveProjectAuthSource();
|
|
18799
|
+
const activeProject = getResolvedProjectAuthSource(
|
|
18800
|
+
config.baseUrl,
|
|
18801
|
+
config.apiKey
|
|
18802
|
+
);
|
|
18803
|
+
const folderTarget = resolveProjectPinTarget();
|
|
18804
|
+
const hostPath = hostEnvFilePath(config.baseUrl);
|
|
18805
|
+
const envApiKey = processEnvValue(API_KEY_ENV);
|
|
18806
|
+
const envHostUrl = processEnvValue(HOST_URL_ENV);
|
|
18807
|
+
const authSource = envApiKey ? {
|
|
18808
|
+
scope: "env",
|
|
18809
|
+
source: "process",
|
|
18810
|
+
path: null,
|
|
18811
|
+
api_key: redactApiKey(envApiKey),
|
|
18812
|
+
host: envHostUrl || null,
|
|
18813
|
+
overrides_global: true,
|
|
18814
|
+
overrides_folder: Boolean(projectCandidate)
|
|
18815
|
+
} : activeProject ? {
|
|
18816
|
+
scope: "folder",
|
|
18817
|
+
source: activeProject.source,
|
|
18818
|
+
path: activeProject.filePath,
|
|
18819
|
+
api_key: redactApiKey(activeProject.env.DEEPLINE_API_KEY),
|
|
18820
|
+
overrides_global: true
|
|
18821
|
+
} : {
|
|
18822
|
+
scope: "global",
|
|
18823
|
+
source: "host",
|
|
18824
|
+
path: hostPath,
|
|
18825
|
+
api_key: redactApiKey(config.apiKey),
|
|
18826
|
+
overrides_global: false
|
|
18827
|
+
};
|
|
18828
|
+
const folderTargetPayload = folderTarget.ok ? {
|
|
18829
|
+
ok: true,
|
|
18830
|
+
source: folderTarget.source,
|
|
18831
|
+
dir: folderTarget.dir,
|
|
18832
|
+
env_path: `${folderTarget.dir}/.env.deepline`
|
|
18833
|
+
} : {
|
|
18834
|
+
ok: false,
|
|
18835
|
+
reason: folderTarget.reason,
|
|
18836
|
+
candidates: folderTarget.candidates
|
|
18837
|
+
};
|
|
18838
|
+
const lines = [
|
|
18839
|
+
`Organization: ${current?.name ?? "(unknown)"}`,
|
|
18840
|
+
`Host: ${config.baseUrl}`,
|
|
18841
|
+
`Auth scope: ${authSource.scope}`
|
|
18842
|
+
];
|
|
18843
|
+
if (authSource.path) {
|
|
18844
|
+
lines.push(`Auth file: ${authSource.path}`);
|
|
18845
|
+
} else {
|
|
18846
|
+
lines.push(`Auth source: ${API_KEY_ENV} process environment`);
|
|
18847
|
+
}
|
|
18848
|
+
if (envApiKey) {
|
|
18849
|
+
lines.push(`${API_KEY_ENV} overrides saved auth for this process.`);
|
|
18850
|
+
} else if (activeProject) {
|
|
18851
|
+
lines.push("Global auth is overridden in this folder.");
|
|
18852
|
+
}
|
|
18853
|
+
printCommandEnvelope(
|
|
18854
|
+
{
|
|
18855
|
+
ok: true,
|
|
18856
|
+
host: config.baseUrl,
|
|
18857
|
+
organization: current,
|
|
18858
|
+
current_org_id: payload.current_org_id,
|
|
18859
|
+
auth_source: authSource,
|
|
18860
|
+
host_env_path: hostPath,
|
|
18861
|
+
folder_target: folderTargetPayload,
|
|
18862
|
+
next: {
|
|
18863
|
+
set_auto: "deepline org set <org>",
|
|
18864
|
+
set_folder: "deepline org set <org> --auth-scope folder",
|
|
18865
|
+
set_global: "deepline org set <org> --auth-scope global"
|
|
18866
|
+
},
|
|
18867
|
+
render: {
|
|
18868
|
+
sections: [{ title: "org status", lines }]
|
|
18869
|
+
}
|
|
18870
|
+
},
|
|
18871
|
+
{ json: options.json }
|
|
18872
|
+
);
|
|
18873
|
+
}
|
|
18494
18874
|
async function handleOrgSwitch(selection, options) {
|
|
18875
|
+
const authScope = normalizeAuthScope(options.authScope);
|
|
18495
18876
|
const config = resolveConfig();
|
|
18496
18877
|
const http = new HttpClient(config);
|
|
18497
18878
|
const payload = await fetchOrganizations(http, config.apiKey);
|
|
@@ -18499,7 +18880,10 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18499
18880
|
printCommandEnvelope(
|
|
18500
18881
|
{
|
|
18501
18882
|
...payload,
|
|
18502
|
-
next: {
|
|
18883
|
+
next: { set: "deepline org set <number>" },
|
|
18884
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
18885
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
18886
|
+
warnings: options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
18503
18887
|
render: {
|
|
18504
18888
|
sections: [
|
|
18505
18889
|
{
|
|
@@ -18507,7 +18891,7 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18507
18891
|
lines: orgListLines(payload.organizations)
|
|
18508
18892
|
}
|
|
18509
18893
|
],
|
|
18510
|
-
actions: [{ label: "Run", command: "deepline org
|
|
18894
|
+
actions: [{ label: "Run", command: "deepline org set <number>" }]
|
|
18511
18895
|
}
|
|
18512
18896
|
},
|
|
18513
18897
|
{ json: options.json }
|
|
@@ -18530,16 +18914,56 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18530
18914
|
if (!target) {
|
|
18531
18915
|
throw new Error("Could not resolve the selected organization.");
|
|
18532
18916
|
}
|
|
18917
|
+
const authTarget = resolveOrgSwitchAuthTarget(authScope, config);
|
|
18533
18918
|
if (target.is_current) {
|
|
18919
|
+
let project_env_paths2 = [];
|
|
18920
|
+
if (authTarget.kind === "folder") {
|
|
18921
|
+
project_env_paths2 = saveProjectDeeplineEnvValues({
|
|
18922
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18923
|
+
DEEPLINE_API_KEY: config.apiKey
|
|
18924
|
+
});
|
|
18925
|
+
} else {
|
|
18926
|
+
saveHostEnvValues(config.baseUrl, {
|
|
18927
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18928
|
+
DEEPLINE_API_KEY: config.apiKey
|
|
18929
|
+
});
|
|
18930
|
+
}
|
|
18931
|
+
const renderLines2 = [`Already on ${target.name}.`];
|
|
18932
|
+
for (const projectPath of project_env_paths2) {
|
|
18933
|
+
renderLines2.push(`Saved folder auth in ${projectPath}`);
|
|
18934
|
+
}
|
|
18935
|
+
if (authTarget.kind === "global") {
|
|
18936
|
+
renderLines2.push(`Saved global auth in ${hostEnvFilePath(config.baseUrl)}`);
|
|
18937
|
+
}
|
|
18938
|
+
renderLines2.push(
|
|
18939
|
+
`Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
|
|
18940
|
+
);
|
|
18941
|
+
if (options.deprecatedSwitch) {
|
|
18942
|
+
renderLines2.push("Warning: org switch is deprecated; use org set.");
|
|
18943
|
+
}
|
|
18944
|
+
for (const warning of authTarget.warnings) {
|
|
18945
|
+
renderLines2.push(`Warning: ${warning}`);
|
|
18946
|
+
}
|
|
18947
|
+
const warnings2 = [
|
|
18948
|
+
...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
18949
|
+
...authTarget.warnings
|
|
18950
|
+
];
|
|
18534
18951
|
printCommandEnvelope(
|
|
18535
18952
|
{
|
|
18536
18953
|
ok: true,
|
|
18537
18954
|
unchanged: true,
|
|
18538
18955
|
organization: target,
|
|
18956
|
+
requested_auth_scope: authTarget.requested_scope,
|
|
18957
|
+
effective_auth_scope: authTarget.effective_scope,
|
|
18958
|
+
auth_scope_reason: authTarget.reason,
|
|
18959
|
+
auth_scope: authTarget.effective_scope,
|
|
18960
|
+
host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
|
|
18961
|
+
project_env_paths: project_env_paths2,
|
|
18962
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
18963
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
18964
|
+
warnings: warnings2,
|
|
18539
18965
|
render: {
|
|
18540
|
-
sections: [
|
|
18541
|
-
{ title: "org switch", lines: [`Already on ${target.name}.`] }
|
|
18542
|
-
]
|
|
18966
|
+
sections: [{ title: "org set", lines: renderLines2 }]
|
|
18543
18967
|
}
|
|
18544
18968
|
},
|
|
18545
18969
|
{ json: options.json }
|
|
@@ -18550,26 +18974,61 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18550
18974
|
api_key: config.apiKey,
|
|
18551
18975
|
org_id: target.org_id
|
|
18552
18976
|
});
|
|
18553
|
-
|
|
18554
|
-
|
|
18555
|
-
|
|
18556
|
-
|
|
18557
|
-
|
|
18977
|
+
let project_env_paths = [];
|
|
18978
|
+
if (authTarget.kind === "folder") {
|
|
18979
|
+
project_env_paths = saveProjectDeeplineEnvValues({
|
|
18980
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18981
|
+
DEEPLINE_API_KEY: switched.api_key
|
|
18982
|
+
});
|
|
18983
|
+
} else {
|
|
18984
|
+
saveHostEnvValues(config.baseUrl, {
|
|
18985
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18986
|
+
DEEPLINE_API_KEY: switched.api_key,
|
|
18987
|
+
DEEPLINE_ACTIVE_ORG_ID: switched.org_id,
|
|
18988
|
+
DEEPLINE_ACTIVE_ORG_NAME: switched.org_name
|
|
18989
|
+
});
|
|
18990
|
+
}
|
|
18558
18991
|
const { api_key: _apiKey, ...publicSwitched } = switched;
|
|
18992
|
+
const renderLines = [`Switched to ${switched.org_name}.`];
|
|
18993
|
+
if (authTarget.kind === "folder") {
|
|
18994
|
+
for (const projectPath of project_env_paths) {
|
|
18995
|
+
renderLines.push(`Saved folder auth in ${projectPath}`);
|
|
18996
|
+
}
|
|
18997
|
+
} else {
|
|
18998
|
+
renderLines.push(`Saved global auth in ${hostEnvFilePath(config.baseUrl)}`);
|
|
18999
|
+
}
|
|
19000
|
+
renderLines.push(
|
|
19001
|
+
`Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
|
|
19002
|
+
);
|
|
19003
|
+
if (options.deprecatedSwitch) {
|
|
19004
|
+
renderLines.push("Warning: org switch is deprecated; use org set.");
|
|
19005
|
+
}
|
|
19006
|
+
for (const warning of authTarget.warnings) {
|
|
19007
|
+
renderLines.push(`Warning: ${warning}`);
|
|
19008
|
+
}
|
|
19009
|
+
const warnings = [
|
|
19010
|
+
...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
19011
|
+
...authTarget.warnings
|
|
19012
|
+
];
|
|
18559
19013
|
printCommandEnvelope(
|
|
18560
19014
|
{
|
|
18561
19015
|
ok: true,
|
|
18562
|
-
host_env_path: hostEnvFilePath(config.baseUrl),
|
|
19016
|
+
host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
|
|
19017
|
+
project_env_paths,
|
|
18563
19018
|
...publicSwitched,
|
|
18564
19019
|
api_key_saved: true,
|
|
19020
|
+
requested_auth_scope: authTarget.requested_scope,
|
|
19021
|
+
effective_auth_scope: authTarget.effective_scope,
|
|
19022
|
+
auth_scope_reason: authTarget.reason,
|
|
19023
|
+
auth_scope: authTarget.effective_scope,
|
|
19024
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
19025
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
19026
|
+
warnings,
|
|
18565
19027
|
render: {
|
|
18566
19028
|
sections: [
|
|
18567
19029
|
{
|
|
18568
|
-
title: "org
|
|
18569
|
-
lines:
|
|
18570
|
-
`Switched to ${switched.org_name}.`,
|
|
18571
|
-
`Saved host auth in ${hostEnvFilePath(config.baseUrl)}`
|
|
18572
|
-
]
|
|
19030
|
+
title: "org set",
|
|
19031
|
+
lines: renderLines
|
|
18573
19032
|
}
|
|
18574
19033
|
]
|
|
18575
19034
|
}
|
|
@@ -18585,6 +19044,7 @@ async function handleOrgCreate(name, options) {
|
|
|
18585
19044
|
name
|
|
18586
19045
|
});
|
|
18587
19046
|
saveHostEnvValues(config.baseUrl, {
|
|
19047
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18588
19048
|
DEEPLINE_API_KEY: created.api_key,
|
|
18589
19049
|
DEEPLINE_ACTIVE_ORG_ID: created.org_id,
|
|
18590
19050
|
DEEPLINE_ACTIVE_ORG_NAME: created.org_name
|
|
@@ -18614,18 +19074,20 @@ async function handleOrgCreate(name, options) {
|
|
|
18614
19074
|
);
|
|
18615
19075
|
}
|
|
18616
19076
|
function registerOrgCommands(program) {
|
|
18617
|
-
const org = program.command("org").description("List, create, and
|
|
19077
|
+
const org = program.command("org").description("List, create, and set organizations.").addHelpText(
|
|
18618
19078
|
"after",
|
|
18619
19079
|
`
|
|
18620
19080
|
Notes:
|
|
18621
|
-
Organizations are workspaces.
|
|
18622
|
-
|
|
19081
|
+
Organizations are workspaces. By default, switching updates the auth scope
|
|
19082
|
+
that will affect later commands from this folder.
|
|
18623
19083
|
|
|
18624
19084
|
Examples:
|
|
18625
19085
|
deepline org list --json
|
|
19086
|
+
deepline org status --json
|
|
18626
19087
|
deepline org create Acme --json
|
|
18627
|
-
deepline org
|
|
18628
|
-
deepline org
|
|
19088
|
+
deepline org set 2
|
|
19089
|
+
deepline org set 2 --auth-scope folder
|
|
19090
|
+
deepline org set --org-id org_123 --json
|
|
18629
19091
|
`
|
|
18630
19092
|
);
|
|
18631
19093
|
org.command("list").description("List your organizations.").addHelpText(
|
|
@@ -18652,21 +19114,65 @@ Examples:
|
|
|
18652
19114
|
deepline org create "Acme Sales" --json
|
|
18653
19115
|
`
|
|
18654
19116
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgCreate);
|
|
18655
|
-
org.command("
|
|
18656
|
-
"Switch to another organization and save the new API key in the host auth file."
|
|
18657
|
-
).addHelpText(
|
|
19117
|
+
org.command("status").description("Show the current organization and auth source.").addHelpText(
|
|
18658
19118
|
"after",
|
|
18659
19119
|
`
|
|
18660
19120
|
Notes:
|
|
18661
|
-
|
|
18662
|
-
|
|
19121
|
+
Read-only. Shows whether commands resolve auth from process env, a folder
|
|
19122
|
+
.env.deepline file, or global host auth.
|
|
19123
|
+
|
|
19124
|
+
Examples:
|
|
19125
|
+
deepline org status
|
|
19126
|
+
deepline org status --json
|
|
19127
|
+
`
|
|
19128
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgStatus);
|
|
19129
|
+
const addOrgSetOptions = (command) => command.option("--org-id <id>", "Set using an explicit organization id").option(
|
|
19130
|
+
"--auth-scope <scope>",
|
|
19131
|
+
"Where to save auth: auto, folder, or global",
|
|
19132
|
+
"auto"
|
|
19133
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped");
|
|
19134
|
+
addOrgSetOptions(
|
|
19135
|
+
org.command("set [selection]").description("Set the organization for the selected auth scope.").addHelpText(
|
|
19136
|
+
"after",
|
|
19137
|
+
`
|
|
19138
|
+
Notes:
|
|
19139
|
+
Selection can be a list number, exact organization name, or organization id.
|
|
19140
|
+
Without a selection, prints choices. The default --auth-scope auto updates
|
|
19141
|
+
the folder auth file when one controls this command, updates the detected
|
|
19142
|
+
Cowork project folder when present, and otherwise updates global host auth.
|
|
19143
|
+
|
|
19144
|
+
Examples:
|
|
19145
|
+
deepline org set
|
|
19146
|
+
deepline org set 2
|
|
19147
|
+
deepline org set 2 --auth-scope folder
|
|
19148
|
+
deepline org set 2 --auth-scope global
|
|
19149
|
+
deepline org set --org-id org_123 --json
|
|
19150
|
+
`
|
|
19151
|
+
)
|
|
19152
|
+
).action(handleOrgSwitch);
|
|
19153
|
+
addOrgSetOptions(
|
|
19154
|
+
org.command("switch [selection]").description(
|
|
19155
|
+
"Deprecated alias for org set. Set the organization for the selected auth scope."
|
|
19156
|
+
).addHelpText(
|
|
19157
|
+
"after",
|
|
19158
|
+
`
|
|
19159
|
+
Notes:
|
|
19160
|
+
Deprecated alias. Use deepline org set instead. The default --auth-scope auto
|
|
19161
|
+
updates the folder auth file when one controls this command, updates the
|
|
19162
|
+
detected Cowork project folder when present, and otherwise updates global host
|
|
19163
|
+
auth.
|
|
18663
19164
|
|
|
18664
19165
|
Examples:
|
|
18665
19166
|
deepline org switch
|
|
18666
19167
|
deepline org switch 2
|
|
19168
|
+
deepline org switch 2 --auth-scope folder
|
|
19169
|
+
deepline org switch 2 --auth-scope global
|
|
18667
19170
|
deepline org switch --org-id org_123 --json
|
|
18668
19171
|
`
|
|
18669
|
-
|
|
19172
|
+
)
|
|
19173
|
+
).action(
|
|
19174
|
+
(selection, options) => handleOrgSwitch(selection, { ...options, deprecatedSwitch: true })
|
|
19175
|
+
);
|
|
18670
19176
|
}
|
|
18671
19177
|
|
|
18672
19178
|
// src/cli/commands/quickstart.ts
|