deepline 0.3.148 → 0.3.150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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.148",
771
+ version: "0.3.150",
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
@@ -1509,6 +1509,11 @@ var HttpClient = class {
1509
1509
  body: options?.formData !== void 0 ? typeof options.formData === "function" ? options.formData() : options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
1510
1510
  signal: controller.signal
1511
1511
  });
1512
+ options?.onResponse?.(response);
1513
+ if (response.status === 404 && options?.allowNotFound) {
1514
+ clearTimeout(timeoutId);
1515
+ return null;
1516
+ }
1512
1517
  clearTimeout(timeoutId);
1513
1518
  const body = await response.text();
1514
1519
  const parsed = parseResponseBody(body);
@@ -1648,7 +1653,8 @@ var HttpClient = class {
1648
1653
  retryAfterMs: null,
1649
1654
  networkKind: code === "NETWORK_TIMEOUT" ? "timeout" : code === "NETWORK_ABORTED" ? "unknown" : "unavailable",
1650
1655
  networkScope: "client_to_deepline",
1651
- details: mappedNetworkError.details
1656
+ details: mappedNetworkError.details,
1657
+ publicDetails: options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : null
1652
1658
  }
1653
1659
  ),
1654
1660
  lastError
@@ -4127,6 +4133,56 @@ var MONITOR_NON_RETRYABLE_MUTATION_OPTIONS = {
4127
4133
  exactUrlOnly: true
4128
4134
  };
4129
4135
  var RAW_V2_EXECUTE_RESPONSE_CONTRACT = RAW_V2_TOOL_RESPONSE_CONTRACT;
4136
+ var DEFAULT_EXECUTION_RECOVERY_TIMEOUT_MS = 15 * 60 * 1e3;
4137
+ function validateExecutionIdempotencyKey(key) {
4138
+ if (typeof key !== "string" || key.length < 1 || key.length > 200 || !/^[A-Za-z0-9._:-]+$/.test(key)) {
4139
+ throw new DeeplineError(
4140
+ "Execution idempotency keys must be 1\u2013200 ASCII letters, digits, dots, underscores, colons, or hyphens.",
4141
+ void 0,
4142
+ "IDEMPOTENCY_KEY_INVALID"
4143
+ );
4144
+ }
4145
+ }
4146
+ function isExecutionInProgressResponse(value) {
4147
+ return typeof value === "object" && value !== null && typeof value.executionRecovery === "object" && value.executionRecovery.state === "running";
4148
+ }
4149
+ function getExecutionRecoveryState(value) {
4150
+ if (typeof value !== "object" || value === null || typeof value.executionRecovery !== "object") {
4151
+ return null;
4152
+ }
4153
+ const state = value.executionRecovery.state;
4154
+ return state === "running" || state === "completed" || state === "outcome_unknown" ? state : null;
4155
+ }
4156
+ function isRecoverableExecutionAttemptError(error) {
4157
+ if (error instanceof ToolExecutionError) {
4158
+ return error.code === "EXECUTION_IN_PROGRESS" || error.origin === "deepline" && error.category === "network" && error.networkScope === "client_to_deepline";
4159
+ }
4160
+ return error instanceof DeeplineError && (error.code === "EXECUTION_IN_PROGRESS" || error.code?.startsWith("NETWORK_") === true && error.statusCode === void 0);
4161
+ }
4162
+ function isRecoverableExecutionLookupError(error) {
4163
+ if (isRecoverableExecutionAttemptError(error)) return true;
4164
+ return error instanceof DeeplineError && (error.statusCode === 429 || error.statusCode !== void 0 && error.statusCode >= 500);
4165
+ }
4166
+ function timeoutWithinRecoveryBudget(requestTimeoutMs, defaultRequestTimeoutMs, remainingMs) {
4167
+ return Math.min(requestTimeoutMs ?? defaultRequestTimeoutMs, remainingMs);
4168
+ }
4169
+ function executionRecoveryError(input) {
4170
+ return new ToolExecutionError(input.message, {
4171
+ toolId: input.toolId,
4172
+ provider: null,
4173
+ operation: input.toolId,
4174
+ code: input.code,
4175
+ origin: "deepline",
4176
+ category: input.code === "EXECUTION_OUTCOME_UNKNOWN" ? "unknown" : "conflict",
4177
+ retryable: input.code !== "EXECUTION_OUTCOME_UNKNOWN",
4178
+ statusCode: null,
4179
+ requestId: null,
4180
+ retryAfterMs: null,
4181
+ networkKind: null,
4182
+ networkScope: null,
4183
+ publicDetails: { idempotencyKey: input.idempotencyKey }
4184
+ });
4185
+ }
4130
4186
  var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
4131
4187
  var REGISTER_PLAY_ARTIFACTS_COMPILE_CONCURRENCY = 3;
4132
4188
  var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_COUNT = 3;
@@ -5061,29 +5117,183 @@ var DeeplineClient = class _DeeplineClient {
5061
5117
  * Deepline execution envelope.
5062
5118
  */
5063
5119
  async executeTool(toolId, input, options) {
5120
+ const inputSnapshot = JSON.parse(JSON.stringify(input));
5121
+ const metadataSnapshot = options?.metadata ? JSON.parse(JSON.stringify(options.metadata)) : void 0;
5122
+ const idempotencyKey = options?.idempotencyKey ?? (options?.recover ? crypto.randomUUID() : void 0);
5123
+ if (idempotencyKey !== void 0) {
5124
+ validateExecutionIdempotencyKey(idempotencyKey);
5125
+ if (options?.recoveryTimeoutMs !== void 0 && (!Number.isFinite(options.recoveryTimeoutMs) || options.recoveryTimeoutMs < 0)) {
5126
+ throw new DeeplineError(
5127
+ "recoveryTimeoutMs must be a finite, non-negative number.",
5128
+ void 0,
5129
+ "IDEMPOTENCY_KEY_INVALID"
5130
+ );
5131
+ }
5132
+ await options?.onExecution?.({ idempotencyKey });
5133
+ const timeoutMs2 = options?.timeout ?? resolveToolExecuteTimeoutMs(toolId, inputSnapshot);
5134
+ await this.lookupExecutionByKey(idempotencyKey, timeoutMs2);
5135
+ }
5136
+ const timeoutMs = options?.timeout ?? resolveToolExecuteTimeoutMs(toolId, inputSnapshot);
5064
5137
  const headers = {
5065
5138
  [EXECUTE_RESPONSE_CONTRACT_HEADER]: RAW_V2_EXECUTE_RESPONSE_CONTRACT,
5066
5139
  [TOOL_EXECUTION_ERROR_SCHEMA_HEADER]: String(
5067
5140
  TOOL_EXECUTION_ERROR_SCHEMA_VERSION
5068
5141
  ),
5069
5142
  ...options?.includeToolMetadata ? { [INCLUDE_TOOL_METADATA_HEADER]: "true" } : {},
5070
- [EXECUTE_RESPONSE_INTENT_HEADER]: options?.responseIntent ?? "raw"
5143
+ [EXECUTE_RESPONSE_INTENT_HEADER]: options?.responseIntent ?? "raw",
5144
+ ...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
5071
5145
  };
5072
- const response = await this.http.post(
5146
+ const request = (requestTimeoutMs) => this.http.post(
5073
5147
  `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
5074
5148
  {
5075
- payload: input,
5076
- ...options?.metadata ? { metadata: options.metadata } : {}
5149
+ payload: inputSnapshot,
5150
+ ...metadataSnapshot ? { metadata: metadataSnapshot } : {}
5077
5151
  },
5078
5152
  headers,
5079
5153
  {
5080
- timeout: options?.timeout ?? resolveToolExecuteTimeoutMs(toolId, input),
5081
- maxRetries: options?.maxRetries ?? 0,
5154
+ timeout: requestTimeoutMs,
5155
+ maxRetries: idempotencyKey ? 0 : options?.maxRetries ?? 0,
5156
+ exactUrlOnly: true,
5157
+ toolId,
5158
+ idempotencyKey
5159
+ }
5160
+ );
5161
+ let response;
5162
+ let recoveryDeadline = null;
5163
+ const recoveryTimeoutMs = options?.recoveryTimeoutMs ?? DEFAULT_EXECUTION_RECOVERY_TIMEOUT_MS;
5164
+ let retryDelayMs = 1e3;
5165
+ const recoveryTimeoutError = () => executionRecoveryError({
5166
+ toolId,
5167
+ idempotencyKey,
5168
+ code: "EXECUTION_RECOVERY_TIMEOUT",
5169
+ message: `Execution recovery for ${idempotencyKey} did not finish before the recovery timeout. Inspect client.executions.getByKey() and resume with the same idempotency key.`
5170
+ });
5171
+ const waitForRecoveryRetry = async (deadline) => {
5172
+ const remainingMs = deadline - Date.now();
5173
+ if (remainingMs <= 0) throw recoveryTimeoutError();
5174
+ await new Promise(
5175
+ (resolve2) => setTimeout(resolve2, Math.min(retryDelayMs, remainingMs))
5176
+ );
5177
+ retryDelayMs = Math.min(retryDelayMs * 2, 5e3);
5178
+ };
5179
+ const lookupDuringRecovery = async () => {
5180
+ while (true) {
5181
+ const remainingMs = recoveryDeadline - Date.now();
5182
+ if (remainingMs <= 0) throw recoveryTimeoutError();
5183
+ try {
5184
+ return await this.lookupExecutionByKey(
5185
+ idempotencyKey,
5186
+ timeoutWithinRecoveryBudget(
5187
+ timeoutMs,
5188
+ this.config.timeout,
5189
+ remainingMs
5190
+ )
5191
+ );
5192
+ } catch (error) {
5193
+ if (!isRecoverableExecutionLookupError(error)) throw error;
5194
+ await waitForRecoveryRetry(recoveryDeadline);
5195
+ }
5196
+ }
5197
+ };
5198
+ while (true) {
5199
+ const remainingMs = recoveryDeadline === null ? null : recoveryDeadline - Date.now();
5200
+ if (remainingMs !== null && remainingMs <= 0) {
5201
+ throw recoveryTimeoutError();
5202
+ }
5203
+ try {
5204
+ response = await request(
5205
+ remainingMs === null ? timeoutMs : timeoutWithinRecoveryBudget(
5206
+ timeoutMs,
5207
+ this.config.timeout,
5208
+ remainingMs
5209
+ )
5210
+ );
5211
+ if (getExecutionRecoveryState(response) === "outcome_unknown") {
5212
+ if (!idempotencyKey) break;
5213
+ throw executionRecoveryError({
5214
+ toolId,
5215
+ idempotencyKey,
5216
+ code: "EXECUTION_OUTCOME_UNKNOWN",
5217
+ message: `The outcome of execution ${idempotencyKey} is unknown. Do not retry with a new key; inspect client.executions.getByKey().`
5218
+ });
5219
+ }
5220
+ if (!idempotencyKey || !isExecutionInProgressResponse(response)) {
5221
+ break;
5222
+ }
5223
+ if (recoveryDeadline === null) {
5224
+ recoveryDeadline = Date.now() + recoveryTimeoutMs;
5225
+ }
5226
+ } catch (error) {
5227
+ if (idempotencyKey && error instanceof DeeplineError && error.code === "EXECUTION_OUTCOME_UNKNOWN") {
5228
+ throw executionRecoveryError({
5229
+ toolId,
5230
+ idempotencyKey,
5231
+ code: "EXECUTION_OUTCOME_UNKNOWN",
5232
+ message: error.message
5233
+ });
5234
+ }
5235
+ if (!idempotencyKey || !isRecoverableExecutionAttemptError(error)) {
5236
+ throw error;
5237
+ }
5238
+ if (recoveryDeadline === null) {
5239
+ recoveryDeadline = Date.now() + recoveryTimeoutMs;
5240
+ }
5241
+ }
5242
+ await waitForRecoveryRetry(recoveryDeadline);
5243
+ const recovered = await lookupDuringRecovery();
5244
+ if (getExecutionRecoveryState(recovered) === "outcome_unknown") {
5245
+ throw executionRecoveryError({
5246
+ toolId,
5247
+ idempotencyKey,
5248
+ code: "EXECUTION_OUTCOME_UNKNOWN",
5249
+ message: `The outcome of execution ${idempotencyKey} is unknown. Do not retry with a new key; inspect client.executions.getByKey().`
5250
+ });
5251
+ }
5252
+ }
5253
+ const materialized = materializeToolExecutionResponse(response);
5254
+ return idempotencyKey ? { ...materialized, idempotencyKey } : materialized;
5255
+ }
5256
+ /** Read the durable state of a keyed tool execution. */
5257
+ async getExecutionByKey(idempotencyKey) {
5258
+ validateExecutionIdempotencyKey(idempotencyKey);
5259
+ const result = await this.lookupExecutionByKey(idempotencyKey);
5260
+ if (!result) {
5261
+ throw new DeeplineError(
5262
+ `No execution exists for idempotency key ${idempotencyKey}.`,
5263
+ 404,
5264
+ "EXECUTION_NOT_FOUND"
5265
+ );
5266
+ }
5267
+ return result;
5268
+ }
5269
+ async lookupExecutionByKey(idempotencyKey, timeoutMs) {
5270
+ validateExecutionIdempotencyKey(idempotencyKey);
5271
+ let supported = false;
5272
+ const result = await this.http.get(
5273
+ `/api/v2/executions/by-key/${encodeURIComponent(idempotencyKey)}`,
5274
+ {
5082
5275
  exactUrlOnly: true,
5083
- toolId
5276
+ maxRetries: 0,
5277
+ timeout: timeoutMs,
5278
+ idempotencyKey,
5279
+ allowNotFound: true,
5280
+ onResponse: (response) => {
5281
+ supported = response.headers.get("X-Deepline-Idempotency-Supported") === "true";
5282
+ }
5084
5283
  }
5085
5284
  );
5086
- return materializeToolExecutionResponse(response);
5285
+ if (!supported) {
5286
+ throw new DeeplineError(
5287
+ "This Deepline server does not support recoverable tool executions; no tool was dispatched.",
5288
+ 422,
5289
+ "IDEMPOTENCY_NOT_SUPPORTED"
5290
+ );
5291
+ }
5292
+ return result;
5293
+ }
5294
+ /** Public recovery namespace. */
5295
+ get executions() {
5296
+ return { getByKey: (key) => this.getExecutionByKey(key) };
5087
5297
  }
5088
5298
  /**
5089
5299
  * Back-compatible alias for {@link executeTool}.
@@ -11170,10 +11380,11 @@ var DeeplineContext = class {
11170
11380
  /** Get detailed metadata for a tool. */
11171
11381
  get: (toolId) => this.client.getTool(toolId),
11172
11382
  /** Execute a tool and return the standard execution envelope. */
11173
- execute: async (toolId, input) => {
11383
+ execute: async (toolId, input, options) => {
11174
11384
  const response = await this.client.executeTool(toolId, input, {
11175
11385
  includeToolMetadata: true,
11176
- responseIntent: "dataset"
11386
+ responseIntent: "dataset",
11387
+ ...options
11177
11388
  });
11178
11389
  return toolExecutionEnvelopeToResult(toolId, response, {
11179
11390
  client: this.client,
@@ -11182,6 +11393,10 @@ var DeeplineContext = class {
11182
11393
  }
11183
11394
  };
11184
11395
  }
11396
+ /** Durable state for recoverable direct tool executions. */
11397
+ get executions() {
11398
+ return { getByKey: (key) => this.client.getExecutionByKey(key) };
11399
+ }
11185
11400
  /**
11186
11401
  * Play discovery and named-play handles.
11187
11402
  *
@@ -11489,7 +11704,7 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
11489
11704
  const meta = response.toolResponse?.meta;
11490
11705
  const metadata = isRecord9(response._metadata) ? response._metadata.tool : null;
11491
11706
  const toolMetadata = isRecord9(metadata) ? metadata : {};
11492
- return attachSdkQueryResultDatasetResult(
11707
+ const result = attachSdkQueryResultDatasetResult(
11493
11708
  fallbackToolId,
11494
11709
  createToolExecuteResult({
11495
11710
  status: typeof response.status === "string" ? response.status : "completed",
@@ -11522,6 +11737,14 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response, options) {
11522
11737
  }),
11523
11738
  options
11524
11739
  );
11740
+ const executionRecovery = isRecord9(response.executionRecovery) ? response.executionRecovery : void 0;
11741
+ if (typeof response.idempotencyKey === "string") {
11742
+ result.idempotencyKey = response.idempotencyKey;
11743
+ }
11744
+ if (executionRecovery) {
11745
+ result.executionRecovery = executionRecovery;
11746
+ }
11747
+ return result;
11525
11748
  }
11526
11749
  function defineInput(schema) {
11527
11750
  return createPlayInputContract(schema);
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.148";
152
+ readonly version: "0.3.150";
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.148";
152
+ readonly version: "0.3.150";
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.148",
77
+ version: "0.3.150",
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.148",
51
+ version: "0.3.150",
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.148",
3
+ "version": "0.3.150",
4
4
  "description": "GTM data CLI and TypeScript SDK for coding agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://code.deepline.com",