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