deepline 0.1.150 → 0.1.151

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 (23) hide show
  1. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +157 -140
  2. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/csv-rows.ts +2 -19
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/row-isolation.ts +5 -53
  4. package/dist/bundling-sources/sdk/src/config.ts +2 -2
  5. package/dist/bundling-sources/sdk/src/release.ts +2 -2
  6. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +100 -158
  7. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +3 -0
  8. package/dist/bundling-sources/shared_libs/play-runtime/durability-store.ts +54 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/map-row-outcome.ts +167 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/pacing.ts +79 -0
  11. package/dist/bundling-sources/shared_libs/play-runtime/row-isolation.ts +39 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +19 -86
  13. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +90 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-session.ts +43 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +142 -11
  16. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +3 -2
  17. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +20 -23
  18. package/dist/cli/index.js +35 -3
  19. package/dist/cli/index.mjs +35 -3
  20. package/dist/index.js +3 -3
  21. package/dist/index.mjs +3 -3
  22. package/dist/plays/bundle-play-file.mjs +22 -19
  23. package/package.json +1 -1
@@ -1,7 +1,15 @@
1
- export const TOOL_EXECUTE_TRANSIENT_HTTP_MAX_ATTEMPTS = 3;
1
+ import {
2
+ isHardBillingToolHttpError,
3
+ normalizeToolHttpErrorMessage,
4
+ type ToolHttpError,
5
+ } from './tool-http-errors';
6
+
7
+ export const TOOL_EXECUTE_TRANSIENT_HTTP_MAX_ATTEMPTS = 2;
2
8
  export const TOOL_EXECUTE_RATE_LIMIT_MAX_ATTEMPTS = 8;
3
9
  export const TOOL_EXECUTE_TRANSPORT_MAX_ATTEMPTS = 3;
4
10
  export const TOOL_EXECUTE_TRANSPORT_RETRY_DELAY_MS = 1_000;
11
+ export const TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS = 1_000;
12
+ export const TOOL_EXECUTE_RETRY_DELAY_MAX_MS = 5_000;
5
13
 
6
14
  export type ToolExecuteHttpRetryDecision = {
7
15
  retryable: boolean;
@@ -9,15 +17,33 @@ export type ToolExecuteHttpRetryDecision = {
9
17
  reason:
10
18
  | 'rate_limit'
11
19
  | 'retry_safe_transient_5xx'
12
- | 'hard_billing_error'
13
20
  | 'unsafe_transient_5xx'
21
+ | 'hard_billing_error'
14
22
  | 'non_retryable_status';
15
23
  };
16
24
 
17
- export function decideToolExecuteHttpRetry(input: {
18
- toolId: string;
25
+ export type ToolExecuteHttpFailureOutcome = ToolExecuteHttpRetryDecision & {
26
+ error: ToolHttpError;
27
+ shouldRetry: boolean;
28
+ isRateLimit: boolean;
29
+ fate: 'retry' | 'settle_row_failure' | 'fail_run';
30
+ retryDelayMs: number;
31
+ backpressureDelayMs: number | null;
32
+ chargeRetryBudget: boolean;
33
+ };
34
+
35
+ export type ToolExecuteHttpFailureAttemptTracker = {
36
+ next(input: {
37
+ toolId: string;
38
+ status: number;
39
+ transientHttpRetrySafe?: boolean;
40
+ }): number;
41
+ };
42
+
43
+ function decideToolExecuteHttpRetry(input: {
19
44
  status: number;
20
45
  hardBillingFailure?: boolean;
46
+ transientHttpRetrySafe?: boolean;
21
47
  }): ToolExecuteHttpRetryDecision {
22
48
  if (input.status === 429) {
23
49
  if (input.hardBillingFailure) {
@@ -34,17 +60,17 @@ export function decideToolExecuteHttpRetry(input: {
34
60
  };
35
61
  }
36
62
  if (input.status >= 500 && input.status < 600) {
37
- if (input.toolId === 'test_transient_500') {
63
+ if (!input.transientHttpRetrySafe) {
38
64
  return {
39
- retryable: true,
40
- attemptCap: TOOL_EXECUTE_TRANSIENT_HTTP_MAX_ATTEMPTS,
41
- reason: 'retry_safe_transient_5xx',
65
+ retryable: false,
66
+ attemptCap: 1,
67
+ reason: 'unsafe_transient_5xx',
42
68
  };
43
69
  }
44
70
  return {
45
- retryable: false,
46
- attemptCap: 1,
47
- reason: 'unsafe_transient_5xx',
71
+ retryable: true,
72
+ attemptCap: TOOL_EXECUTE_TRANSIENT_HTTP_MAX_ATTEMPTS,
73
+ reason: 'retry_safe_transient_5xx',
48
74
  };
49
75
  }
50
76
  return {
@@ -53,3 +79,108 @@ export function decideToolExecuteHttpRetry(input: {
53
79
  reason: 'non_retryable_status',
54
80
  };
55
81
  }
82
+
83
+ export function createToolExecuteHttpFailureAttemptTracker(): ToolExecuteHttpFailureAttemptTracker {
84
+ const attemptsByReason: Record<
85
+ ToolExecuteHttpRetryDecision['reason'],
86
+ number
87
+ > = {
88
+ rate_limit: 0,
89
+ retry_safe_transient_5xx: 0,
90
+ unsafe_transient_5xx: 0,
91
+ hard_billing_error: 0,
92
+ non_retryable_status: 0,
93
+ };
94
+
95
+ return {
96
+ next(input) {
97
+ const decision = decideToolExecuteHttpRetry({
98
+ status: input.status,
99
+ transientHttpRetrySafe: input.transientHttpRetrySafe === true,
100
+ });
101
+ attemptsByReason[decision.reason] += 1;
102
+ return attemptsByReason[decision.reason];
103
+ },
104
+ };
105
+ }
106
+
107
+ export function parseToolExecuteRetryAfterMs(
108
+ header: string | null | undefined,
109
+ nowMs = Date.now(),
110
+ ): number {
111
+ if (!header) return TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
112
+ const seconds = Number(header);
113
+ if (Number.isFinite(seconds) && seconds > 0) {
114
+ return Math.ceil(seconds * 1000);
115
+ }
116
+ const retryAt = Date.parse(header);
117
+ if (Number.isFinite(retryAt)) {
118
+ return Math.max(1, retryAt - nowMs);
119
+ }
120
+ return TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
121
+ }
122
+
123
+ export function classifyToolExecuteHttpFailure(input: {
124
+ toolId: string;
125
+ status: number;
126
+ attempt: number;
127
+ bodyText: string;
128
+ retryAfterHeader?: string | null;
129
+ transientHttpRetrySafe?: boolean;
130
+ nowMs?: number;
131
+ }): ToolExecuteHttpFailureOutcome {
132
+ const transientHttpRetrySafe = input.transientHttpRetrySafe === true;
133
+ const initialRetryDecision = decideToolExecuteHttpRetry({
134
+ status: input.status,
135
+ transientHttpRetrySafe,
136
+ });
137
+ const error = normalizeToolHttpErrorMessage({
138
+ toolId: input.toolId,
139
+ status: input.status,
140
+ attempt: input.attempt,
141
+ maxAttempts: initialRetryDecision.attemptCap,
142
+ bodyText: input.bodyText,
143
+ });
144
+ const retryDecision = decideToolExecuteHttpRetry({
145
+ status: input.status,
146
+ hardBillingFailure: isHardBillingToolHttpError(error),
147
+ transientHttpRetrySafe,
148
+ });
149
+ const shouldRetry =
150
+ retryDecision.retryable && input.attempt < retryDecision.attemptCap;
151
+ const retryAfterMs = parseToolExecuteRetryAfterMs(
152
+ input.retryAfterHeader,
153
+ input.nowMs,
154
+ );
155
+ const retryDelayMs =
156
+ input.status === 429
157
+ ? Math.min(
158
+ TOOL_EXECUTE_RETRY_DELAY_MAX_MS,
159
+ Math.max(
160
+ retryAfterMs,
161
+ TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS * input.attempt,
162
+ ),
163
+ )
164
+ : retryAfterMs > 0
165
+ ? Math.min(TOOL_EXECUTE_RETRY_DELAY_MAX_MS, retryAfterMs)
166
+ : TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
167
+ return {
168
+ ...retryDecision,
169
+ error,
170
+ shouldRetry,
171
+ isRateLimit: input.status === 429,
172
+ fate: shouldRetry
173
+ ? 'retry'
174
+ : retryDecision.reason === 'hard_billing_error'
175
+ ? 'fail_run'
176
+ : 'settle_row_failure',
177
+ retryDelayMs,
178
+ backpressureDelayMs:
179
+ input.status === 429
180
+ ? retryAfterMs > 0
181
+ ? retryAfterMs
182
+ : TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS
183
+ : null,
184
+ chargeRetryBudget: shouldRetry,
185
+ };
186
+ }
@@ -240,8 +240,9 @@ export function isHardBillingToolHttpError(error: unknown): boolean {
240
240
 
241
241
  /**
242
242
  * A tool call that ultimately failed with HTTP 429 — provider or
243
- * Deepline-internal rate-limit pushback that survived the in-process retry
244
- * budget. This is run-level throughput pressure, never a row-specific defect.
243
+ * Deepline-internal rate-limit pushback. While the local retry budget is
244
+ * active it feeds provider pacing; after exhaustion it becomes a row-scoped
245
+ * Map Row Outcome unless the payload is a hard Deepline billing failure.
245
246
  */
246
247
  export function isRateLimitToolHttpError(error: unknown): boolean {
247
248
  return error instanceof ToolHttpError && error.status === 429;
@@ -1513,18 +1513,28 @@ async function computeWorkersHarnessFingerprintWithAdapter(
1513
1513
  hash: sha256(contents),
1514
1514
  });
1515
1515
  };
1516
- const collectTopLevelTsFiles = async (
1516
+ const collectTsFilesRecursive = async (
1517
1517
  rootDir: string,
1518
1518
  parts: Array<{ name: string; hash: string }>,
1519
1519
  ) => {
1520
1520
  if (!(await fileExists(rootDir))) return;
1521
- const entries = await readdir(rootDir, { withFileTypes: true });
1522
- const tsFiles = entries
1523
- .filter((entry) => entry.isFile() && /\.[cm]?ts$/.test(entry.name))
1524
- .map((entry) => entry.name)
1525
- .sort();
1526
- for (const name of tsFiles) {
1527
- await addFilePart(parts, rootDir, join(rootDir, name));
1521
+ const filePaths: string[] = [];
1522
+ const visitDir = async (dir: string) => {
1523
+ const entries = await readdir(dir, { withFileTypes: true });
1524
+ for (const entry of entries) {
1525
+ const childPath = join(dir, entry.name);
1526
+ if (entry.isDirectory()) {
1527
+ await visitDir(childPath);
1528
+ continue;
1529
+ }
1530
+ if (entry.isFile() && /\.[cm]?ts$/.test(entry.name)) {
1531
+ filePaths.push(childPath);
1532
+ }
1533
+ }
1534
+ };
1535
+ await visitDir(rootDir);
1536
+ for (const filePath of filePaths.sort()) {
1537
+ await addFilePart(parts, rootDir, filePath);
1528
1538
  }
1529
1539
  };
1530
1540
  const collectIntegrationBatchingFiles = async (
@@ -1554,26 +1564,13 @@ async function computeWorkersHarnessFingerprintWithAdapter(
1554
1564
  }
1555
1565
  };
1556
1566
 
1557
- const entries = await readdir(adapter.workersHarnessFilesDir, {
1558
- withFileTypes: true,
1559
- });
1560
- const tsFiles = entries
1561
- .filter((e) => e.isFile() && /\.[cm]?ts$/.test(e.name))
1562
- .map((e) => e.name)
1563
- .sort();
1564
1567
  const parts: Array<{ name: string; hash: string }> = [];
1565
- for (const name of tsFiles) {
1566
- await addFilePart(
1567
- parts,
1568
- adapter.workersHarnessFilesDir,
1569
- join(adapter.workersHarnessFilesDir, name),
1570
- );
1571
- }
1568
+ await collectTsFilesRecursive(adapter.workersHarnessFilesDir, parts);
1572
1569
  for (const dir of adapter.workersRuntimeFingerprintDirs ?? []) {
1573
1570
  if (basename(dir) === 'integrations') {
1574
1571
  await collectIntegrationBatchingFiles(dir, parts);
1575
1572
  } else {
1576
- await collectTopLevelTsFiles(dir, parts);
1573
+ await collectTsFilesRecursive(dir, parts);
1577
1574
  }
1578
1575
  }
1579
1576
  return sha256(JSON.stringify(parts));
package/dist/cli/index.js CHANGED
@@ -420,7 +420,7 @@ function loadProjectEnvCandidates(startDir = process.cwd()) {
420
420
  }));
421
421
  }
422
422
  function normalizeBaseUrl(baseUrl) {
423
- const trimmed = baseUrl.trim().replace(/\/+$/, "");
423
+ const trimmed = baseUrl?.trim().replace(/\/+$/, "") ?? "";
424
424
  if (!trimmed) return "";
425
425
  try {
426
426
  const parsed = new URL(trimmed);
@@ -655,10 +655,10 @@ var SDK_RELEASE = {
655
655
  // the SDK enrich generator's one-second stale policy.
656
656
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
657
657
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
658
- version: "0.1.150",
658
+ version: "0.1.151",
659
659
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
660
660
  supportPolicy: {
661
- latest: "0.1.150",
661
+ latest: "0.1.151",
662
662
  minimumSupported: "0.1.53",
663
663
  deprecatedBelow: "0.1.53",
664
664
  commandMinimumSupported: [
@@ -10790,6 +10790,23 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
10790
10790
  },
10791
10791
  Math.max(1, input2.waitTimeoutMs)
10792
10792
  );
10793
+ const fetchKnownTerminalStatus = async () => {
10794
+ if (!lastKnownWorkflowId) {
10795
+ return null;
10796
+ }
10797
+ let refreshed;
10798
+ try {
10799
+ refreshed = await input2.client.getPlayStatus(lastKnownWorkflowId, {
10800
+ billing: false
10801
+ });
10802
+ } catch (error) {
10803
+ if (isTransientPlayStreamError(error)) {
10804
+ return null;
10805
+ }
10806
+ throw error;
10807
+ }
10808
+ return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? { ...refreshed, dashboardUrl } : null;
10809
+ };
10793
10810
  try {
10794
10811
  for await (const event of input2.client.startPlayRunStream(input2.request, {
10795
10812
  signal: controller.signal
@@ -10885,6 +10902,21 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
10885
10902
  }
10886
10903
  } catch (error) {
10887
10904
  if (timedOut) {
10905
+ const terminal = await fetchKnownTerminalStatus();
10906
+ if (terminal) {
10907
+ recordCliTrace({
10908
+ phase: "cli.play_start_stream_timeout_status_reconcile",
10909
+ ms: Date.now() - startedAt,
10910
+ ok: true,
10911
+ playName: input2.playName,
10912
+ workflowId: lastKnownWorkflowId,
10913
+ eventCount,
10914
+ firstRunIdMs,
10915
+ lastPhase,
10916
+ status: terminal.status
10917
+ });
10918
+ return terminal;
10919
+ }
10888
10920
  assertPlayWaitNotTimedOut({
10889
10921
  workflowId: lastKnownWorkflowId,
10890
10922
  startedAt,
@@ -405,7 +405,7 @@ function loadProjectEnvCandidates(startDir = process.cwd()) {
405
405
  }));
406
406
  }
407
407
  function normalizeBaseUrl(baseUrl) {
408
- const trimmed = baseUrl.trim().replace(/\/+$/, "");
408
+ const trimmed = baseUrl?.trim().replace(/\/+$/, "") ?? "";
409
409
  if (!trimmed) return "";
410
410
  try {
411
411
  const parsed = new URL(trimmed);
@@ -640,10 +640,10 @@ var SDK_RELEASE = {
640
640
  // the SDK enrich generator's one-second stale policy.
641
641
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
642
642
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
643
- version: "0.1.150",
643
+ version: "0.1.151",
644
644
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
645
645
  supportPolicy: {
646
- latest: "0.1.150",
646
+ latest: "0.1.151",
647
647
  minimumSupported: "0.1.53",
648
648
  deprecatedBelow: "0.1.53",
649
649
  commandMinimumSupported: [
@@ -10807,6 +10807,23 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
10807
10807
  },
10808
10808
  Math.max(1, input2.waitTimeoutMs)
10809
10809
  );
10810
+ const fetchKnownTerminalStatus = async () => {
10811
+ if (!lastKnownWorkflowId) {
10812
+ return null;
10813
+ }
10814
+ let refreshed;
10815
+ try {
10816
+ refreshed = await input2.client.getPlayStatus(lastKnownWorkflowId, {
10817
+ billing: false
10818
+ });
10819
+ } catch (error) {
10820
+ if (isTransientPlayStreamError(error)) {
10821
+ return null;
10822
+ }
10823
+ throw error;
10824
+ }
10825
+ return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? { ...refreshed, dashboardUrl } : null;
10826
+ };
10810
10827
  try {
10811
10828
  for await (const event of input2.client.startPlayRunStream(input2.request, {
10812
10829
  signal: controller.signal
@@ -10902,6 +10919,21 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
10902
10919
  }
10903
10920
  } catch (error) {
10904
10921
  if (timedOut) {
10922
+ const terminal = await fetchKnownTerminalStatus();
10923
+ if (terminal) {
10924
+ recordCliTrace({
10925
+ phase: "cli.play_start_stream_timeout_status_reconcile",
10926
+ ms: Date.now() - startedAt,
10927
+ ok: true,
10928
+ playName: input2.playName,
10929
+ workflowId: lastKnownWorkflowId,
10930
+ eventCount,
10931
+ firstRunIdMs,
10932
+ lastPhase,
10933
+ status: terminal.status
10934
+ });
10935
+ return terminal;
10936
+ }
10905
10937
  assertPlayWaitNotTimedOut({
10906
10938
  workflowId: lastKnownWorkflowId,
10907
10939
  startedAt,
package/dist/index.js CHANGED
@@ -308,7 +308,7 @@ function loadProjectEnvCandidates(startDir = process.cwd()) {
308
308
  }));
309
309
  }
310
310
  function normalizeBaseUrl(baseUrl) {
311
- const trimmed = baseUrl.trim().replace(/\/+$/, "");
311
+ const trimmed = baseUrl?.trim().replace(/\/+$/, "") ?? "";
312
312
  if (!trimmed) return "";
313
313
  try {
314
314
  const parsed = new URL(trimmed);
@@ -419,10 +419,10 @@ var SDK_RELEASE = {
419
419
  // the SDK enrich generator's one-second stale policy.
420
420
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
421
421
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
422
- version: "0.1.150",
422
+ version: "0.1.151",
423
423
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
424
424
  supportPolicy: {
425
- latest: "0.1.150",
425
+ latest: "0.1.151",
426
426
  minimumSupported: "0.1.53",
427
427
  deprecatedBelow: "0.1.53",
428
428
  commandMinimumSupported: [
package/dist/index.mjs CHANGED
@@ -238,7 +238,7 @@ function loadProjectEnvCandidates(startDir = process.cwd()) {
238
238
  }));
239
239
  }
240
240
  function normalizeBaseUrl(baseUrl) {
241
- const trimmed = baseUrl.trim().replace(/\/+$/, "");
241
+ const trimmed = baseUrl?.trim().replace(/\/+$/, "") ?? "";
242
242
  if (!trimmed) return "";
243
243
  try {
244
244
  const parsed = new URL(trimmed);
@@ -349,10 +349,10 @@ var SDK_RELEASE = {
349
349
  // the SDK enrich generator's one-second stale policy.
350
350
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
351
351
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
352
- version: "0.1.150",
352
+ version: "0.1.151",
353
353
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
354
354
  supportPolicy: {
355
- latest: "0.1.150",
355
+ latest: "0.1.151",
356
356
  minimumSupported: "0.1.53",
357
357
  deprecatedBelow: "0.1.53",
358
358
  commandMinimumSupported: [
@@ -1120,19 +1120,32 @@ async function computeWorkersHarnessFingerprintWithAdapter(adapter) {
1120
1120
  hash: sha256(contents)
1121
1121
  });
1122
1122
  };
1123
- const collectTopLevelTsFiles = async (rootDir, parts2) => {
1123
+ const collectTsFilesRecursive = async (rootDir, parts2) => {
1124
1124
  if (!await fileExists(rootDir)) return;
1125
- const entries2 = await readdir(rootDir, { withFileTypes: true });
1126
- const tsFiles2 = entries2.filter((entry) => entry.isFile() && /\.[cm]?ts$/.test(entry.name)).map((entry) => entry.name).sort();
1127
- for (const name of tsFiles2) {
1128
- await addFilePart(parts2, rootDir, join(rootDir, name));
1125
+ const filePaths = [];
1126
+ const visitDir = async (dir) => {
1127
+ const entries = await readdir(dir, { withFileTypes: true });
1128
+ for (const entry of entries) {
1129
+ const childPath = join(dir, entry.name);
1130
+ if (entry.isDirectory()) {
1131
+ await visitDir(childPath);
1132
+ continue;
1133
+ }
1134
+ if (entry.isFile() && /\.[cm]?ts$/.test(entry.name)) {
1135
+ filePaths.push(childPath);
1136
+ }
1137
+ }
1138
+ };
1139
+ await visitDir(rootDir);
1140
+ for (const filePath of filePaths.sort()) {
1141
+ await addFilePart(parts2, rootDir, filePath);
1129
1142
  }
1130
1143
  };
1131
1144
  const collectIntegrationBatchingFiles = async (rootDir, parts2) => {
1132
1145
  if (!await fileExists(rootDir)) return;
1133
- const entries2 = await readdir(rootDir, { withFileTypes: true });
1146
+ const entries = await readdir(rootDir, { withFileTypes: true });
1134
1147
  const filePaths = [];
1135
- for (const entry of entries2) {
1148
+ for (const entry of entries) {
1136
1149
  if (entry.isFile() && (entry.name === "play-runtime-batching-registry.ts" || /^batching.*\.ts$/.test(entry.name))) {
1137
1150
  filePaths.push(join(rootDir, entry.name));
1138
1151
  }
@@ -1147,23 +1160,13 @@ async function computeWorkersHarnessFingerprintWithAdapter(adapter) {
1147
1160
  await addFilePart(parts2, rootDir, filePath);
1148
1161
  }
1149
1162
  };
1150
- const entries = await readdir(adapter.workersHarnessFilesDir, {
1151
- withFileTypes: true
1152
- });
1153
- const tsFiles = entries.filter((e) => e.isFile() && /\.[cm]?ts$/.test(e.name)).map((e) => e.name).sort();
1154
1163
  const parts = [];
1155
- for (const name of tsFiles) {
1156
- await addFilePart(
1157
- parts,
1158
- adapter.workersHarnessFilesDir,
1159
- join(adapter.workersHarnessFilesDir, name)
1160
- );
1161
- }
1164
+ await collectTsFilesRecursive(adapter.workersHarnessFilesDir, parts);
1162
1165
  for (const dir of adapter.workersRuntimeFingerprintDirs ?? []) {
1163
1166
  if (basename(dir) === "integrations") {
1164
1167
  await collectIntegrationBatchingFiles(dir, parts);
1165
1168
  } else {
1166
- await collectTopLevelTsFiles(dir, parts);
1169
+ await collectTsFilesRecursive(dir, parts);
1167
1170
  }
1168
1171
  }
1169
1172
  return sha256(JSON.stringify(parts));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.150",
3
+ "version": "0.1.151",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {