deepline 0.1.102 → 0.1.104
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 +14 -12
- package/dist/cli/index.js +711 -132
- package/dist/cli/index.mjs +721 -135
- package/dist/index.d.mts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +7 -5
- package/dist/index.mjs +7 -5
- package/dist/repo/sdk/src/client.ts +3 -3
- package/dist/repo/sdk/src/index.ts +1 -1
- package/dist/repo/sdk/src/play.ts +2 -2
- package/dist/repo/sdk/src/release.ts +4 -2
- package/dist/repo/sdk/src/types.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/csv-rename.ts +26 -0
- package/dist/repo/shared_libs/play-runtime/providers.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +2 -0
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
4
|
import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile6 } from "fs/promises";
|
|
5
|
-
import { join as
|
|
5
|
+
import { join as join15 } from "path";
|
|
6
6
|
import { tmpdir as tmpdir5 } from "os";
|
|
7
7
|
import { Command as Command3 } from "commander";
|
|
8
8
|
|
|
@@ -214,10 +214,12 @@ var SDK_RELEASE = {
|
|
|
214
214
|
// failed runs, persisted/succeeded/failed row counts, strict local CSV
|
|
215
215
|
// preflight (existence, data rows, quotes, duplicate headers), HTML error
|
|
216
216
|
// scrubbing, and word-boundary watch truncation.
|
|
217
|
-
|
|
217
|
+
// 0.1.103 ships the refined SDK CLI command surface.
|
|
218
|
+
// 0.1.104 ships postgres_fast suspension/billing parity and runtime worker hardening.
|
|
219
|
+
version: "0.1.104",
|
|
218
220
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
219
221
|
supportPolicy: {
|
|
220
|
-
latest: "0.1.
|
|
222
|
+
latest: "0.1.104",
|
|
221
223
|
minimumSupported: "0.1.53",
|
|
222
224
|
deprecatedBelow: "0.1.53"
|
|
223
225
|
}
|
|
@@ -626,7 +628,7 @@ function decodeSseFrame(frame) {
|
|
|
626
628
|
return parsed;
|
|
627
629
|
}
|
|
628
630
|
function sleep(ms) {
|
|
629
|
-
return new Promise((
|
|
631
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
630
632
|
}
|
|
631
633
|
|
|
632
634
|
// src/stream-reconnect.ts
|
|
@@ -1337,14 +1339,14 @@ async function* observeRunEvents(options) {
|
|
|
1337
1339
|
try {
|
|
1338
1340
|
for (; ; ) {
|
|
1339
1341
|
if (queue.length === 0) {
|
|
1340
|
-
const waitForItem = new Promise((
|
|
1341
|
-
wake =
|
|
1342
|
+
const waitForItem = new Promise((resolve16) => {
|
|
1343
|
+
wake = resolve16;
|
|
1342
1344
|
});
|
|
1343
1345
|
if (!sawFirstSnapshot) {
|
|
1344
1346
|
const timedOut = await Promise.race([
|
|
1345
1347
|
waitForItem.then(() => false),
|
|
1346
1348
|
new Promise(
|
|
1347
|
-
(
|
|
1349
|
+
(resolve16) => setTimeout(() => resolve16(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
|
|
1348
1350
|
)
|
|
1349
1351
|
]);
|
|
1350
1352
|
if (timedOut && queue.length === 0) {
|
|
@@ -1441,7 +1443,7 @@ var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
|
|
|
1441
1443
|
var V2_EXECUTE_RESPONSE_CONTRACT = "v2-tool-response";
|
|
1442
1444
|
var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
|
|
1443
1445
|
function sleep2(ms) {
|
|
1444
|
-
return new Promise((
|
|
1446
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
1445
1447
|
}
|
|
1446
1448
|
function isTransientCompileManifestError(error) {
|
|
1447
1449
|
if (error instanceof DeeplineError && typeof error.statusCode === "number") {
|
|
@@ -1883,7 +1885,7 @@ var DeeplineClient = class {
|
|
|
1883
1885
|
* or {@link runPlay}.
|
|
1884
1886
|
*
|
|
1885
1887
|
* Supported invocation surfaces intentionally share this same run contract:
|
|
1886
|
-
* `deepline
|
|
1888
|
+
* `deepline plays run`, repo scripts such as `bun run deepline -- plays run`,
|
|
1887
1889
|
* SDK context calls like `Deepline.connect().play(name).run()`, and direct
|
|
1888
1890
|
* `POST /api/v2/plays/run` calls all return a workflow/run id. The completed
|
|
1889
1891
|
* output is always retrievable from `getPlayStatus(runId).result` (or from
|
|
@@ -2052,7 +2054,7 @@ var DeeplineClient = class {
|
|
|
2052
2054
|
*
|
|
2053
2055
|
* Unlike {@link registerPlayArtifact}, this does not store the artifact,
|
|
2054
2056
|
* publish a revision, or start a run. It is the authoritative cloud validation
|
|
2055
|
-
* path used by `deepline
|
|
2057
|
+
* path used by `deepline plays check`.
|
|
2056
2058
|
*/
|
|
2057
2059
|
async checkPlayArtifact(input2) {
|
|
2058
2060
|
return this.http.post("/api/v2/plays/check", input2);
|
|
@@ -2245,7 +2247,7 @@ var DeeplineClient = class {
|
|
|
2245
2247
|
* Get the current status of a play execution.
|
|
2246
2248
|
*
|
|
2247
2249
|
* Internal/advanced primitive. Public callers should usually prefer
|
|
2248
|
-
* {@link runPlay}, {@link PlayJob.get}, or `deepline
|
|
2250
|
+
* {@link runPlay}, {@link PlayJob.get}, or `deepline plays run --watch`.
|
|
2249
2251
|
*
|
|
2250
2252
|
* @param workflowId - Play-run id from {@link startPlayRun}
|
|
2251
2253
|
* @returns Current status with progress logs and partial results
|
|
@@ -3100,9 +3102,9 @@ async function writeOutputFile(filename, content) {
|
|
|
3100
3102
|
return fullPath;
|
|
3101
3103
|
}
|
|
3102
3104
|
function browserOpenStateFile() {
|
|
3103
|
-
const
|
|
3105
|
+
const homeDir2 = process.env.HOME || homedir3();
|
|
3104
3106
|
return join3(
|
|
3105
|
-
|
|
3107
|
+
homeDir2,
|
|
3106
3108
|
".local",
|
|
3107
3109
|
"deepline",
|
|
3108
3110
|
"runtime",
|
|
@@ -3576,8 +3578,8 @@ function printCommandEnvelope(envelope, options = {}) {
|
|
|
3576
3578
|
|
|
3577
3579
|
// src/cli/commands/auth.ts
|
|
3578
3580
|
var EXIT_OK = 0;
|
|
3579
|
-
var EXIT_AUTH =
|
|
3580
|
-
var EXIT_SERVER =
|
|
3581
|
+
var EXIT_AUTH = 3;
|
|
3582
|
+
var EXIT_SERVER = 5;
|
|
3581
3583
|
function envFilePath(baseUrl) {
|
|
3582
3584
|
return hostEnvFilePath(baseUrl);
|
|
3583
3585
|
}
|
|
@@ -3669,7 +3671,7 @@ function buildCandidateUrls2(url) {
|
|
|
3669
3671
|
}
|
|
3670
3672
|
}
|
|
3671
3673
|
function sleep4(ms) {
|
|
3672
|
-
return new Promise((
|
|
3674
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
3673
3675
|
}
|
|
3674
3676
|
function printDeeplineLogo() {
|
|
3675
3677
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
@@ -3932,7 +3934,7 @@ async function handleStatus(args) {
|
|
|
3932
3934
|
...hostStatusPayload ?? { host: baseUrl },
|
|
3933
3935
|
status: "not connected",
|
|
3934
3936
|
connected: false,
|
|
3935
|
-
next: "deepline auth register",
|
|
3937
|
+
next: "deepline auth register --no-wait && deepline auth wait",
|
|
3936
3938
|
render: {
|
|
3937
3939
|
sections: [
|
|
3938
3940
|
{
|
|
@@ -3940,7 +3942,10 @@ async function handleStatus(args) {
|
|
|
3940
3942
|
lines: [...hostLines, "Status: not connected"]
|
|
3941
3943
|
}
|
|
3942
3944
|
],
|
|
3943
|
-
actions: [
|
|
3945
|
+
actions: [
|
|
3946
|
+
{ label: "Register", command: "deepline auth register --no-wait" },
|
|
3947
|
+
{ label: "Wait", command: "deepline auth wait" }
|
|
3948
|
+
]
|
|
3944
3949
|
}
|
|
3945
3950
|
},
|
|
3946
3951
|
{ json: jsonOutput }
|
|
@@ -3962,7 +3967,7 @@ async function handleStatus(args) {
|
|
|
3962
3967
|
...hostStatusPayload ?? { host: baseUrl },
|
|
3963
3968
|
status: "unauthorized",
|
|
3964
3969
|
connected: false,
|
|
3965
|
-
next: "deepline auth register",
|
|
3970
|
+
next: "deepline auth register --no-wait && deepline auth wait",
|
|
3966
3971
|
render: {
|
|
3967
3972
|
sections: [
|
|
3968
3973
|
{
|
|
@@ -3970,7 +3975,10 @@ async function handleStatus(args) {
|
|
|
3970
3975
|
lines: [...hostLines, "Status: unauthorized"]
|
|
3971
3976
|
}
|
|
3972
3977
|
],
|
|
3973
|
-
actions: [
|
|
3978
|
+
actions: [
|
|
3979
|
+
{ label: "Register", command: "deepline auth register --no-wait" },
|
|
3980
|
+
{ label: "Wait", command: "deepline auth wait" }
|
|
3981
|
+
]
|
|
3974
3982
|
}
|
|
3975
3983
|
},
|
|
3976
3984
|
{ json: jsonOutput }
|
|
@@ -5616,7 +5624,7 @@ async function handleDbQuery(args) {
|
|
|
5616
5624
|
return 0;
|
|
5617
5625
|
}
|
|
5618
5626
|
function registerDbCommands(program) {
|
|
5619
|
-
const db = program.command("db").
|
|
5627
|
+
const db = program.command("db").description("Query the tenant customer database.").addHelpText(
|
|
5620
5628
|
"after",
|
|
5621
5629
|
`
|
|
5622
5630
|
Notes:
|
|
@@ -5637,7 +5645,7 @@ Examples:
|
|
|
5637
5645
|
deepline db query --sql "select domain, name from companies limit 20" --format markdown
|
|
5638
5646
|
`
|
|
5639
5647
|
);
|
|
5640
|
-
db.command("query").
|
|
5648
|
+
db.command("query").description("Run SQL against the tenant customer database.").addHelpText(
|
|
5641
5649
|
"after",
|
|
5642
5650
|
`
|
|
5643
5651
|
Notes:
|
|
@@ -5653,7 +5661,7 @@ Examples:
|
|
|
5653
5661
|
deepline db query --sql "select * from companies limit 20"
|
|
5654
5662
|
deepline db query --sql "select domain, name from companies limit 20" --json
|
|
5655
5663
|
deepline db query --sql "create table if not exists storage.agent_notes (id text primary key, note text not null)"
|
|
5656
|
-
deepline db
|
|
5664
|
+
deepline db query --sql "select count(*) from contacts" --json
|
|
5657
5665
|
deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
|
|
5658
5666
|
deepline db query --sql "select domain, name from companies limit 20" --format markdown
|
|
5659
5667
|
`
|
|
@@ -6925,7 +6933,7 @@ var PLAY_RUNTIME_PROVIDERS = {
|
|
|
6925
6933
|
runner: PLAY_RUNTIME_BACKENDS.daytona,
|
|
6926
6934
|
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
6927
6935
|
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
6928
|
-
label: "
|
|
6936
|
+
label: "BETA: Postgres Scheduler + warm sandbox runner + DO dedup"
|
|
6929
6937
|
},
|
|
6930
6938
|
postgres_fast_sandbox: {
|
|
6931
6939
|
id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastSandbox,
|
|
@@ -6933,7 +6941,7 @@ var PLAY_RUNTIME_PROVIDERS = {
|
|
|
6933
6941
|
runner: PLAY_RUNTIME_BACKENDS.daytona,
|
|
6934
6942
|
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
6935
6943
|
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
6936
|
-
label: "
|
|
6944
|
+
label: "BETA: Postgres Scheduler + warm sandbox runner + DO dedup"
|
|
6937
6945
|
},
|
|
6938
6946
|
postgres_fast_workers: {
|
|
6939
6947
|
id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastWorkers,
|
|
@@ -9238,7 +9246,7 @@ function traceCliSync(phase, fields, run) {
|
|
|
9238
9246
|
}
|
|
9239
9247
|
}
|
|
9240
9248
|
function sleep5(ms) {
|
|
9241
|
-
return new Promise((
|
|
9249
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
9242
9250
|
}
|
|
9243
9251
|
function parseReferencedPlayTarget2(target) {
|
|
9244
9252
|
const trimmed = target.trim();
|
|
@@ -12170,7 +12178,7 @@ function writeStartedPlayRun(input2) {
|
|
|
12170
12178
|
);
|
|
12171
12179
|
}
|
|
12172
12180
|
function parsePlayRunOptions(args) {
|
|
12173
|
-
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.dataset guidance.";
|
|
12181
|
+
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n --profile defaults to workers_edge; postgres_fast is BETA (opt-in per run, never the default).\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.dataset guidance.";
|
|
12174
12182
|
let filePath = null;
|
|
12175
12183
|
let playName = null;
|
|
12176
12184
|
let input2 = null;
|
|
@@ -12306,7 +12314,7 @@ function parsePlayRunOptions(args) {
|
|
|
12306
12314
|
function parsePlayCheckOptions(args) {
|
|
12307
12315
|
const target = args[0];
|
|
12308
12316
|
if (!target) {
|
|
12309
|
-
throw new Error("Usage: deepline
|
|
12317
|
+
throw new Error("Usage: deepline plays check <play-file.ts> [--json]");
|
|
12310
12318
|
}
|
|
12311
12319
|
const jsonOutput = argsWantJson(args);
|
|
12312
12320
|
return { target, jsonOutput };
|
|
@@ -13236,7 +13244,9 @@ async function handleRunExport(args) {
|
|
|
13236
13244
|
async function handlePlayGet(args) {
|
|
13237
13245
|
const target = args[0];
|
|
13238
13246
|
if (!target) {
|
|
13239
|
-
console.error(
|
|
13247
|
+
console.error(
|
|
13248
|
+
"Usage: deepline plays get <play-file.ts|play-name> [--json]"
|
|
13249
|
+
);
|
|
13240
13250
|
return 1;
|
|
13241
13251
|
}
|
|
13242
13252
|
if (looksLikeRunId(target)) {
|
|
@@ -13334,7 +13344,7 @@ async function handlePlayVersions(args) {
|
|
|
13334
13344
|
const nameIndex = args.indexOf("--name");
|
|
13335
13345
|
const playName = nameIndex >= 0 ? args[nameIndex + 1] : void 0;
|
|
13336
13346
|
if (!playName) {
|
|
13337
|
-
console.error("Usage: deepline
|
|
13347
|
+
console.error("Usage: deepline plays versions --name <name> [--json]");
|
|
13338
13348
|
return 1;
|
|
13339
13349
|
}
|
|
13340
13350
|
const client2 = new DeeplineClient();
|
|
@@ -13714,7 +13724,7 @@ async function handlePlayPublish(args) {
|
|
|
13714
13724
|
const playName = args[0];
|
|
13715
13725
|
if (!playName) {
|
|
13716
13726
|
console.error(
|
|
13717
|
-
"Usage: deepline
|
|
13727
|
+
"Usage: deepline plays publish <play-file.ts|play-name> [--latest|--revision-id <id>] [--json]"
|
|
13718
13728
|
);
|
|
13719
13729
|
return 1;
|
|
13720
13730
|
}
|
|
@@ -13858,7 +13868,7 @@ async function handlePlayDelete(args) {
|
|
|
13858
13868
|
return result.deleted ? 0 : 1;
|
|
13859
13869
|
}
|
|
13860
13870
|
function registerPlayCommands(program) {
|
|
13861
|
-
const play = program.command("plays").
|
|
13871
|
+
const play = program.command("plays").description("Search, validate, run, and manage cloud plays.").addHelpText(
|
|
13862
13872
|
"after",
|
|
13863
13873
|
`
|
|
13864
13874
|
Concepts:
|
|
@@ -16365,7 +16375,7 @@ async function runGeneratedEnrichPlay(runArgs, options = {}) {
|
|
|
16365
16375
|
});
|
|
16366
16376
|
} catch (error) {
|
|
16367
16377
|
if (attempt === 0 && isPlayStartStreamEndedError(error)) {
|
|
16368
|
-
await new Promise((
|
|
16378
|
+
await new Promise((resolve16) => setTimeout(resolve16, 250));
|
|
16369
16379
|
continue;
|
|
16370
16380
|
}
|
|
16371
16381
|
throw error;
|
|
@@ -17165,19 +17175,16 @@ Notes:
|
|
|
17165
17175
|
Use --command and --payload to attach a reproducible command shape.
|
|
17166
17176
|
|
|
17167
17177
|
Examples:
|
|
17168
|
-
deepline feedback "plays run failed after upload" --command "deepline plays run my.play.ts --watch"
|
|
17169
|
-
deepline feedback "unexpected billing output" --payload '{"command":"billing usage"}' --json
|
|
17178
|
+
deepline feedback send "plays run failed after upload" --command "deepline plays run my.play.ts --watch"
|
|
17179
|
+
deepline feedback send "unexpected billing output" --payload '{"command":"billing usage"}' --json
|
|
17170
17180
|
`
|
|
17171
17181
|
);
|
|
17172
|
-
feedback.
|
|
17173
|
-
program.command("provide-feedback").description("Legacy alias for `deepline feedback`.").addHelpText(
|
|
17182
|
+
feedback.command("send").description("Send CLI feedback to Deepline.").addHelpText(
|
|
17174
17183
|
"after",
|
|
17175
17184
|
`
|
|
17176
|
-
Notes:
|
|
17177
|
-
Compatibility alias. Prefer deepline feedback in new scripts and docs.
|
|
17178
|
-
|
|
17179
17185
|
Examples:
|
|
17180
|
-
deepline feedback "tools search returned stale results" --json
|
|
17186
|
+
deepline feedback send "tools search returned stale results" --json
|
|
17187
|
+
deepline feedback send "plays run failed after upload" --command "deepline plays run my.play.ts --watch"
|
|
17181
17188
|
`
|
|
17182
17189
|
).argument("<text>", "Feedback text").option("--command <command>", "Command that reproduced the issue").option("--payload <payload>", "JSON or plain-text payload for the repro").option("--json", "Emit JSON output").action(handleFeedback);
|
|
17183
17190
|
}
|
|
@@ -17298,8 +17305,44 @@ async function handleOrgSwitch(selection, options) {
|
|
|
17298
17305
|
{ json: options.json }
|
|
17299
17306
|
);
|
|
17300
17307
|
}
|
|
17308
|
+
async function handleOrgCreate(name, options) {
|
|
17309
|
+
const config = resolveConfig();
|
|
17310
|
+
const http = new HttpClient(config);
|
|
17311
|
+
const created = await http.post("/api/v2/auth/cli/org-create", {
|
|
17312
|
+
api_key: config.apiKey,
|
|
17313
|
+
name
|
|
17314
|
+
});
|
|
17315
|
+
saveHostEnvValues(config.baseUrl, {
|
|
17316
|
+
DEEPLINE_API_KEY: created.api_key,
|
|
17317
|
+
DEEPLINE_ACTIVE_ORG_ID: created.org_id,
|
|
17318
|
+
DEEPLINE_ACTIVE_ORG_NAME: created.org_name
|
|
17319
|
+
});
|
|
17320
|
+
const { api_key: _apiKey, ...publicCreated } = created;
|
|
17321
|
+
printCommandEnvelope(
|
|
17322
|
+
{
|
|
17323
|
+
ok: true,
|
|
17324
|
+
...publicCreated,
|
|
17325
|
+
api_key_saved: true,
|
|
17326
|
+
switched: true,
|
|
17327
|
+
host_env_path: hostEnvFilePath(config.baseUrl),
|
|
17328
|
+
render: {
|
|
17329
|
+
sections: [
|
|
17330
|
+
{
|
|
17331
|
+
title: "org create",
|
|
17332
|
+
lines: [
|
|
17333
|
+
`Created organization: ${created.org_name}.`,
|
|
17334
|
+
`Switched to ${created.org_name}.`,
|
|
17335
|
+
`Saved host auth in ${hostEnvFilePath(config.baseUrl)}`
|
|
17336
|
+
]
|
|
17337
|
+
}
|
|
17338
|
+
]
|
|
17339
|
+
}
|
|
17340
|
+
},
|
|
17341
|
+
{ json: options.json }
|
|
17342
|
+
);
|
|
17343
|
+
}
|
|
17301
17344
|
function registerOrgCommands(program) {
|
|
17302
|
-
const org = program.command("org").description("List and switch organizations.").addHelpText(
|
|
17345
|
+
const org = program.command("org").description("List, create, and switch organizations.").addHelpText(
|
|
17303
17346
|
"after",
|
|
17304
17347
|
`
|
|
17305
17348
|
Notes:
|
|
@@ -17308,6 +17351,7 @@ Notes:
|
|
|
17308
17351
|
|
|
17309
17352
|
Examples:
|
|
17310
17353
|
deepline org list --json
|
|
17354
|
+
deepline org create Acme --json
|
|
17311
17355
|
deepline org switch 2
|
|
17312
17356
|
deepline org switch --org-id org_123 --json
|
|
17313
17357
|
`
|
|
@@ -17323,6 +17367,19 @@ Examples:
|
|
|
17323
17367
|
deepline org list --json
|
|
17324
17368
|
`
|
|
17325
17369
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgList);
|
|
17370
|
+
org.command("create <name>").description("Create a new organization and switch this CLI to it.").addHelpText(
|
|
17371
|
+
"after",
|
|
17372
|
+
`
|
|
17373
|
+
Notes:
|
|
17374
|
+
Mutates workspace state. The new organization is created for the current
|
|
17375
|
+
authenticated user, then the returned API key is saved for this host so later
|
|
17376
|
+
CLI commands target the new organization.
|
|
17377
|
+
|
|
17378
|
+
Examples:
|
|
17379
|
+
deepline org create Acme
|
|
17380
|
+
deepline org create "Acme Sales" --json
|
|
17381
|
+
`
|
|
17382
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgCreate);
|
|
17326
17383
|
org.command("switch [selection]").description(
|
|
17327
17384
|
"Switch to another organization and save the new API key in the host auth file."
|
|
17328
17385
|
).addHelpText(
|
|
@@ -17367,7 +17424,7 @@ async function readHiddenLine(prompt) {
|
|
|
17367
17424
|
if (typeof input.setRawMode === "function") input.setRawMode(true);
|
|
17368
17425
|
let value = "";
|
|
17369
17426
|
input.resume();
|
|
17370
|
-
return await new Promise((
|
|
17427
|
+
return await new Promise((resolve16, reject) => {
|
|
17371
17428
|
let settled = false;
|
|
17372
17429
|
const cleanup = () => {
|
|
17373
17430
|
input.off("data", onData);
|
|
@@ -17382,7 +17439,7 @@ async function readHiddenLine(prompt) {
|
|
|
17382
17439
|
settled = true;
|
|
17383
17440
|
output.write("\n");
|
|
17384
17441
|
cleanup();
|
|
17385
|
-
|
|
17442
|
+
resolve16(line);
|
|
17386
17443
|
};
|
|
17387
17444
|
const fail = (error) => {
|
|
17388
17445
|
if (settled) return;
|
|
@@ -17552,22 +17609,566 @@ Examples:
|
|
|
17552
17609
|
);
|
|
17553
17610
|
}
|
|
17554
17611
|
|
|
17612
|
+
// src/cli/commands/sessions.ts
|
|
17613
|
+
import {
|
|
17614
|
+
existsSync as existsSync8,
|
|
17615
|
+
mkdirSync as mkdirSync4,
|
|
17616
|
+
readdirSync as readdirSync2,
|
|
17617
|
+
readFileSync as readFileSync7,
|
|
17618
|
+
statSync as statSync3,
|
|
17619
|
+
writeFileSync as writeFileSync8
|
|
17620
|
+
} from "fs";
|
|
17621
|
+
import { homedir as homedir5, platform } from "os";
|
|
17622
|
+
import { basename as basename4, dirname as dirname9, join as join9, resolve as resolve12 } from "path";
|
|
17623
|
+
import { gzipSync } from "zlib";
|
|
17624
|
+
import { randomUUID } from "crypto";
|
|
17625
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
17626
|
+
var MAX_SESSION_UPLOAD_BYTES = 35e5;
|
|
17627
|
+
var MAX_DIRECT_SESSION_DECODED_BYTES = 50 * 1024 * 1024;
|
|
17628
|
+
var CHUNK_SIZE_BYTES = 25e5;
|
|
17629
|
+
var MAX_EVENT_STRING_CHARS = 8e3;
|
|
17630
|
+
var MAX_EVENT_LIST_ITEMS = 40;
|
|
17631
|
+
var MAX_EVENT_OBJECT_KEYS = 80;
|
|
17632
|
+
var TRUNCATION_MARKER = "...[truncated]";
|
|
17633
|
+
var NOISE_EVENT_TYPES = /* @__PURE__ */ new Set(["progress", "file-history-snapshot"]);
|
|
17634
|
+
function homeDir() {
|
|
17635
|
+
return process.env.HOME?.trim() || homedir5();
|
|
17636
|
+
}
|
|
17637
|
+
function detectShellContext() {
|
|
17638
|
+
const shellPath = process.env.SHELL?.trim() || process.env.ComSpec?.trim() || process.env.COMSPEC?.trim() || "";
|
|
17639
|
+
return {
|
|
17640
|
+
shell: shellPath ? basename4(shellPath).replace(/\.exe$/i, "") : "unknown",
|
|
17641
|
+
shell_path: shellPath || null,
|
|
17642
|
+
os: platform(),
|
|
17643
|
+
cwd: process.cwd()
|
|
17644
|
+
};
|
|
17645
|
+
}
|
|
17646
|
+
function claudeProjectsRoot() {
|
|
17647
|
+
return join9(homeDir(), ".claude", "projects");
|
|
17648
|
+
}
|
|
17649
|
+
function listClaudeSessionFiles() {
|
|
17650
|
+
const root = claudeProjectsRoot();
|
|
17651
|
+
if (!existsSync8(root)) return [];
|
|
17652
|
+
const projectDirs = readDirectoryNames(root);
|
|
17653
|
+
const files = [];
|
|
17654
|
+
for (const projectDir of projectDirs) {
|
|
17655
|
+
const fullProjectDir = join9(root, projectDir);
|
|
17656
|
+
for (const fileName of readDirectoryNames(fullProjectDir)) {
|
|
17657
|
+
if (fileName.endsWith(".jsonl")) {
|
|
17658
|
+
files.push(join9(fullProjectDir, fileName));
|
|
17659
|
+
}
|
|
17660
|
+
}
|
|
17661
|
+
}
|
|
17662
|
+
return files;
|
|
17663
|
+
}
|
|
17664
|
+
function readDirectoryNames(dir) {
|
|
17665
|
+
try {
|
|
17666
|
+
return readdirSync2(dir);
|
|
17667
|
+
} catch {
|
|
17668
|
+
return [];
|
|
17669
|
+
}
|
|
17670
|
+
}
|
|
17671
|
+
function newestClaudeSessionFile() {
|
|
17672
|
+
let newest = null;
|
|
17673
|
+
for (const filePath of listClaudeSessionFiles()) {
|
|
17674
|
+
try {
|
|
17675
|
+
const stat4 = statSync3(filePath);
|
|
17676
|
+
if (!newest || stat4.mtimeMs > newest.mtimeMs) {
|
|
17677
|
+
newest = { filePath, mtimeMs: stat4.mtimeMs };
|
|
17678
|
+
}
|
|
17679
|
+
} catch {
|
|
17680
|
+
continue;
|
|
17681
|
+
}
|
|
17682
|
+
}
|
|
17683
|
+
return newest?.filePath ?? null;
|
|
17684
|
+
}
|
|
17685
|
+
function sessionIdFromFilePath(filePath) {
|
|
17686
|
+
return basename4(filePath, ".jsonl");
|
|
17687
|
+
}
|
|
17688
|
+
function findSessionFile(sessionId) {
|
|
17689
|
+
if (!UUID_RE.test(sessionId)) {
|
|
17690
|
+
throw new Error(
|
|
17691
|
+
"Invalid session ID format. Expected a UUID such as 5a3bfb97-a2d9-49d9-82c6-52ccc03dadca."
|
|
17692
|
+
);
|
|
17693
|
+
}
|
|
17694
|
+
for (const filePath of listClaudeSessionFiles()) {
|
|
17695
|
+
if (sessionIdFromFilePath(filePath) === sessionId) {
|
|
17696
|
+
return filePath;
|
|
17697
|
+
}
|
|
17698
|
+
}
|
|
17699
|
+
return null;
|
|
17700
|
+
}
|
|
17701
|
+
function resolveSessionTargets(input2) {
|
|
17702
|
+
const targets = [];
|
|
17703
|
+
if (input2.currentSession) {
|
|
17704
|
+
const currentFile = newestClaudeSessionFile();
|
|
17705
|
+
if (!currentFile) {
|
|
17706
|
+
throw new Error("No session files found in ~/.claude/projects/*/.");
|
|
17707
|
+
}
|
|
17708
|
+
const sessionId = sessionIdFromFilePath(currentFile);
|
|
17709
|
+
targets.push({
|
|
17710
|
+
sessionId,
|
|
17711
|
+
label: `session-${sessionId}`,
|
|
17712
|
+
filePath: currentFile
|
|
17713
|
+
});
|
|
17714
|
+
}
|
|
17715
|
+
for (const [index, sessionId] of (input2.sessionIds ?? []).entries()) {
|
|
17716
|
+
const filePath = findSessionFile(sessionId);
|
|
17717
|
+
if (!filePath) {
|
|
17718
|
+
throw new Error(
|
|
17719
|
+
`Session file not found: ~/.claude/projects/*/${sessionId}.jsonl`
|
|
17720
|
+
);
|
|
17721
|
+
}
|
|
17722
|
+
targets.push({
|
|
17723
|
+
sessionId,
|
|
17724
|
+
label: input2.labels?.[index] ?? `session-${sessionId}`,
|
|
17725
|
+
filePath
|
|
17726
|
+
});
|
|
17727
|
+
}
|
|
17728
|
+
if (targets.length === 0) {
|
|
17729
|
+
throw new Error("One of --session-id or --current-session is required.");
|
|
17730
|
+
}
|
|
17731
|
+
return targets;
|
|
17732
|
+
}
|
|
17733
|
+
function parseJsonLine(line) {
|
|
17734
|
+
try {
|
|
17735
|
+
return JSON.parse(line);
|
|
17736
|
+
} catch {
|
|
17737
|
+
return null;
|
|
17738
|
+
}
|
|
17739
|
+
}
|
|
17740
|
+
function normalizedJsonLines(raw) {
|
|
17741
|
+
return raw.toString("utf8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
17742
|
+
}
|
|
17743
|
+
function stripNoiseEvents(raw) {
|
|
17744
|
+
const lines = [];
|
|
17745
|
+
for (const line of normalizedJsonLines(raw)) {
|
|
17746
|
+
const parsed = parseJsonLine(line);
|
|
17747
|
+
if (parsed && typeof parsed === "object" && NOISE_EVENT_TYPES.has(String(parsed.type ?? ""))) {
|
|
17748
|
+
continue;
|
|
17749
|
+
}
|
|
17750
|
+
lines.push(line);
|
|
17751
|
+
}
|
|
17752
|
+
return Buffer.from(lines.length > 0 ? `${lines.join("\n")}
|
|
17753
|
+
` : "", "utf8");
|
|
17754
|
+
}
|
|
17755
|
+
function messageContentKey(value) {
|
|
17756
|
+
const message = value.message;
|
|
17757
|
+
if (!message || typeof message !== "object") return null;
|
|
17758
|
+
const content = message.content;
|
|
17759
|
+
if (typeof content === "string") return content;
|
|
17760
|
+
if (!Array.isArray(content)) return null;
|
|
17761
|
+
return content.map((block) => {
|
|
17762
|
+
if (!block || typeof block !== "object") return String(block);
|
|
17763
|
+
const record = block;
|
|
17764
|
+
const type = String(record.type ?? "");
|
|
17765
|
+
if (type === "tool_use") {
|
|
17766
|
+
return `tool_use:${String(record.name ?? "")}:${String(record.id ?? "")}`;
|
|
17767
|
+
}
|
|
17768
|
+
if (type === "tool_result") {
|
|
17769
|
+
return `tool_result:${String(record.tool_use_id ?? "")}`;
|
|
17770
|
+
}
|
|
17771
|
+
return String(record.text ?? type);
|
|
17772
|
+
}).join("\n");
|
|
17773
|
+
}
|
|
17774
|
+
function dedupConsecutiveEvents(raw) {
|
|
17775
|
+
const rawLines = normalizedJsonLines(raw);
|
|
17776
|
+
const parsedEvents = rawLines.map(parseJsonLine);
|
|
17777
|
+
const output2 = [];
|
|
17778
|
+
let index = 0;
|
|
17779
|
+
while (index < parsedEvents.length) {
|
|
17780
|
+
const event = parsedEvents[index];
|
|
17781
|
+
if (!event || typeof event !== "object") {
|
|
17782
|
+
output2.push(rawLines[index] ?? "");
|
|
17783
|
+
index += 1;
|
|
17784
|
+
continue;
|
|
17785
|
+
}
|
|
17786
|
+
const record = event;
|
|
17787
|
+
const eventType = String(record.type ?? "");
|
|
17788
|
+
const eventKey = messageContentKey(record);
|
|
17789
|
+
if (!["user", "assistant"].includes(eventType) || !eventKey) {
|
|
17790
|
+
output2.push(rawLines[index] ?? "");
|
|
17791
|
+
index += 1;
|
|
17792
|
+
continue;
|
|
17793
|
+
}
|
|
17794
|
+
let runCount = 1;
|
|
17795
|
+
let cursor = index + 1;
|
|
17796
|
+
while (cursor < parsedEvents.length) {
|
|
17797
|
+
const next = parsedEvents[cursor];
|
|
17798
|
+
if (!next || typeof next !== "object") break;
|
|
17799
|
+
const nextRecord = next;
|
|
17800
|
+
if (String(nextRecord.type ?? "") !== eventType || messageContentKey(nextRecord) !== eventKey) {
|
|
17801
|
+
break;
|
|
17802
|
+
}
|
|
17803
|
+
runCount += 1;
|
|
17804
|
+
cursor += 1;
|
|
17805
|
+
}
|
|
17806
|
+
if (runCount > 1) {
|
|
17807
|
+
record._repeat_count = runCount;
|
|
17808
|
+
record._repeat_summary = `${runCount} consecutive identical ${eventType} messages collapsed`;
|
|
17809
|
+
output2.push(JSON.stringify(record));
|
|
17810
|
+
index = cursor;
|
|
17811
|
+
continue;
|
|
17812
|
+
}
|
|
17813
|
+
output2.push(rawLines[index] ?? "");
|
|
17814
|
+
index += 1;
|
|
17815
|
+
}
|
|
17816
|
+
return Buffer.from(output2.length > 0 ? `${output2.join("\n")}
|
|
17817
|
+
` : "", "utf8");
|
|
17818
|
+
}
|
|
17819
|
+
function compactEventValue(value) {
|
|
17820
|
+
if (typeof value === "string") {
|
|
17821
|
+
if (value.length <= MAX_EVENT_STRING_CHARS) return value;
|
|
17822
|
+
return `${value.slice(0, MAX_EVENT_STRING_CHARS - TRUNCATION_MARKER.length)}${TRUNCATION_MARKER}`;
|
|
17823
|
+
}
|
|
17824
|
+
if (Array.isArray(value)) {
|
|
17825
|
+
const compacted = value.slice(0, MAX_EVENT_LIST_ITEMS).map(compactEventValue);
|
|
17826
|
+
if (value.length > MAX_EVENT_LIST_ITEMS) {
|
|
17827
|
+
compacted.push(
|
|
17828
|
+
`${TRUNCATION_MARKER} ${value.length - MAX_EVENT_LIST_ITEMS} more item(s)`
|
|
17829
|
+
);
|
|
17830
|
+
}
|
|
17831
|
+
return compacted;
|
|
17832
|
+
}
|
|
17833
|
+
if (value && typeof value === "object") {
|
|
17834
|
+
const entries = Object.entries(value);
|
|
17835
|
+
const compacted = {};
|
|
17836
|
+
for (const [key, item] of entries.slice(0, MAX_EVENT_OBJECT_KEYS)) {
|
|
17837
|
+
compacted[key] = compactEventValue(item);
|
|
17838
|
+
}
|
|
17839
|
+
if (entries.length > MAX_EVENT_OBJECT_KEYS) {
|
|
17840
|
+
compacted._truncated_keys = entries.length - MAX_EVENT_OBJECT_KEYS;
|
|
17841
|
+
}
|
|
17842
|
+
return compacted;
|
|
17843
|
+
}
|
|
17844
|
+
return value;
|
|
17845
|
+
}
|
|
17846
|
+
function selectiveCompactToolResults(raw) {
|
|
17847
|
+
const lines = [];
|
|
17848
|
+
for (const line of normalizedJsonLines(raw)) {
|
|
17849
|
+
const parsed = parseJsonLine(line);
|
|
17850
|
+
if (!parsed || typeof parsed !== "object") {
|
|
17851
|
+
lines.push(line);
|
|
17852
|
+
continue;
|
|
17853
|
+
}
|
|
17854
|
+
const record = parsed;
|
|
17855
|
+
if (record.type === "user") {
|
|
17856
|
+
const message = record.message;
|
|
17857
|
+
const content = message && typeof message === "object" ? message.content : null;
|
|
17858
|
+
if (Array.isArray(content)) {
|
|
17859
|
+
message.content = content.map(
|
|
17860
|
+
(block) => block && typeof block === "object" && block.type === "tool_result" ? compactEventValue(block) : block
|
|
17861
|
+
);
|
|
17862
|
+
}
|
|
17863
|
+
}
|
|
17864
|
+
lines.push(JSON.stringify(record));
|
|
17865
|
+
}
|
|
17866
|
+
return Buffer.from(lines.length > 0 ? `${lines.join("\n")}
|
|
17867
|
+
` : "", "utf8");
|
|
17868
|
+
}
|
|
17869
|
+
function prepareSessionBuffer(raw) {
|
|
17870
|
+
return selectiveCompactToolResults(
|
|
17871
|
+
dedupConsecutiveEvents(stripNoiseEvents(raw))
|
|
17872
|
+
);
|
|
17873
|
+
}
|
|
17874
|
+
function buildSessionUploadContent(raw) {
|
|
17875
|
+
const prepared = prepareSessionBuffer(raw);
|
|
17876
|
+
const encoded = gzipSync(prepared).toString("base64");
|
|
17877
|
+
if (encoded.length <= MAX_SESSION_UPLOAD_BYTES && prepared.length <= MAX_DIRECT_SESSION_DECODED_BYTES) {
|
|
17878
|
+
return { encodedContent: encoded, needsChunking: false };
|
|
17879
|
+
}
|
|
17880
|
+
return { encodedContent: encoded, needsChunking: true };
|
|
17881
|
+
}
|
|
17882
|
+
async function uploadPayload(path, payload) {
|
|
17883
|
+
const { http } = getAuthedHttpClient();
|
|
17884
|
+
return await http.post(path, payload);
|
|
17885
|
+
}
|
|
17886
|
+
async function uploadChunkedSessions(sessions, options) {
|
|
17887
|
+
const uploadId = randomUUID();
|
|
17888
|
+
for (const session of sessions) {
|
|
17889
|
+
const bytes = Buffer.from(session.encodedContent, "base64");
|
|
17890
|
+
const chunks = [];
|
|
17891
|
+
for (let offset = 0; offset < bytes.length; offset += CHUNK_SIZE_BYTES) {
|
|
17892
|
+
chunks.push(bytes.subarray(offset, offset + CHUNK_SIZE_BYTES));
|
|
17893
|
+
}
|
|
17894
|
+
process.stderr.write(
|
|
17895
|
+
`Uploading ${session.label} in ${chunks.length} chunk(s)...
|
|
17896
|
+
`
|
|
17897
|
+
);
|
|
17898
|
+
for (const [index, chunk] of chunks.entries()) {
|
|
17899
|
+
await uploadPayload("/api/v2/cli/send-session/chunk", {
|
|
17900
|
+
upload_id: uploadId,
|
|
17901
|
+
session_id: session.sessionId,
|
|
17902
|
+
index,
|
|
17903
|
+
total_chunks: chunks.length,
|
|
17904
|
+
data: chunk.toString("base64")
|
|
17905
|
+
});
|
|
17906
|
+
}
|
|
17907
|
+
}
|
|
17908
|
+
const response = await uploadPayload("/api/v2/cli/send-session/finalize", {
|
|
17909
|
+
upload_id: uploadId,
|
|
17910
|
+
session_ids: sessions.map((session) => session.sessionId),
|
|
17911
|
+
labels: sessions.map((session) => session.label),
|
|
17912
|
+
environments: sessions.map(() => detectShellContext())
|
|
17913
|
+
});
|
|
17914
|
+
printCommandEnvelope(
|
|
17915
|
+
{
|
|
17916
|
+
...response,
|
|
17917
|
+
ok: true,
|
|
17918
|
+
uploaded: sessions.length,
|
|
17919
|
+
render: {
|
|
17920
|
+
sections: [
|
|
17921
|
+
{
|
|
17922
|
+
title: "sessions send",
|
|
17923
|
+
lines: ["Session uploaded to #internal-reports (chunked)."]
|
|
17924
|
+
}
|
|
17925
|
+
]
|
|
17926
|
+
}
|
|
17927
|
+
},
|
|
17928
|
+
{ json: options.json }
|
|
17929
|
+
);
|
|
17930
|
+
}
|
|
17931
|
+
async function handleSessionsSend(options) {
|
|
17932
|
+
if (options.file) {
|
|
17933
|
+
const filePath = resolve12(options.file);
|
|
17934
|
+
if (!existsSync8(filePath)) {
|
|
17935
|
+
throw new Error(`File not found: ${options.file}`);
|
|
17936
|
+
}
|
|
17937
|
+
const response2 = await uploadPayload("/api/v2/cli/send-session", {
|
|
17938
|
+
file: readFileSync7(filePath).toString("base64"),
|
|
17939
|
+
filename: basename4(filePath)
|
|
17940
|
+
});
|
|
17941
|
+
printCommandEnvelope(
|
|
17942
|
+
{
|
|
17943
|
+
...response2,
|
|
17944
|
+
ok: true,
|
|
17945
|
+
filename: basename4(filePath),
|
|
17946
|
+
render: {
|
|
17947
|
+
sections: [
|
|
17948
|
+
{
|
|
17949
|
+
title: "sessions send",
|
|
17950
|
+
lines: [
|
|
17951
|
+
`File '${basename4(filePath)}' uploaded to #internal-reports.`
|
|
17952
|
+
]
|
|
17953
|
+
}
|
|
17954
|
+
]
|
|
17955
|
+
}
|
|
17956
|
+
},
|
|
17957
|
+
{ json: options.json }
|
|
17958
|
+
);
|
|
17959
|
+
return;
|
|
17960
|
+
}
|
|
17961
|
+
const targets = resolveSessionTargets({
|
|
17962
|
+
sessionIds: options.sessionId,
|
|
17963
|
+
labels: options.label,
|
|
17964
|
+
currentSession: options.currentSession
|
|
17965
|
+
});
|
|
17966
|
+
const built = targets.map((target) => {
|
|
17967
|
+
const upload = buildSessionUploadContent(readFileSync7(target.filePath));
|
|
17968
|
+
return { ...target, ...upload };
|
|
17969
|
+
});
|
|
17970
|
+
if (built.some((session) => session.needsChunking)) {
|
|
17971
|
+
await uploadChunkedSessions(built, options);
|
|
17972
|
+
return;
|
|
17973
|
+
}
|
|
17974
|
+
const response = built.length === 1 && !options.label?.length ? await uploadPayload("/api/v2/cli/send-session", {
|
|
17975
|
+
session_id: built[0]?.sessionId,
|
|
17976
|
+
content: built[0]?.encodedContent,
|
|
17977
|
+
environment: detectShellContext()
|
|
17978
|
+
}) : await uploadPayload("/api/v2/cli/send-session", {
|
|
17979
|
+
sessions: built.map((session) => ({
|
|
17980
|
+
session_id: session.sessionId,
|
|
17981
|
+
content: session.encodedContent,
|
|
17982
|
+
label: session.label,
|
|
17983
|
+
environment: detectShellContext()
|
|
17984
|
+
})),
|
|
17985
|
+
environment: detectShellContext()
|
|
17986
|
+
});
|
|
17987
|
+
printCommandEnvelope(
|
|
17988
|
+
{
|
|
17989
|
+
...response,
|
|
17990
|
+
ok: true,
|
|
17991
|
+
uploaded: built.length,
|
|
17992
|
+
render: {
|
|
17993
|
+
sections: [
|
|
17994
|
+
{
|
|
17995
|
+
title: "sessions send",
|
|
17996
|
+
lines: ["Session uploaded to #internal-reports."]
|
|
17997
|
+
}
|
|
17998
|
+
]
|
|
17999
|
+
}
|
|
18000
|
+
},
|
|
18001
|
+
{ json: options.json }
|
|
18002
|
+
);
|
|
18003
|
+
}
|
|
18004
|
+
function fallbackViewerAssets() {
|
|
18005
|
+
return {
|
|
18006
|
+
css: [
|
|
18007
|
+
"body{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;margin:0;padding:16px;background:#fafafa;color:#111}",
|
|
18008
|
+
".section{background:#fff;border:1px solid #ddd;border-radius:8px;padding:12px;margin-bottom:12px}",
|
|
18009
|
+
".section h2{margin:0 0 8px 0;font-size:14px}",
|
|
18010
|
+
"pre{margin:0;white-space:pre-wrap;word-break:break-word;background:#f6f8fa;border:1px solid #e3e5e8;border-radius:6px;padding:10px}"
|
|
18011
|
+
].join(""),
|
|
18012
|
+
js: [
|
|
18013
|
+
"(() => {",
|
|
18014
|
+
'const root=document.getElementById("main-content");',
|
|
18015
|
+
'const raw=document.getElementById("raw-sessions");',
|
|
18016
|
+
"if(!root||!raw)return;",
|
|
18017
|
+
'let sessions=[];try{sessions=JSON.parse(raw.textContent||"[]")}catch{}',
|
|
18018
|
+
'root.innerHTML="";',
|
|
18019
|
+
"for(const session of sessions){",
|
|
18020
|
+
'const section=document.createElement("section");section.className="section";',
|
|
18021
|
+
'const title=document.createElement("h2");title.textContent=String(session.label||"session");',
|
|
18022
|
+
'const pre=document.createElement("pre");',
|
|
18023
|
+
'pre.textContent=(Array.isArray(session.events)?session.events:[]).map((event)=>JSON.stringify(event)).join("\\n");',
|
|
18024
|
+
"section.append(title,pre);root.appendChild(section);",
|
|
18025
|
+
"}",
|
|
18026
|
+
"})();"
|
|
18027
|
+
].join("")
|
|
18028
|
+
};
|
|
18029
|
+
}
|
|
18030
|
+
function parsePreparedEvents(buffer) {
|
|
18031
|
+
return normalizedJsonLines(buffer).map((line) => {
|
|
18032
|
+
const parsed = parseJsonLine(line);
|
|
18033
|
+
return parsed ?? line;
|
|
18034
|
+
});
|
|
18035
|
+
}
|
|
18036
|
+
async function handleSessionsRender(options) {
|
|
18037
|
+
const targets = resolveSessionTargets({
|
|
18038
|
+
sessionIds: options.sessionId,
|
|
18039
|
+
labels: options.label,
|
|
18040
|
+
currentSession: options.currentSession
|
|
18041
|
+
});
|
|
18042
|
+
let outputPath = options.output ? resolve12(options.output) : "";
|
|
18043
|
+
if (!outputPath) {
|
|
18044
|
+
const outputDir = join9(process.cwd(), "deepline", "data");
|
|
18045
|
+
mkdirSync4(outputDir, { recursive: true });
|
|
18046
|
+
outputPath = join9(
|
|
18047
|
+
outputDir,
|
|
18048
|
+
targets.length > 1 ? "session-viewer.html" : `session-${targets[0]?.sessionId}.html`
|
|
18049
|
+
);
|
|
18050
|
+
} else {
|
|
18051
|
+
mkdirSync4(dirname9(outputPath), { recursive: true });
|
|
18052
|
+
}
|
|
18053
|
+
const sessions = targets.map((target) => ({
|
|
18054
|
+
label: target.label,
|
|
18055
|
+
events: parsePreparedEvents(
|
|
18056
|
+
prepareSessionBuffer(readFileSync7(target.filePath))
|
|
18057
|
+
)
|
|
18058
|
+
}));
|
|
18059
|
+
const { css, js } = fallbackViewerAssets();
|
|
18060
|
+
const refreshMeta = options.autoRefresh ? `<meta http-equiv="refresh" content="${Number.parseInt(options.autoRefresh, 10)}">` : "";
|
|
18061
|
+
const rawJson = JSON.stringify(sessions).replace(/<\//g, "<\\/");
|
|
18062
|
+
const html = `<!DOCTYPE html>
|
|
18063
|
+
<html lang="en">
|
|
18064
|
+
<head>
|
|
18065
|
+
<meta charset="UTF-8">
|
|
18066
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
18067
|
+
${refreshMeta}
|
|
18068
|
+
<title>Session Viewer</title>
|
|
18069
|
+
<style>${css}</style>
|
|
18070
|
+
</head>
|
|
18071
|
+
<body>
|
|
18072
|
+
<div class="layout">
|
|
18073
|
+
<div class="main" id="main-content"></div>
|
|
18074
|
+
</div>
|
|
18075
|
+
<script type="application/json" id="raw-sessions">${rawJson}</script>
|
|
18076
|
+
<script>${js}</script>
|
|
18077
|
+
</body>
|
|
18078
|
+
</html>`;
|
|
18079
|
+
writeFileSync8(outputPath, html, "utf8");
|
|
18080
|
+
printCommandEnvelope(
|
|
18081
|
+
{
|
|
18082
|
+
ok: true,
|
|
18083
|
+
file: outputPath,
|
|
18084
|
+
session_count: targets.length,
|
|
18085
|
+
render: {
|
|
18086
|
+
sections: [
|
|
18087
|
+
{
|
|
18088
|
+
title: "sessions render",
|
|
18089
|
+
lines: [`Rendered session viewer: ${outputPath}`]
|
|
18090
|
+
}
|
|
18091
|
+
]
|
|
18092
|
+
}
|
|
18093
|
+
},
|
|
18094
|
+
{ json: options.json }
|
|
18095
|
+
);
|
|
18096
|
+
}
|
|
18097
|
+
function collectOption(value, previous) {
|
|
18098
|
+
previous.push(value);
|
|
18099
|
+
return previous;
|
|
18100
|
+
}
|
|
18101
|
+
function registerSessionsCommands(program) {
|
|
18102
|
+
const sessions = program.command("sessions").description("Upload and render local agent session transcripts.").addHelpText(
|
|
18103
|
+
"after",
|
|
18104
|
+
`
|
|
18105
|
+
Notes:
|
|
18106
|
+
Session commands operate on local Claude session JSONL files under
|
|
18107
|
+
~/.claude/projects. send uploads a compacted transcript or file to Deepline.
|
|
18108
|
+
render writes a local HTML viewer.
|
|
18109
|
+
|
|
18110
|
+
Examples:
|
|
18111
|
+
deepline sessions send --current-session --json
|
|
18112
|
+
deepline sessions send --session-id 5a3bfb97-a2d9-49d9-82c6-52ccc03dadca
|
|
18113
|
+
deepline sessions render --current-session --output session.html
|
|
18114
|
+
`
|
|
18115
|
+
);
|
|
18116
|
+
sessions.command("send").description("Upload session transcript(s) or a local file to Deepline.").addHelpText(
|
|
18117
|
+
"after",
|
|
18118
|
+
`
|
|
18119
|
+
Examples:
|
|
18120
|
+
deepline sessions send --current-session --json
|
|
18121
|
+
deepline sessions send --session-id 5a3bfb97-a2d9-49d9-82c6-52ccc03dadca --label "pilot run"
|
|
18122
|
+
deepline sessions send --file ./debug.log --json
|
|
18123
|
+
`
|
|
18124
|
+
).option(
|
|
18125
|
+
"--session-id <uuid>",
|
|
18126
|
+
"Claude session UUID. Repeat for multiple sessions.",
|
|
18127
|
+
collectOption,
|
|
18128
|
+
[]
|
|
18129
|
+
).option(
|
|
18130
|
+
"--label <label>",
|
|
18131
|
+
"Label for the preceding session id",
|
|
18132
|
+
collectOption,
|
|
18133
|
+
[]
|
|
18134
|
+
).option("--current-session", "Use the newest local Claude session JSONL").option("--file <path>", "Upload a raw local file instead of a session").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSessionsSend);
|
|
18135
|
+
sessions.command("render").description("Render local session transcript(s) to an HTML viewer.").addHelpText(
|
|
18136
|
+
"after",
|
|
18137
|
+
`
|
|
18138
|
+
Examples:
|
|
18139
|
+
deepline sessions render --current-session
|
|
18140
|
+
deepline sessions render --session-id 5a3bfb97-a2d9-49d9-82c6-52ccc03dadca --output session.html
|
|
18141
|
+
deepline sessions render --current-session --auto-refresh 5 --json
|
|
18142
|
+
`
|
|
18143
|
+
).option(
|
|
18144
|
+
"--session-id <uuid>",
|
|
18145
|
+
"Claude session UUID. Repeat for multiple sessions.",
|
|
18146
|
+
collectOption,
|
|
18147
|
+
[]
|
|
18148
|
+
).option(
|
|
18149
|
+
"--label <label>",
|
|
18150
|
+
"Label for the preceding session id",
|
|
18151
|
+
collectOption,
|
|
18152
|
+
[]
|
|
18153
|
+
).option("--current-session", "Use the newest local Claude session JSONL").option("--auto-refresh <seconds>", "Add a browser auto-refresh interval").option("-o, --output <path>", "Output HTML path").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSessionsRender);
|
|
18154
|
+
}
|
|
18155
|
+
|
|
17555
18156
|
// src/cli/commands/tools.ts
|
|
17556
18157
|
import { Option } from "commander";
|
|
17557
18158
|
import {
|
|
17558
18159
|
chmodSync,
|
|
17559
|
-
existsSync as
|
|
18160
|
+
existsSync as existsSync9,
|
|
17560
18161
|
mkdtempSync,
|
|
17561
|
-
readFileSync as
|
|
17562
|
-
writeFileSync as
|
|
18162
|
+
readFileSync as readFileSync8,
|
|
18163
|
+
writeFileSync as writeFileSync10
|
|
17563
18164
|
} from "fs";
|
|
17564
18165
|
import { tmpdir as tmpdir4 } from "os";
|
|
17565
|
-
import { join as
|
|
18166
|
+
import { join as join11, resolve as resolve13 } from "path";
|
|
17566
18167
|
|
|
17567
18168
|
// src/tool-output.ts
|
|
17568
|
-
import { mkdirSync as
|
|
17569
|
-
import { homedir as
|
|
17570
|
-
import { join as
|
|
18169
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
18170
|
+
import { homedir as homedir6 } from "os";
|
|
18171
|
+
import { join as join10 } from "path";
|
|
17571
18172
|
function isPlainObject(value) {
|
|
17572
18173
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
17573
18174
|
}
|
|
@@ -17663,19 +18264,19 @@ function tryConvertToList(payload, options) {
|
|
|
17663
18264
|
return null;
|
|
17664
18265
|
}
|
|
17665
18266
|
function ensureOutputDir() {
|
|
17666
|
-
const outputDir =
|
|
17667
|
-
|
|
18267
|
+
const outputDir = join10(homedir6(), ".local", "share", "deepline", "data");
|
|
18268
|
+
mkdirSync5(outputDir, { recursive: true });
|
|
17668
18269
|
return outputDir;
|
|
17669
18270
|
}
|
|
17670
18271
|
function writeJsonOutputFile(payload, stem) {
|
|
17671
18272
|
const outputDir = ensureOutputDir();
|
|
17672
|
-
const outputPath =
|
|
17673
|
-
|
|
18273
|
+
const outputPath = join10(outputDir, `${stem}_${Date.now()}.json`);
|
|
18274
|
+
writeFileSync9(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
17674
18275
|
return outputPath;
|
|
17675
18276
|
}
|
|
17676
18277
|
function writeCsvOutputFile(rows, stem) {
|
|
17677
18278
|
const outputDir = ensureOutputDir();
|
|
17678
|
-
const outputPath =
|
|
18279
|
+
const outputPath = join10(outputDir, `${stem}_${Date.now()}.csv`);
|
|
17679
18280
|
const seen = /* @__PURE__ */ new Set();
|
|
17680
18281
|
const columns = [];
|
|
17681
18282
|
for (const row of rows) {
|
|
@@ -17698,7 +18299,7 @@ function writeCsvOutputFile(rows, stem) {
|
|
|
17698
18299
|
for (const row of rows) {
|
|
17699
18300
|
lines.push(columns.map((column) => escapeCell(row[column])).join(","));
|
|
17700
18301
|
}
|
|
17701
|
-
|
|
18302
|
+
writeFileSync9(outputPath, `${lines.join("\n")}
|
|
17702
18303
|
`, "utf-8");
|
|
17703
18304
|
const previewRows = rows.slice(0, 5);
|
|
17704
18305
|
const previewColumns = columns.slice(0, 5);
|
|
@@ -17984,7 +18585,7 @@ Common commands:
|
|
|
17984
18585
|
|
|
17985
18586
|
Output:
|
|
17986
18587
|
Use describe for tool contracts.
|
|
17987
|
-
Use execute to run a tool.
|
|
18588
|
+
Use execute to run a tool.
|
|
17988
18589
|
`
|
|
17989
18590
|
);
|
|
17990
18591
|
tools.command("list").description("List available tools.").addHelpText(
|
|
@@ -18077,7 +18678,7 @@ Examples:
|
|
|
18077
18678
|
Notes:
|
|
18078
18679
|
Shows the compact agent contract by default: what the tool does, cost,
|
|
18079
18680
|
required inputs, play getters, and a runnable ctx.tools.execute snippet.
|
|
18080
|
-
|
|
18681
|
+
get is accepted as a compatibility alias for describe.
|
|
18081
18682
|
|
|
18082
18683
|
Examples:
|
|
18083
18684
|
deepline tools describe hunter_email_verifier
|
|
@@ -18111,29 +18712,13 @@ Examples:
|
|
|
18111
18712
|
gettersOnly: Boolean(options.gettersOnly)
|
|
18112
18713
|
});
|
|
18113
18714
|
});
|
|
18114
|
-
addToolMetadataCommand(tools.command("describe <toolId>"));
|
|
18115
|
-
tools.command("
|
|
18116
|
-
"after",
|
|
18117
|
-
`
|
|
18118
|
-
Examples:
|
|
18119
|
-
deepline tools describe hunter_email_verifier --json
|
|
18120
|
-
`
|
|
18121
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (toolId, options) => {
|
|
18122
|
-
const message = `tools get has been removed from the V2 SDK CLI. Use: deepline tools describe ${toolId} --json`;
|
|
18123
|
-
if (options.json || shouldEmitJson()) {
|
|
18124
|
-
printJsonError({ message, code: "TOOLS_GET_REMOVED" });
|
|
18125
|
-
} else {
|
|
18126
|
-
console.error(message);
|
|
18127
|
-
}
|
|
18128
|
-
process.exitCode = 2;
|
|
18129
|
-
});
|
|
18130
|
-
tools.command("execute <toolId>").alias("run").description("Execute a tool by id.").addHelpText(
|
|
18715
|
+
addToolMetadataCommand(tools.command("describe <toolId>").alias("get"));
|
|
18716
|
+
tools.command("execute <toolId>").description("Execute a tool by id.").addHelpText(
|
|
18131
18717
|
"after",
|
|
18132
18718
|
`
|
|
18133
18719
|
Notes:
|
|
18134
18720
|
Use tools for one atomic provider/API operation. Use plays for composed workflows,
|
|
18135
18721
|
waterfalls, row maps, checkpoints, and retries.
|
|
18136
|
-
execute is the canonical execution verb. run is a compatibility alias.
|
|
18137
18722
|
Calling a provider-backed tool can spend Deepline credits. Use --json for the
|
|
18138
18723
|
stable result payload plus output preview and debugging helpers.
|
|
18139
18724
|
|
|
@@ -18181,7 +18766,7 @@ Examples:
|
|
|
18181
18766
|
}
|
|
18182
18767
|
async function getTool(toolId, options = {}) {
|
|
18183
18768
|
if (!toolId) {
|
|
18184
|
-
console.error("Usage: deepline tools
|
|
18769
|
+
console.error("Usage: deepline tools describe <toolId> [--json]");
|
|
18185
18770
|
return 1;
|
|
18186
18771
|
}
|
|
18187
18772
|
const client2 = new DeeplineClient();
|
|
@@ -18732,11 +19317,11 @@ function normalizeOutputFormat(raw) {
|
|
|
18732
19317
|
}
|
|
18733
19318
|
function resolveAtFilePath(rawPath) {
|
|
18734
19319
|
const trimmed = rawPath.trim();
|
|
18735
|
-
const resolved =
|
|
18736
|
-
if (
|
|
19320
|
+
const resolved = resolve13(trimmed);
|
|
19321
|
+
if (existsSync9(resolved)) return resolved;
|
|
18737
19322
|
if (process.platform !== "win32" && trimmed.includes("\\")) {
|
|
18738
|
-
const normalized =
|
|
18739
|
-
if (
|
|
19323
|
+
const normalized = resolve13(trimmed.replace(/\\/g, "/"));
|
|
19324
|
+
if (existsSync9(normalized)) return normalized;
|
|
18740
19325
|
}
|
|
18741
19326
|
return resolved;
|
|
18742
19327
|
}
|
|
@@ -18747,7 +19332,7 @@ function readJsonArgument(raw, flagName) {
|
|
|
18747
19332
|
throw new Error(`Invalid ${flagName} value: empty @file path.`);
|
|
18748
19333
|
}
|
|
18749
19334
|
try {
|
|
18750
|
-
return
|
|
19335
|
+
return readFileSync8(resolveAtFilePath(filePath), "utf8").replace(
|
|
18751
19336
|
/^\uFEFF/,
|
|
18752
19337
|
""
|
|
18753
19338
|
);
|
|
@@ -18838,9 +19423,9 @@ function powerShellQuote(value) {
|
|
|
18838
19423
|
function seedToolListScript(input2) {
|
|
18839
19424
|
const stem = safeFileStem(input2.toolId);
|
|
18840
19425
|
const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
|
|
18841
|
-
const scriptDir = mkdtempSync(
|
|
19426
|
+
const scriptDir = mkdtempSync(join11(tmpdir4(), "deepline-workflow-seed-"));
|
|
18842
19427
|
chmodSync(scriptDir, 448);
|
|
18843
|
-
const scriptPath =
|
|
19428
|
+
const scriptPath = join11(scriptDir, fileName);
|
|
18844
19429
|
const projectDir = `deepline/projects/${stem}-workflow`;
|
|
18845
19430
|
const playName = `${stem}-workflow`;
|
|
18846
19431
|
const sampleRows = input2.rows.length > 0 ? `${JSON.stringify(input2.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
|
|
@@ -18876,7 +19461,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
|
18876
19461
|
};
|
|
18877
19462
|
});
|
|
18878
19463
|
`;
|
|
18879
|
-
|
|
19464
|
+
writeFileSync10(scriptPath, script, { encoding: "utf-8", mode: 384 });
|
|
18880
19465
|
return {
|
|
18881
19466
|
path: scriptPath,
|
|
18882
19467
|
sourceCode: script,
|
|
@@ -19131,7 +19716,7 @@ async function executeTool(args) {
|
|
|
19131
19716
|
|
|
19132
19717
|
// src/cli/commands/workflow.ts
|
|
19133
19718
|
import { mkdir as mkdir5, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
19134
|
-
import { dirname as
|
|
19719
|
+
import { dirname as dirname10, join as join12, resolve as resolve14 } from "path";
|
|
19135
19720
|
|
|
19136
19721
|
// src/cli/workflow-to-play.ts
|
|
19137
19722
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -19338,7 +19923,7 @@ function readStatus(payload) {
|
|
|
19338
19923
|
}
|
|
19339
19924
|
async function readJsonOption(payload, file) {
|
|
19340
19925
|
if (file) {
|
|
19341
|
-
const raw = await readFile4(
|
|
19926
|
+
const raw = await readFile4(resolve14(file), "utf8");
|
|
19342
19927
|
return JSON.parse(raw);
|
|
19343
19928
|
}
|
|
19344
19929
|
if (payload) {
|
|
@@ -19372,8 +19957,8 @@ async function transformOne(api, workflowId, outDir, publish) {
|
|
|
19372
19957
|
revision.config,
|
|
19373
19958
|
{ workflowName: workflow.name, version: revision.version }
|
|
19374
19959
|
);
|
|
19375
|
-
const file =
|
|
19376
|
-
await mkdir5(
|
|
19960
|
+
const file = join12(resolve14(outDir), `${compiled.playName}.play.ts`);
|
|
19961
|
+
await mkdir5(dirname10(file), { recursive: true });
|
|
19377
19962
|
await writeFile5(file, compiled.sourceCode, "utf8");
|
|
19378
19963
|
let published = false;
|
|
19379
19964
|
if (publish) {
|
|
@@ -19620,8 +20205,8 @@ Notes:
|
|
|
19620
20205
|
|
|
19621
20206
|
// src/cli/commands/update.ts
|
|
19622
20207
|
import { spawn } from "child_process";
|
|
19623
|
-
import { existsSync as
|
|
19624
|
-
import { dirname as
|
|
20208
|
+
import { existsSync as existsSync10 } from "fs";
|
|
20209
|
+
import { dirname as dirname11, join as join13, resolve as resolve15 } from "path";
|
|
19625
20210
|
function posixShellQuote(value) {
|
|
19626
20211
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
19627
20212
|
}
|
|
@@ -19640,19 +20225,19 @@ function buildSourceUpdateCommand(sourceRoot) {
|
|
|
19640
20225
|
return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
|
|
19641
20226
|
}
|
|
19642
20227
|
function findRepoBackedSdkRoot(startPath) {
|
|
19643
|
-
let current =
|
|
20228
|
+
let current = resolve15(startPath);
|
|
19644
20229
|
while (true) {
|
|
19645
|
-
if (
|
|
20230
|
+
if (existsSync10(join13(current, "sdk", "package.json")) && existsSync10(join13(current, "sdk", "bin", "deepline-dev.ts"))) {
|
|
19646
20231
|
return current;
|
|
19647
20232
|
}
|
|
19648
|
-
const parent =
|
|
20233
|
+
const parent = dirname11(current);
|
|
19649
20234
|
if (parent === current) return null;
|
|
19650
20235
|
current = parent;
|
|
19651
20236
|
}
|
|
19652
20237
|
}
|
|
19653
20238
|
function resolveUpdatePlan() {
|
|
19654
|
-
const entrypoint = process.argv[1] ?
|
|
19655
|
-
const sourceRoot = entrypoint ? findRepoBackedSdkRoot(
|
|
20239
|
+
const entrypoint = process.argv[1] ? resolve15(process.argv[1]) : "";
|
|
20240
|
+
const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname11(entrypoint)) : null;
|
|
19656
20241
|
if (sourceRoot) {
|
|
19657
20242
|
return {
|
|
19658
20243
|
kind: "source",
|
|
@@ -19727,7 +20312,7 @@ async function handleUpdate(options) {
|
|
|
19727
20312
|
return runCommand(plan.command, plan.args);
|
|
19728
20313
|
}
|
|
19729
20314
|
function registerUpdateCommand(program) {
|
|
19730
|
-
program.command("update").
|
|
20315
|
+
program.command("update").description("Update the Deepline SDK/CLI.").addHelpText(
|
|
19731
20316
|
"after",
|
|
19732
20317
|
`
|
|
19733
20318
|
Notes:
|
|
@@ -19755,7 +20340,7 @@ var command_compatibility_default = {
|
|
|
19755
20340
|
session: {
|
|
19756
20341
|
family: "python",
|
|
19757
20342
|
label: "a legacy Python CLI session/playground command",
|
|
19758
|
-
sdk_alternative: "Use
|
|
20343
|
+
sdk_alternative: "Use `deepline sessions send ...` or `deepline sessions render ...` for transcript workflows."
|
|
19759
20344
|
},
|
|
19760
20345
|
workflows: {
|
|
19761
20346
|
family: "python",
|
|
@@ -19775,15 +20360,14 @@ var command_compatibility_default = {
|
|
|
19775
20360
|
label: "an SDK CLI play command",
|
|
19776
20361
|
python_alternative: "Use `deepline workflows ...` only for legacy workflows."
|
|
19777
20362
|
},
|
|
19778
|
-
play: {
|
|
19779
|
-
family: "sdk",
|
|
19780
|
-
label: "an SDK CLI play command",
|
|
19781
|
-
python_alternative: "Use `deepline workflows ...` only for legacy workflows."
|
|
19782
|
-
},
|
|
19783
20363
|
runs: {
|
|
19784
20364
|
family: "sdk",
|
|
19785
20365
|
label: "an SDK CLI run inspection command"
|
|
19786
20366
|
},
|
|
20367
|
+
sessions: {
|
|
20368
|
+
family: "sdk",
|
|
20369
|
+
label: "an SDK CLI session transcript command"
|
|
20370
|
+
},
|
|
19787
20371
|
health: {
|
|
19788
20372
|
family: "sdk",
|
|
19789
20373
|
label: "an SDK CLI health command"
|
|
@@ -19916,15 +20500,15 @@ function unknownCommandNameFromMessage(message) {
|
|
|
19916
20500
|
// src/cli/skills-sync.ts
|
|
19917
20501
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
19918
20502
|
import {
|
|
19919
|
-
existsSync as
|
|
19920
|
-
mkdirSync as
|
|
19921
|
-
readdirSync as
|
|
19922
|
-
readFileSync as
|
|
19923
|
-
statSync as
|
|
19924
|
-
writeFileSync as
|
|
20503
|
+
existsSync as existsSync11,
|
|
20504
|
+
mkdirSync as mkdirSync6,
|
|
20505
|
+
readdirSync as readdirSync3,
|
|
20506
|
+
readFileSync as readFileSync9,
|
|
20507
|
+
statSync as statSync4,
|
|
20508
|
+
writeFileSync as writeFileSync11
|
|
19925
20509
|
} from "fs";
|
|
19926
|
-
import { homedir as
|
|
19927
|
-
import { dirname as
|
|
20510
|
+
import { homedir as homedir7 } from "os";
|
|
20511
|
+
import { dirname as dirname12, join as join14 } from "path";
|
|
19928
20512
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
19929
20513
|
var SDK_SKILL_NAME = "deepline-plays";
|
|
19930
20514
|
var attemptedSync = false;
|
|
@@ -19938,20 +20522,20 @@ function activePluginSkillsDir() {
|
|
|
19938
20522
|
return "";
|
|
19939
20523
|
}
|
|
19940
20524
|
const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
|
|
19941
|
-
return dir &&
|
|
20525
|
+
return dir && existsSync11(dir) ? dir : "";
|
|
19942
20526
|
}
|
|
19943
20527
|
function readPluginSkillsVersion() {
|
|
19944
20528
|
const dir = activePluginSkillsDir();
|
|
19945
20529
|
if (!dir) return "";
|
|
19946
20530
|
try {
|
|
19947
|
-
return
|
|
20531
|
+
return readFileSync9(join14(dir, ".version"), "utf-8").trim();
|
|
19948
20532
|
} catch {
|
|
19949
20533
|
return "";
|
|
19950
20534
|
}
|
|
19951
20535
|
}
|
|
19952
20536
|
function sdkSkillsVersionPath(baseUrl) {
|
|
19953
|
-
const home = process.env.HOME?.trim() ||
|
|
19954
|
-
return
|
|
20537
|
+
const home = process.env.HOME?.trim() || homedir7();
|
|
20538
|
+
return join14(
|
|
19955
20539
|
home,
|
|
19956
20540
|
".local",
|
|
19957
20541
|
"deepline",
|
|
@@ -19964,25 +20548,25 @@ function readLocalSkillsVersion(baseUrl) {
|
|
|
19964
20548
|
const pluginVersion = readPluginSkillsVersion();
|
|
19965
20549
|
if (pluginVersion) return pluginVersion;
|
|
19966
20550
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
19967
|
-
if (!
|
|
20551
|
+
if (!existsSync11(path)) return "";
|
|
19968
20552
|
try {
|
|
19969
|
-
return
|
|
20553
|
+
return readFileSync9(path, "utf-8").trim();
|
|
19970
20554
|
} catch {
|
|
19971
20555
|
return "";
|
|
19972
20556
|
}
|
|
19973
20557
|
}
|
|
19974
20558
|
function writeLocalSkillsVersion(baseUrl, version) {
|
|
19975
20559
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
19976
|
-
|
|
19977
|
-
|
|
20560
|
+
mkdirSync6(dirname12(path), { recursive: true });
|
|
20561
|
+
writeFileSync11(path, `${version}
|
|
19978
20562
|
`, "utf-8");
|
|
19979
20563
|
}
|
|
19980
20564
|
function installedSdkSkillHasStalePositionalExecuteExamples() {
|
|
19981
|
-
const home = process.env.HOME?.trim() ||
|
|
20565
|
+
const home = process.env.HOME?.trim() || homedir7();
|
|
19982
20566
|
const pluginSkillsDir = activePluginSkillsDir();
|
|
19983
|
-
const roots = pluginSkillsDir ? [
|
|
19984
|
-
|
|
19985
|
-
|
|
20567
|
+
const roots = pluginSkillsDir ? [join14(pluginSkillsDir, SDK_SKILL_NAME)] : [
|
|
20568
|
+
join14(home, ".claude", "skills", SDK_SKILL_NAME),
|
|
20569
|
+
join14(home, ".agents", "skills", SDK_SKILL_NAME)
|
|
19986
20570
|
];
|
|
19987
20571
|
const staleMarkers = [
|
|
19988
20572
|
"ctx.tools.execute(key",
|
|
@@ -19992,22 +20576,22 @@ function installedSdkSkillHasStalePositionalExecuteExamples() {
|
|
|
19992
20576
|
'rowCtx.tools.execute("'
|
|
19993
20577
|
];
|
|
19994
20578
|
const scan = (dir) => {
|
|
19995
|
-
for (const entry of
|
|
19996
|
-
const path =
|
|
19997
|
-
const stat4 =
|
|
20579
|
+
for (const entry of readdirSync3(dir)) {
|
|
20580
|
+
const path = join14(dir, entry);
|
|
20581
|
+
const stat4 = statSync4(path);
|
|
19998
20582
|
if (stat4.isDirectory()) {
|
|
19999
20583
|
if (scan(path)) return true;
|
|
20000
20584
|
continue;
|
|
20001
20585
|
}
|
|
20002
20586
|
if (!entry.endsWith(".md")) continue;
|
|
20003
|
-
const text =
|
|
20587
|
+
const text = readFileSync9(path, "utf-8");
|
|
20004
20588
|
if (staleMarkers.some((marker) => text.includes(marker))) return true;
|
|
20005
20589
|
}
|
|
20006
20590
|
return false;
|
|
20007
20591
|
};
|
|
20008
20592
|
for (const root of roots) {
|
|
20009
20593
|
try {
|
|
20010
|
-
if (
|
|
20594
|
+
if (existsSync11(root) && scan(root)) return true;
|
|
20011
20595
|
} catch {
|
|
20012
20596
|
continue;
|
|
20013
20597
|
}
|
|
@@ -20079,7 +20663,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
20079
20663
|
return [npxInstall];
|
|
20080
20664
|
}
|
|
20081
20665
|
function runOneSkillsInstall(install) {
|
|
20082
|
-
return new Promise((
|
|
20666
|
+
return new Promise((resolve16) => {
|
|
20083
20667
|
const child = spawn2(install.command, install.args, {
|
|
20084
20668
|
stdio: ["ignore", "ignore", "pipe"],
|
|
20085
20669
|
env: process.env
|
|
@@ -20089,7 +20673,7 @@ function runOneSkillsInstall(install) {
|
|
|
20089
20673
|
stderr += chunk.toString("utf-8");
|
|
20090
20674
|
});
|
|
20091
20675
|
child.on("error", (error) => {
|
|
20092
|
-
|
|
20676
|
+
resolve16({
|
|
20093
20677
|
ok: false,
|
|
20094
20678
|
detail: `failed to start ${install.command}: ${error.message}`,
|
|
20095
20679
|
manualCommand: install.manualCommand
|
|
@@ -20097,11 +20681,11 @@ function runOneSkillsInstall(install) {
|
|
|
20097
20681
|
});
|
|
20098
20682
|
child.on("close", (code) => {
|
|
20099
20683
|
if (code === 0) {
|
|
20100
|
-
|
|
20684
|
+
resolve16({ ok: true, detail: "", manualCommand: install.manualCommand });
|
|
20101
20685
|
return;
|
|
20102
20686
|
}
|
|
20103
20687
|
const detail = stderr.trim();
|
|
20104
|
-
|
|
20688
|
+
resolve16({
|
|
20105
20689
|
ok: false,
|
|
20106
20690
|
detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
|
|
20107
20691
|
manualCommand: install.manualCommand
|
|
@@ -20189,8 +20773,8 @@ function shouldDeferSkillsSyncForCommand() {
|
|
|
20189
20773
|
return (command === "play" || command === "plays") && subcommand === "run" && args.includes("--json");
|
|
20190
20774
|
}
|
|
20191
20775
|
async function runPlayRunnerHealthCheck() {
|
|
20192
|
-
const dir = await mkdtemp2(
|
|
20193
|
-
const file =
|
|
20776
|
+
const dir = await mkdtemp2(join15(tmpdir5(), "deepline-health-play-"));
|
|
20777
|
+
const file = join15(dir, "health-check.play.ts");
|
|
20194
20778
|
try {
|
|
20195
20779
|
await writeFile6(
|
|
20196
20780
|
file,
|
|
@@ -20378,6 +20962,7 @@ Common commands:
|
|
|
20378
20962
|
deepline preflight
|
|
20379
20963
|
deepline health
|
|
20380
20964
|
deepline auth status --json
|
|
20965
|
+
deepline sessions send --current-session --json
|
|
20381
20966
|
deepline plays search email --json
|
|
20382
20967
|
deepline plays describe person-linkedin-to-email --json
|
|
20383
20968
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
@@ -20430,6 +21015,7 @@ Exit codes:
|
|
|
20430
21015
|
registerAuthCommands(program);
|
|
20431
21016
|
registerToolsCommands(program);
|
|
20432
21017
|
registerPlayCommands(program);
|
|
21018
|
+
registerSessionsCommands(program);
|
|
20433
21019
|
registerWorkflowCommands(program);
|
|
20434
21020
|
registerSecretsCommands(program);
|
|
20435
21021
|
registerBillingCommands(program);
|