deepline 0.3.212 → 0.3.214

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.
Files changed (30) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +137 -32
  2. package/dist/bundling-sources/sdk/src/compat.ts +2 -0
  3. package/dist/bundling-sources/sdk/src/deployment-protection.ts +19 -0
  4. package/dist/bundling-sources/sdk/src/http.ts +3 -7
  5. package/dist/bundling-sources/sdk/src/index.ts +7 -0
  6. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  7. package/dist/bundling-sources/sdk/src/types.ts +25 -0
  8. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +18 -0
  9. package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +1 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +33 -7
  11. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +11 -1
  12. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +3 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +53 -1
  14. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +187 -6
  15. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +67 -37
  16. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +12 -3
  17. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +5 -2
  18. package/dist/bundling-sources/shared_libs/plays/settings-contract.ts +176 -0
  19. package/dist/cli/index.js +572 -92
  20. package/dist/cli/index.mjs +572 -92
  21. package/dist/index.d.mts +191 -3
  22. package/dist/index.d.ts +191 -3
  23. package/dist/index.js +67 -35
  24. package/dist/index.mjs +67 -35
  25. package/dist/install-integrity.json +2 -0
  26. package/dist/release.d.mts +1 -1
  27. package/dist/release.d.ts +1 -1
  28. package/dist/release.js +1 -1
  29. package/dist/release.mjs +1 -1
  30. package/package.json +3 -2
package/dist/cli/index.js CHANGED
@@ -3051,7 +3051,7 @@ var SDK_RELEASE = {
3051
3051
  // getters keep their established compatibility behavior.
3052
3052
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3053
3053
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3054
- version: "0.3.212",
3054
+ version: "0.3.214",
3055
3055
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3056
3056
  packageCapabilities: {
3057
3057
  updatePreferences: 1
@@ -3372,6 +3372,22 @@ function writeSdkSkillsLocalVersion(baseUrl, version, agents) {
3372
3372
  return complete;
3373
3373
  }
3374
3374
 
3375
+ // src/deployment-protection.ts
3376
+ function deploymentProtectionHeaders() {
3377
+ const token = typeof process !== "undefined" ? process.env?.VERCEL_PROTECTION_BYPASS_TOKEN : void 0;
3378
+ return token ? { "x-vercel-protection-bypass": token } : {};
3379
+ }
3380
+ var fetchWithDeploymentProtection = (input2, init) => {
3381
+ const headers = new Headers(
3382
+ input2 instanceof Request ? input2.headers : void 0
3383
+ );
3384
+ new Headers(init?.headers).forEach((value, name) => headers.set(name, value));
3385
+ for (const [name, value] of Object.entries(deploymentProtectionHeaders())) {
3386
+ headers.set(name, value);
3387
+ }
3388
+ return fetch(input2, { ...init, headers });
3389
+ };
3390
+
3375
3391
  // ../play-runtime/coordinator-headers.ts
3376
3392
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
3377
3393
  var COORDINATOR_URL_OVERRIDE_HEADER = "x-deepline-coordinator-url";
@@ -3754,16 +3770,13 @@ var HttpClient = class {
3754
3770
  "X-Deepline-SDK-Version": SDK_VERSION,
3755
3771
  "X-Deepline-API-Contract": SDK_API_CONTRACT,
3756
3772
  "X-Deepline-Run-Result-Shape": "canonical",
3757
- ...extra
3773
+ ...extra,
3774
+ ...deploymentProtectionHeaders()
3758
3775
  };
3759
3776
  const skillsVersion = this.readSkillsVersionHeader();
3760
3777
  if (skillsVersion) {
3761
3778
  headers["X-Deepline-Skills-Version"] = skillsVersion;
3762
3779
  }
3763
- const bypassToken = typeof process !== "undefined" ? process.env?.VERCEL_PROTECTION_BYPASS_TOKEN : void 0;
3764
- if (bypassToken) {
3765
- headers["x-vercel-protection-bypass"] = bypassToken;
3766
- }
3767
3780
  const playArtifactR2Prefix = typeof process !== "undefined" ? process.env?.DEEPLINE_PLAY_ARTIFACT_R2_PREFIX : void 0;
3768
3781
  if (playArtifactR2Prefix) {
3769
3782
  headers["x-deepline-play-artifact-r2-prefix"] = playArtifactR2Prefix;
@@ -4892,13 +4905,13 @@ function previewValue(value, input2) {
4892
4905
  ([, descriptor]) => descriptor.enumerable
4893
4906
  );
4894
4907
  const selected = entries.slice(0, DOCFLOW_NODE_IO_LIMITS.maxObjectFields);
4895
- const fields = {};
4908
+ const fields2 = {};
4896
4909
  for (const [key, descriptor] of selected) {
4897
4910
  const safeKey = truncateUtf8(
4898
4911
  ledgerSafeDocflowPreviewKey(input2.redactor.redactString(key)),
4899
4912
  DOCFLOW_NODE_IO_LIMITS.maxStringBytes
4900
4913
  );
4901
- fields[safeKey] = "value" in descriptor ? previewValue(descriptor.value, {
4914
+ fields2[safeKey] = "value" in descriptor ? previewValue(descriptor.value, {
4902
4915
  ...input2,
4903
4916
  depth: input2.depth + 1,
4904
4917
  key
@@ -4906,7 +4919,7 @@ function previewValue(value, input2) {
4906
4919
  }
4907
4920
  return {
4908
4921
  kind: "object",
4909
- fields,
4922
+ fields: fields2,
4910
4923
  totalFields: entries.length,
4911
4924
  ...entries.length > selected.length ? { truncated: true } : {}
4912
4925
  };
@@ -5015,20 +5028,20 @@ function normalizePreview(value, depth) {
5015
5028
  };
5016
5029
  }
5017
5030
  if (value.kind === "object" && isRecord3(value.fields)) {
5018
- const fields = {};
5031
+ const fields2 = {};
5019
5032
  for (const [key, field] of Object.entries(value.fields).slice(
5020
5033
  0,
5021
5034
  DOCFLOW_NODE_IO_LIMITS.maxObjectFields
5022
5035
  )) {
5023
5036
  const normalized = normalizePreview(field, depth + 1);
5024
- if (normalized) fields[ledgerSafeDocflowPreviewKey(key)] = normalized;
5037
+ if (normalized) fields2[ledgerSafeDocflowPreviewKey(key)] = normalized;
5025
5038
  }
5026
- const totalFields = typeof value.totalFields === "number" && Number.isFinite(value.totalFields) ? Math.max(Object.keys(fields).length, Math.floor(value.totalFields)) : Object.keys(fields).length;
5039
+ const totalFields = typeof value.totalFields === "number" && Number.isFinite(value.totalFields) ? Math.max(Object.keys(fields2).length, Math.floor(value.totalFields)) : Object.keys(fields2).length;
5027
5040
  return {
5028
5041
  kind: "object",
5029
- fields,
5042
+ fields: fields2,
5030
5043
  totalFields,
5031
- ...value.truncated === true || totalFields > Object.keys(fields).length ? { truncated: true } : {}
5044
+ ...value.truncated === true || totalFields > Object.keys(fields2).length ? { truncated: true } : {}
5032
5045
  };
5033
5046
  }
5034
5047
  return null;
@@ -7040,10 +7053,19 @@ function normalizePlayStatus(raw) {
7040
7053
  );
7041
7054
  }
7042
7055
  const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : packageRun?.id ?? "";
7056
+ const legacyOverview = runPackage?.overview ?? raw.overview;
7057
+ const runStatus = runPackage?.runStatus ?? raw.runStatus;
7043
7058
  return {
7044
7059
  ...raw,
7045
7060
  runId,
7046
- ...runPackage ? { package: runPackage, outputs: runPackage.outputs } : {},
7061
+ ...isRecord7(legacyOverview) ? {
7062
+ overview: legacyOverview
7063
+ } : {},
7064
+ ...isRecord7(runStatus) ? { runStatus } : {},
7065
+ ...runPackage ? {
7066
+ package: runPackage,
7067
+ outputs: runPackage.outputs
7068
+ } : {},
7047
7069
  status
7048
7070
  };
7049
7071
  }
@@ -7225,18 +7247,6 @@ function playRunResultFromStatus(status, startedAt, fallbackRunId) {
7225
7247
  error: status.progress?.error ?? (status.status !== "completed" ? status.status : void 0)
7226
7248
  };
7227
7249
  }
7228
- function playRunStatusFromState(state) {
7229
- return {
7230
- runId: state.runId,
7231
- status: state.status,
7232
- progress: {
7233
- status: state.status,
7234
- logs: state.logs,
7235
- ...state.error ? { error: state.error } : {}
7236
- },
7237
- ..."result" in state ? { result: state.result } : {}
7238
- };
7239
- }
7240
7250
  var DeeplineClient = class _DeeplineClient {
7241
7251
  http;
7242
7252
  config;
@@ -7379,14 +7389,14 @@ var DeeplineClient = class _DeeplineClient {
7379
7389
  }
7380
7390
  compactSchema(schema) {
7381
7391
  if (!schema) return null;
7382
- const fields = Array.isArray(schema.fields) ? schema.fields.map(
7392
+ const fields2 = Array.isArray(schema.fields) ? schema.fields.map(
7383
7393
  (field) => field && typeof field === "object" ? {
7384
7394
  name: String(field.name ?? ""),
7385
7395
  type: field.type ?? void 0,
7386
7396
  required: field.required ?? void 0
7387
7397
  } : null
7388
7398
  ).filter((field) => Boolean(field?.name)) : [];
7389
- return fields.length > 0 ? { fields } : schema;
7399
+ return fields2.length > 0 ? { fields: fields2 } : schema;
7390
7400
  }
7391
7401
  schemaMetadata(schema, key) {
7392
7402
  if (!isRecord7(schema)) return null;
@@ -7573,6 +7583,12 @@ var DeeplineClient = class _DeeplineClient {
7573
7583
  options.includeSearchDebug ? "true" : "false"
7574
7584
  );
7575
7585
  params.set("search_mode", options.searchMode ?? "v2");
7586
+ if (options.limit !== void 0) {
7587
+ params.set("limit", String(options.limit));
7588
+ }
7589
+ if (options.offset !== void 0) {
7590
+ params.set("offset", String(options.offset));
7591
+ }
7576
7592
  if (options.categories?.trim()) {
7577
7593
  params.set("categories", options.categories.trim());
7578
7594
  }
@@ -8634,9 +8650,18 @@ var DeeplineClient = class _DeeplineClient {
8634
8650
  }
8635
8651
  const query = params.size > 0 ? `?${params.toString()}` : "";
8636
8652
  const response = await this.http.get(
8637
- `/api/v2/runs/${encodeURIComponent(runId)}${query}`
8653
+ `/api/v2/runs/${encodeURIComponent(runId)}${query}`,
8654
+ { headers: { "x-deepline-run-status": "1" } }
8638
8655
  );
8656
+ const responseRunStatus = isPlayRunPackage(response) ? response.runStatus : isPlayRunPackage(response.package) ? response.package.runStatus : response.runStatus;
8657
+ const responseOverview = isPlayRunPackage(response) ? response.overview : isPlayRunPackage(response.package) ? response.package.overview : response.overview;
8639
8658
  const status = normalizePlayStatus(response);
8659
+ if (isRecord7(responseRunStatus)) {
8660
+ status.runStatus = responseRunStatus;
8661
+ }
8662
+ if (isRecord7(responseOverview)) {
8663
+ status.overview = responseOverview;
8664
+ }
8640
8665
  if (options?.failedLogs !== true || status.status !== "failed") {
8641
8666
  return status;
8642
8667
  }
@@ -8677,7 +8702,10 @@ var DeeplineClient = class _DeeplineClient {
8677
8702
  }
8678
8703
  };
8679
8704
  }
8680
- /** Read only the bounded scalar projection; does not hydrate the run package. */
8705
+ /** Fetch only the legacy scalar lifecycle status for a run.
8706
+ *
8707
+ * @deprecated Use `client.runs.get(runId)` for the canonical run read.
8708
+ */
8681
8709
  async getRunLifecycleStatus(runId) {
8682
8710
  const response = await this.http.get(
8683
8711
  `/api/v2/runs/${encodeURIComponent(runId)}/status`
@@ -8853,9 +8881,7 @@ var DeeplineClient = class _DeeplineClient {
8853
8881
  if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
8854
8882
  continue;
8855
8883
  }
8856
- return await this.getRunStatus(status.runId || runId).catch(
8857
- () => state.latest ?? playRunStatusFromState(state)
8858
- );
8884
+ return await this.getRunStatus(status.runId || runId);
8859
8885
  }
8860
8886
  if (options?.signal?.aborted) {
8861
8887
  throw new DeeplineError("Run observation aborted.", void 0, "ABORTED");
@@ -8906,6 +8932,7 @@ var DeeplineClient = class _DeeplineClient {
8906
8932
  for (; ; ) {
8907
8933
  const connectedAt = Date.now();
8908
8934
  let sawEvent = false;
8935
+ let terminalRunId = null;
8909
8936
  let endedReason = "stream window ended before a terminal event";
8910
8937
  try {
8911
8938
  for await (const event of this.streamPlayRunEvents(runId, {
@@ -8918,9 +8945,8 @@ var DeeplineClient = class _DeeplineClient {
8918
8945
  if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
8919
8946
  continue;
8920
8947
  }
8921
- return await this.getRunStatus(status.runId || runId).catch(
8922
- () => state.latest ?? playRunStatusFromState(state)
8923
- );
8948
+ terminalRunId = status.runId || runId;
8949
+ break;
8924
8950
  }
8925
8951
  } catch (error) {
8926
8952
  if (options?.signal?.aborted || !isTransientPlayStreamError(error)) {
@@ -8928,15 +8954,11 @@ var DeeplineClient = class _DeeplineClient {
8928
8954
  }
8929
8955
  endedReason = error instanceof Error ? error.message : String(error);
8930
8956
  }
8931
- let refreshed = null;
8932
- try {
8933
- refreshed = await this.getRunStatus(runId);
8934
- } catch (error) {
8935
- if (!isTransientPlayStreamError(error)) {
8936
- throw error;
8937
- }
8957
+ if (terminalRunId) {
8958
+ return await this.getRunStatus(terminalRunId);
8938
8959
  }
8939
- if (refreshed && TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
8960
+ const refreshed = await this.getRunStatus(runId);
8961
+ if (TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
8940
8962
  return refreshed;
8941
8963
  }
8942
8964
  if (sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
@@ -9225,6 +9247,26 @@ var DeeplineClient = class _DeeplineClient {
9225
9247
  hasMore: Boolean(response.pagination?.hasMore ?? response.hasMore)
9226
9248
  };
9227
9249
  }
9250
+ /** Read definition-level settings, independently of code revisions. */
9251
+ async getPlaySettings(playName) {
9252
+ return this.http.get(
9253
+ `/api/v2/plays/${encodeURIComponent(playName)}/settings`
9254
+ );
9255
+ }
9256
+ /** Retry-safe field patch; omitted fields retain their current value. */
9257
+ async updatePlaySettings(playName, patch) {
9258
+ return this.http.patch(
9259
+ `/api/v2/plays/${encodeURIComponent(playName)}/settings`,
9260
+ patch
9261
+ );
9262
+ }
9263
+ /** List one bounded page of existing Play locations; continue with cursor. */
9264
+ async listPlaySettingsPaths(options = {}) {
9265
+ const query = new URLSearchParams();
9266
+ for (const [key, value] of Object.entries(options))
9267
+ if (value !== void 0) query.set(key, String(value));
9268
+ return this.http.get(`/api/v2/plays/settings/paths?${query}`);
9269
+ }
9228
9270
  /** Set whether an org-owned Play sorts before unpinned Plays. */
9229
9271
  async setPlayPinned(playName, pinned) {
9230
9272
  return this.http.post(`/api/v2/plays/${encodeURIComponent(playName)}/pin`, {
@@ -10842,6 +10884,7 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
10842
10884
  const response = await fetch(url, {
10843
10885
  method: "GET",
10844
10886
  headers: {
10887
+ ...deploymentProtectionHeaders(),
10845
10888
  "User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
10846
10889
  "X-Deepline-SDK-Version": SDK_VERSION,
10847
10890
  "X-Deepline-API-Major": String(SDK_API_MAJOR),
@@ -11706,8 +11749,8 @@ function resolvePendingAuthClaimForResume(baseUrl, requestedScope) {
11706
11749
  const claim = readPendingAuthClaim(baseUrl, requestedScope);
11707
11750
  return { claim, scope: claim?.scope ?? requestedScope };
11708
11751
  }
11709
- const folder = readPendingAuthClaim(baseUrl, "folder");
11710
- if (folder) return { claim: folder, scope: folder.scope };
11752
+ const folder2 = readPendingAuthClaim(baseUrl, "folder");
11753
+ if (folder2) return { claim: folder2, scope: folder2.scope };
11711
11754
  const global = readPendingAuthClaim(baseUrl, "global");
11712
11755
  return { claim: global, scope: global?.scope ?? "global" };
11713
11756
  }
@@ -15891,6 +15934,332 @@ var import_node_os10 = require("os");
15891
15934
  var import_node_path18 = require("path");
15892
15935
  var import_commander2 = require("commander");
15893
15936
 
15937
+ // ../plays/settings-contract.ts
15938
+ var import_zod = require("zod");
15939
+ function formatPlaySettingsError(error) {
15940
+ if (error instanceof import_zod.z.ZodError)
15941
+ return [...new Set(error.issues.map((issue) => issue.message))].join(" ");
15942
+ return error instanceof Error ? error.message : String(error);
15943
+ }
15944
+ var PLAY_LOCATION_ROOTS = [
15945
+ {
15946
+ value: "person",
15947
+ label: "Personal",
15948
+ description: "The creator\u2019s personal root, displayed as their name followed by \u201C\u2019s team\u201D."
15949
+ },
15950
+ {
15951
+ value: "team",
15952
+ label: "Team library",
15953
+ description: "The shared team library. Publishing moves personal locations here, keeping their folders."
15954
+ }
15955
+ ];
15956
+ var folder = import_zod.z.string().min(1).max(128).refine(
15957
+ (value) => value === value.trim() && value !== "." && value !== ".." && !/[\\/\u0000-\u001f\u007f]/u.test(value),
15958
+ "Folder names must be trimmed, cannot be . or .., and cannot contain slashes or control characters."
15959
+ );
15960
+ var playPathSchema = import_zod.z.union([
15961
+ import_zod.z.null(),
15962
+ import_zod.z.object({
15963
+ root: import_zod.z.enum(["person", "team"]),
15964
+ folders: import_zod.z.array(folder).max(16).default([])
15965
+ }).strict()
15966
+ ]).transform(
15967
+ (path) => path?.root === "person" && path.folders.length === 0 ? null : path
15968
+ );
15969
+ function parsePlayPath(value) {
15970
+ const [root, ...parts] = value.split("/");
15971
+ if (!PLAY_LOCATION_ROOTS.some((option) => option.value === root)) {
15972
+ throw new Error(
15973
+ "Path must start with person or team. Example: person/Research/ICP."
15974
+ );
15975
+ }
15976
+ let folders;
15977
+ try {
15978
+ folders = parts.map(decodeURIComponent);
15979
+ } catch {
15980
+ throw new Error(
15981
+ "Path contains an invalid percent escape. Encode a literal % as %25."
15982
+ );
15983
+ }
15984
+ return playPathSchema.parse({ root, folders });
15985
+ }
15986
+ function formatPlayPath(path) {
15987
+ return path === null ? "person" : [path.root, ...path.folders.map(encodeURIComponent)].join("/");
15988
+ }
15989
+ function personalPlayRootLabel(ownerName) {
15990
+ const name = ownerName?.trim();
15991
+ return name ? `${name.split(/\s+/)[0]}\u2019s team` : "Personal";
15992
+ }
15993
+ function displayPlayPath(path, ownerName) {
15994
+ return [
15995
+ path?.root === "team" ? "Team library" : personalPlayRootLabel(ownerName),
15996
+ ...path?.folders ?? []
15997
+ ].join(" / ");
15998
+ }
15999
+ var PLAY_SETTING_FIELDS = {
16000
+ path: {
16001
+ schema: playPathSchema.default(null).describe(
16002
+ "Play location. Null means the creator\u2019s personal root. Publishing moves it into Team library, preserving folders."
16003
+ ),
16004
+ label: "Location",
16005
+ description: "Organize this Play in the creator\u2019s personal root or Team library. Publishing moves it to Team library and keeps its folders. Workspace sharing permissions apply in both roots.",
16006
+ get defaultValue() {
16007
+ return this.schema.parse(void 0);
16008
+ },
16009
+ cli: {
16010
+ valueSyntax: "person[/folder/\u2026] | team[/folder/\u2026] | null",
16011
+ examples: [
16012
+ "person",
16013
+ "person/Research/ICP",
16014
+ "team",
16015
+ "team/Research",
16016
+ "null"
16017
+ ],
16018
+ parse: (value) => value === "null" ? null : parsePlayPath(value),
16019
+ format: formatPlayPath
16020
+ },
16021
+ ui: { control: "play-location-picker" }
16022
+ }
16023
+ };
16024
+ var playSettingsSchema = import_zod.z.object(
16025
+ Object.fromEntries(
16026
+ Object.entries(PLAY_SETTING_FIELDS).map(([key, field]) => [
16027
+ key,
16028
+ field.schema
16029
+ ])
16030
+ )
16031
+ ).passthrough();
16032
+ var playSettingsPatchSchema = import_zod.z.object(
16033
+ Object.fromEntries(
16034
+ Object.entries(PLAY_SETTING_FIELDS).map(([key, field]) => [
16035
+ key,
16036
+ field.schema.unwrap().optional()
16037
+ ])
16038
+ )
16039
+ ).strict().refine(
16040
+ (patch) => Object.keys(patch).length > 0,
16041
+ "Supply at least one setting."
16042
+ );
16043
+ function parsePlaySettings(value) {
16044
+ return playSettingsSchema.parse(value);
16045
+ }
16046
+ var DEFAULT_PLAY_SETTINGS = parsePlaySettings({});
16047
+
16048
+ // src/cli/commands/plays-settings.ts
16049
+ var fields = Object.entries(PLAY_SETTING_FIELDS);
16050
+ var help = `
16051
+ Settings live on the Play definition. Edits preserve code revisions.
16052
+ New Plays start at person (the creator\u2019s personal root, e.g. Chirag\u2019s team).
16053
+ Publishing moves a Play into team and keeps its folders. Workspace sharing
16054
+ permissions apply in both roots. Folder paths are independent of your cwd.
16055
+
16056
+ Setting names and values:
16057
+ ${fields.map(([key, field]) => ` ${key}: ${field.schema.description}
16058
+ Values: ${field.cli.valueSyntax}
16059
+ Default: ${JSON.stringify(field.defaultValue)} (${field.cli.format(field.defaultValue)})`).join("\n")}
16060
+
16061
+ Roots:
16062
+ ${PLAY_LOCATION_ROOTS.map((root) => ` ${root.value}: ${root.description}`).join("\n")}
16063
+
16064
+ Examples:
16065
+ deepline plays settings describe --name path --json
16066
+ deepline plays settings get --play company-research --json
16067
+ deepline plays settings get --play company-research --name path
16068
+ deepline plays settings set --play company-research --name path --value person/Research/ICP
16069
+ deepline plays settings set --play company-research --name path --value team/Research
16070
+ deepline plays settings reset --play company-research --name path
16071
+ deepline plays settings paths --root team --json
16072
+
16073
+ Quote values containing spaces. Use percent escapes for literal % characters.
16074
+ `;
16075
+ function resolveField(key, command) {
16076
+ const entry = fields.find(([name]) => name === key);
16077
+ if (!entry)
16078
+ command.error(
16079
+ `Unknown --name ${JSON.stringify(key)}. Available settings: ${fields.map(([name]) => name).join(", ")}. Run deepline plays settings describe.`,
16080
+ { exitCode: 2 }
16081
+ );
16082
+ return entry[1];
16083
+ }
16084
+ function printSettings(result, json2, name) {
16085
+ const selected = fields.filter(([key]) => !name || key === name);
16086
+ printCommandEnvelope(
16087
+ {
16088
+ ...result,
16089
+ settings: Object.fromEntries(
16090
+ selected.map(([key]) => [
16091
+ key,
16092
+ result.settings[key]
16093
+ ])
16094
+ ),
16095
+ render: {
16096
+ sections: [
16097
+ {
16098
+ title: "Play settings",
16099
+ lines: selected.map(
16100
+ ([key, field]) => `${field.label}: ${key === "path" ? displayPlayPath(result.settings.path, result.ownerName) : field.cli.format(result.settings[key])} (${field.cli.format(result.settings[key])})`
16101
+ )
16102
+ }
16103
+ ]
16104
+ }
16105
+ },
16106
+ { json: json2 }
16107
+ );
16108
+ }
16109
+ function registerPlaySettingsCommands(plays) {
16110
+ const settings = plays.command("settings").description("Read and change Play settings by name and value.").exitOverride((error) => {
16111
+ if (error.exitCode !== 0) error.exitCode = 2;
16112
+ throw error;
16113
+ }).addHelpText("after", help);
16114
+ settings.command("describe").usage("[--name <setting>] [options]").description(
16115
+ "List setting names, values, examples and defaults; no authentication required."
16116
+ ).option(
16117
+ "--name <setting>",
16118
+ `Describe one setting. Available: ${fields.map(([key]) => key).join(", ")}`
16119
+ ).option("--json", "Emit JSON; automatic when piped").addHelpText("after", help).action((options, command) => {
16120
+ if (options.name !== void 0) resolveField(options.name, command);
16121
+ const descriptions = fields.filter(([name]) => !options.name || options.name === name).map(([name, field]) => ({
16122
+ key: name,
16123
+ label: field.label,
16124
+ description: field.schema.description ?? field.description,
16125
+ default: field.defaultValue,
16126
+ defaultText: field.cli.format(field.defaultValue),
16127
+ valueSyntax: field.cli.valueSyntax,
16128
+ examples: field.cli.examples
16129
+ }));
16130
+ printCommandEnvelope(
16131
+ {
16132
+ fields: descriptions,
16133
+ render: {
16134
+ sections: descriptions.map((field) => ({
16135
+ title: field.key,
16136
+ lines: [
16137
+ field.description,
16138
+ `Values: ${field.valueSyntax}`,
16139
+ `Default: ${JSON.stringify(field.default)} (${field.defaultText})`,
16140
+ `Examples: ${field.examples.join(", ")}`
16141
+ ]
16142
+ }))
16143
+ }
16144
+ },
16145
+ { json: options.json }
16146
+ );
16147
+ });
16148
+ settings.command("get").usage("--play <play> [--name <setting>] [options]").description("Read all settings, or one setting selected with --name.").requiredOption("--play <play>", "Play to read").option(
16149
+ "--name <setting>",
16150
+ `Read one setting. Available: ${fields.map(([key]) => key).join(", ")}`
16151
+ ).option("--json", "Emit JSON; automatic when piped").addHelpText("after", help).action(
16152
+ async (options, command) => {
16153
+ if (options.name !== void 0) resolveField(options.name, command);
16154
+ printSettings(
16155
+ await new DeeplineClient().getPlaySettings(options.play),
16156
+ options.json,
16157
+ options.name
16158
+ );
16159
+ }
16160
+ );
16161
+ const set = settings.command("set").usage("--play <play> --name <setting> --value <value> [options]").requiredOption("--play <play>", "Play to update").requiredOption(
16162
+ "--name <setting>",
16163
+ `Setting name. Available: ${fields.map(([key]) => key).join(", ")}`
16164
+ ).requiredOption(
16165
+ "--value <value>",
16166
+ "New value; see settings describe --name <setting>"
16167
+ ).description("Set one setting without creating or publishing a revision.");
16168
+ const reset = settings.command("reset").usage("--play <play> --name <setting> [options]").requiredOption("--play <play>", "Play to update").requiredOption(
16169
+ "--name <setting>",
16170
+ `Setting name. Available: ${fields.map(([key]) => key).join(", ")}`
16171
+ ).description("Reset one setting to its schema default.");
16172
+ const change = async (command, play, key, value, options, resetting) => {
16173
+ const field = resolveField(key, command);
16174
+ let patch;
16175
+ try {
16176
+ patch = playSettingsPatchSchema.parse({
16177
+ [key]: resetting ? field.defaultValue : field.cli.parse(value)
16178
+ });
16179
+ } catch (error) {
16180
+ command.error(
16181
+ `Invalid --value for --name ${key}: ${formatPlaySettingsError(error)} Values: ${field.cli.valueSyntax}.`,
16182
+ { exitCode: 2 }
16183
+ );
16184
+ }
16185
+ if (options.dryRun) {
16186
+ printCommandEnvelope(
16187
+ {
16188
+ dryRun: true,
16189
+ play,
16190
+ patch,
16191
+ render: {
16192
+ sections: [
16193
+ {
16194
+ title: "Planned settings patch",
16195
+ lines: Object.entries(patch).map(
16196
+ ([name, setting]) => `${name}: ${JSON.stringify(setting)}`
16197
+ )
16198
+ }
16199
+ ]
16200
+ }
16201
+ },
16202
+ { json: options.json }
16203
+ );
16204
+ return;
16205
+ }
16206
+ printSettings(
16207
+ await new DeeplineClient().updatePlaySettings(play, patch),
16208
+ options.json
16209
+ );
16210
+ };
16211
+ for (const [command, resetting] of [
16212
+ [set, false],
16213
+ [reset, true]
16214
+ ])
16215
+ command.option("--dry-run", "Show the patch without changing settings").option("--json", "Emit JSON; automatic when piped").addHelpText("after", help).action(
16216
+ (options) => change(
16217
+ command,
16218
+ options.play,
16219
+ options.name,
16220
+ options.value,
16221
+ options,
16222
+ resetting
16223
+ )
16224
+ );
16225
+ settings.command("paths").description("List existing locations (one bounded page).").option("--root <person|team>", "Filter by root").option("--limit <n>", "Plays to inspect, 1\u2013100", "50").option("--cursor <cursor>", "Continue from a previous page").option("--json", "Emit JSON; automatic when piped").addHelpText("after", help).action(
16226
+ async (options, command) => {
16227
+ const limit = Number(options.limit);
16228
+ if (options.root !== void 0 && options.root !== "person" && options.root !== "team" || !Number.isInteger(limit) || limit < 1 || limit > 100)
16229
+ command.error(
16230
+ "--root must be person or team; --limit must be 1\u2013100.",
16231
+ { exitCode: 2 }
16232
+ );
16233
+ const page = await new DeeplineClient().listPlaySettingsPaths({
16234
+ root: options.root,
16235
+ limit,
16236
+ cursor: options.cursor
16237
+ });
16238
+ const nextCommand = page.hasMore ? `deepline plays settings paths --cursor '${page.cursor}'${options.root ? ` --root ${options.root}` : ""} --json` : null;
16239
+ printCommandEnvelope(
16240
+ {
16241
+ ...page,
16242
+ nextCommand,
16243
+ render: {
16244
+ sections: [
16245
+ {
16246
+ title: "Play locations",
16247
+ lines: [
16248
+ ...page.paths.map(
16249
+ (item) => `${displayPlayPath(item.path, item.ownerName)} (${formatPlayPath(item.path)}) \u2014 ${item.playName}`
16250
+ ),
16251
+ ...nextCommand ? [`More: ${nextCommand}`] : []
16252
+ ]
16253
+ }
16254
+ ]
16255
+ }
16256
+ },
16257
+ { json: options.json }
16258
+ );
16259
+ }
16260
+ );
16261
+ }
16262
+
15894
16263
  // src/cli/commands/play.ts
15895
16264
  var import_node_crypto7 = require("crypto");
15896
16265
  var import_node_fs12 = require("fs");
@@ -16506,8 +16875,8 @@ function readCsvHeaderFields(csvPath, sample) {
16506
16875
  skip_empty_lines: false
16507
16876
  });
16508
16877
  const firstRecord = Array.isArray(records) ? records[0] : null;
16509
- const fields = Array.isArray(firstRecord) ? firstRecord.map((field) => String(field ?? "").trim()).filter(Boolean) : [];
16510
- const uniqueFields = [...new Set(fields)];
16878
+ const fields2 = Array.isArray(firstRecord) ? firstRecord.map((field) => String(field ?? "").trim()).filter(Boolean) : [];
16879
+ const uniqueFields = [...new Set(fields2)];
16511
16880
  if (uniqueFields.length === 0) {
16512
16881
  throw new PlayBootstrapUsageError(
16513
16882
  `Could not read a header row from --from csv:${csvPath}.`
@@ -17596,6 +17965,45 @@ Examples:
17596
17965
  });
17597
17966
  }
17598
17967
 
17968
+ // src/cli/commands/plays/run-history.ts
17969
+ async function handleRunsHistory(options) {
17970
+ const query = new URLSearchParams();
17971
+ if (options.cursor) query.set("cursor", options.cursor);
17972
+ if (options.org) query.set("orgId", options.org);
17973
+ if (options.limit !== void 0) {
17974
+ const limit = Number(options.limit);
17975
+ if (!/^\d+$/.test(options.limit) || !Number.isSafeInteger(limit) || limit < 1) {
17976
+ throw new Error("--limit must be a positive integer.");
17977
+ }
17978
+ query.set("limit", String(limit));
17979
+ }
17980
+ const search = query.toString();
17981
+ const page = await new HttpClient(resolveConfig()).get(
17982
+ `/api/v2/dashboard/runs-history${search ? `?${search}` : ""}`
17983
+ );
17984
+ const lines = page.runs.map(
17985
+ (run) => `${run.workflowName} \xB7 ${run.status} \xB7 ${run.runId}`
17986
+ );
17987
+ if (lines.length === 0) lines.push("No runs found on this page.");
17988
+ if (page.hasMore) lines.push(`Next cursor: ${page.nextCursor}`);
17989
+ printCommandEnvelope(
17990
+ { ...page, render: { sections: [{ title: "Run history", lines }] } },
17991
+ options.json ? { json: true } : {}
17992
+ );
17993
+ }
17994
+ function registerRunHistoryCommand(runs) {
17995
+ runs.command("history").description("Page workspace run history.").option(
17996
+ "--cursor <cursor>",
17997
+ "Opaque nextCursor returned by the previous page"
17998
+ ).option("--limit <count>", "Maximum runs on this page").option(
17999
+ "--org <id>",
18000
+ "Workspace ID (must match the authenticated workspace)"
18001
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").addHelpText(
18002
+ "after",
18003
+ "\nUse the opaque --cursor returned by the previous page to continue.\n\nExample:\n deepline runs history --limit 100 --json\n"
18004
+ ).action(handleRunsHistory);
18005
+ }
18006
+
17599
18007
  // src/plays/bundle-play-file.ts
17600
18008
  var import_node_os8 = require("os");
17601
18009
  var import_node_path13 = require("path");
@@ -20481,7 +20889,7 @@ function recordCliTrace(event) {
20481
20889
  process.stderr.write(`[cli-trace] ${JSON.stringify(payload)}
20482
20890
  `);
20483
20891
  }
20484
- async function traceCliSpan(phase, fields, run) {
20892
+ async function traceCliSpan(phase, fields2, run) {
20485
20893
  if (!isCliTraceEnabled()) {
20486
20894
  return run();
20487
20895
  }
@@ -20492,7 +20900,7 @@ async function traceCliSpan(phase, fields, run) {
20492
20900
  phase,
20493
20901
  ms: Date.now() - startedAt,
20494
20902
  ok: true,
20495
- ...fields
20903
+ ...fields2
20496
20904
  });
20497
20905
  return result;
20498
20906
  } catch (error) {
@@ -20501,7 +20909,7 @@ async function traceCliSpan(phase, fields, run) {
20501
20909
  ms: Date.now() - startedAt,
20502
20910
  ok: false,
20503
20911
  error: error instanceof Error ? error.message : String(error),
20504
- ...fields
20912
+ ...fields2
20505
20913
  });
20506
20914
  throw error;
20507
20915
  }
@@ -22345,6 +22753,7 @@ async function handlePlaysDeploy(directory, options) {
22345
22753
  },
22346
22754
  {
22347
22755
  bundle: bundleDeployPlayFile,
22756
+ fetchImpl: fetchWithDeploymentProtection,
22348
22757
  // The plays are already here: "opening" the source is naming it.
22349
22758
  openSource: async () => ({
22350
22759
  open: async () => ({ repoRoot: root })
@@ -23056,7 +23465,7 @@ async function writePlayRunIdFile(destination, runId, options = {}) {
23056
23465
  await removeRunIdTempFile(tempPath);
23057
23466
  }
23058
23467
  }
23059
- function traceCliSync(phase, fields, run) {
23468
+ function traceCliSync(phase, fields2, run) {
23060
23469
  const startedAt = Date.now();
23061
23470
  try {
23062
23471
  const result = run();
@@ -23064,7 +23473,7 @@ function traceCliSync(phase, fields, run) {
23064
23473
  phase,
23065
23474
  ms: Date.now() - startedAt,
23066
23475
  ok: true,
23067
- ...fields
23476
+ ...fields2
23068
23477
  });
23069
23478
  return result;
23070
23479
  } catch (error) {
@@ -23073,7 +23482,7 @@ function traceCliSync(phase, fields, run) {
23073
23482
  ms: Date.now() - startedAt,
23074
23483
  ok: false,
23075
23484
  error: error instanceof Error ? error.message : String(error),
23076
- ...fields
23485
+ ...fields2
23077
23486
  });
23078
23487
  throw error;
23079
23488
  }
@@ -24397,7 +24806,8 @@ function formatProgressCounts(input2) {
24397
24806
  Math.min(100, Math.round(completed / total * 100))
24398
24807
  );
24399
24808
  const failed = typeof input2.failed === "number" && Number.isFinite(input2.failed) && input2.failed > 0 ? `, failed ${formatInteger(input2.failed)}` : "";
24400
- return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
24809
+ const completedLabel = typeof input2.failed === "number" ? "successful " : "";
24810
+ return `${completedLabel}${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
24401
24811
  }
24402
24812
  function formatProgressMessageSuffix(input2) {
24403
24813
  const message = typeof input2.message === "string" ? input2.message.trim() : "";
@@ -25283,8 +25693,8 @@ function formatPlayLogLine(rawLine, status, state) {
25283
25693
  if (!logLevelReaches("info", state.logLevel ?? "info")) {
25284
25694
  return null;
25285
25695
  }
25286
- const [, rows, fields, namespace, cached, pending] = mapStart;
25287
- return `${prefix}map ${sourceLabelForNamespace(namespace)}: ${formatInteger(Number(rows))} rows, ${fields} fields, ${formatInteger(Number(cached))} cached, ${formatInteger(Number(pending))} pending`;
25696
+ const [, rows, fields2, namespace, cached, pending] = mapStart;
25697
+ return `${prefix}map ${sourceLabelForNamespace(namespace)}: ${formatInteger(Number(rows))} rows, ${fields2} fields, ${formatInteger(Number(cached))} cached, ${formatInteger(Number(pending))} pending`;
25288
25698
  }
25289
25699
  const mapDone = message.match(
25290
25700
  /^Map completed: (\d+) results \((\d+) executed, (\d+) already satisfied\)$/
@@ -26338,6 +26748,54 @@ function buildRunActivityTextLines(run) {
26338
26748
  if (observedAt) lines.push(` observed: ${observedAt}`);
26339
26749
  return lines;
26340
26750
  }
26751
+ function formatObservedRunCounter(value) {
26752
+ const counter = readRecord(value);
26753
+ const count = counter?.value;
26754
+ if (typeof count !== "number" || !Number.isSafeInteger(count) || count < 0) {
26755
+ return "unknown";
26756
+ }
26757
+ return counter?.confirmed === true ? formatInteger(count) : `${formatInteger(count)} observed`;
26758
+ }
26759
+ function buildRunStatusEvidenceTextLines(packaged) {
26760
+ const evidence = readRecord(packaged.runStatus);
26761
+ if (!evidence || evidence.available !== true) return [];
26762
+ const calls = readRecord(evidence.calls);
26763
+ const lines = [];
26764
+ if (calls) {
26765
+ lines.push(
26766
+ ` calls: ${formatObservedRunCounter(calls.logicalCalls)} logical, ${formatObservedRunCounter(calls.toolDispatches)} tool dispatches, ${formatObservedRunCounter(calls.provider429s)} provider 429s`
26767
+ );
26768
+ }
26769
+ const source = readRecord(evidence.source);
26770
+ if (source?.aligned === false) {
26771
+ lines.push(
26772
+ ` consistency: run snapshot event ${String(source.runSnapshotLedgerNextSeq)} and progress event ${String(source.ledgerNextSeq)} differ; retry this read to align them`
26773
+ );
26774
+ }
26775
+ const focus = readRecord(evidence.focusStep);
26776
+ const rows = readRecord(focus?.rows);
26777
+ if (focus) {
26778
+ const id = typeof focus.id === "string" && focus.id.trim() ? focus.id.trim() : "unknown step";
26779
+ const label = typeof focus.label === "string" && focus.label.trim() ? ` (${focus.label.trim()})` : "";
26780
+ const state = typeof focus.status === "string" && focus.status.trim() ? `: ${focus.status.trim()}` : "";
26781
+ const rowCounts = rows ? `; rows ${formatObservedRunCounter({ value: rows.succeeded, confirmed: true })} succeeded, ${formatObservedRunCounter({ value: rows.failed, confirmed: true })} failed, ${formatObservedRunCounter({ value: rows.total, confirmed: true })} total` : "";
26782
+ lines.push(` current step: ${id}${label}${state}${rowCounts}`);
26783
+ }
26784
+ return lines;
26785
+ }
26786
+ function buildRecentRunLogTextLines(packaged) {
26787
+ const logs = readRecord(packaged.logs);
26788
+ const tail = Array.isArray(logs?.tail) ? logs.tail.filter((line) => typeof line === "string") : [];
26789
+ if (tail.length === 0) return [];
26790
+ const visible = tail.slice(-5);
26791
+ const total = typeof logs?.totalCount === "number" && Number.isFinite(logs.totalCount) ? ` of ${formatInteger(logs.totalCount)}` : "";
26792
+ const lines = [` recent logs: showing ${visible.length}${total}`];
26793
+ lines.push(...visible.map((line) => ` ${line}`));
26794
+ if (logs?.truncated === true) {
26795
+ lines.push(" older log lines were truncated by the retention cap");
26796
+ }
26797
+ return lines;
26798
+ }
26341
26799
  function buildRunPackageTextLines(packaged) {
26342
26800
  const run = readRunPackageRun(packaged);
26343
26801
  const runId = typeof run.id === "string" ? run.id : "unknown";
@@ -26407,6 +26865,8 @@ function buildRunPackageTextLines(packaged) {
26407
26865
  if (!isRuntimeLimitCheckpoint) {
26408
26866
  lines.push(...buildRunActivityTextLines(run));
26409
26867
  }
26868
+ lines.push(...buildRunStatusEvidenceTextLines(packaged));
26869
+ lines.push(...buildRecentRunLogTextLines(packaged));
26410
26870
  lines.push(...formatPackageValueOutputLines(packaged));
26411
26871
  lines.push(
26412
26872
  ...formatPackageDatasetActionLines(packaged, {
@@ -26414,12 +26874,7 @@ function buildRunPackageTextLines(packaged) {
26414
26874
  })
26415
26875
  );
26416
26876
  const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
26417
- const billingCommand = actionToCommand(next.billing);
26418
26877
  const logsCommand = actionToCommand(next.logs);
26419
- if (billingCommand) {
26420
- const costState = status === "completed" || status === "failed" || status === "cancelled" ? "settles asynchronously \u2014 run the billing command below for totals" : "pending";
26421
- lines.push(` cost: ${costState}`);
26422
- }
26423
26878
  for (const step of isRuntimeLimitCheckpoint ? [] : readRecordArray(packaged.steps).slice(0, 8)) {
26424
26879
  const id = typeof step.id === "string" ? step.id : "step";
26425
26880
  const kind = typeof step.kind === "string" ? step.kind : "step";
@@ -26449,7 +26904,6 @@ function buildRunPackageTextLines(packaged) {
26449
26904
  ` ${isRuntimeTimeout ? "full run details" : "full result"}: ${fullResultCommand}`
26450
26905
  );
26451
26906
  if (logsCommand) lines.push(` logs: ${logsCommand}`);
26452
- if (billingCommand) lines.push(` billing: ${billingCommand}`);
26453
26907
  if (legacyExportCommand) {
26454
26908
  lines.push(` export CSV: ${legacyExportCommand}`);
26455
26909
  }
@@ -28877,11 +29331,23 @@ async function handleRunLifecycleStatus(args) {
28877
29331
  console.log(
28878
29332
  `Map-step work (summed, not unique rows): completed ${formatCount(status.mapStepWork.completed)} / ${formatCount(status.mapStepWork.total)}, failed ${formatCount(status.mapStepWork.failed)}`
28879
29333
  );
29334
+ if (status.activity) {
29335
+ const { activity } = status;
29336
+ const reason = activity.reason ? ` (${activity.reason})` : "";
29337
+ const nextDate = typeof activity.nextAt === "number" ? new Date(activity.nextAt) : null;
29338
+ const next = nextDate && Number.isFinite(nextDate.getTime()) ? `; next at ${nextDate.toISOString()}` : "";
29339
+ console.log(`Activity: ${activity.kind}${reason}${next}`);
29340
+ }
28880
29341
  if (status.lifecycle.status === "waiting") {
28881
29342
  console.log(
28882
29343
  status.wait.confirmed && status.wait.kind ? `Waiting: ${status.wait.kind}` : "Waiting reason: unknown"
28883
29344
  );
28884
29345
  }
29346
+ if (status.calls) {
29347
+ console.log(
29348
+ `Calls: ${formatCount(status.calls.logicalCalls)} logical, ${formatCount(status.calls.providerRequests)} provider requests, ${formatCount(status.calls.provider429s)} provider 429s`
29349
+ );
29350
+ }
28885
29351
  return 0;
28886
29352
  }
28887
29353
  async function handleRunsRerun(args) {
@@ -30032,8 +30498,8 @@ function printPlayDescription(play) {
30032
30498
  }
30033
30499
  }
30034
30500
  function inputFieldNames(schema) {
30035
- const fields = Array.isArray(schema?.fields) ? schema.fields : [];
30036
- return fields.map(
30501
+ const fields2 = Array.isArray(schema?.fields) ? schema.fields : [];
30502
+ return fields2.map(
30037
30503
  (field) => field && typeof field === "object" ? String(field.name ?? "").trim() : ""
30038
30504
  ).filter(Boolean);
30039
30505
  }
@@ -30050,9 +30516,9 @@ function printCompactPlaySearchResult(play) {
30050
30516
  if (aliases) {
30051
30517
  console.log(` Aliases: ${aliases}`);
30052
30518
  }
30053
- const fields = inputFieldNames(play.inputSchema);
30054
- if (fields.length > 0) {
30055
- console.log(` Inputs: ${fields.join(", ")}`);
30519
+ const fields2 = inputFieldNames(play.inputSchema);
30520
+ if (fields2.length > 0) {
30521
+ console.log(` Inputs: ${fields2.join(", ")}`);
30056
30522
  } else if (play.inputSchema) {
30057
30523
  console.log(" Inputs: see describe");
30058
30524
  }
@@ -30061,14 +30527,14 @@ function printCompactPlaySearchResult(play) {
30061
30527
  }
30062
30528
  function compactPlaySchema(schema) {
30063
30529
  if (!schema) return null;
30064
- const fields = Array.isArray(schema.fields) ? schema.fields.map(
30530
+ const fields2 = Array.isArray(schema.fields) ? schema.fields.map(
30065
30531
  (field) => field && typeof field === "object" ? {
30066
30532
  name: String(field.name ?? ""),
30067
30533
  type: field.type ?? void 0,
30068
30534
  required: field.required ?? void 0
30069
30535
  } : null
30070
30536
  ).filter((field) => Boolean(field?.name)) : [];
30071
- return fields.length > 0 ? { fields } : schema;
30537
+ return fields2.length > 0 ? { fields: fields2 } : schema;
30072
30538
  }
30073
30539
  function summarizePlayGrepResult(play) {
30074
30540
  const reference = formatPlayListReference(play);
@@ -30697,6 +31163,8 @@ Concepts:
30697
31163
  Installed npm and repo-local CLIs can run saved/prebuilt plays by name or
30698
31164
  bundle local .play.ts files for development workflows.
30699
31165
  Running a local file does not make it live; use publish or set-live for that.
31166
+ plays settings organizes a Play independently of code revisions.
31167
+ New Plays start at person; publishing moves them to team, preserving folders.
30700
31168
 
30701
31169
  Authoring:
30702
31170
  Use normal TypeScript interpolation for human-facing strings:
@@ -30902,6 +31370,7 @@ Pass-through input flags:
30902
31370
  process.exitCode = exitCode;
30903
31371
  });
30904
31372
  registerPlayBootstrapCommand(play);
31373
+ registerPlaySettingsCommands(play);
30905
31374
  play.command("get <target>").description(
30906
31375
  "Fetch full play details or materialize a saved source bundle."
30907
31376
  ).addHelpText(
@@ -31170,6 +31639,8 @@ Notes:
31170
31639
  plays check to refuse publishing bytes that changed after validation.
31171
31640
  --dry-run bundles only and prints the exact artifact that would be published.
31172
31641
  Running a local file with plays run does not publish it.
31642
+ Publishing moves personal locations into Team library, preserving folders.
31643
+ Change location with: deepline plays settings set --play <play> --name path --value team/Research
31173
31644
 
31174
31645
  Examples:
31175
31646
  deepline plays set-live my-play --latest --json
@@ -31313,7 +31784,10 @@ Examples:
31313
31784
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv
31314
31785
  `
31315
31786
  );
31316
- runs.command("status <runId>").description("Read bounded lifecycle and confirmed work counts for a run.").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
31787
+ registerRunHistoryCommand(runs);
31788
+ runs.command("status <runId>").description(
31789
+ "Legacy scalar-only read. Use runs get for canonical status, progress, logs, and results."
31790
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
31317
31791
  process.exitCode = await handleRunLifecycleStatus([
31318
31792
  runId,
31319
31793
  ...options.json ? ["--json"] : []
@@ -34919,9 +35393,9 @@ function readEnrichRunStatus(status) {
34919
35393
  return null;
34920
35394
  }
34921
35395
  function firstCollectedStringField(value, key) {
34922
- const fields = /* @__PURE__ */ new Set();
34923
- collectStringFields(value, key, fields);
34924
- return fields.values().next().value ?? null;
35396
+ const fields2 = /* @__PURE__ */ new Set();
35397
+ collectStringFields(value, key, fields2);
35398
+ return fields2.values().next().value ?? null;
34925
35399
  }
34926
35400
  function emitPlainRunFailure(status) {
34927
35401
  const runId = extractRunId(status) ?? firstCollectedStringField(status, "runId");
@@ -47658,7 +48132,7 @@ function requireCatalogEvent(settings, eventType) {
47658
48132
  }
47659
48133
  return event;
47660
48134
  }
47661
- async function printSettings(options) {
48135
+ async function printSettings2(options) {
47662
48136
  const settings = await new DeeplineClient().getNotificationSettings();
47663
48137
  const slack = slackDestination(settings);
47664
48138
  const destinationId = typeof slack?._id === "string" ? slack._id : void 0;
@@ -47785,7 +48259,7 @@ Slack is the delivery integration. This command group only manages product
47785
48259
  notifications; there is no general integrations CLI.
47786
48260
  `
47787
48261
  );
47788
- notifications.command("get").description("Show destination, subscriptions, and DLQ health.").option("--json", "Emit JSON output").action(printSettings);
48262
+ notifications.command("get").description("Show destination, subscriptions, and DLQ health.").option("--json", "Emit JSON output").action(printSettings2);
47789
48263
  notifications.command("connect").description("Start the OAuth connection required by a destination.").argument("<destination>", "Destination kind (currently slack)").option("--open", "Open the Slack authorization URL in a browser").option("--dry-run", "Describe the mutation without starting OAuth").option("--json", "Emit JSON output").action(
47790
48264
  async (destination, options) => {
47791
48265
  if (destination !== "slack")
@@ -49208,6 +49682,8 @@ async function searchTools(queryInput, options = {}) {
49208
49682
  query,
49209
49683
  categories: options.categories,
49210
49684
  searchTerms: options.searchTerms,
49685
+ limit: options.limit,
49686
+ offset: options.offset,
49211
49687
  searchMode: options.searchMode,
49212
49688
  includeSearchDebug: options.includeSearchDebug
49213
49689
  });
@@ -49438,13 +49914,15 @@ Notes:
49438
49914
  that can be passed to deepline tools describe or deepline tools execute.
49439
49915
  Provide a query, or omit it only when --categories and/or --search_terms is
49440
49916
  supplied. Providing neither is a usage error. Both filters accept
49441
- comma-separated values. Use a provider name in the query; --prefix is not a
49442
- supported option.
49917
+ comma-separated values. Use --limit and --offset to page through ranked
49918
+ results (limit 1-50, offset is zero-based); JSON includes next_offset.
49919
+ Use a provider name in the query; --prefix is not a supported option.
49443
49920
  The grep alias is the same ranked retrieval surface with a more literal name
49444
49921
  for agents that are filtering a registry rather than choosing a workflow.
49445
49922
 
49446
49923
  Examples:
49447
- deepline tools search email
49924
+ deepline tools search email --limit 10 --json
49925
+ deepline tools search email --limit 10 --offset 10 --json
49448
49926
  deepline tools search --categories company_search --search_terms "investors,funding"
49449
49927
  deepline tools grep "company enrichment" --categories enrichment --json
49450
49928
  deepline tools search verifier --search-mode v2 --json
@@ -49455,10 +49933,12 @@ Examples:
49455
49933
  ).option(
49456
49934
  "--search_terms <terms>",
49457
49935
  "Comma-separated structured search terms; may be used without a query"
49458
- ).option("--search-terms <terms>", "Alias for --search_terms").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
49936
+ ).option("--search-terms <terms>", "Alias for --search_terms").option("--limit <count>", "Maximum ranked results to return (1-50)").option("--offset <count>", "Zero-based ranked result offset").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
49459
49937
  process.exitCode = await searchTools(query, {
49460
49938
  json: options.json,
49461
49939
  compact: options.compact,
49940
+ limit: options.limit !== void 0 ? Number.parseInt(options.limit, 10) : void 0,
49941
+ offset: options.offset !== void 0 ? Number.parseInt(options.offset, 10) : void 0,
49462
49942
  categories: options.categories,
49463
49943
  searchTerms: options.searchTerms ?? options.search_terms,
49464
49944
  searchMode: options.searchMode === "v1" || options.searchMode === "v2" ? options.searchMode : void 0,
@@ -49861,8 +50341,8 @@ function printMonitorTypeFilters(tool) {
49861
50341
  }
49862
50342
  function printMonitorTypeFilterExamples(tool) {
49863
50343
  const documentation = recordField2(tool, "documentation");
49864
- const fields = recordField2(documentation, "fields");
49865
- const examples = Object.entries(fields).flatMap(([name, rawField]) => {
50344
+ const fields2 = recordField2(documentation, "fields");
50345
+ const examples = Object.entries(fields2).flatMap(([name, rawField]) => {
49866
50346
  const grammar = recordField2(isRecord12(rawField) ? rawField : {}, "grammar");
49867
50347
  const example = stringField2(grammar, "example");
49868
50348
  const values = [
@@ -50217,9 +50697,9 @@ function sampleValueForField(field) {
50217
50697
  if (type === "object") return {};
50218
50698
  return "...";
50219
50699
  }
50220
- function samplePayloadForInputFields(fields) {
50700
+ function samplePayloadForInputFields(fields2) {
50221
50701
  return Object.fromEntries(
50222
- fields.slice(0, 4).flatMap((field) => {
50702
+ fields2.slice(0, 4).flatMap((field) => {
50223
50703
  if (!isRecord12(field)) return [];
50224
50704
  const name = stringField2(field, "name");
50225
50705
  if (!name) return [];
@@ -50350,8 +50830,8 @@ function formatListedToolCost(tool) {
50350
50830
  }
50351
50831
  function toolInputFieldsForDisplay(inputSchema) {
50352
50832
  if (Array.isArray(inputSchema.fields)) {
50353
- const fields = inputSchema.fields.filter(isRecord12);
50354
- if (!isRecord12(inputSchema.jsonSchema)) return fields;
50833
+ const fields2 = inputSchema.fields.filter(isRecord12);
50834
+ if (!isRecord12(inputSchema.jsonSchema)) return fields2;
50355
50835
  const jsonSchemaFields = new Map(
50356
50836
  recursiveToolInputFieldsForDisplay({
50357
50837
  jsonSchema: inputSchema.jsonSchema
@@ -50359,7 +50839,7 @@ function toolInputFieldsForDisplay(inputSchema) {
50359
50839
  (field) => typeof field.name === "string" ? [[field.name, field]] : []
50360
50840
  )
50361
50841
  );
50362
- return fields.map((field) => {
50842
+ return fields2.map((field) => {
50363
50843
  const jsonSchemaField = typeof field.name === "string" ? jsonSchemaFields.get(field.name) : void 0;
50364
50844
  const minItems = typeof field.minItems === "number" ? field.minItems : jsonSchemaField?.minItems;
50365
50845
  const maxItems = typeof field.maxItems === "number" ? field.maxItems : jsonSchemaField?.maxItems;
@@ -50456,7 +50936,7 @@ function publicToolInputSchemaForDescribe(inputSchema) {
50456
50936
  }
50457
50937
  function recursiveToolInputFieldsForDisplay(inputSchema) {
50458
50938
  const root = canonicalToolJsonSchema(inputSchema);
50459
- const fields = /* @__PURE__ */ new Map();
50939
+ const fields2 = /* @__PURE__ */ new Map();
50460
50940
  const schemasById = /* @__PURE__ */ new Map();
50461
50941
  const collectSchemaIds = (value) => {
50462
50942
  if (Array.isArray(value)) {
@@ -50484,9 +50964,9 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
50484
50964
  const addField = (field) => {
50485
50965
  const name = typeof field.name === "string" ? field.name : "";
50486
50966
  if (!name) return;
50487
- const existing = fields.get(name);
50967
+ const existing = fields2.get(name);
50488
50968
  if (!existing || existing.type === "unknown") {
50489
- fields.set(name, field);
50969
+ fields2.set(name, field);
50490
50970
  }
50491
50971
  };
50492
50972
  const visit = (unresolvedSchema, path, required, activeRefs = /* @__PURE__ */ new Set()) => {
@@ -50534,7 +51014,7 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
50534
51014
  }
50535
51015
  };
50536
51016
  visit(root, "", false);
50537
- return fields.size ? [...fields.values()] : toolInputFieldsForDisplay(inputSchema);
51017
+ return fields2.size ? [...fields2.values()] : toolInputFieldsForDisplay(inputSchema);
50538
51018
  }
50539
51019
  function inputFieldJsonForDescribe(field) {
50540
51020
  const publicItems = isRecord12(field.items) ? publicToolInputSchemaForDescribe({ items: field.items }).items : void 0;