deepline 0.3.142 → 0.3.144

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.
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
200
200
  // getters keep their established compatibility behavior.
201
201
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
202
202
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
203
- version: '0.3.142',
203
+ version: '0.3.144',
204
204
  updateSummary:
205
205
  '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.',
206
206
  packageCapabilities: {
@@ -330,6 +330,18 @@ export type QueueItemUnavailable = {
330
330
  readonly reason: string;
331
331
  };
332
332
 
333
+ /** Server attestation that an item page came from the owner's bounded,
334
+ * indexed failed-time reader rather than the generic item listing. */
335
+ export type QueueItemFailedTimeRange = {
336
+ readonly kind: 'failed-time-range';
337
+ readonly after: string | null;
338
+ readonly before: string;
339
+ readonly index: string;
340
+ readonly indexed: true;
341
+ /** Stable across every page in the same cursor-bound plan. */
342
+ readonly snapshotAt: string;
343
+ };
344
+
333
345
  export type QueueItemList = {
334
346
  readonly contractVersion: typeof QUEUE_ITEM_CONTROL_CONTRACT_VERSION;
335
347
  readonly queueId: string;
@@ -339,6 +351,8 @@ export type QueueItemList = {
339
351
  readonly nextCursor: string | null;
340
352
  readonly limit: number;
341
353
  readonly cursor: string | null;
354
+ /** Present only for a successfully measured indexed failure-time range. */
355
+ readonly failedTimeRange?: QueueItemFailedTimeRange;
342
356
  readonly unavailable?: QueueItemUnavailable;
343
357
  };
344
358
 
@@ -108,6 +108,13 @@ type ProductNotificationRuleDefinition = {
108
108
  type NotificationTypeRegistration = NotificationTypeDefinition & {
109
109
  catalog?: ProductNotificationTypeCatalogMetadata;
110
110
  rule?: ProductNotificationRuleDefinition;
111
+ /**
112
+ * A platform-emitted rule with no catalog entry: never listed, never
113
+ * accepted by a workspace mutation, regardless of caller. Distinct from an
114
+ * inert catalog-less type (e.g. one with no producer yet) because a shadow
115
+ * type still ships a `rule.default` and fires for every workspace.
116
+ */
117
+ shadow?: true;
111
118
  };
112
119
 
113
120
  function validateInsufficientCreditDisable(
@@ -643,29 +650,19 @@ const PRODUCT_NOTIFICATION_TYPE_REGISTRY = [
643
650
  eventName: ProductNotificationEvent.CreditsPurchaseCompleted,
644
651
  requiredFilter: {},
645
652
  allowedTriggers: ['threshold_crossing'],
646
- catalog: {
647
- name: 'Credit purchase thank-you',
648
- category: 'credits',
649
- description:
650
- 'Thank the workspace when a credit purchase of at least the chosen size completes.',
651
- allowMultiple: false,
652
- editor: {
653
- kind: 'threshold',
654
- label: 'Minimum credits',
655
- defaultThreshold: 500,
656
- minimum: 0,
657
- suffix: 'credits',
658
- },
659
- },
653
+ // Credit purchase thank-you: fires for every workspace once a purchase
654
+ // reaches 500 credits. Not configurable — see the `shadow` field.
655
+ catalog: undefined,
656
+ shadow: true,
660
657
  rule: {
661
- default: { ruleKey: 'default.credits_purchased', groupKey: 'default' },
662
- create: (input, base, editor) => ({
658
+ default: { ruleKey: 'default.credits_purchased', groupKey: 'shadow' },
659
+ create: (input, base) => ({
663
660
  ...base,
664
661
  repeatMode: 'every_match',
665
662
  trigger: {
666
663
  kind: 'threshold_crossing',
667
664
  direction: 'at_or_above',
668
- threshold: input.threshold ?? defaultThreshold(editor),
665
+ threshold: input.threshold ?? 500,
669
666
  unit: 'credits',
670
667
  },
671
668
  }),
@@ -707,15 +704,12 @@ const PRODUCT_NOTIFICATION_TYPE_REGISTRY = [
707
704
  eventName: ProductNotificationEvent.BillingPlanPurchased,
708
705
  requiredFilter: {},
709
706
  allowedTriggers: ['each_match'],
710
- catalog: {
711
- name: 'Plan welcome',
712
- category: 'credits',
713
- description: 'Thank the workspace when it purchases a plan.',
714
- allowMultiple: false,
715
- editor: { kind: 'none' },
716
- },
707
+ // Plan welcome: fires for every workspace on plan purchase. Not
708
+ // configurable — see the `shadow` field.
709
+ catalog: undefined,
710
+ shadow: true,
717
711
  rule: {
718
- default: { ruleKey: 'default.plan_purchased', groupKey: 'default' },
712
+ default: { ruleKey: 'default.plan_purchased', groupKey: 'shadow' },
719
713
  create: (_input, base) => ({
720
714
  ...base,
721
715
  repeatMode: 'every_match',
@@ -911,10 +905,10 @@ export function createProductNotificationRule(input: {
911
905
  };
912
906
  if (rule?.create) {
913
907
  const editor = registration.catalog?.editor;
914
- if (!editor) {
908
+ if (!editor && !(registration as NotificationTypeRegistration).shadow) {
915
909
  throw new Error(`${input.notificationType} is not configurable.`);
916
910
  }
917
- return rule.create(input, base, editor);
911
+ return rule.create(input, base, editor ?? { kind: 'none' });
918
912
  }
919
913
  throw new Error(
920
914
  `Notification type ${input.notificationType} has no rule builder.`,
@@ -927,6 +921,17 @@ export const PRODUCT_NOTIFICATION_TYPE_CATALOG: readonly ProductNotificationType
927
921
  catalog ? [{ id, ...catalog }] : [],
928
922
  );
929
923
 
924
+ /**
925
+ * Platform-owned notification types with a default rule that fires for every
926
+ * workspace but is never listed or user-editable. A workspace mutation must
927
+ * reject any of these ids outright, not merely omit them from a listing.
928
+ */
929
+ export const PRODUCT_NOTIFICATION_SHADOW_TYPES: ReadonlySet<string> = new Set(
930
+ PRODUCT_NOTIFICATION_TYPE_REGISTRY.filter(
931
+ (registration) => (registration as NotificationTypeRegistration).shadow,
932
+ ).map(({ id }) => id),
933
+ );
934
+
930
935
  /** Code-owned defaults declared beside the notification types they enable. */
931
936
  export const PRODUCT_NOTIFICATION_DEFAULT_RULES =
932
937
  PRODUCT_NOTIFICATION_TYPE_REGISTRY.flatMap((registration) => {
@@ -14,7 +14,7 @@ import {
14
14
  * they create sparse copy-on-write overrides.
15
15
  */
16
16
  export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
17
- version: 7,
17
+ version: 8,
18
18
  groups: [
19
19
  {
20
20
  groupKey: 'default',
@@ -22,6 +22,16 @@ export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
22
22
  enabled: true,
23
23
  deliveryTiming: DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
24
24
  },
25
+ {
26
+ // Holds shadow (platform-owned, unconfigurable) rules. Kept in its own
27
+ // group so a customer save of the "default" group's rules never diffs
28
+ // against — and so never implicitly disables — a shadow rule it can't
29
+ // see. See PRODUCT_NOTIFICATION_SHADOW_TYPES.
30
+ groupKey: 'shadow',
31
+ name: 'Platform notifications',
32
+ enabled: true,
33
+ deliveryTiming: DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
34
+ },
25
35
  ],
26
36
  destinations: [
27
37
  {
@@ -31,6 +41,13 @@ export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
31
41
  enabled: true,
32
42
  settings: { kind: 'email_roles', roles: ['owner'] },
33
43
  },
44
+ {
45
+ destinationKey: 'shadow.roles',
46
+ groupKey: 'shadow',
47
+ name: 'Workspace owners',
48
+ enabled: true,
49
+ settings: { kind: 'email_roles', roles: ['owner'] },
50
+ },
34
51
  ],
35
52
  rules: PRODUCT_NOTIFICATION_DEFAULT_RULES,
36
53
  } satisfies ProductNotificationDefaultPolicy;
package/dist/cli/index.js CHANGED
@@ -3068,7 +3068,7 @@ var SDK_RELEASE = {
3068
3068
  // getters keep their established compatibility behavior.
3069
3069
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3070
3070
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3071
- version: "0.3.142",
3071
+ version: "0.3.144",
3072
3072
  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.",
3073
3073
  packageCapabilities: {
3074
3074
  updatePreferences: 1
@@ -47961,6 +47961,7 @@ Notes:
47961
47961
  Examples:
47962
47962
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
47963
47963
  deepline tools execute hunter_email_verifier -p email=a@b.com
47964
+ deepline tools execute test_rate_limit --input '{"key":"smoke"}' --timeout 90s --json
47964
47965
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --json | jq '.status'
47965
47966
  deepline tools execute free_simple_company_search --input '{"sql":"SELECT company_name FROM companies LIMIT 10"}' --out companies.csv
47966
47967
  `
@@ -47981,6 +47982,9 @@ Examples:
47981
47982
  ).option(
47982
47983
  "--payload <payload>",
47983
47984
  "Merge a JSON object or @file path into the tool params"
47985
+ ).option(
47986
+ "--timeout <duration>",
47987
+ "Execution HTTP deadline (for example 90s, 5m, or 1h; bare numbers are seconds)"
47984
47988
  ).option(
47985
47989
  "--output-format <format>",
47986
47990
  "Output format: auto, csv, csv_file, json, or json_file"
@@ -47995,6 +47999,7 @@ Examples:
47995
47999
  ...typeof options.json === "string" ? ["--json", options.json] : [],
47996
48000
  ...options.input ? ["--input", options.input] : [],
47997
48001
  ...options.payload ? ["--payload", options.payload] : [],
48002
+ ...options.timeout ? ["--timeout", options.timeout] : [],
47998
48003
  ...options.outputFormat ? ["--output-format", options.outputFormat] : [],
47999
48004
  ...options.out ? ["--out", options.out] : [],
48000
48005
  ...options.preview === false ? ["--no-preview"] : []
@@ -48747,8 +48752,10 @@ function toolInputFieldsForDisplay(inputSchema) {
48747
48752
  const jsonSchemaField = typeof field.name === "string" ? jsonSchemaFields.get(field.name) : void 0;
48748
48753
  const minItems = typeof field.minItems === "number" ? field.minItems : jsonSchemaField?.minItems;
48749
48754
  const maxItems = typeof field.maxItems === "number" ? field.maxItems : jsonSchemaField?.maxItems;
48755
+ const items = isRecord12(field.items) ? field.items : jsonSchemaField?.items;
48750
48756
  return {
48751
48757
  ...field,
48758
+ ...isRecord12(items) ? { items } : {},
48752
48759
  ...typeof minItems === "number" ? { minItems } : {},
48753
48760
  ...typeof maxItems === "number" ? { maxItems } : {}
48754
48761
  };
@@ -48764,6 +48771,7 @@ function toolInputFieldsForDisplay(inputSchema) {
48764
48771
  type: typeof property.type === "string" ? property.type : "unknown",
48765
48772
  required: required.has(name),
48766
48773
  description: property.description,
48774
+ ...isRecord12(property.items) ? { items: property.items } : {},
48767
48775
  ...typeof property.minItems === "number" ? { minItems: property.minItems } : {},
48768
48776
  ...typeof property.maxItems === "number" ? { maxItems: property.maxItems } : {},
48769
48777
  ...Object.prototype.hasOwnProperty.call(property, "default") ? { default: property.default } : {}
@@ -48883,6 +48891,7 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
48883
48891
  required,
48884
48892
  description: schema.description,
48885
48893
  ...Array.isArray(schema.enum) ? { enum: schema.enum } : {},
48894
+ ...isRecord12(schema.items) ? { items: schema.items } : {},
48886
48895
  ...typeof schema.minItems === "number" ? { minItems: schema.minItems } : {},
48887
48896
  ...typeof schema.maxItems === "number" ? { maxItems: schema.maxItems } : {},
48888
48897
  ...Object.prototype.hasOwnProperty.call(schema, "default") ? { default: schema.default } : {}
@@ -48917,25 +48926,31 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
48917
48926
  return fields.size ? [...fields.values()] : toolInputFieldsForDisplay(inputSchema);
48918
48927
  }
48919
48928
  function inputFieldJsonForDescribe(field) {
48929
+ const publicItems = isRecord12(field.items) ? publicToolInputSchemaForDescribe({ items: field.items }).items : void 0;
48920
48930
  return {
48921
48931
  name: field.name,
48922
48932
  type: field.type ?? "unknown",
48923
48933
  required: Boolean(field.required),
48924
48934
  ...field.description ? { description: field.description } : {},
48935
+ ...isRecord12(publicItems) ? { items: publicItems } : {},
48925
48936
  ...typeof field.minItems === "number" ? { minItems: field.minItems } : {},
48926
48937
  ...typeof field.maxItems === "number" ? { maxItems: field.maxItems } : {},
48927
48938
  ...Object.prototype.hasOwnProperty.call(field, "default") ? { default: field.default } : {}
48928
48939
  };
48929
48940
  }
48930
48941
  function arrayItemBoundsSuffix(field) {
48942
+ const itemSchema = isRecord12(field.items) ? field.items : null;
48943
+ const itemType = itemSchema ? typeof itemSchema.type === "string" ? itemSchema.type : isRecord12(itemSchema.properties) ? "object" : "unknown" : null;
48944
+ const itemEnum = Array.isArray(itemSchema?.enum) ? ` enum=${itemSchema.enum.map(String).join("|")}` : "";
48945
+ const itemTypeSuffix = itemType && itemType !== "unknown" ? ` items=${itemType}${itemEnum}` : "";
48931
48946
  const minItems = typeof field.minItems === "number" && Number.isFinite(field.minItems) ? field.minItems : null;
48932
48947
  const maxItems = typeof field.maxItems === "number" && Number.isFinite(field.maxItems) ? field.maxItems : null;
48933
48948
  if (minItems !== null && maxItems !== null) {
48934
- return ` items=${minItems}..${maxItems}`;
48949
+ return itemTypeSuffix ? `${itemTypeSuffix} minItems=${minItems} maxItems=${maxItems}` : ` items=${minItems}..${maxItems}`;
48935
48950
  }
48936
- if (minItems !== null) return ` minItems=${minItems}`;
48937
- if (maxItems !== null) return ` maxItems=${maxItems}`;
48938
- return "";
48951
+ if (minItems !== null) return `${itemTypeSuffix} minItems=${minItems}`;
48952
+ if (maxItems !== null) return `${itemTypeSuffix} maxItems=${maxItems}`;
48953
+ return itemTypeSuffix;
48939
48954
  }
48940
48955
  function printToolExecutionHints(value) {
48941
48956
  const batchCapabilityRecord = recordField2(
@@ -49224,13 +49239,14 @@ function parseExecuteOptions(args) {
49224
49239
  const toolId = args[0];
49225
49240
  if (!toolId) {
49226
49241
  throw new Error(
49227
- `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--out rows.csv] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
49242
+ `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--timeout <duration>] [--out rows.csv] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
49228
49243
  );
49229
49244
  }
49230
49245
  const params = {};
49231
49246
  let outputFormat = "auto";
49232
49247
  let noPreview = false;
49233
49248
  let outPath = null;
49249
+ let timeoutMs;
49234
49250
  for (let index = 1; index < args.length; index += 1) {
49235
49251
  const arg = args[index];
49236
49252
  if ((arg === "--param" || arg === "-p") && args[index + 1]) {
@@ -49254,6 +49270,10 @@ function parseExecuteOptions(args) {
49254
49270
  Object.assign(params, parseJsonObjectArgument(args[++index], arg));
49255
49271
  continue;
49256
49272
  }
49273
+ if (arg === "--timeout" && args[index + 1]) {
49274
+ timeoutMs = parseToolExecuteTimeout(args[++index]);
49275
+ continue;
49276
+ }
49257
49277
  if (arg === "--output-format" && args[index + 1]) {
49258
49278
  outputFormat = normalizeOutputFormat(args[++index]);
49259
49279
  continue;
@@ -49268,7 +49288,25 @@ function parseExecuteOptions(args) {
49268
49288
  }
49269
49289
  throw new Error(`Unknown option: ${arg}`);
49270
49290
  }
49271
- return { toolId, params, outputFormat, noPreview, outPath };
49291
+ return { toolId, params, outputFormat, noPreview, outPath, timeoutMs };
49292
+ }
49293
+ function parseToolExecuteTimeout(raw) {
49294
+ const match = /^(\d+)(ms|s|m|h)?$/i.exec(raw.trim());
49295
+ if (!match) {
49296
+ throw new Error(
49297
+ "--timeout must be a duration like 500ms, 90s, 10m, or 1h (a bare number is seconds)."
49298
+ );
49299
+ }
49300
+ const value = Number(match[1]);
49301
+ const unit = (match[2] ?? "s").toLowerCase();
49302
+ const factor = unit === "ms" ? 1 : unit === "s" ? 1e3 : unit === "m" ? 6e4 : 36e5;
49303
+ const timeoutMs = value * factor;
49304
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647) {
49305
+ throw new Error(
49306
+ "--timeout must be between 1ms and 2147483647ms (24d 20h 31m 23s)."
49307
+ );
49308
+ }
49309
+ return timeoutMs;
49272
49310
  }
49273
49311
  function safeFileStem(value) {
49274
49312
  return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
@@ -49571,7 +49609,8 @@ async function executeTool(args) {
49571
49609
  return 2;
49572
49610
  }
49573
49611
  const rawResponse = await client2.executeTool(parsed.toolId, parsed.params, {
49574
- responseIntent: parsed.outPath || parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file" ? "row_artifact" : "raw"
49612
+ responseIntent: parsed.outPath || parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file" ? "row_artifact" : "raw",
49613
+ ...parsed.timeoutMs !== void 0 ? { timeout: parsed.timeoutMs } : {}
49575
49614
  });
49576
49615
  const listConversion = tryConvertToList(rawResponse, {
49577
49616
  listExtractorPaths: listExtractorPathsFromUsageGuidance(metadata)
@@ -3063,7 +3063,7 @@ var SDK_RELEASE = {
3063
3063
  // getters keep their established compatibility behavior.
3064
3064
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3065
3065
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3066
- version: "0.3.142",
3066
+ version: "0.3.144",
3067
3067
  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.",
3068
3068
  packageCapabilities: {
3069
3069
  updatePreferences: 1
@@ -48103,6 +48103,7 @@ Notes:
48103
48103
  Examples:
48104
48104
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
48105
48105
  deepline tools execute hunter_email_verifier -p email=a@b.com
48106
+ deepline tools execute test_rate_limit --input '{"key":"smoke"}' --timeout 90s --json
48106
48107
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --json | jq '.status'
48107
48108
  deepline tools execute free_simple_company_search --input '{"sql":"SELECT company_name FROM companies LIMIT 10"}' --out companies.csv
48108
48109
  `
@@ -48123,6 +48124,9 @@ Examples:
48123
48124
  ).option(
48124
48125
  "--payload <payload>",
48125
48126
  "Merge a JSON object or @file path into the tool params"
48127
+ ).option(
48128
+ "--timeout <duration>",
48129
+ "Execution HTTP deadline (for example 90s, 5m, or 1h; bare numbers are seconds)"
48126
48130
  ).option(
48127
48131
  "--output-format <format>",
48128
48132
  "Output format: auto, csv, csv_file, json, or json_file"
@@ -48137,6 +48141,7 @@ Examples:
48137
48141
  ...typeof options.json === "string" ? ["--json", options.json] : [],
48138
48142
  ...options.input ? ["--input", options.input] : [],
48139
48143
  ...options.payload ? ["--payload", options.payload] : [],
48144
+ ...options.timeout ? ["--timeout", options.timeout] : [],
48140
48145
  ...options.outputFormat ? ["--output-format", options.outputFormat] : [],
48141
48146
  ...options.out ? ["--out", options.out] : [],
48142
48147
  ...options.preview === false ? ["--no-preview"] : []
@@ -48889,8 +48894,10 @@ function toolInputFieldsForDisplay(inputSchema) {
48889
48894
  const jsonSchemaField = typeof field.name === "string" ? jsonSchemaFields.get(field.name) : void 0;
48890
48895
  const minItems = typeof field.minItems === "number" ? field.minItems : jsonSchemaField?.minItems;
48891
48896
  const maxItems = typeof field.maxItems === "number" ? field.maxItems : jsonSchemaField?.maxItems;
48897
+ const items = isRecord12(field.items) ? field.items : jsonSchemaField?.items;
48892
48898
  return {
48893
48899
  ...field,
48900
+ ...isRecord12(items) ? { items } : {},
48894
48901
  ...typeof minItems === "number" ? { minItems } : {},
48895
48902
  ...typeof maxItems === "number" ? { maxItems } : {}
48896
48903
  };
@@ -48906,6 +48913,7 @@ function toolInputFieldsForDisplay(inputSchema) {
48906
48913
  type: typeof property.type === "string" ? property.type : "unknown",
48907
48914
  required: required.has(name),
48908
48915
  description: property.description,
48916
+ ...isRecord12(property.items) ? { items: property.items } : {},
48909
48917
  ...typeof property.minItems === "number" ? { minItems: property.minItems } : {},
48910
48918
  ...typeof property.maxItems === "number" ? { maxItems: property.maxItems } : {},
48911
48919
  ...Object.prototype.hasOwnProperty.call(property, "default") ? { default: property.default } : {}
@@ -49025,6 +49033,7 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
49025
49033
  required,
49026
49034
  description: schema.description,
49027
49035
  ...Array.isArray(schema.enum) ? { enum: schema.enum } : {},
49036
+ ...isRecord12(schema.items) ? { items: schema.items } : {},
49028
49037
  ...typeof schema.minItems === "number" ? { minItems: schema.minItems } : {},
49029
49038
  ...typeof schema.maxItems === "number" ? { maxItems: schema.maxItems } : {},
49030
49039
  ...Object.prototype.hasOwnProperty.call(schema, "default") ? { default: schema.default } : {}
@@ -49059,25 +49068,31 @@ function recursiveToolInputFieldsForDisplay(inputSchema) {
49059
49068
  return fields.size ? [...fields.values()] : toolInputFieldsForDisplay(inputSchema);
49060
49069
  }
49061
49070
  function inputFieldJsonForDescribe(field) {
49071
+ const publicItems = isRecord12(field.items) ? publicToolInputSchemaForDescribe({ items: field.items }).items : void 0;
49062
49072
  return {
49063
49073
  name: field.name,
49064
49074
  type: field.type ?? "unknown",
49065
49075
  required: Boolean(field.required),
49066
49076
  ...field.description ? { description: field.description } : {},
49077
+ ...isRecord12(publicItems) ? { items: publicItems } : {},
49067
49078
  ...typeof field.minItems === "number" ? { minItems: field.minItems } : {},
49068
49079
  ...typeof field.maxItems === "number" ? { maxItems: field.maxItems } : {},
49069
49080
  ...Object.prototype.hasOwnProperty.call(field, "default") ? { default: field.default } : {}
49070
49081
  };
49071
49082
  }
49072
49083
  function arrayItemBoundsSuffix(field) {
49084
+ const itemSchema = isRecord12(field.items) ? field.items : null;
49085
+ const itemType = itemSchema ? typeof itemSchema.type === "string" ? itemSchema.type : isRecord12(itemSchema.properties) ? "object" : "unknown" : null;
49086
+ const itemEnum = Array.isArray(itemSchema?.enum) ? ` enum=${itemSchema.enum.map(String).join("|")}` : "";
49087
+ const itemTypeSuffix = itemType && itemType !== "unknown" ? ` items=${itemType}${itemEnum}` : "";
49073
49088
  const minItems = typeof field.minItems === "number" && Number.isFinite(field.minItems) ? field.minItems : null;
49074
49089
  const maxItems = typeof field.maxItems === "number" && Number.isFinite(field.maxItems) ? field.maxItems : null;
49075
49090
  if (minItems !== null && maxItems !== null) {
49076
- return ` items=${minItems}..${maxItems}`;
49091
+ return itemTypeSuffix ? `${itemTypeSuffix} minItems=${minItems} maxItems=${maxItems}` : ` items=${minItems}..${maxItems}`;
49077
49092
  }
49078
- if (minItems !== null) return ` minItems=${minItems}`;
49079
- if (maxItems !== null) return ` maxItems=${maxItems}`;
49080
- return "";
49093
+ if (minItems !== null) return `${itemTypeSuffix} minItems=${minItems}`;
49094
+ if (maxItems !== null) return `${itemTypeSuffix} maxItems=${maxItems}`;
49095
+ return itemTypeSuffix;
49081
49096
  }
49082
49097
  function printToolExecutionHints(value) {
49083
49098
  const batchCapabilityRecord = recordField2(
@@ -49366,13 +49381,14 @@ function parseExecuteOptions(args) {
49366
49381
  const toolId = args[0];
49367
49382
  if (!toolId) {
49368
49383
  throw new Error(
49369
- `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--out rows.csv] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
49384
+ `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--timeout <duration>] [--out rows.csv] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
49370
49385
  );
49371
49386
  }
49372
49387
  const params = {};
49373
49388
  let outputFormat = "auto";
49374
49389
  let noPreview = false;
49375
49390
  let outPath = null;
49391
+ let timeoutMs;
49376
49392
  for (let index = 1; index < args.length; index += 1) {
49377
49393
  const arg = args[index];
49378
49394
  if ((arg === "--param" || arg === "-p") && args[index + 1]) {
@@ -49396,6 +49412,10 @@ function parseExecuteOptions(args) {
49396
49412
  Object.assign(params, parseJsonObjectArgument(args[++index], arg));
49397
49413
  continue;
49398
49414
  }
49415
+ if (arg === "--timeout" && args[index + 1]) {
49416
+ timeoutMs = parseToolExecuteTimeout(args[++index]);
49417
+ continue;
49418
+ }
49399
49419
  if (arg === "--output-format" && args[index + 1]) {
49400
49420
  outputFormat = normalizeOutputFormat(args[++index]);
49401
49421
  continue;
@@ -49410,7 +49430,25 @@ function parseExecuteOptions(args) {
49410
49430
  }
49411
49431
  throw new Error(`Unknown option: ${arg}`);
49412
49432
  }
49413
- return { toolId, params, outputFormat, noPreview, outPath };
49433
+ return { toolId, params, outputFormat, noPreview, outPath, timeoutMs };
49434
+ }
49435
+ function parseToolExecuteTimeout(raw) {
49436
+ const match = /^(\d+)(ms|s|m|h)?$/i.exec(raw.trim());
49437
+ if (!match) {
49438
+ throw new Error(
49439
+ "--timeout must be a duration like 500ms, 90s, 10m, or 1h (a bare number is seconds)."
49440
+ );
49441
+ }
49442
+ const value = Number(match[1]);
49443
+ const unit = (match[2] ?? "s").toLowerCase();
49444
+ const factor = unit === "ms" ? 1 : unit === "s" ? 1e3 : unit === "m" ? 6e4 : 36e5;
49445
+ const timeoutMs = value * factor;
49446
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647) {
49447
+ throw new Error(
49448
+ "--timeout must be between 1ms and 2147483647ms (24d 20h 31m 23s)."
49449
+ );
49450
+ }
49451
+ return timeoutMs;
49414
49452
  }
49415
49453
  function safeFileStem(value) {
49416
49454
  return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
@@ -49713,7 +49751,8 @@ async function executeTool(args) {
49713
49751
  return 2;
49714
49752
  }
49715
49753
  const rawResponse = await client2.executeTool(parsed.toolId, parsed.params, {
49716
- responseIntent: parsed.outPath || parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file" ? "row_artifact" : "raw"
49754
+ responseIntent: parsed.outPath || parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file" ? "row_artifact" : "raw",
49755
+ ...parsed.timeoutMs !== void 0 ? { timeout: parsed.timeoutMs } : {}
49717
49756
  });
49718
49757
  const listConversion = tryConvertToList(rawResponse, {
49719
49758
  listExtractorPaths: listExtractorPathsFromUsageGuidance(metadata)
package/dist/index.d.mts CHANGED
@@ -770,45 +770,14 @@ declare const PRODUCT_NOTIFICATION_TYPE_REGISTRY: readonly [{
770
770
  readonly eventName: "credits.purchase.completed";
771
771
  readonly requiredFilter: {};
772
772
  readonly allowedTriggers: ["threshold_crossing"];
773
- readonly catalog: {
774
- readonly name: "Credit purchase thank-you";
775
- readonly category: "credits";
776
- readonly description: "Thank the workspace when a credit purchase of at least the chosen size completes.";
777
- readonly allowMultiple: false;
778
- readonly editor: {
779
- readonly kind: "threshold";
780
- readonly label: "Minimum credits";
781
- readonly defaultThreshold: 500;
782
- readonly minimum: 0;
783
- readonly suffix: "credits";
784
- };
785
- };
773
+ readonly catalog: undefined;
774
+ readonly shadow: true;
786
775
  readonly rule: {
787
776
  readonly default: {
788
777
  readonly ruleKey: "default.credits_purchased";
789
- readonly groupKey: "default";
778
+ readonly groupKey: "shadow";
790
779
  };
791
- readonly create: (input: ProductNotificationRuleInput, base: ProductNotificationRuleBase, editor: {
792
- kind: "threshold";
793
- label: string;
794
- defaultThreshold: number;
795
- minimum: number;
796
- maximum?: number;
797
- suffix?: string;
798
- /**
799
- * When set, editors show and accept `remainingOf - threshold` (for
800
- * example percent remaining) while the stored trigger stays in the
801
- * runtime's "used" terms. Bounds and defaults are stored values.
802
- */
803
- remainingOf?: number;
804
- } | {
805
- kind: "play_failure";
806
- defaultFailureCount: number;
807
- } | {
808
- kind: "play_scope";
809
- } | {
810
- kind: "none";
811
- }) => {
780
+ readonly create: (input: ProductNotificationRuleInput, base: ProductNotificationRuleBase) => {
812
781
  repeatMode: "every_match";
813
782
  trigger: {
814
783
  kind: "threshold_crossing";
@@ -859,19 +828,12 @@ declare const PRODUCT_NOTIFICATION_TYPE_REGISTRY: readonly [{
859
828
  readonly eventName: "billing.plan.purchased";
860
829
  readonly requiredFilter: {};
861
830
  readonly allowedTriggers: ["each_match"];
862
- readonly catalog: {
863
- readonly name: "Plan welcome";
864
- readonly category: "credits";
865
- readonly description: "Thank the workspace when it purchases a plan.";
866
- readonly allowMultiple: false;
867
- readonly editor: {
868
- readonly kind: "none";
869
- };
870
- };
831
+ readonly catalog: undefined;
832
+ readonly shadow: true;
871
833
  readonly rule: {
872
834
  readonly default: {
873
835
  readonly ruleKey: "default.plan_purchased";
874
- readonly groupKey: "default";
836
+ readonly groupKey: "shadow";
875
837
  };
876
838
  readonly create: (_input: ProductNotificationRuleInput, base: ProductNotificationRuleBase) => {
877
839
  repeatMode: "every_match";
package/dist/index.d.ts CHANGED
@@ -770,45 +770,14 @@ declare const PRODUCT_NOTIFICATION_TYPE_REGISTRY: readonly [{
770
770
  readonly eventName: "credits.purchase.completed";
771
771
  readonly requiredFilter: {};
772
772
  readonly allowedTriggers: ["threshold_crossing"];
773
- readonly catalog: {
774
- readonly name: "Credit purchase thank-you";
775
- readonly category: "credits";
776
- readonly description: "Thank the workspace when a credit purchase of at least the chosen size completes.";
777
- readonly allowMultiple: false;
778
- readonly editor: {
779
- readonly kind: "threshold";
780
- readonly label: "Minimum credits";
781
- readonly defaultThreshold: 500;
782
- readonly minimum: 0;
783
- readonly suffix: "credits";
784
- };
785
- };
773
+ readonly catalog: undefined;
774
+ readonly shadow: true;
786
775
  readonly rule: {
787
776
  readonly default: {
788
777
  readonly ruleKey: "default.credits_purchased";
789
- readonly groupKey: "default";
778
+ readonly groupKey: "shadow";
790
779
  };
791
- readonly create: (input: ProductNotificationRuleInput, base: ProductNotificationRuleBase, editor: {
792
- kind: "threshold";
793
- label: string;
794
- defaultThreshold: number;
795
- minimum: number;
796
- maximum?: number;
797
- suffix?: string;
798
- /**
799
- * When set, editors show and accept `remainingOf - threshold` (for
800
- * example percent remaining) while the stored trigger stays in the
801
- * runtime's "used" terms. Bounds and defaults are stored values.
802
- */
803
- remainingOf?: number;
804
- } | {
805
- kind: "play_failure";
806
- defaultFailureCount: number;
807
- } | {
808
- kind: "play_scope";
809
- } | {
810
- kind: "none";
811
- }) => {
780
+ readonly create: (input: ProductNotificationRuleInput, base: ProductNotificationRuleBase) => {
812
781
  repeatMode: "every_match";
813
782
  trigger: {
814
783
  kind: "threshold_crossing";
@@ -859,19 +828,12 @@ declare const PRODUCT_NOTIFICATION_TYPE_REGISTRY: readonly [{
859
828
  readonly eventName: "billing.plan.purchased";
860
829
  readonly requiredFilter: {};
861
830
  readonly allowedTriggers: ["each_match"];
862
- readonly catalog: {
863
- readonly name: "Plan welcome";
864
- readonly category: "credits";
865
- readonly description: "Thank the workspace when it purchases a plan.";
866
- readonly allowMultiple: false;
867
- readonly editor: {
868
- readonly kind: "none";
869
- };
870
- };
831
+ readonly catalog: undefined;
832
+ readonly shadow: true;
871
833
  readonly rule: {
872
834
  readonly default: {
873
835
  readonly ruleKey: "default.plan_purchased";
874
- readonly groupKey: "default";
836
+ readonly groupKey: "shadow";
875
837
  };
876
838
  readonly create: (_input: ProductNotificationRuleInput, base: ProductNotificationRuleBase) => {
877
839
  repeatMode: "every_match";
package/dist/index.js CHANGED
@@ -864,7 +864,7 @@ var SDK_RELEASE = {
864
864
  // getters keep their established compatibility behavior.
865
865
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
866
866
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
867
- version: "0.3.142",
867
+ version: "0.3.144",
868
868
  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.",
869
869
  packageCapabilities: {
870
870
  updatePreferences: 1
package/dist/index.mjs CHANGED
@@ -768,7 +768,7 @@ var SDK_RELEASE = {
768
768
  // getters keep their established compatibility behavior.
769
769
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
770
770
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
771
- version: "0.3.142",
771
+ version: "0.3.144",
772
772
  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.",
773
773
  packageCapabilities: {
774
774
  updatePreferences: 1
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.142";
152
+ readonly version: "0.3.144";
153
153
  readonly 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.";
154
154
  readonly packageCapabilities: {
155
155
  readonly updatePreferences: 1;
package/dist/release.d.ts CHANGED
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.142";
152
+ readonly version: "0.3.144";
153
153
  readonly 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.";
154
154
  readonly packageCapabilities: {
155
155
  readonly updatePreferences: 1;
package/dist/release.js CHANGED
@@ -74,7 +74,7 @@ var SDK_RELEASE = {
74
74
  // getters keep their established compatibility behavior.
75
75
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
76
76
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
77
- version: "0.3.142",
77
+ version: "0.3.144",
78
78
  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.",
79
79
  packageCapabilities: {
80
80
  updatePreferences: 1
package/dist/release.mjs CHANGED
@@ -48,7 +48,7 @@ var SDK_RELEASE = {
48
48
  // getters keep their established compatibility behavior.
49
49
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
50
50
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
51
- version: "0.3.142",
51
+ version: "0.3.144",
52
52
  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.",
53
53
  packageCapabilities: {
54
54
  updatePreferences: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.3.142",
3
+ "version": "0.3.144",
4
4
  "description": "GTM data CLI and TypeScript SDK for coding agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://code.deepline.com",