deepline 0.1.136 → 0.1.138
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 +576 -80
- package/dist/cli/index.mjs +600 -96
- package/dist/index.js +148 -14
- package/dist/index.mjs +157 -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.138",
|
|
394
608
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
395
609
|
supportPolicy: {
|
|
396
|
-
latest: "0.1.
|
|
610
|
+
latest: "0.1.138",
|
|
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}
|
|
@@ -6983,9 +7197,9 @@ import { createHash as createHash2 } from "crypto";
|
|
|
6983
7197
|
import {
|
|
6984
7198
|
existsSync as existsSync6,
|
|
6985
7199
|
readFileSync as readFileSync6,
|
|
6986
|
-
readdirSync,
|
|
6987
|
-
realpathSync,
|
|
6988
|
-
statSync as
|
|
7200
|
+
readdirSync as readdirSync2,
|
|
7201
|
+
realpathSync as realpathSync2,
|
|
7202
|
+
statSync as statSync3,
|
|
6989
7203
|
writeFileSync as writeFileSync8
|
|
6990
7204
|
} from "fs";
|
|
6991
7205
|
import { basename, dirname as dirname6, join as join5, resolve as resolve7 } from "path";
|
|
@@ -6996,7 +7210,7 @@ import {
|
|
|
6996
7210
|
closeSync,
|
|
6997
7211
|
openSync,
|
|
6998
7212
|
readSync,
|
|
6999
|
-
statSync,
|
|
7213
|
+
statSync as statSync2,
|
|
7000
7214
|
writeFileSync as writeFileSync7
|
|
7001
7215
|
} from "fs";
|
|
7002
7216
|
import { isAbsolute, relative, resolve as resolve6 } from "path";
|
|
@@ -7429,7 +7643,7 @@ function inferCsvColumnSpecs(headers, rows) {
|
|
|
7429
7643
|
}
|
|
7430
7644
|
function readCsvSample(csvPath) {
|
|
7431
7645
|
const resolvedPath = resolve6(csvPath);
|
|
7432
|
-
const size =
|
|
7646
|
+
const size = statSync2(resolvedPath).size;
|
|
7433
7647
|
const fd = openSync(resolvedPath, "r");
|
|
7434
7648
|
const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
|
|
7435
7649
|
const buffer = Buffer.alloc(byteLength);
|
|
@@ -9465,7 +9679,7 @@ function preflightLocalFileInputs(runtimeInput) {
|
|
|
9465
9679
|
}
|
|
9466
9680
|
let stat2;
|
|
9467
9681
|
try {
|
|
9468
|
-
stat2 =
|
|
9682
|
+
stat2 = statSync3(absolutePath);
|
|
9469
9683
|
} catch (error) {
|
|
9470
9684
|
throw new DeeplineError(
|
|
9471
9685
|
`Input ${ref.inputPath} references a local file that is not readable: ${ref.value} (${error instanceof Error ? error.message : String(error)}). No run was created.`,
|
|
@@ -9617,7 +9831,7 @@ function stageFile(logicalPath, absolutePath) {
|
|
|
9617
9831
|
}
|
|
9618
9832
|
function normalizePlayPath(filePath) {
|
|
9619
9833
|
try {
|
|
9620
|
-
return
|
|
9834
|
+
return realpathSync2.native(resolve7(filePath));
|
|
9621
9835
|
} catch {
|
|
9622
9836
|
return resolve7(filePath);
|
|
9623
9837
|
}
|
|
@@ -12879,7 +13093,7 @@ async function handlePlayRun(args) {
|
|
|
12879
13093
|
if (existsSync6(dir)) {
|
|
12880
13094
|
const base = basename(resolved);
|
|
12881
13095
|
try {
|
|
12882
|
-
const siblings =
|
|
13096
|
+
const siblings = readdirSync2(dir).filter(
|
|
12883
13097
|
(f) => f.includes(base.replace(/\.(play\.)?ts$/, "")) || f.endsWith(".play.ts")
|
|
12884
13098
|
);
|
|
12885
13099
|
if (siblings.length > 0) {
|
|
@@ -17672,9 +17886,9 @@ Examples:
|
|
|
17672
17886
|
import {
|
|
17673
17887
|
existsSync as existsSync7,
|
|
17674
17888
|
mkdirSync as mkdirSync5,
|
|
17675
|
-
readdirSync as
|
|
17889
|
+
readdirSync as readdirSync3,
|
|
17676
17890
|
readFileSync as readFileSync7,
|
|
17677
|
-
statSync as
|
|
17891
|
+
statSync as statSync4,
|
|
17678
17892
|
writeFileSync as writeFileSync9
|
|
17679
17893
|
} from "fs";
|
|
17680
17894
|
import { homedir as homedir7, platform } from "os";
|
|
@@ -17759,7 +17973,7 @@ function listSessionFiles(agent) {
|
|
|
17759
17973
|
}
|
|
17760
17974
|
function readDirectoryNames(dir) {
|
|
17761
17975
|
try {
|
|
17762
|
-
return
|
|
17976
|
+
return readdirSync3(dir);
|
|
17763
17977
|
} catch {
|
|
17764
17978
|
return [];
|
|
17765
17979
|
}
|
|
@@ -17770,7 +17984,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
|
|
|
17770
17984
|
if (depth > maxDepth) return;
|
|
17771
17985
|
let entries;
|
|
17772
17986
|
try {
|
|
17773
|
-
entries =
|
|
17987
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
17774
17988
|
} catch {
|
|
17775
17989
|
return;
|
|
17776
17990
|
}
|
|
@@ -17788,7 +18002,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
|
|
|
17788
18002
|
}
|
|
17789
18003
|
function statIfReadable(filePath) {
|
|
17790
18004
|
try {
|
|
17791
|
-
return
|
|
18005
|
+
return statSync4(filePath);
|
|
17792
18006
|
} catch {
|
|
17793
18007
|
return null;
|
|
17794
18008
|
}
|
|
@@ -18481,6 +18695,15 @@ Examples:
|
|
|
18481
18695
|
async function fetchOrganizations(http, apiKey) {
|
|
18482
18696
|
return http.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
|
|
18483
18697
|
}
|
|
18698
|
+
function normalizeAuthScope(value) {
|
|
18699
|
+
if (!value) return "auto";
|
|
18700
|
+
if (value === "auto" || value === "folder" || value === "global") {
|
|
18701
|
+
return value;
|
|
18702
|
+
}
|
|
18703
|
+
throw new Error(
|
|
18704
|
+
`Invalid --auth-scope "${value}". Expected one of: auto, folder, global.`
|
|
18705
|
+
);
|
|
18706
|
+
}
|
|
18484
18707
|
function orgListLines(orgs) {
|
|
18485
18708
|
return orgs.map((org, index) => {
|
|
18486
18709
|
const current = org.is_current ? " (current)" : "";
|
|
@@ -18488,6 +18711,90 @@ function orgListLines(orgs) {
|
|
|
18488
18711
|
return `${index + 1}. ${org.name}${role}${current}`;
|
|
18489
18712
|
});
|
|
18490
18713
|
}
|
|
18714
|
+
function redactApiKey(value) {
|
|
18715
|
+
if (!value) return null;
|
|
18716
|
+
if (value.length <= 10) return `${value.slice(0, 3)}...`;
|
|
18717
|
+
return `${value.slice(0, 8)}...${value.slice(-4)}`;
|
|
18718
|
+
}
|
|
18719
|
+
function processEnvValue(name) {
|
|
18720
|
+
return process.env[name]?.trim() ?? "";
|
|
18721
|
+
}
|
|
18722
|
+
function resolveOrgSwitchAuthTarget(scope, config) {
|
|
18723
|
+
const activeProject = getResolvedProjectAuthSource(
|
|
18724
|
+
config.baseUrl,
|
|
18725
|
+
config.apiKey
|
|
18726
|
+
);
|
|
18727
|
+
const folderTarget = resolveProjectPinTarget();
|
|
18728
|
+
const globalOverrideWarning = activeProject && scope === "global" ? [
|
|
18729
|
+
`Folder auth in ${activeProject.filePath} overrides global auth for commands run here.`
|
|
18730
|
+
] : [];
|
|
18731
|
+
if (scope === "folder") {
|
|
18732
|
+
if (!folderTarget.ok) {
|
|
18733
|
+
throw new Error(
|
|
18734
|
+
`Cowork project folder is ambiguous. Candidate folders: ${folderTarget.candidates.join(
|
|
18735
|
+
", "
|
|
18736
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder before running this command.`
|
|
18737
|
+
);
|
|
18738
|
+
}
|
|
18739
|
+
return {
|
|
18740
|
+
kind: "folder",
|
|
18741
|
+
requested_scope: scope,
|
|
18742
|
+
effective_scope: "folder",
|
|
18743
|
+
reason: "explicit_folder",
|
|
18744
|
+
source: folderTarget.source,
|
|
18745
|
+
warnings: []
|
|
18746
|
+
};
|
|
18747
|
+
}
|
|
18748
|
+
if (scope === "global") {
|
|
18749
|
+
return {
|
|
18750
|
+
kind: "global",
|
|
18751
|
+
requested_scope: scope,
|
|
18752
|
+
effective_scope: "global",
|
|
18753
|
+
reason: "explicit_global",
|
|
18754
|
+
warnings: globalOverrideWarning
|
|
18755
|
+
};
|
|
18756
|
+
}
|
|
18757
|
+
if (activeProject) {
|
|
18758
|
+
return {
|
|
18759
|
+
kind: "folder",
|
|
18760
|
+
requested_scope: scope,
|
|
18761
|
+
effective_scope: "folder",
|
|
18762
|
+
reason: "existing_folder_auth",
|
|
18763
|
+
source: activeProject.source,
|
|
18764
|
+
warnings: []
|
|
18765
|
+
};
|
|
18766
|
+
}
|
|
18767
|
+
if (folderTarget.ok && folderTarget.source === "cowork") {
|
|
18768
|
+
return {
|
|
18769
|
+
kind: "folder",
|
|
18770
|
+
requested_scope: scope,
|
|
18771
|
+
effective_scope: "folder",
|
|
18772
|
+
reason: "detected_cowork_project",
|
|
18773
|
+
source: "cowork",
|
|
18774
|
+
warnings: []
|
|
18775
|
+
};
|
|
18776
|
+
}
|
|
18777
|
+
if (!folderTarget.ok) {
|
|
18778
|
+
return {
|
|
18779
|
+
kind: "global",
|
|
18780
|
+
requested_scope: scope,
|
|
18781
|
+
effective_scope: "global",
|
|
18782
|
+
reason: "ambiguous_cowork_fell_back_global",
|
|
18783
|
+
warnings: [
|
|
18784
|
+
`Cowork project folder is ambiguous, so global auth was updated. Candidate folders: ${folderTarget.candidates.join(
|
|
18785
|
+
", "
|
|
18786
|
+
)}. Set CLAUDE_PROJECT_DIR or cd into the intended project folder to update folder auth.`
|
|
18787
|
+
]
|
|
18788
|
+
};
|
|
18789
|
+
}
|
|
18790
|
+
return {
|
|
18791
|
+
kind: "global",
|
|
18792
|
+
requested_scope: scope,
|
|
18793
|
+
effective_scope: "global",
|
|
18794
|
+
reason: "default_global",
|
|
18795
|
+
warnings: []
|
|
18796
|
+
};
|
|
18797
|
+
}
|
|
18491
18798
|
async function handleOrgList(options) {
|
|
18492
18799
|
const config = resolveConfig();
|
|
18493
18800
|
const http = new HttpClient(config);
|
|
@@ -18507,7 +18814,89 @@ async function handleOrgList(options) {
|
|
|
18507
18814
|
{ json: options.json }
|
|
18508
18815
|
);
|
|
18509
18816
|
}
|
|
18817
|
+
async function handleOrgStatus(options) {
|
|
18818
|
+
const config = resolveConfig();
|
|
18819
|
+
const http = new HttpClient(config);
|
|
18820
|
+
const payload = await fetchOrganizations(http, config.apiKey);
|
|
18821
|
+
const current = payload.organizations.find((org) => org.is_current) ?? payload.organizations.find((org) => org.org_id === payload.current_org_id) ?? null;
|
|
18822
|
+
const projectCandidate = getActiveProjectAuthSource();
|
|
18823
|
+
const activeProject = getResolvedProjectAuthSource(
|
|
18824
|
+
config.baseUrl,
|
|
18825
|
+
config.apiKey
|
|
18826
|
+
);
|
|
18827
|
+
const folderTarget = resolveProjectPinTarget();
|
|
18828
|
+
const hostPath = hostEnvFilePath(config.baseUrl);
|
|
18829
|
+
const envApiKey = processEnvValue(API_KEY_ENV);
|
|
18830
|
+
const envHostUrl = processEnvValue(HOST_URL_ENV);
|
|
18831
|
+
const authSource = envApiKey ? {
|
|
18832
|
+
scope: "env",
|
|
18833
|
+
source: "process",
|
|
18834
|
+
path: null,
|
|
18835
|
+
api_key: redactApiKey(envApiKey),
|
|
18836
|
+
host: envHostUrl || null,
|
|
18837
|
+
overrides_global: true,
|
|
18838
|
+
overrides_folder: Boolean(projectCandidate)
|
|
18839
|
+
} : activeProject ? {
|
|
18840
|
+
scope: "folder",
|
|
18841
|
+
source: activeProject.source,
|
|
18842
|
+
path: activeProject.filePath,
|
|
18843
|
+
api_key: redactApiKey(activeProject.env.DEEPLINE_API_KEY),
|
|
18844
|
+
overrides_global: true
|
|
18845
|
+
} : {
|
|
18846
|
+
scope: "global",
|
|
18847
|
+
source: "host",
|
|
18848
|
+
path: hostPath,
|
|
18849
|
+
api_key: redactApiKey(config.apiKey),
|
|
18850
|
+
overrides_global: false
|
|
18851
|
+
};
|
|
18852
|
+
const folderTargetPayload = folderTarget.ok ? {
|
|
18853
|
+
ok: true,
|
|
18854
|
+
source: folderTarget.source,
|
|
18855
|
+
dir: folderTarget.dir,
|
|
18856
|
+
env_path: `${folderTarget.dir}/.env.deepline`
|
|
18857
|
+
} : {
|
|
18858
|
+
ok: false,
|
|
18859
|
+
reason: folderTarget.reason,
|
|
18860
|
+
candidates: folderTarget.candidates
|
|
18861
|
+
};
|
|
18862
|
+
const lines = [
|
|
18863
|
+
`Organization: ${current?.name ?? "(unknown)"}`,
|
|
18864
|
+
`Host: ${config.baseUrl}`,
|
|
18865
|
+
`Auth scope: ${authSource.scope}`
|
|
18866
|
+
];
|
|
18867
|
+
if (authSource.path) {
|
|
18868
|
+
lines.push(`Auth file: ${authSource.path}`);
|
|
18869
|
+
} else {
|
|
18870
|
+
lines.push(`Auth source: ${API_KEY_ENV} process environment`);
|
|
18871
|
+
}
|
|
18872
|
+
if (envApiKey) {
|
|
18873
|
+
lines.push(`${API_KEY_ENV} overrides saved auth for this process.`);
|
|
18874
|
+
} else if (activeProject) {
|
|
18875
|
+
lines.push("Global auth is overridden in this folder.");
|
|
18876
|
+
}
|
|
18877
|
+
printCommandEnvelope(
|
|
18878
|
+
{
|
|
18879
|
+
ok: true,
|
|
18880
|
+
host: config.baseUrl,
|
|
18881
|
+
organization: current,
|
|
18882
|
+
current_org_id: payload.current_org_id,
|
|
18883
|
+
auth_source: authSource,
|
|
18884
|
+
host_env_path: hostPath,
|
|
18885
|
+
folder_target: folderTargetPayload,
|
|
18886
|
+
next: {
|
|
18887
|
+
set_auto: "deepline org set <org>",
|
|
18888
|
+
set_folder: "deepline org set <org> --auth-scope folder",
|
|
18889
|
+
set_global: "deepline org set <org> --auth-scope global"
|
|
18890
|
+
},
|
|
18891
|
+
render: {
|
|
18892
|
+
sections: [{ title: "org status", lines }]
|
|
18893
|
+
}
|
|
18894
|
+
},
|
|
18895
|
+
{ json: options.json }
|
|
18896
|
+
);
|
|
18897
|
+
}
|
|
18510
18898
|
async function handleOrgSwitch(selection, options) {
|
|
18899
|
+
const authScope = normalizeAuthScope(options.authScope);
|
|
18511
18900
|
const config = resolveConfig();
|
|
18512
18901
|
const http = new HttpClient(config);
|
|
18513
18902
|
const payload = await fetchOrganizations(http, config.apiKey);
|
|
@@ -18515,7 +18904,10 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18515
18904
|
printCommandEnvelope(
|
|
18516
18905
|
{
|
|
18517
18906
|
...payload,
|
|
18518
|
-
next: {
|
|
18907
|
+
next: { set: "deepline org set <number>" },
|
|
18908
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
18909
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
18910
|
+
warnings: options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
18519
18911
|
render: {
|
|
18520
18912
|
sections: [
|
|
18521
18913
|
{
|
|
@@ -18523,7 +18915,7 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18523
18915
|
lines: orgListLines(payload.organizations)
|
|
18524
18916
|
}
|
|
18525
18917
|
],
|
|
18526
|
-
actions: [{ label: "Run", command: "deepline org
|
|
18918
|
+
actions: [{ label: "Run", command: "deepline org set <number>" }]
|
|
18527
18919
|
}
|
|
18528
18920
|
},
|
|
18529
18921
|
{ json: options.json }
|
|
@@ -18546,16 +18938,56 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18546
18938
|
if (!target) {
|
|
18547
18939
|
throw new Error("Could not resolve the selected organization.");
|
|
18548
18940
|
}
|
|
18941
|
+
const authTarget = resolveOrgSwitchAuthTarget(authScope, config);
|
|
18549
18942
|
if (target.is_current) {
|
|
18943
|
+
let project_env_paths2 = [];
|
|
18944
|
+
if (authTarget.kind === "folder") {
|
|
18945
|
+
project_env_paths2 = saveProjectDeeplineEnvValues({
|
|
18946
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18947
|
+
DEEPLINE_API_KEY: config.apiKey
|
|
18948
|
+
});
|
|
18949
|
+
} else {
|
|
18950
|
+
saveHostEnvValues(config.baseUrl, {
|
|
18951
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18952
|
+
DEEPLINE_API_KEY: config.apiKey
|
|
18953
|
+
});
|
|
18954
|
+
}
|
|
18955
|
+
const renderLines2 = [`Already on ${target.name}.`];
|
|
18956
|
+
for (const projectPath of project_env_paths2) {
|
|
18957
|
+
renderLines2.push(`Saved folder auth in ${projectPath}`);
|
|
18958
|
+
}
|
|
18959
|
+
if (authTarget.kind === "global") {
|
|
18960
|
+
renderLines2.push(`Saved global auth in ${hostEnvFilePath(config.baseUrl)}`);
|
|
18961
|
+
}
|
|
18962
|
+
renderLines2.push(
|
|
18963
|
+
`Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
|
|
18964
|
+
);
|
|
18965
|
+
if (options.deprecatedSwitch) {
|
|
18966
|
+
renderLines2.push("Warning: org switch is deprecated; use org set.");
|
|
18967
|
+
}
|
|
18968
|
+
for (const warning of authTarget.warnings) {
|
|
18969
|
+
renderLines2.push(`Warning: ${warning}`);
|
|
18970
|
+
}
|
|
18971
|
+
const warnings2 = [
|
|
18972
|
+
...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
18973
|
+
...authTarget.warnings
|
|
18974
|
+
];
|
|
18550
18975
|
printCommandEnvelope(
|
|
18551
18976
|
{
|
|
18552
18977
|
ok: true,
|
|
18553
18978
|
unchanged: true,
|
|
18554
18979
|
organization: target,
|
|
18980
|
+
requested_auth_scope: authTarget.requested_scope,
|
|
18981
|
+
effective_auth_scope: authTarget.effective_scope,
|
|
18982
|
+
auth_scope_reason: authTarget.reason,
|
|
18983
|
+
auth_scope: authTarget.effective_scope,
|
|
18984
|
+
host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
|
|
18985
|
+
project_env_paths: project_env_paths2,
|
|
18986
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
18987
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
18988
|
+
warnings: warnings2,
|
|
18555
18989
|
render: {
|
|
18556
|
-
sections: [
|
|
18557
|
-
{ title: "org switch", lines: [`Already on ${target.name}.`] }
|
|
18558
|
-
]
|
|
18990
|
+
sections: [{ title: "org set", lines: renderLines2 }]
|
|
18559
18991
|
}
|
|
18560
18992
|
},
|
|
18561
18993
|
{ json: options.json }
|
|
@@ -18566,26 +18998,61 @@ async function handleOrgSwitch(selection, options) {
|
|
|
18566
18998
|
api_key: config.apiKey,
|
|
18567
18999
|
org_id: target.org_id
|
|
18568
19000
|
});
|
|
18569
|
-
|
|
18570
|
-
|
|
18571
|
-
|
|
18572
|
-
|
|
18573
|
-
|
|
19001
|
+
let project_env_paths = [];
|
|
19002
|
+
if (authTarget.kind === "folder") {
|
|
19003
|
+
project_env_paths = saveProjectDeeplineEnvValues({
|
|
19004
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
19005
|
+
DEEPLINE_API_KEY: switched.api_key
|
|
19006
|
+
});
|
|
19007
|
+
} else {
|
|
19008
|
+
saveHostEnvValues(config.baseUrl, {
|
|
19009
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
19010
|
+
DEEPLINE_API_KEY: switched.api_key,
|
|
19011
|
+
DEEPLINE_ACTIVE_ORG_ID: switched.org_id,
|
|
19012
|
+
DEEPLINE_ACTIVE_ORG_NAME: switched.org_name
|
|
19013
|
+
});
|
|
19014
|
+
}
|
|
18574
19015
|
const { api_key: _apiKey, ...publicSwitched } = switched;
|
|
19016
|
+
const renderLines = [`Switched to ${switched.org_name}.`];
|
|
19017
|
+
if (authTarget.kind === "folder") {
|
|
19018
|
+
for (const projectPath of project_env_paths) {
|
|
19019
|
+
renderLines.push(`Saved folder auth in ${projectPath}`);
|
|
19020
|
+
}
|
|
19021
|
+
} else {
|
|
19022
|
+
renderLines.push(`Saved global auth in ${hostEnvFilePath(config.baseUrl)}`);
|
|
19023
|
+
}
|
|
19024
|
+
renderLines.push(
|
|
19025
|
+
`Scope: ${authTarget.requested_scope} -> ${authTarget.effective_scope} (${authTarget.reason})`
|
|
19026
|
+
);
|
|
19027
|
+
if (options.deprecatedSwitch) {
|
|
19028
|
+
renderLines.push("Warning: org switch is deprecated; use org set.");
|
|
19029
|
+
}
|
|
19030
|
+
for (const warning of authTarget.warnings) {
|
|
19031
|
+
renderLines.push(`Warning: ${warning}`);
|
|
19032
|
+
}
|
|
19033
|
+
const warnings = [
|
|
19034
|
+
...options.deprecatedSwitch ? ["org switch is deprecated; use org set."] : [],
|
|
19035
|
+
...authTarget.warnings
|
|
19036
|
+
];
|
|
18575
19037
|
printCommandEnvelope(
|
|
18576
19038
|
{
|
|
18577
19039
|
ok: true,
|
|
18578
|
-
host_env_path: hostEnvFilePath(config.baseUrl),
|
|
19040
|
+
host_env_path: authTarget.kind === "global" ? hostEnvFilePath(config.baseUrl) : null,
|
|
19041
|
+
project_env_paths,
|
|
18579
19042
|
...publicSwitched,
|
|
18580
19043
|
api_key_saved: true,
|
|
19044
|
+
requested_auth_scope: authTarget.requested_scope,
|
|
19045
|
+
effective_auth_scope: authTarget.effective_scope,
|
|
19046
|
+
auth_scope_reason: authTarget.reason,
|
|
19047
|
+
auth_scope: authTarget.effective_scope,
|
|
19048
|
+
deprecated_command: options.deprecatedSwitch ? "org switch" : null,
|
|
19049
|
+
replacement_command: options.deprecatedSwitch ? "deepline org set" : null,
|
|
19050
|
+
warnings,
|
|
18581
19051
|
render: {
|
|
18582
19052
|
sections: [
|
|
18583
19053
|
{
|
|
18584
|
-
title: "org
|
|
18585
|
-
lines:
|
|
18586
|
-
`Switched to ${switched.org_name}.`,
|
|
18587
|
-
`Saved host auth in ${hostEnvFilePath(config.baseUrl)}`
|
|
18588
|
-
]
|
|
19054
|
+
title: "org set",
|
|
19055
|
+
lines: renderLines
|
|
18589
19056
|
}
|
|
18590
19057
|
]
|
|
18591
19058
|
}
|
|
@@ -18601,6 +19068,7 @@ async function handleOrgCreate(name, options) {
|
|
|
18601
19068
|
name
|
|
18602
19069
|
});
|
|
18603
19070
|
saveHostEnvValues(config.baseUrl, {
|
|
19071
|
+
DEEPLINE_HOST_URL: config.baseUrl,
|
|
18604
19072
|
DEEPLINE_API_KEY: created.api_key,
|
|
18605
19073
|
DEEPLINE_ACTIVE_ORG_ID: created.org_id,
|
|
18606
19074
|
DEEPLINE_ACTIVE_ORG_NAME: created.org_name
|
|
@@ -18630,18 +19098,20 @@ async function handleOrgCreate(name, options) {
|
|
|
18630
19098
|
);
|
|
18631
19099
|
}
|
|
18632
19100
|
function registerOrgCommands(program) {
|
|
18633
|
-
const org = program.command("org").description("List, create, and
|
|
19101
|
+
const org = program.command("org").description("List, create, and set organizations.").addHelpText(
|
|
18634
19102
|
"after",
|
|
18635
19103
|
`
|
|
18636
19104
|
Notes:
|
|
18637
|
-
Organizations are workspaces.
|
|
18638
|
-
|
|
19105
|
+
Organizations are workspaces. By default, switching updates the auth scope
|
|
19106
|
+
that will affect later commands from this folder.
|
|
18639
19107
|
|
|
18640
19108
|
Examples:
|
|
18641
19109
|
deepline org list --json
|
|
19110
|
+
deepline org status --json
|
|
18642
19111
|
deepline org create Acme --json
|
|
18643
|
-
deepline org
|
|
18644
|
-
deepline org
|
|
19112
|
+
deepline org set 2
|
|
19113
|
+
deepline org set 2 --auth-scope folder
|
|
19114
|
+
deepline org set --org-id org_123 --json
|
|
18645
19115
|
`
|
|
18646
19116
|
);
|
|
18647
19117
|
org.command("list").description("List your organizations.").addHelpText(
|
|
@@ -18668,21 +19138,65 @@ Examples:
|
|
|
18668
19138
|
deepline org create "Acme Sales" --json
|
|
18669
19139
|
`
|
|
18670
19140
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgCreate);
|
|
18671
|
-
org.command("
|
|
18672
|
-
"Switch to another organization and save the new API key in the host auth file."
|
|
18673
|
-
).addHelpText(
|
|
19141
|
+
org.command("status").description("Show the current organization and auth source.").addHelpText(
|
|
18674
19142
|
"after",
|
|
18675
19143
|
`
|
|
18676
19144
|
Notes:
|
|
18677
|
-
|
|
18678
|
-
|
|
19145
|
+
Read-only. Shows whether commands resolve auth from process env, a folder
|
|
19146
|
+
.env.deepline file, or global host auth.
|
|
19147
|
+
|
|
19148
|
+
Examples:
|
|
19149
|
+
deepline org status
|
|
19150
|
+
deepline org status --json
|
|
19151
|
+
`
|
|
19152
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgStatus);
|
|
19153
|
+
const addOrgSetOptions = (command) => command.option("--org-id <id>", "Set using an explicit organization id").option(
|
|
19154
|
+
"--auth-scope <scope>",
|
|
19155
|
+
"Where to save auth: auto, folder, or global",
|
|
19156
|
+
"auto"
|
|
19157
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped");
|
|
19158
|
+
addOrgSetOptions(
|
|
19159
|
+
org.command("set [selection]").description("Set the organization for the selected auth scope.").addHelpText(
|
|
19160
|
+
"after",
|
|
19161
|
+
`
|
|
19162
|
+
Notes:
|
|
19163
|
+
Selection can be a list number, exact organization name, or organization id.
|
|
19164
|
+
Without a selection, prints choices. The default --auth-scope auto updates
|
|
19165
|
+
the folder auth file when one controls this command, updates the detected
|
|
19166
|
+
Cowork project folder when present, and otherwise updates global host auth.
|
|
19167
|
+
|
|
19168
|
+
Examples:
|
|
19169
|
+
deepline org set
|
|
19170
|
+
deepline org set 2
|
|
19171
|
+
deepline org set 2 --auth-scope folder
|
|
19172
|
+
deepline org set 2 --auth-scope global
|
|
19173
|
+
deepline org set --org-id org_123 --json
|
|
19174
|
+
`
|
|
19175
|
+
)
|
|
19176
|
+
).action(handleOrgSwitch);
|
|
19177
|
+
addOrgSetOptions(
|
|
19178
|
+
org.command("switch [selection]").description(
|
|
19179
|
+
"Deprecated alias for org set. Set the organization for the selected auth scope."
|
|
19180
|
+
).addHelpText(
|
|
19181
|
+
"after",
|
|
19182
|
+
`
|
|
19183
|
+
Notes:
|
|
19184
|
+
Deprecated alias. Use deepline org set instead. The default --auth-scope auto
|
|
19185
|
+
updates the folder auth file when one controls this command, updates the
|
|
19186
|
+
detected Cowork project folder when present, and otherwise updates global host
|
|
19187
|
+
auth.
|
|
18679
19188
|
|
|
18680
19189
|
Examples:
|
|
18681
19190
|
deepline org switch
|
|
18682
19191
|
deepline org switch 2
|
|
19192
|
+
deepline org switch 2 --auth-scope folder
|
|
19193
|
+
deepline org switch 2 --auth-scope global
|
|
18683
19194
|
deepline org switch --org-id org_123 --json
|
|
18684
19195
|
`
|
|
18685
|
-
|
|
19196
|
+
)
|
|
19197
|
+
).action(
|
|
19198
|
+
(selection, options) => handleOrgSwitch(selection, { ...options, deprecatedSwitch: true })
|
|
19199
|
+
);
|
|
18686
19200
|
}
|
|
18687
19201
|
|
|
18688
19202
|
// src/cli/commands/quickstart.ts
|
|
@@ -21456,7 +21970,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
21456
21970
|
import {
|
|
21457
21971
|
existsSync as existsSync11,
|
|
21458
21972
|
mkdirSync as mkdirSync9,
|
|
21459
|
-
realpathSync as
|
|
21973
|
+
realpathSync as realpathSync3,
|
|
21460
21974
|
readFileSync as readFileSync11,
|
|
21461
21975
|
renameSync,
|
|
21462
21976
|
rmSync as rmSync3,
|
|
@@ -21650,34 +22164,6 @@ async function fetchV1SkillNames(baseUrl) {
|
|
|
21650
22164
|
function buildSdkSkillNames(v1SkillNames) {
|
|
21651
22165
|
return sortedUniqueSkillNames(v1SkillNames);
|
|
21652
22166
|
}
|
|
21653
|
-
async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
21654
|
-
const controller = new AbortController();
|
|
21655
|
-
const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
|
|
21656
|
-
try {
|
|
21657
|
-
const response = await fetch(new URL("/api/v2/cli/update-check", baseUrl), {
|
|
21658
|
-
method: "POST",
|
|
21659
|
-
headers: { "Content-Type": "application/json" },
|
|
21660
|
-
body: JSON.stringify({
|
|
21661
|
-
skills: {
|
|
21662
|
-
version: localVersion
|
|
21663
|
-
}
|
|
21664
|
-
}),
|
|
21665
|
-
signal: controller.signal
|
|
21666
|
-
});
|
|
21667
|
-
if (!response.ok) return null;
|
|
21668
|
-
const data = await response.json().catch(() => null);
|
|
21669
|
-
const skills = data?.skills;
|
|
21670
|
-
if (!skills) return null;
|
|
21671
|
-
return {
|
|
21672
|
-
needsUpdate: skills.needs_update === true,
|
|
21673
|
-
remoteVersion: typeof skills.remote?.version === "string" ? skills.remote.version.trim() : ""
|
|
21674
|
-
};
|
|
21675
|
-
} catch {
|
|
21676
|
-
return null;
|
|
21677
|
-
} finally {
|
|
21678
|
-
clearTimeout(timeout);
|
|
21679
|
-
}
|
|
21680
|
-
}
|
|
21681
22167
|
function buildSkillsInstallArgs(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
|
|
21682
22168
|
return buildSkillsAddArgs(baseUrl, sortedUniqueSkillNames(skillNames));
|
|
21683
22169
|
}
|
|
@@ -21818,6 +22304,12 @@ function writeSdkSkillsStatusLine(line) {
|
|
|
21818
22304
|
process.stderr.write(`${line}
|
|
21819
22305
|
`);
|
|
21820
22306
|
}
|
|
22307
|
+
function skillsStaleHintLine(update) {
|
|
22308
|
+
if (!update?.needs_update || !update.remote.version) {
|
|
22309
|
+
return null;
|
|
22310
|
+
}
|
|
22311
|
+
return "Deepline agent skills are out of date. Run `deepline update` to sync.";
|
|
22312
|
+
}
|
|
21821
22313
|
async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
|
|
21822
22314
|
if (attemptedSync || shouldSkipSkillsSync()) return;
|
|
21823
22315
|
attemptedSync = true;
|
|
@@ -21825,14 +22317,11 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
|
|
|
21825
22317
|
if (usingPluginSkills) {
|
|
21826
22318
|
return;
|
|
21827
22319
|
}
|
|
21828
|
-
const
|
|
21829
|
-
|
|
21830
|
-
needsUpdate: options.update.needs_update,
|
|
21831
|
-
remoteVersion: options.update.remote.version
|
|
21832
|
-
} : null;
|
|
21833
|
-
if (!update?.needsUpdate || !update.remoteVersion) {
|
|
22320
|
+
const update = options.update ?? null;
|
|
22321
|
+
if (!update?.needs_update || !update.remote.version) {
|
|
21834
22322
|
return;
|
|
21835
22323
|
}
|
|
22324
|
+
const remoteVersion = update.remote.version;
|
|
21836
22325
|
const remoteSkillNames = await fetchV1SkillNames(baseUrl);
|
|
21837
22326
|
const skillNames = buildSdkSkillNames(
|
|
21838
22327
|
remoteSkillNames.length > 0 ? remoteSkillNames : DEFAULT_SDK_SKILL_NAMES
|
|
@@ -21842,11 +22331,17 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
|
|
|
21842
22331
|
const installed = await runSkillsInstall(baseUrl, skillNames);
|
|
21843
22332
|
if (!installed) return;
|
|
21844
22333
|
runLegacySkillsCleanup();
|
|
21845
|
-
writeLocalSkillsVersion(baseUrl,
|
|
22334
|
+
writeLocalSkillsVersion(baseUrl, remoteVersion);
|
|
21846
22335
|
writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
|
|
21847
22336
|
}
|
|
21848
22337
|
|
|
21849
22338
|
// src/cli/commands/update.ts
|
|
22339
|
+
async function resolveSkillsVerdictFromCompat(baseUrl) {
|
|
22340
|
+
const { response } = await checkSdkCompatibility(baseUrl, {
|
|
22341
|
+
skillsVersion: readSdkSkillsLocalVersion(baseUrl)
|
|
22342
|
+
});
|
|
22343
|
+
return response?.skills ?? null;
|
|
22344
|
+
}
|
|
21850
22345
|
var NPM_SDK_INSTALL_COMMON_FLAGS = ["--no-audit", "--no-fund"];
|
|
21851
22346
|
var NPM_SDK_GLOBAL_INSTALL_FLAGS = [
|
|
21852
22347
|
"--no-audit",
|
|
@@ -21955,7 +22450,7 @@ function findRepoBackedSdkRoot(startPath) {
|
|
|
21955
22450
|
function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
|
|
21956
22451
|
const normalized = (() => {
|
|
21957
22452
|
try {
|
|
21958
|
-
return
|
|
22453
|
+
return realpathSync3(entrypoint);
|
|
21959
22454
|
} catch {
|
|
21960
22455
|
return resolve12(entrypoint);
|
|
21961
22456
|
}
|
|
@@ -22285,6 +22780,7 @@ async function runUpdateCommand(options, dependencies = {}) {
|
|
|
22285
22780
|
const detectBaseUrl = dependencies.detectBaseUrl ?? autoDetectBaseUrl;
|
|
22286
22781
|
const resolvePlan = dependencies.resolvePlan ?? resolveUpdatePlan;
|
|
22287
22782
|
const runPlan = dependencies.runPlan ?? runUpdatePlan;
|
|
22783
|
+
const resolveSkillsVerdict = dependencies.resolveSkillsVerdict ?? resolveSkillsVerdictFromCompat;
|
|
22288
22784
|
const syncSkills = dependencies.syncSkillsIfNeeded ?? syncSdkSkillsIfNeeded;
|
|
22289
22785
|
const stderr = dependencies.stderr ?? process.stderr;
|
|
22290
22786
|
const plan = resolvePlan();
|
|
@@ -22329,7 +22825,9 @@ async function runUpdateCommand(options, dependencies = {}) {
|
|
|
22329
22825
|
if (updateExitCode !== 0) {
|
|
22330
22826
|
return updateExitCode;
|
|
22331
22827
|
}
|
|
22332
|
-
|
|
22828
|
+
const updatedBaseUrl = normalizeBaseUrl3(detectBaseUrl());
|
|
22829
|
+
const skillsUpdate = await resolveSkillsVerdict(updatedBaseUrl);
|
|
22830
|
+
await syncSkills(updatedBaseUrl, { update: skillsUpdate });
|
|
22333
22831
|
return 0;
|
|
22334
22832
|
}
|
|
22335
22833
|
function registerUpdateCommand(program) {
|
|
@@ -23046,7 +23544,7 @@ Exit codes:
|
|
|
23046
23544
|
const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
|
|
23047
23545
|
const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
|
|
23048
23546
|
const shouldDeferSkillsSync = shouldDeferSkillsSyncForCommand();
|
|
23049
|
-
const skillsVersion =
|
|
23547
|
+
const skillsVersion = readSdkSkillsLocalVersion(baseUrl);
|
|
23050
23548
|
const compatibility = await traceCliSpan(
|
|
23051
23549
|
"cli.sdk_compatibility",
|
|
23052
23550
|
{
|
|
@@ -23082,8 +23580,14 @@ Exit codes:
|
|
|
23082
23580
|
if (printStartupPhase) {
|
|
23083
23581
|
progress?.phase("checking sdk skills");
|
|
23084
23582
|
}
|
|
23085
|
-
|
|
23086
|
-
|
|
23583
|
+
const skillsUpdate = compatibility.response?.skills ?? null;
|
|
23584
|
+
if (shouldDeferSkillsSync) {
|
|
23585
|
+
const hint = skillsStaleHintLine(skillsUpdate);
|
|
23586
|
+
if (hint && !process.argv.includes("--json")) {
|
|
23587
|
+
process.stderr.write(`${hint}
|
|
23588
|
+
`);
|
|
23589
|
+
}
|
|
23590
|
+
} else {
|
|
23087
23591
|
await traceCliSpan(
|
|
23088
23592
|
"cli.sdk_skills_sync",
|
|
23089
23593
|
{ baseUrl },
|