deepline 0.2.70 → 0.2.72
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/dist/bundling-sources/sdk/src/client.ts +45 -12
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/types.ts +18 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +67 -14
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +1 -1
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +55 -14
- package/dist/bundling-sources/shared_libs/plays/enrich-play-compiler.ts +13 -3
- package/dist/bundling-sources/shared_libs/plays/tool-category-descriptions.ts +12 -0
- package/dist/cli/index.js +428 -40
- package/dist/cli/index.mjs +465 -69
- package/dist/index.d.mts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +64 -26
- package/dist/index.mjs +64 -26
- package/dist/plays/bundle-play-file.mjs +35 -14
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1044,7 +1044,7 @@ var SDK_RELEASE = {
|
|
|
1044
1044
|
// 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
|
|
1045
1045
|
// exposed storage-dependent synchronous access. This deliberate minor
|
|
1046
1046
|
// release keeps lazy paging semantics independent of row residency.
|
|
1047
|
-
version: "0.2.
|
|
1047
|
+
version: "0.2.72",
|
|
1048
1048
|
contracts: {
|
|
1049
1049
|
api: {
|
|
1050
1050
|
name: "sdk-http-api",
|
|
@@ -3983,16 +3983,9 @@ function isPrebuiltPlayDescription(play) {
|
|
|
3983
3983
|
return play.origin === "prebuilt" || play.ownerType === "deepline";
|
|
3984
3984
|
}
|
|
3985
3985
|
function preferPrebuiltPlayDescriptions(plays) {
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
if (isPrebuiltPlayDescription(play)) {
|
|
3990
|
-
prebuilt.push(play);
|
|
3991
|
-
} else {
|
|
3992
|
-
owned.push(play);
|
|
3993
|
-
}
|
|
3994
|
-
}
|
|
3995
|
-
return [...prebuilt, ...owned];
|
|
3986
|
+
return plays.map((play, index) => ({ play, index })).sort(
|
|
3987
|
+
(left, right) => Number(right.play.pinned) - Number(left.play.pinned) || Number(isPrebuiltPlayDescription(right.play)) - Number(isPrebuiltPlayDescription(left.play)) || left.index - right.index
|
|
3988
|
+
).map(({ play }) => play);
|
|
3996
3989
|
}
|
|
3997
3990
|
function isPlayRunPackage(value) {
|
|
3998
3991
|
return Boolean(
|
|
@@ -4339,6 +4332,8 @@ var DeeplineClient = class {
|
|
|
4339
4332
|
...play.reference ? { reference: play.reference } : {},
|
|
4340
4333
|
...play.displayName ? { displayName: play.displayName } : {},
|
|
4341
4334
|
...description ? { description } : {},
|
|
4335
|
+
pinned: Boolean(play.pinned),
|
|
4336
|
+
toolCategories: play.toolCategories ?? [],
|
|
4342
4337
|
origin: play.origin,
|
|
4343
4338
|
ownerType: play.ownerType,
|
|
4344
4339
|
canEdit: play.canEdit,
|
|
@@ -5837,6 +5832,16 @@ var DeeplineClient = class {
|
|
|
5837
5832
|
async listPlays(options) {
|
|
5838
5833
|
const params = new URLSearchParams();
|
|
5839
5834
|
if (options?.origin) params.set("origin", options.origin);
|
|
5835
|
+
if (options?.categories) {
|
|
5836
|
+
params.set(
|
|
5837
|
+
"categories",
|
|
5838
|
+
Array.isArray(options.categories) ? options.categories.join(",") : options.categories
|
|
5839
|
+
);
|
|
5840
|
+
}
|
|
5841
|
+
if (options?.categories || options?.includeToolCategories) {
|
|
5842
|
+
params.set("include_tool_categories", "1");
|
|
5843
|
+
}
|
|
5844
|
+
if (options?.includeArchived) params.set("include_archived", "1");
|
|
5840
5845
|
if (options?.grep?.trim()) {
|
|
5841
5846
|
params.set("grep", options.grep.trim());
|
|
5842
5847
|
params.set("grep_mode", options.grepMode ?? "all");
|
|
@@ -5848,6 +5853,12 @@ var DeeplineClient = class {
|
|
|
5848
5853
|
);
|
|
5849
5854
|
return response.plays ?? [];
|
|
5850
5855
|
}
|
|
5856
|
+
/** Set whether an org-owned Play sorts before unpinned Plays. */
|
|
5857
|
+
async setPlayPinned(playName, pinned) {
|
|
5858
|
+
return this.http.post(`/api/v2/plays/${encodeURIComponent(playName)}/pin`, {
|
|
5859
|
+
pinned
|
|
5860
|
+
});
|
|
5861
|
+
}
|
|
5851
5862
|
/** Read product-notification destinations, subscriptions, event catalog, and DLQ health. */
|
|
5852
5863
|
async getNotificationSettings() {
|
|
5853
5864
|
return this.http.get("/api/v2/settings/notifications");
|
|
@@ -5981,9 +5992,10 @@ var DeeplineClient = class {
|
|
|
5981
5992
|
* console.log(`Total runs: ${detail.play.runCount}`);
|
|
5982
5993
|
* ```
|
|
5983
5994
|
*/
|
|
5984
|
-
async getPlay(name) {
|
|
5995
|
+
async getPlay(name, options) {
|
|
5985
5996
|
const encodedName = encodeURIComponent(name);
|
|
5986
|
-
|
|
5997
|
+
const query = options?.source ? `?include=source&revision=${encodeURIComponent(options.source)}` : "";
|
|
5998
|
+
return this.http.get(`/api/v2/plays/${encodedName}${query}`);
|
|
5987
5999
|
}
|
|
5988
6000
|
/**
|
|
5989
6001
|
* Get a normalized play description suitable for agents and CLIs.
|
|
@@ -18580,7 +18592,10 @@ async function assertCanonicalNamedPlayReference(client2, target, options = {})
|
|
|
18580
18592
|
const parsed = parseReferencedPlayTarget2(target);
|
|
18581
18593
|
let detail;
|
|
18582
18594
|
try {
|
|
18583
|
-
detail = await client2.getPlay(
|
|
18595
|
+
detail = await client2.getPlay(
|
|
18596
|
+
parsed.playName,
|
|
18597
|
+
options.source ? { source: options.source } : void 0
|
|
18598
|
+
);
|
|
18584
18599
|
} catch (error) {
|
|
18585
18600
|
if (isPlayNotFoundError(error)) {
|
|
18586
18601
|
throw await buildPlayReferenceNotFoundError({
|
|
@@ -18633,19 +18648,54 @@ function materializeRemotePlaySource(input2) {
|
|
|
18633
18648
|
if (isFileTarget(input2.target)) {
|
|
18634
18649
|
return null;
|
|
18635
18650
|
}
|
|
18636
|
-
|
|
18651
|
+
const entrySource = input2.source.files[input2.source.entryFile];
|
|
18652
|
+
if (!entrySource?.trim()) {
|
|
18637
18653
|
return null;
|
|
18638
18654
|
}
|
|
18655
|
+
const files = Object.entries(input2.source.files);
|
|
18656
|
+
if (files.length > 1) {
|
|
18657
|
+
if (!input2.outPath) {
|
|
18658
|
+
throw new Error(
|
|
18659
|
+
`Play ${input2.playName} has ${files.length} source files. Use --out <directory> to write the complete bundle.`
|
|
18660
|
+
);
|
|
18661
|
+
}
|
|
18662
|
+
const outputDirectory = (0, import_node_path14.resolve)(input2.outPath);
|
|
18663
|
+
let created = 0;
|
|
18664
|
+
let updated = 0;
|
|
18665
|
+
for (const [logicalPath, sourceCode] of files) {
|
|
18666
|
+
const outputPath2 = (0, import_node_path14.resolve)(outputDirectory, logicalPath);
|
|
18667
|
+
const outputRelativePath = (0, import_node_path14.relative)(outputDirectory, outputPath2);
|
|
18668
|
+
if (!outputRelativePath || outputRelativePath.startsWith("..") || (0, import_node_path14.isAbsolute)(outputRelativePath)) {
|
|
18669
|
+
throw new Error(
|
|
18670
|
+
`Refusing to materialize unsafe Play source path ${JSON.stringify(logicalPath)}.`
|
|
18671
|
+
);
|
|
18672
|
+
}
|
|
18673
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path14.dirname)(outputPath2), { recursive: true });
|
|
18674
|
+
if (!(0, import_node_fs12.existsSync)(outputPath2)) {
|
|
18675
|
+
(0, import_node_fs12.writeFileSync)(outputPath2, sourceCode, "utf-8");
|
|
18676
|
+
created += 1;
|
|
18677
|
+
} else if ((0, import_node_fs12.readFileSync)(outputPath2, "utf-8") !== sourceCode) {
|
|
18678
|
+
(0, import_node_fs12.writeFileSync)(outputPath2, sourceCode, "utf-8");
|
|
18679
|
+
updated += 1;
|
|
18680
|
+
}
|
|
18681
|
+
}
|
|
18682
|
+
return {
|
|
18683
|
+
path: outputDirectory,
|
|
18684
|
+
status: created > 0 ? "created" : updated > 0 ? "updated" : "unchanged",
|
|
18685
|
+
created: created > 0,
|
|
18686
|
+
fileCount: files.length
|
|
18687
|
+
};
|
|
18688
|
+
}
|
|
18639
18689
|
const outputPath = input2.outPath ?? defaultMaterializedPlayPath(input2.playName);
|
|
18640
18690
|
if ((0, import_node_fs12.existsSync)(outputPath)) {
|
|
18641
18691
|
const existingSource = (0, import_node_fs12.readFileSync)(outputPath, "utf-8");
|
|
18642
|
-
if (existingSource ===
|
|
18692
|
+
if (existingSource === entrySource) {
|
|
18643
18693
|
return { path: outputPath, status: "unchanged", created: false };
|
|
18644
18694
|
}
|
|
18645
|
-
(0, import_node_fs12.writeFileSync)(outputPath,
|
|
18695
|
+
(0, import_node_fs12.writeFileSync)(outputPath, entrySource, "utf-8");
|
|
18646
18696
|
return { path: outputPath, status: "updated", created: false };
|
|
18647
18697
|
}
|
|
18648
|
-
(0, import_node_fs12.writeFileSync)(outputPath,
|
|
18698
|
+
(0, import_node_fs12.writeFileSync)(outputPath, entrySource, "utf-8");
|
|
18649
18699
|
return { path: outputPath, status: "created", created: true };
|
|
18650
18700
|
}
|
|
18651
18701
|
function formatLoadedPlayMessage(materializedFile) {
|
|
@@ -22518,6 +22568,47 @@ ${PLAY_PUBLISH_USAGE}`
|
|
|
22518
22568
|
jsonOutput: argsWantJson(args)
|
|
22519
22569
|
};
|
|
22520
22570
|
}
|
|
22571
|
+
var PLAY_SAVE_USAGE = "Usage: deepline plays save <play-file.ts> [--expected-artifact <hash>] [--dry-run] [--json]";
|
|
22572
|
+
function parsePlaySaveOptions(args) {
|
|
22573
|
+
const target = args[0];
|
|
22574
|
+
if (!target) throw new Error(PLAY_SAVE_USAGE);
|
|
22575
|
+
if (target.startsWith("-")) {
|
|
22576
|
+
throw new Error(`${PLAY_SAVE_USAGE}
|
|
22577
|
+
The Play file is positional.`);
|
|
22578
|
+
}
|
|
22579
|
+
let expectedArtifactHash;
|
|
22580
|
+
let dryRun = false;
|
|
22581
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
22582
|
+
const arg = args[index];
|
|
22583
|
+
if (arg === "--expected-artifact") {
|
|
22584
|
+
expectedArtifactHash = args[++index];
|
|
22585
|
+
if (!expectedArtifactHash) {
|
|
22586
|
+
throw new Error("--expected-artifact requires an artifact hash.");
|
|
22587
|
+
}
|
|
22588
|
+
continue;
|
|
22589
|
+
}
|
|
22590
|
+
if (arg.startsWith("--expected-artifact=")) {
|
|
22591
|
+
expectedArtifactHash = arg.slice("--expected-artifact=".length);
|
|
22592
|
+
if (!expectedArtifactHash) {
|
|
22593
|
+
throw new Error("--expected-artifact requires an artifact hash.");
|
|
22594
|
+
}
|
|
22595
|
+
continue;
|
|
22596
|
+
}
|
|
22597
|
+
if (arg === "--dry-run") {
|
|
22598
|
+
dryRun = true;
|
|
22599
|
+
continue;
|
|
22600
|
+
}
|
|
22601
|
+
if (arg === "--json") continue;
|
|
22602
|
+
throw new Error(`Unknown option: ${arg}
|
|
22603
|
+
${PLAY_SAVE_USAGE}`);
|
|
22604
|
+
}
|
|
22605
|
+
return {
|
|
22606
|
+
target,
|
|
22607
|
+
expectedArtifactHash,
|
|
22608
|
+
dryRun,
|
|
22609
|
+
jsonOutput: argsWantJson(args)
|
|
22610
|
+
};
|
|
22611
|
+
}
|
|
22521
22612
|
function formatByteBudget(usedBytes, limitBytes) {
|
|
22522
22613
|
return `${usedBytes.toLocaleString()} B / ${limitBytes.toLocaleString()} B`;
|
|
22523
22614
|
}
|
|
@@ -22848,6 +22939,29 @@ function resolvePlayCheckExportNames(sourceCode) {
|
|
|
22848
22939
|
if (!exports2 || exports2.length === 0) return [PLAY_DEFAULT_EXPORT];
|
|
22849
22940
|
return exports2.map((entry) => entry.name);
|
|
22850
22941
|
}
|
|
22942
|
+
function artifactForProductionCompatibilityCheck(artifact) {
|
|
22943
|
+
const rawEdition = process.env.DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION?.trim();
|
|
22944
|
+
if (!rawEdition) return artifact;
|
|
22945
|
+
if (!/^\d+$/.test(rawEdition)) {
|
|
22946
|
+
throw new Error(
|
|
22947
|
+
"DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION must be a positive integer."
|
|
22948
|
+
);
|
|
22949
|
+
}
|
|
22950
|
+
const edition = Number(rawEdition);
|
|
22951
|
+
if (edition < 1) {
|
|
22952
|
+
throw new Error(
|
|
22953
|
+
"DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION must be a positive integer."
|
|
22954
|
+
);
|
|
22955
|
+
}
|
|
22956
|
+
const compatibility = isRecord10(artifact.compatibility) ? artifact.compatibility : {};
|
|
22957
|
+
return {
|
|
22958
|
+
...artifact,
|
|
22959
|
+
compatibility: {
|
|
22960
|
+
...compatibility,
|
|
22961
|
+
authoringContractEdition: edition
|
|
22962
|
+
}
|
|
22963
|
+
};
|
|
22964
|
+
}
|
|
22851
22965
|
async function checkOneExportedPlay(input2) {
|
|
22852
22966
|
const { absolutePlayPath, sourceCode, exportName } = input2;
|
|
22853
22967
|
const fallbackName = extractPlayName(sourceCode, absolutePlayPath);
|
|
@@ -22887,7 +23001,7 @@ async function checkOneExportedPlay(input2) {
|
|
|
22887
23001
|
sourceCode: graph.root.sourceCode,
|
|
22888
23002
|
sourceFiles: graph.root.sourceFiles,
|
|
22889
23003
|
description: graph.root.playDescription ?? void 0,
|
|
22890
|
-
artifact: graph.root.artifact,
|
|
23004
|
+
artifact: artifactForProductionCompatibilityCheck(graph.root.artifact),
|
|
22891
23005
|
...exportName === PLAY_DEFAULT_EXPORT ? {} : { exportName },
|
|
22892
23006
|
...importedPlays.length > 0 ? { importedPlays } : {},
|
|
22893
23007
|
...integrationMode ? { integrationMode } : {}
|
|
@@ -23958,24 +24072,63 @@ async function handlePlayGet(args) {
|
|
|
23958
24072
|
const explicitJson = args.includes("--json");
|
|
23959
24073
|
const sourceOutput = args.includes("--source");
|
|
23960
24074
|
const jsonOutput = sourceOutput ? explicitJson : argsWantJson(args);
|
|
24075
|
+
const requestedRevisionFlags = [
|
|
24076
|
+
args.includes("--working"),
|
|
24077
|
+
args.includes("--live"),
|
|
24078
|
+
args.includes("--revision")
|
|
24079
|
+
].filter(Boolean).length;
|
|
24080
|
+
if (requestedRevisionFlags > 1) {
|
|
24081
|
+
console.error("Use only one of --working, --live, or --revision <number>.");
|
|
24082
|
+
return 2;
|
|
24083
|
+
}
|
|
24084
|
+
let sourceSelector = "working";
|
|
24085
|
+
if (args.includes("--live")) {
|
|
24086
|
+
sourceSelector = "live";
|
|
24087
|
+
}
|
|
23961
24088
|
let outPath = null;
|
|
24089
|
+
let requestedVersion = null;
|
|
23962
24090
|
for (let index = 1; index < args.length; index += 1) {
|
|
23963
24091
|
const arg = args[index];
|
|
23964
24092
|
if (arg === "--out" && args[index + 1]) {
|
|
23965
24093
|
outPath = (0, import_node_path14.resolve)(args[++index]);
|
|
23966
24094
|
}
|
|
24095
|
+
if (arg === "--revision") {
|
|
24096
|
+
const rawVersion = args[++index];
|
|
24097
|
+
const version = Number(rawVersion);
|
|
24098
|
+
if (!rawVersion || !Number.isInteger(version) || version < 1) {
|
|
24099
|
+
console.error("--revision must be a positive integer.");
|
|
24100
|
+
return 2;
|
|
24101
|
+
}
|
|
24102
|
+
requestedVersion = version;
|
|
24103
|
+
}
|
|
24104
|
+
}
|
|
24105
|
+
if (requestedVersion !== null) {
|
|
24106
|
+
sourceSelector = `version:${requestedVersion}`;
|
|
24107
|
+
}
|
|
24108
|
+
if (requestedRevisionFlags > 0 && !sourceOutput && !outPath) {
|
|
24109
|
+
console.error(
|
|
24110
|
+
"--working, --live, and --revision only apply when reading source with --source or --out."
|
|
24111
|
+
);
|
|
24112
|
+
return 2;
|
|
23967
24113
|
}
|
|
23968
24114
|
const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs12.readFileSync)((0, import_node_path14.resolve)(target), "utf-8"), (0, import_node_path14.resolve)(target)) : parseReferencedPlayTarget2(target).playName;
|
|
23969
|
-
const
|
|
23970
|
-
|
|
23971
|
-
});
|
|
23972
|
-
const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
|
|
23973
|
-
const materializedFile = outPath ? materializeRemotePlaySource({
|
|
23974
|
-
target,
|
|
24115
|
+
const includeSource = sourceOutput || outPath !== null;
|
|
24116
|
+
const detail = isFileTarget(target) ? await client2.getPlay(
|
|
23975
24117
|
playName,
|
|
23976
|
-
|
|
23977
|
-
|
|
23978
|
-
|
|
24118
|
+
includeSource ? { source: sourceSelector } : void 0
|
|
24119
|
+
) : await assertCanonicalNamedPlayReference(client2, target, {
|
|
24120
|
+
command: "get",
|
|
24121
|
+
...includeSource ? { source: sourceSelector } : {}
|
|
24122
|
+
});
|
|
24123
|
+
const source = detail.source;
|
|
24124
|
+
const resolvedSource = source?.files[source.entryFile] ?? "";
|
|
24125
|
+
let materializedFile = null;
|
|
24126
|
+
try {
|
|
24127
|
+
materializedFile = outPath && source ? materializeRemotePlaySource({ target, playName, source, outPath }) : null;
|
|
24128
|
+
} catch (error) {
|
|
24129
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
24130
|
+
return 2;
|
|
24131
|
+
}
|
|
23979
24132
|
const loadedMessage = materializedFile ? formatLoadedPlayMessage(materializedFile) : null;
|
|
23980
24133
|
if (jsonOutput) {
|
|
23981
24134
|
process.stdout.write(
|
|
@@ -23996,14 +24149,20 @@ async function handlePlayGet(args) {
|
|
|
23996
24149
|
return 0;
|
|
23997
24150
|
}
|
|
23998
24151
|
if (sourceOutput) {
|
|
23999
|
-
if (!resolvedSource.trim()) {
|
|
24152
|
+
if (!source || !resolvedSource.trim()) {
|
|
24000
24153
|
console.error(`No source code available for ${playName}.`);
|
|
24001
|
-
return
|
|
24154
|
+
return 4;
|
|
24002
24155
|
}
|
|
24003
24156
|
if (materializedFile) {
|
|
24004
24157
|
console.log(loadedMessage);
|
|
24005
24158
|
return 0;
|
|
24006
24159
|
}
|
|
24160
|
+
if (Object.keys(source.files).length > 1) {
|
|
24161
|
+
console.error(
|
|
24162
|
+
`Play ${playName} has ${Object.keys(source.files).length} source files. Use --out <directory> to write the complete bundle.`
|
|
24163
|
+
);
|
|
24164
|
+
return 2;
|
|
24165
|
+
}
|
|
24007
24166
|
process.stdout.write(resolvedSource);
|
|
24008
24167
|
if (!resolvedSource.endsWith("\n")) {
|
|
24009
24168
|
process.stdout.write("\n");
|
|
@@ -24073,7 +24232,12 @@ async function handlePlayVersions(args) {
|
|
|
24073
24232
|
async function handlePlayList(args) {
|
|
24074
24233
|
const jsonOutput = argsWantJson(args);
|
|
24075
24234
|
const client2 = new DeeplineClient();
|
|
24076
|
-
const
|
|
24235
|
+
const categoriesIndex = args.indexOf("--categories");
|
|
24236
|
+
const categories = categoriesIndex >= 0 ? args[categoriesIndex + 1]?.trim() : void 0;
|
|
24237
|
+
const plays = await client2.listPlays({
|
|
24238
|
+
categories,
|
|
24239
|
+
includeToolCategories: true
|
|
24240
|
+
});
|
|
24077
24241
|
if (jsonOutput) {
|
|
24078
24242
|
process.stdout.write(`${JSON.stringify(plays)}
|
|
24079
24243
|
`);
|
|
@@ -24084,6 +24248,8 @@ async function handlePlayList(args) {
|
|
|
24084
24248
|
`);
|
|
24085
24249
|
for (const play of plays) {
|
|
24086
24250
|
const flags = [
|
|
24251
|
+
play.pinned ? "pinned" : null,
|
|
24252
|
+
...(play.toolCategories ?? []).map((category) => `category:${category}`),
|
|
24087
24253
|
play.origin === "prebuilt" || play.ownerType === "deepline" ? "prebuilt" : "owned",
|
|
24088
24254
|
play.canEdit ? "editable" : "readonly",
|
|
24089
24255
|
play.isDraftDirty ? "draft-dirty" : null
|
|
@@ -24113,6 +24279,36 @@ async function handlePlayList(args) {
|
|
|
24113
24279
|
}
|
|
24114
24280
|
return 0;
|
|
24115
24281
|
}
|
|
24282
|
+
async function handlePlayPin(args, pinned) {
|
|
24283
|
+
const target = args.find((arg) => !arg.startsWith("-"))?.trim();
|
|
24284
|
+
const jsonOutput = argsWantJson(args);
|
|
24285
|
+
const dryRun = args.includes("--dry-run");
|
|
24286
|
+
if (!target) {
|
|
24287
|
+
console.error(
|
|
24288
|
+
`Usage: deepline plays ${pinned ? "pin" : "unpin"} <play> [--dry-run] [--json]`
|
|
24289
|
+
);
|
|
24290
|
+
return 2;
|
|
24291
|
+
}
|
|
24292
|
+
const parsedTarget = parseReferencedPlayTarget2(target);
|
|
24293
|
+
if (parsedTarget.ownerSlug) {
|
|
24294
|
+
console.error(
|
|
24295
|
+
`deepline plays ${pinned ? "pin" : "unpin"} accepts an org-owned Play identifier without a namespace. Use "${parsedTarget.unqualifiedPlayName}" instead of "${target}".`
|
|
24296
|
+
);
|
|
24297
|
+
return 2;
|
|
24298
|
+
}
|
|
24299
|
+
const name = parsedTarget.playName;
|
|
24300
|
+
const plan = { name, pinned, dryRun };
|
|
24301
|
+
if (dryRun) {
|
|
24302
|
+
process.stdout.write(`${JSON.stringify(plan)}
|
|
24303
|
+
`);
|
|
24304
|
+
return 0;
|
|
24305
|
+
}
|
|
24306
|
+
const result = await new DeeplineClient().setPlayPinned(name, pinned);
|
|
24307
|
+
if (jsonOutput) process.stdout.write(`${JSON.stringify(result)}
|
|
24308
|
+
`);
|
|
24309
|
+
else console.log(`${result.pinned ? "Pinned" : "Unpinned"} ${result.name}.`);
|
|
24310
|
+
return 0;
|
|
24311
|
+
}
|
|
24116
24312
|
function parsePlaySearchOptions(args) {
|
|
24117
24313
|
const query = args[0]?.trim();
|
|
24118
24314
|
if (!query) {
|
|
@@ -24147,6 +24343,12 @@ function printPlayDescription(play) {
|
|
|
24147
24343
|
if (play.description) {
|
|
24148
24344
|
console.log(` Description: ${play.description}`);
|
|
24149
24345
|
}
|
|
24346
|
+
if (play.pinned) {
|
|
24347
|
+
console.log(" Pinned: yes");
|
|
24348
|
+
}
|
|
24349
|
+
if (play.toolCategories?.length) {
|
|
24350
|
+
console.log(` Tool categories: ${play.toolCategories.join(", ")}`);
|
|
24351
|
+
}
|
|
24150
24352
|
if (play.aliases.length > 0) {
|
|
24151
24353
|
console.log(` Aliases: ${play.aliases.join(", ")}`);
|
|
24152
24354
|
}
|
|
@@ -24252,6 +24454,8 @@ function summarizePlayListItemForCli(play, options) {
|
|
|
24252
24454
|
name: play.name,
|
|
24253
24455
|
...play.reference ? { reference: play.reference } : {},
|
|
24254
24456
|
...play.displayName ? { displayName: play.displayName } : {},
|
|
24457
|
+
pinned: Boolean(play.pinned),
|
|
24458
|
+
toolCategories: play.toolCategories ?? [],
|
|
24255
24459
|
origin: play.origin,
|
|
24256
24460
|
ownerType: play.ownerType,
|
|
24257
24461
|
canEdit: play.canEdit,
|
|
@@ -24382,6 +24586,7 @@ async function handlePlayGrep(args) {
|
|
|
24382
24586
|
origin: play.origin,
|
|
24383
24587
|
ownerType: play.ownerType,
|
|
24384
24588
|
aliases: play.aliases,
|
|
24589
|
+
toolCategories: play.toolCategories,
|
|
24385
24590
|
inputSchema: play.inputSchema,
|
|
24386
24591
|
outputSchema: play.outputSchema
|
|
24387
24592
|
},
|
|
@@ -24479,6 +24684,128 @@ async function handlePlayDescribe(args) {
|
|
|
24479
24684
|
printPlayDescription(play);
|
|
24480
24685
|
return 0;
|
|
24481
24686
|
}
|
|
24687
|
+
async function handlePlaySave(args) {
|
|
24688
|
+
let options;
|
|
24689
|
+
try {
|
|
24690
|
+
options = parsePlaySaveOptions(args);
|
|
24691
|
+
} catch (error) {
|
|
24692
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
24693
|
+
return 2;
|
|
24694
|
+
}
|
|
24695
|
+
if (!isFileTarget(options.target)) {
|
|
24696
|
+
console.error(
|
|
24697
|
+
"plays save requires a local .play.ts file. Use plays publish <play-name> to promote an existing saved revision."
|
|
24698
|
+
);
|
|
24699
|
+
return 2;
|
|
24700
|
+
}
|
|
24701
|
+
let graph;
|
|
24702
|
+
try {
|
|
24703
|
+
graph = await traceCliSpan(
|
|
24704
|
+
"cli.play_save_bundle_graph",
|
|
24705
|
+
{ targetKind: "file" },
|
|
24706
|
+
() => collectBundledPlayGraph((0, import_node_path14.resolve)(options.target))
|
|
24707
|
+
);
|
|
24708
|
+
assertBundledPlayGraphDescriptions(graph);
|
|
24709
|
+
} catch (error) {
|
|
24710
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
24711
|
+
return 7;
|
|
24712
|
+
}
|
|
24713
|
+
const playName = graph.root.playName ?? extractPlayName(graph.root.sourceCode, graph.root.filePath);
|
|
24714
|
+
const artifactHash = graph.root.artifact.artifactHash;
|
|
24715
|
+
if (options.expectedArtifactHash && options.expectedArtifactHash !== artifactHash) {
|
|
24716
|
+
const result = {
|
|
24717
|
+
ok: false,
|
|
24718
|
+
code: "PLAY_ARTIFACT_HASH_MISMATCH",
|
|
24719
|
+
message: "Refusing to save: the local file no longer produces the artifact checked earlier.",
|
|
24720
|
+
expectedArtifactHash: options.expectedArtifactHash,
|
|
24721
|
+
currentArtifactHash: artifactHash,
|
|
24722
|
+
next: `deepline plays check ${shellQuote2(options.target)}`
|
|
24723
|
+
};
|
|
24724
|
+
if (options.jsonOutput) {
|
|
24725
|
+
process.stdout.write(`${JSON.stringify(result)}
|
|
24726
|
+
`);
|
|
24727
|
+
} else {
|
|
24728
|
+
console.error(result.message);
|
|
24729
|
+
console.error(` checked artifact: ${result.expectedArtifactHash}`);
|
|
24730
|
+
console.error(` current artifact: ${result.currentArtifactHash}`);
|
|
24731
|
+
console.error(` run: ${result.next}`);
|
|
24732
|
+
}
|
|
24733
|
+
return 7;
|
|
24734
|
+
}
|
|
24735
|
+
const dryRun = {
|
|
24736
|
+
ok: true,
|
|
24737
|
+
dryRun: true,
|
|
24738
|
+
name: playName,
|
|
24739
|
+
sourcePath: graph.root.filePath,
|
|
24740
|
+
sourceHash: graph.root.artifact.sourceHash,
|
|
24741
|
+
artifactHash,
|
|
24742
|
+
graphHash: graph.root.artifact.graphHash,
|
|
24743
|
+
sourceFileCount: Object.keys(graph.root.sourceFiles).length,
|
|
24744
|
+
plannedMutation: "save or update the mutable working draft; does not change the live revision"
|
|
24745
|
+
};
|
|
24746
|
+
if (options.dryRun) {
|
|
24747
|
+
if (options.jsonOutput) {
|
|
24748
|
+
process.stdout.write(`${JSON.stringify(dryRun)}
|
|
24749
|
+
`);
|
|
24750
|
+
} else {
|
|
24751
|
+
console.log(`Dry run: ${playName}`);
|
|
24752
|
+
console.log(` source: ${dryRun.sourceHash}`);
|
|
24753
|
+
console.log(` artifact: ${dryRun.artifactHash}`);
|
|
24754
|
+
console.log(` would: ${dryRun.plannedMutation}`);
|
|
24755
|
+
}
|
|
24756
|
+
return 0;
|
|
24757
|
+
}
|
|
24758
|
+
const client2 = new DeeplineClient();
|
|
24759
|
+
try {
|
|
24760
|
+
await traceCliSpan(
|
|
24761
|
+
"cli.play_save_compile_manifests",
|
|
24762
|
+
{ targetKind: "file", nodeCount: graph.nodes.size },
|
|
24763
|
+
() => compileBundledPlayGraphManifests(client2, graph)
|
|
24764
|
+
);
|
|
24765
|
+
const saved = await traceCliSpan(
|
|
24766
|
+
"cli.play_save_register_draft",
|
|
24767
|
+
{ targetKind: "file", playName, artifactHash },
|
|
24768
|
+
() => client2.registerPlayArtifact({
|
|
24769
|
+
name: playName,
|
|
24770
|
+
sourceCode: graph.root.sourceCode,
|
|
24771
|
+
sourceFiles: graph.root.sourceFiles,
|
|
24772
|
+
description: graph.root.playDescription ?? void 0,
|
|
24773
|
+
artifact: graph.root.artifact,
|
|
24774
|
+
compilerManifest: requireCompilerManifest(graph.root),
|
|
24775
|
+
publish: false
|
|
24776
|
+
})
|
|
24777
|
+
);
|
|
24778
|
+
const result = {
|
|
24779
|
+
success: true,
|
|
24780
|
+
name: playName,
|
|
24781
|
+
draft: true,
|
|
24782
|
+
revisionId: saved.revisionId ?? null,
|
|
24783
|
+
version: saved.version ?? null,
|
|
24784
|
+
sourceHash: graph.root.artifact.sourceHash,
|
|
24785
|
+
artifactHash,
|
|
24786
|
+
graphHash: graph.root.artifact.graphHash,
|
|
24787
|
+
artifactStorageKey: saved.artifactStorageKey,
|
|
24788
|
+
next: {
|
|
24789
|
+
publish: `deepline plays publish ${shellQuote2(options.target)} --expected-artifact ${artifactHash}`,
|
|
24790
|
+
get: `deepline plays get ${playName} --source --out ./${playName}/ --working`
|
|
24791
|
+
}
|
|
24792
|
+
};
|
|
24793
|
+
if (options.jsonOutput) {
|
|
24794
|
+
process.stdout.write(`${JSON.stringify(result)}
|
|
24795
|
+
`);
|
|
24796
|
+
} else {
|
|
24797
|
+
console.log(
|
|
24798
|
+
`\u2713 Saved ${playName} working draft as v${result.version ?? "?"}`
|
|
24799
|
+
);
|
|
24800
|
+
console.log(" Live revision unchanged.");
|
|
24801
|
+
console.log(` publish: ${result.next.publish}`);
|
|
24802
|
+
}
|
|
24803
|
+
return 0;
|
|
24804
|
+
} catch (error) {
|
|
24805
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
24806
|
+
return 5;
|
|
24807
|
+
}
|
|
24808
|
+
}
|
|
24482
24809
|
async function handlePlayPublish(args) {
|
|
24483
24810
|
let options;
|
|
24484
24811
|
try {
|
|
@@ -25009,7 +25336,9 @@ Pass-through input flags:
|
|
|
25009
25336
|
]);
|
|
25010
25337
|
});
|
|
25011
25338
|
registerPlayBootstrapCommand(play);
|
|
25012
|
-
play.command("get <target>").description(
|
|
25339
|
+
play.command("get <target>").description(
|
|
25340
|
+
"Fetch full play details or materialize a saved source bundle."
|
|
25341
|
+
).addHelpText(
|
|
25013
25342
|
"after",
|
|
25014
25343
|
`
|
|
25015
25344
|
Notes:
|
|
@@ -25021,17 +25350,24 @@ Examples:
|
|
|
25021
25350
|
deepline plays get prebuilt/person-linkedin-to-email
|
|
25022
25351
|
deepline plays get prebuilt/person-linkedin-to-email --json | jq '.play.liveRevision'
|
|
25023
25352
|
deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source > email-waterfall.play.ts
|
|
25024
|
-
deepline plays get
|
|
25353
|
+
deepline plays get my-play --source --out ./my-play/ --working
|
|
25354
|
+
deepline plays get my-play --source --out ./my-play-v3/ --revision 3
|
|
25025
25355
|
`
|
|
25026
25356
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
|
|
25027
25357
|
"--source",
|
|
25028
|
-
"
|
|
25029
|
-
).option(
|
|
25358
|
+
"Read source; prints single-file Plays or combines with --out to write the full bundle"
|
|
25359
|
+
).option(
|
|
25360
|
+
"--out <path>",
|
|
25361
|
+
"Write source to a file or, for multi-file Plays, a directory"
|
|
25362
|
+
).option("--working", "Read the current working draft source (default)").option("--live", "Read the live revision source").option("--revision <number>", "Read a specific revision source").action(async (target, options) => {
|
|
25030
25363
|
process.exitCode = await handlePlayGet([
|
|
25031
25364
|
target,
|
|
25032
25365
|
...options.json ? ["--json"] : [],
|
|
25033
25366
|
...options.source ? ["--source"] : [],
|
|
25034
|
-
...options.out ? ["--out", options.out] : []
|
|
25367
|
+
...options.out ? ["--out", options.out] : [],
|
|
25368
|
+
...options.working ? ["--working"] : [],
|
|
25369
|
+
...options.live ? ["--live"] : [],
|
|
25370
|
+
...options.revision ? ["--revision", options.revision] : []
|
|
25035
25371
|
]);
|
|
25036
25372
|
});
|
|
25037
25373
|
play.command("list").description("List saved and prebuilt plays.").addHelpText(
|
|
@@ -25045,11 +25381,35 @@ Examples:
|
|
|
25045
25381
|
deepline plays list
|
|
25046
25382
|
deepline plays search email --json
|
|
25047
25383
|
`
|
|
25048
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").
|
|
25384
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
|
|
25385
|
+
"--categories <categories>",
|
|
25386
|
+
"Filter by comma-separated canonical tool categories"
|
|
25387
|
+
).action(async (options) => {
|
|
25049
25388
|
process.exitCode = await handlePlayList([
|
|
25389
|
+
...options.categories ? ["--categories", options.categories] : [],
|
|
25050
25390
|
...options.json ? ["--json"] : []
|
|
25051
25391
|
]);
|
|
25052
25392
|
});
|
|
25393
|
+
play.command("pin <target>").description("Pin an org-owned play to the top of play listings.").option("--dry-run", "Print the planned change without saving it").option("--json", "Emit JSON output").action(async (target, options) => {
|
|
25394
|
+
process.exitCode = await handlePlayPin(
|
|
25395
|
+
[
|
|
25396
|
+
target,
|
|
25397
|
+
...options.dryRun ? ["--dry-run"] : [],
|
|
25398
|
+
...options.json ? ["--json"] : []
|
|
25399
|
+
],
|
|
25400
|
+
true
|
|
25401
|
+
);
|
|
25402
|
+
});
|
|
25403
|
+
play.command("unpin <target>").description("Remove an org-owned play from the pinned group.").option("--dry-run", "Print the planned change without saving it").option("--json", "Emit JSON output").action(async (target, options) => {
|
|
25404
|
+
process.exitCode = await handlePlayPin(
|
|
25405
|
+
[
|
|
25406
|
+
target,
|
|
25407
|
+
...options.dryRun ? ["--dry-run"] : [],
|
|
25408
|
+
...options.json ? ["--json"] : []
|
|
25409
|
+
],
|
|
25410
|
+
false
|
|
25411
|
+
);
|
|
25412
|
+
});
|
|
25053
25413
|
const addPlaySearchCommand = (command) => command.description("Search Deepline prebuilt plays by task.").option(
|
|
25054
25414
|
"--prebuilt",
|
|
25055
25415
|
"Only show Deepline-managed prebuilt plays (default)"
|
|
@@ -25142,6 +25502,32 @@ Examples:
|
|
|
25142
25502
|
...options.json ? ["--json"] : []
|
|
25143
25503
|
]);
|
|
25144
25504
|
});
|
|
25505
|
+
play.command("save <file>").description(
|
|
25506
|
+
"Save or update a local Play working draft without publishing it."
|
|
25507
|
+
).addHelpText(
|
|
25508
|
+
"after",
|
|
25509
|
+
`
|
|
25510
|
+
Notes:
|
|
25511
|
+
Mutates cloud state, but does not change the live revision or active triggers.
|
|
25512
|
+
Repeated saves update one working draft. Publishing it, or running a named
|
|
25513
|
+
draft revision, freezes it; the next save starts a new revision.
|
|
25514
|
+
|
|
25515
|
+
Examples:
|
|
25516
|
+
deepline plays save ./company-research.play.ts
|
|
25517
|
+
deepline plays save ./company-research.play.ts --dry-run --json
|
|
25518
|
+
deepline plays publish ./company-research.play.ts
|
|
25519
|
+
`
|
|
25520
|
+
).option("--expected-artifact <hash>", "Require the checked artifact hash").option(
|
|
25521
|
+
"--dry-run",
|
|
25522
|
+
"Bundle and show the planned draft save without mutation"
|
|
25523
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (file, options) => {
|
|
25524
|
+
process.exitCode = await handlePlaySave([
|
|
25525
|
+
file,
|
|
25526
|
+
...options.expectedArtifact ? ["--expected-artifact", options.expectedArtifact] : [],
|
|
25527
|
+
...options.dryRun ? ["--dry-run"] : [],
|
|
25528
|
+
...options.json ? ["--json"] : []
|
|
25529
|
+
]);
|
|
25530
|
+
});
|
|
25145
25531
|
const addPublishHelp = (command) => command.addHelpText(
|
|
25146
25532
|
"after",
|
|
25147
25533
|
`
|
|
@@ -26404,10 +26790,12 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
|
|
|
26404
26790
|
const metadataColumnSource = renderMetadataColumnStep(config);
|
|
26405
26791
|
const generatedAliases = collectGeneratedAliases(config.commands);
|
|
26406
26792
|
const runOptionsSource = options.failFast ? `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart), onRowError: 'fail' as const }` : `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart) }`;
|
|
26793
|
+
const describedColumns = config.commands.filter((command) => isWaterfall(command) || !command.disabled).map(
|
|
26794
|
+
(command) => (isWaterfall(command) ? command.with_waterfall : command.alias).replace(/[_-]+/g, " ").trim()
|
|
26795
|
+
).filter(Boolean).slice(0, 3);
|
|
26796
|
+
const generatedDescription = describedColumns.length ? `Enrich CSV rows with ${describedColumns.join(", ")}.` : "Prepare CSV rows for enrichment.";
|
|
26407
26797
|
const playOptionsSource = [
|
|
26408
|
-
`description: ${stringLiteral(
|
|
26409
|
-
"Read a CSV file, run the configured Deepline enrich commands, and return enriched rows."
|
|
26410
|
-
)}`,
|
|
26798
|
+
`description: ${stringLiteral(generatedDescription)}`,
|
|
26411
26799
|
...options.maxCreditsPerRun === void 0 ? [] : [`billing: { maxCreditsPerRun: ${String(options.maxCreditsPerRun)} }`]
|
|
26412
26800
|
].join(", ");
|
|
26413
26801
|
const body = [
|