deepline 0.3.462 → 0.3.464

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 (162) hide show
  1. package/dist/bundling-sources/sdk/src/play.ts +3 -0
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/monitors/billing/tamradar.ts +17 -17
  4. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +2 -0
  5. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +28 -1
  6. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +3 -1
  7. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +16 -2
  8. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +12 -9
  9. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +115 -7
  10. package/dist/bundling-sources/shared_libs/plays/field-catalog.ts +353 -52
  11. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +63 -3
  12. package/dist/cli/{auth-JDLEY7VU.mjs → auth-GMSI6QWR.mjs} +5 -5
  13. package/dist/cli/auth-P4E7M3AV.js +41 -0
  14. package/dist/cli/{billing-SDHLBLMV.mjs → billing-6G2RFLM7.mjs} +6 -6
  15. package/dist/cli/{billing-HXAXB3XZ.js → billing-MGH36CNP.js} +77 -77
  16. package/dist/cli/{chunk-UAJFWWZE.js → chunk-2RFTOESC.js} +5 -5
  17. package/dist/cli/{chunk-VFGVXXZP.js → chunk-3AIMFE3Z.js} +36 -36
  18. package/dist/cli/{chunk-O2RX5A66.mjs → chunk-3MKRAI6R.mjs} +5 -5
  19. package/dist/cli/{chunk-7MJ6VI2T.mjs → chunk-44BEFU62.mjs} +2 -2
  20. package/dist/cli/{chunk-7VZHXVOQ.js → chunk-4XNXFHG6.js} +1 -1
  21. package/dist/cli/{chunk-D6DXOUTO.mjs → chunk-5CKIO7KA.mjs} +1 -1
  22. package/dist/cli/{chunk-XANRM3QA.js → chunk-5XIGEYYK.js} +6 -6
  23. package/dist/cli/{chunk-NHRWZPWZ.mjs → chunk-6A7OH2PV.mjs} +2 -2
  24. package/dist/cli/{chunk-4KQ6SIBC.mjs → chunk-6COF5LIE.mjs} +2 -2
  25. package/dist/cli/{chunk-S6UAJR6V.mjs → chunk-6E2KNNTD.mjs} +2 -2
  26. package/dist/cli/{chunk-S42YIQNE.mjs → chunk-6KDOO7IM.mjs} +4 -4
  27. package/dist/cli/{chunk-5LEAXRHV.js → chunk-6P4OYABU.js} +54 -226
  28. package/dist/cli/chunk-7YDN6AEK.mjs +649 -0
  29. package/dist/cli/{chunk-HUB3CCM2.js → chunk-ACZLDP7L.js} +3 -3
  30. package/dist/cli/{chunk-BGTPIMSM.js → chunk-BMUDQMYE.js} +6 -6
  31. package/dist/cli/{chunk-6NNVJDVR.mjs → chunk-CUZVOPPY.mjs} +3 -3
  32. package/dist/cli/{chunk-ZUK6LIJB.mjs → chunk-DO3FSI4C.mjs} +1 -1
  33. package/dist/cli/{chunk-NBLSCHKK.js → chunk-E4QJKJH6.js} +51 -51
  34. package/dist/cli/{chunk-ZGQSFYD2.js → chunk-EQNJUG3N.js} +53 -53
  35. package/dist/cli/{chunk-GEGW5HPZ.js → chunk-FEWZT4RV.js} +21 -21
  36. package/dist/cli/{chunk-QJZ6WNWD.js → chunk-FVAB2JRO.js} +8 -8
  37. package/dist/cli/{chunk-Y4DPU4OM.js → chunk-GVJVBBGV.js} +3 -3
  38. package/dist/cli/{chunk-MUUQZIOF.mjs → chunk-HGUHBLX5.mjs} +3 -3
  39. package/dist/cli/{chunk-6PMCRYDA.js → chunk-HIMV32ZX.js} +6 -4
  40. package/dist/cli/{chunk-MSY22NQW.mjs → chunk-I2TCWIW2.mjs} +44 -216
  41. package/dist/cli/{chunk-XZAFIOUQ.mjs → chunk-J327QVQV.mjs} +1 -1
  42. package/dist/cli/chunk-JLZKF7EY.js +649 -0
  43. package/dist/cli/{chunk-7LFIMWMW.js → chunk-K3BARC72.js} +2 -2
  44. package/dist/cli/{chunk-LROWFPGN.js → chunk-K4DVRQTY.js} +16 -16
  45. package/dist/cli/{chunk-XQCTG5OO.js → chunk-L3U44YVO.js} +5 -5
  46. package/dist/cli/{chunk-CKSOY47X.mjs → chunk-M4QVY6RW.mjs} +2 -2
  47. package/dist/cli/{chunk-6RNQGWFD.mjs → chunk-MP3O4ISC.mjs} +1 -1
  48. package/dist/cli/{chunk-PHSEINNH.mjs → chunk-MQNBOSQP.mjs} +5 -5
  49. package/dist/cli/{chunk-TKAQR3IB.mjs → chunk-MUQAKLBP.mjs} +1 -1
  50. package/dist/cli/{chunk-YT5EODJO.js → chunk-NI3QFUK7.js} +4 -4
  51. package/dist/cli/{chunk-PKHVSIJG.mjs → chunk-O4AOYLZE.mjs} +2 -2
  52. package/dist/cli/{chunk-3ACMRZRV.js → chunk-O4ZMADW4.js} +7 -7
  53. package/dist/cli/{chunk-V3MEA7NB.mjs → chunk-OA7IIOLW.mjs} +4 -4
  54. package/dist/cli/{chunk-VPHN2HAL.mjs → chunk-OGCAGZXO.mjs} +6 -4
  55. package/dist/cli/{chunk-LFXLQEZN.mjs → chunk-PPQL5F4P.mjs} +1 -1
  56. package/dist/cli/{chunk-WIY6U6GD.mjs → chunk-RFOQRCMW.mjs} +5 -5
  57. package/dist/cli/{chunk-FKVYR3QA.mjs → chunk-TMVBBGSK.mjs} +1 -1
  58. package/dist/cli/{chunk-EM4TXCCI.js → chunk-TU3M7UXJ.js} +13 -13
  59. package/dist/cli/{chunk-AT636LLU.mjs → chunk-UM363DQF.mjs} +2 -2
  60. package/dist/cli/{chunk-V335HGX5.js → chunk-UOAHDEAI.js} +9 -9
  61. package/dist/cli/{chunk-UDRPEZ5F.mjs → chunk-VQHEMZ33.mjs} +1 -1
  62. package/dist/cli/{chunk-3KZCFOZ6.mjs → chunk-VYDOPASG.mjs} +1 -1
  63. package/dist/cli/{chunk-ULK7JGGI.js → chunk-VZX4P5FT.js} +258 -258
  64. package/dist/cli/{chunk-OPJAJBD4.js → chunk-WLIFUH6W.js} +8 -8
  65. package/dist/cli/{chunk-OMQ23IXL.js → chunk-X3XJ6ZSJ.js} +2 -2
  66. package/dist/cli/{chunk-7U3XNPOA.mjs → chunk-XMDBN2K7.mjs} +11 -11
  67. package/dist/cli/{chunk-7SWNPNML.js → chunk-ZAB6KCZW.js} +3 -3
  68. package/dist/cli/{chunk-JF3TLIMQ.js → chunk-ZIMCLWEW.js} +5 -5
  69. package/dist/cli/{chunk-I6VHOU5O.js → chunk-ZQERHPZA.js} +26 -26
  70. package/dist/cli/command-docs.js +2 -2
  71. package/dist/cli/command-docs.mjs +1 -1
  72. package/dist/cli/{csv-L54JS7TF.mjs → csv-4ZVMBOCK.mjs} +4 -4
  73. package/dist/cli/{csv-C56GSCEU.js → csv-W2JPV57R.js} +13 -13
  74. package/dist/cli/{db-MOGRMZTA.js → db-6YNFDHEW.js} +27 -27
  75. package/dist/cli/{db-YVBUW2DX.mjs → db-TVK6BLRB.mjs} +6 -6
  76. package/dist/cli/describe-APW5TWBT.js +48 -0
  77. package/dist/cli/{describe-NLZKKT7C.mjs → describe-JFN4ECPO.mjs} +20 -20
  78. package/dist/cli/describe-core.d.mts +3 -3
  79. package/dist/cli/describe-core.d.ts +3 -3
  80. package/dist/cli/describe-core.js +4 -4
  81. package/dist/cli/describe-core.mjs +3 -3
  82. package/dist/cli/{executions-ZBGSTT37.mjs → executions-2FK4FFKE.mjs} +6 -6
  83. package/dist/cli/{executions-A7L4ULPP.js → executions-J4CAN7RB.js} +8 -8
  84. package/dist/cli/{feedback-G6GU37FD.mjs → feedback-EYRRLA2P.mjs} +4 -4
  85. package/dist/cli/{feedback-OHLY7RYD.js → feedback-NOO4OM4U.js} +8 -8
  86. package/dist/cli/{git-PKZW3QD5.mjs → git-D3Q4JKBC.mjs} +5 -5
  87. package/dist/cli/git-FPF6DT43.js +25 -0
  88. package/dist/cli/index.js +139 -139
  89. package/dist/cli/index.mjs +41 -41
  90. package/dist/cli/{legacy-noops-5LM3D724.js → legacy-noops-5ZGRKSN3.js} +8 -8
  91. package/dist/cli/{legacy-noops-LJJYG6YA.mjs → legacy-noops-SUFJWBLZ.mjs} +5 -5
  92. package/dist/cli/{monitors-UX3H5DC2.js → monitors-3QFJZA6Z.js} +91 -91
  93. package/dist/cli/{monitors-72QV4ALO.mjs → monitors-IRDIIR6J.mjs} +7 -7
  94. package/dist/cli/{org-IF7ISUVB.js → org-275OJJ7W.js} +68 -68
  95. package/dist/cli/{org-6RRRKOCP.mjs → org-2VA2FSMG.mjs} +6 -6
  96. package/dist/cli/{pages-3SU3HKL7.js → pages-SPRBOZRA.js} +17 -17
  97. package/dist/cli/{pages-DXDYYKEK.mjs → pages-WCUEBFYU.mjs} +6 -6
  98. package/dist/cli/{play-AHASKRLA.mjs → play-7UL5H6QU.mjs} +18 -18
  99. package/dist/cli/{play-EUIUVLUH.js → play-NMHUWBET.js} +305 -305
  100. package/dist/cli/{providers-V5WU4VXJ.js → providers-72LUJEAT.js} +9 -9
  101. package/dist/cli/{providers-GWGE3WY3.mjs → providers-WSCKV557.mjs} +6 -6
  102. package/dist/cli/{quickstart-OXKQ5ZST.mjs → quickstart-K4LAKJKJ.mjs} +4 -4
  103. package/dist/cli/{quickstart-QP65I5PF.js → quickstart-XSUUAE2Y.js} +6 -6
  104. package/dist/cli/{run-F3FTYS56.js → run-MLV2CLW7.js} +40 -40
  105. package/dist/cli/{run-6MM72IGL.mjs → run-R2MOXXHH.mjs} +25 -25
  106. package/dist/cli/search-AYFUV6YV.js +32 -0
  107. package/dist/cli/{search-ZMEBVJZB.mjs → search-WHJZNWKE.mjs} +7 -7
  108. package/dist/cli/{secrets-ACND5N6A.js → secrets-7PXFBOFY.js} +15 -15
  109. package/dist/cli/{secrets-XRCJFF3L.mjs → secrets-YGVOFLI5.mjs} +6 -6
  110. package/dist/cli/{sessions-ZGRJPCFF.js → sessions-ASXXZI42.js} +6 -6
  111. package/dist/cli/{sessions-RTK3CEW6.mjs → sessions-G7I54W4L.mjs} +5 -5
  112. package/dist/cli/{settings-XDRBPRDE.mjs → settings-4GFO6JYO.mjs} +11 -11
  113. package/dist/cli/{settings-PD5KWQQZ.js → settings-RTEBMDPC.js} +78 -78
  114. package/dist/cli/{setup-3HPYAOCC.mjs → setup-4RJGKSDC.mjs} +9 -9
  115. package/dist/cli/{setup-E2Q6PXHC.js → setup-A6V2MJK7.js} +44 -44
  116. package/dist/cli/{skills-OOQFMPOV.mjs → skills-432W6EGS.mjs} +7 -7
  117. package/dist/cli/skills-GOQECD7H.js +31 -0
  118. package/dist/cli/tools-JXYN7WOE.js +55 -0
  119. package/dist/cli/{tools-C5ZT3UIC.mjs → tools-SABREK3C.mjs} +18 -18
  120. package/dist/cli/update-BSB4TJER.js +33 -0
  121. package/dist/cli/{update-ZWJTADIW.mjs → update-F7NO5RDW.mjs} +9 -9
  122. package/dist/cli/{workflow-23NMPAJ7.mjs → workflow-F4N7CFUX.mjs} +7 -7
  123. package/dist/cli/{workflow-TCXU5YJV.js → workflow-TF6YDWTM.js} +17 -17
  124. package/dist/{client-DTwnz_AW.d.mts → client-ADFHNtFM.d.mts} +1 -1
  125. package/dist/{client-DS2IWYZF.d.ts → client-BClp2yrq.d.ts} +1 -1
  126. package/dist/{client-core-B_6HAIBy.d.ts → client-core-BFU73Ttw.d.ts} +1 -1
  127. package/dist/{client-core-DzBSlY1U.d.mts → client-core-DWLmmJWo.d.mts} +1 -1
  128. package/dist/{compiler-manifest-Dcyd3-Zd.d.mts → compiler-manifest-Cs17yO-H.d.mts} +321 -3
  129. package/dist/{compiler-manifest-Dcyd3-Zd.d.ts → compiler-manifest-Cs17yO-H.d.ts} +321 -3
  130. package/dist/{errors-yQwfgrcX.d.ts → errors-Dee-QpVS.d.ts} +1 -1
  131. package/dist/{errors-d-sTrZhe.d.mts → errors-qNfvQuRB.d.mts} +1 -1
  132. package/dist/{index-C6oXchjN.d.mts → index-BTqNNXmC.d.mts} +1 -1
  133. package/dist/{index-P56zy_z5.d.ts → index-DXTh1Lxe.d.ts} +1 -1
  134. package/dist/index.d.mts +7 -7
  135. package/dist/index.d.ts +7 -7
  136. package/dist/index.js +81 -14
  137. package/dist/index.mjs +77 -10
  138. package/dist/install-integrity.json +114 -114
  139. package/dist/plays/bundle-play-file.d.mts +3 -3
  140. package/dist/plays/bundle-play-file.d.ts +3 -3
  141. package/dist/plays/play-description.d.mts +2 -2
  142. package/dist/plays/play-description.d.ts +2 -2
  143. package/dist/plays/run-request.d.mts +2 -2
  144. package/dist/plays/run-request.d.ts +2 -2
  145. package/dist/release.d.mts +1 -1
  146. package/dist/release.d.ts +1 -1
  147. package/dist/release.js +2 -2
  148. package/dist/release.mjs +1 -1
  149. package/dist/server.d.mts +4 -4
  150. package/dist/server.d.ts +4 -4
  151. package/dist/server.js +5 -5
  152. package/dist/server.mjs +3 -3
  153. package/package.json +1 -1
  154. package/dist/cli/auth-UXKY6TCC.js +0 -41
  155. package/dist/cli/chunk-NA4T3B62.js +0 -286
  156. package/dist/cli/chunk-TXZVVBQZ.mjs +0 -286
  157. package/dist/cli/describe-KYEULWPG.js +0 -48
  158. package/dist/cli/git-P76N4NDQ.js +0 -25
  159. package/dist/cli/search-OYKOOI7A.js +0 -32
  160. package/dist/cli/skills-XYWV52KB.js +0 -31
  161. package/dist/cli/tools-ASCDZJCK.js +0 -55
  162. package/dist/cli/update-5RQSEIFM.js +0 -33
@@ -1498,6 +1498,8 @@ function extractorDescriptorRecord(
1498
1498
  .map((entry) => entry.trim())
1499
1499
  .filter(Boolean);
1500
1500
  const emailStatus = emailStatusExtractorConfig(descriptor.emailStatus);
1501
+ const means =
1502
+ typeof descriptor.means === 'string' ? descriptor.means : undefined;
1501
1503
  return [
1502
1504
  [
1503
1505
  key,
@@ -1506,6 +1508,7 @@ function extractorDescriptorRecord(
1506
1508
  ...(transforms.length > 0 ? { transforms } : {}),
1507
1509
  ...(enumValues.length > 0 ? { enum: enumValues } : {}),
1508
1510
  ...(emailStatus ? { emailStatus } : {}),
1511
+ ...(means !== undefined ? { means } : {}),
1509
1512
  },
1510
1513
  ],
1511
1514
  ];
@@ -205,7 +205,7 @@ export const SDK_RELEASE = {
205
205
  // getters keep their established compatibility behavior.
206
206
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
207
207
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
208
- version: '0.3.462',
208
+ version: '0.3.464',
209
209
  updateSummary: {
210
210
  introducedIn: '0.3.90',
211
211
  summary:
@@ -106,17 +106,25 @@ export const TAMRADAR_RADAR_TYPE_PRICING = {
106
106
  providerCostUsd: 0.045,
107
107
  unitLabel: 'finding',
108
108
  },
109
- // DORMANT (disabled from deployment — see TAMRADAR_DISABLED_RADAR_TYPES).
110
- // Kept for reversibility: $150/mo resell-tier subscription pricing is retained
111
- // so the type can be re-enabled per-partner by removing it from the disabled
112
- // set. It is excluded from the deployable enum + public pricing surface.
109
+ // Source: TAMRadar per-update pricing (confidential/internal), confirmed
110
+ // per result with TAMRadar on 2026-11-03 (it was a $150/mo resell tier).
111
+ // https://docs.tamradar.com/webhooks/industry/funding-rounds
113
112
  industry_funding_rounds: {
114
113
  capability: 'industry_radar',
115
114
  label: 'Industry funding rounds',
116
- mode: 'monitor_subscription',
117
- providerCostUsd: 150,
118
- unitLabel: 'month',
119
- periodDays: 30,
115
+ mode: 'monitor_usage',
116
+ providerCostUsd: 0.1,
117
+ unitLabel: 'finding',
118
+ },
119
+ // Source: TAMRadar per-update pricing (confidential/internal), confirmed
120
+ // per result with TAMRadar on 2026-11-03 (it was a $250/mo resell tier).
121
+ // https://docs.tamradar.com/webhooks/industry/new-companies
122
+ industry_new_companies: {
123
+ capability: 'industry_radar',
124
+ label: 'Industry new companies',
125
+ mode: 'monitor_usage',
126
+ providerCostUsd: 0.15,
127
+ unitLabel: 'finding',
120
128
  },
121
129
  } as const;
122
130
 
@@ -132,9 +140,7 @@ export function isTamradarRadarType(value: string): value is TamradarRadarType {
132
140
  // `radar_type` enum (so they never appear in `monitors tools`/CLI and payload
133
141
  // validation rejects them) and from the public pricing surface — the deploy
134
142
  // path surfaces a clear "radar type not available for deployment" error rather
135
- // than a bare enum mismatch. Flipping a type back on is a one-line delete here
136
- // (the two resell-tier types below carry resell rights and may be enabled
137
- // per-partner).
143
+ // than a bare enum mismatch. Flipping a type back on is a one-line delete here.
138
144
  //
139
145
  // IMPORTANT (guardrail): these reason strings are CUSTOMER-VISIBLE — they flow
140
146
  // into the deploy-rejection `suggestion` via `tamradarDisabledRadarTypeReason`.
@@ -144,12 +150,6 @@ export function isTamradarRadarType(value: string): value is TamradarRadarType {
144
150
  export const TAMRADAR_DISABLED_RADAR_TYPES: Record<string, string> = {
145
151
  company_social_posts_cxo:
146
152
  'This Deepline radar type is not available for self-serve deploy.',
147
- // Internal note (NOT customer-visible): $250/mo resell-tier subscription.
148
- industry_new_companies:
149
- 'This Deepline radar type is not available for self-serve deploy.',
150
- // Internal note (NOT customer-visible): $150/mo resell-tier subscription.
151
- industry_funding_rounds:
152
- 'This Deepline radar type is not available for self-serve deploy.',
153
153
  };
154
154
 
155
155
  export function isTamradarDisabledRadarType(value: string): boolean {
@@ -521,6 +521,8 @@ export const PROVIDER_MONITOR_BATCH_CHANGE_BUCKETS: Readonly<
521
521
  provider_create_adjudicated: 'created',
522
522
  provider_create_adopted_by_operator: 'created',
523
523
  named_batch_create: 'created',
524
+ // A named Batch dry run's planned create, counted as the create it plans.
525
+ dry_run_create: 'created',
524
526
  named_batch_start: 'created',
525
527
  provider_repaired: 'created',
526
528
  fleet_converged: 'created',
@@ -31,6 +31,17 @@ type ProviderMonitorUpstreamIdentityDefinition = {
31
31
  * treating different authored filters as an exact duplicate.
32
32
  */
33
33
  allowDistinctConfigurations?: boolean;
34
+ /**
35
+ * Scope values whose provider resource has no configuration of its own: a
36
+ * global feed delivers the same findings whatever else the payload says.
37
+ * Inside these scopes every other payload field (such as `updates_since`)
38
+ * is left out of the claim, so a second monitor for the same feed is an
39
+ * exact duplicate even when its other fields differ.
40
+ */
41
+ configurationFreeScopes?: readonly {
42
+ field: string;
43
+ values: readonly string[];
44
+ }[];
34
45
  /**
35
46
  * Payload fields that never change which findings the provider resource
36
47
  * delivers. `updates_since` only sets how far back the first delivery
@@ -58,6 +69,14 @@ const PROVIDER_MONITOR_UPSTREAM_IDENTITY_FIELDS = {
58
69
  { name: 'industry', runtimePayloadAliases: ['keyword'] },
59
70
  ],
60
71
  allowDistinctConfigurations: true,
72
+ // TamRadar's funding-round and new-company radars take no filter, so one
73
+ // per workspace is the whole feed.
74
+ configurationFreeScopes: [
75
+ {
76
+ field: 'radar_type',
77
+ values: ['industry_funding_rounds', 'industry_new_companies'],
78
+ },
79
+ ],
61
80
  nonConfigurationFields: ['updates_since'],
62
81
  },
63
82
  } as const satisfies Record<string, ProviderMonitorUpstreamIdentityDefinition>;
@@ -167,10 +186,18 @@ export function providerMonitorUpstreamIdentityClaimKey(
167
186
  return scopeKey;
168
187
  }
169
188
 
170
- const definition =
189
+ const definition: ProviderMonitorUpstreamIdentityDefinition =
171
190
  PROVIDER_MONITOR_UPSTREAM_IDENTITY_FIELDS[
172
191
  signature.tool as keyof typeof PROVIDER_MONITOR_UPSTREAM_IDENTITY_FIELDS
173
192
  ];
193
+ if (
194
+ definition.configurationFreeScopes?.some((scope) => {
195
+ const value = signature.key[scope.field];
196
+ return typeof value === 'string' && scope.values.includes(value);
197
+ })
198
+ ) {
199
+ return scopeKey;
200
+ }
174
201
  const scopeAndAliases = new Set<string>(
175
202
  definition.fields.flatMap((field) => [
176
203
  field.name,
@@ -705,7 +705,9 @@ const TOOL_RETRY_AFTER_FALLBACK_MS = 1_000;
705
705
  // broken gateway-to-runner connection, not slow provider work.
706
706
  export const TOOL_EXECUTE_RESPONSE_BODY_TIMEOUT_MS = 30_000;
707
707
  const TOOL_RETRY_HEARTBEAT_INTERVAL_MS = 30_000;
708
- const TOOL_PROVIDER_RESIDENT_WAIT_BUDGET_MS = 5_000;
708
+ // Avoid paying sandbox startup and checkpoint replay for ordinary provider
709
+ // holds. Bound cumulative residency so sustained holds still park durably.
710
+ const TOOL_PROVIDER_RESIDENT_WAIT_BUDGET_MS = 10 * 60_000;
709
711
  // The call already waited its whole admission budget in this sandbox, so it
710
712
  // rejoins the shared lane promptly instead of adding a fixed delay of its own.
711
713
  const PROVIDER_ADMISSION_REQUEUE_DELAY_MS = 1_000;
@@ -4932,6 +4932,20 @@ async function buildRuntimeSheetDatasetStartResult(
4932
4932
  );
4933
4933
  return Object.keys(cells).length ? [{ key, cells }] : [];
4934
4934
  });
4935
+ // History readers (`datasetRowInput: current_run`) seed rows from authored
4936
+ // input plus `__deepline*` runtime fields only and read stored output through
4937
+ // `previousCells`. Merging that output into the rows too would send every
4938
+ // completed cell twice and can push a resume admission past its byte budget.
4939
+ const rowFieldsForReader = (
4940
+ data: Record<string, unknown>,
4941
+ ): Record<string, unknown> =>
4942
+ input.includePreviousCells
4943
+ ? Object.fromEntries(
4944
+ Object.entries(data).filter(([field]) =>
4945
+ field.startsWith('__deepline'),
4946
+ ),
4947
+ )
4948
+ : data;
4935
4949
  const buildFreshRow = (entry: RuntimeDatasetRowEntry) => {
4936
4950
  const row: Record<string, unknown> = {
4937
4951
  ...sanitizePostgresJsonValue(entry.row),
@@ -5024,7 +5038,7 @@ async function buildRuntimeSheetDatasetStartResult(
5024
5038
  }
5025
5039
  completedRows.push({
5026
5040
  ...entry.row,
5027
- ...stored,
5041
+ ...rowFieldsForReader(stored),
5028
5042
  __deeplineRowKey: entry.key,
5029
5043
  });
5030
5044
  } else if (disposition === 'blocked') {
@@ -5056,7 +5070,7 @@ async function buildRuntimeSheetDatasetStartResult(
5056
5070
  const buildMergedRow = (entry: RuntimeDatasetRowEntry) => {
5057
5071
  const merged = { ...entry.row };
5058
5072
  for (const [field, value] of Object.entries(
5059
- persistedRowsByKey.get(entry.key) ?? {},
5073
+ rowFieldsForReader(persistedRowsByKey.get(entry.key) ?? {}),
5060
5074
  )) {
5061
5075
  if (
5062
5076
  value !== null ||
@@ -399,22 +399,25 @@ function isConcurrencyBackpressureResponse(input: {
399
399
  );
400
400
  }
401
401
 
402
- function isCredentialDispatchRefusalResponse(input: {
402
+ function isPreDispatchRateRefusalResponse(input: {
403
403
  status: number;
404
404
  bodyText: string;
405
405
  executionFenced?: boolean;
406
406
  }): boolean {
407
- // Fenced gateway attempts have their own qualified redelivery contract.
408
- // This exemption is only for the ordinary execute route's released charge.
409
- if (input.status !== 429 || input.executionFenced === true) return false;
407
+ if (input.status !== 429) return false;
410
408
  const body = parseJsonObject(input.bodyText);
411
409
  return (
412
410
  body?.code === 'RATE_LIMIT' &&
413
411
  body.failure_origin === 'deepline_rate_limit' &&
414
412
  body.error_category === 'rate_limit' &&
415
- body.rate_limit_bucket_scope === 'credential_shared' &&
416
- body.rate_limit_kind === 'requests_per_second' &&
417
- body.provider_request_dispatched === false
413
+ body.provider_request_dispatched === false &&
414
+ // Workspace tool admission precedes billing for both execute paths.
415
+ // Credential refusals release a charge and retain their unfenced contract.
416
+ ((body.rate_limit_bucket_scope === 'customer_tool' &&
417
+ body.rate_limit_kind === 'requests_per_minute') ||
418
+ (input.executionFenced !== true &&
419
+ body.rate_limit_bucket_scope === 'credential_shared' &&
420
+ body.rate_limit_kind === 'requests_per_second'))
418
421
  );
419
422
  }
420
423
 
@@ -768,7 +771,7 @@ export function classifyToolExecuteHttpFailure(input: {
768
771
  const concurrencyBackpressure = isConcurrencyBackpressureResponse(input);
769
772
  const runtimeSchedulerCapacity = isRuntimeSchedulerCapacityResponse(input);
770
773
  const providerPacingWait = isProviderPacingWaitResponse(input);
771
- const credentialDispatchRefusal = isCredentialDispatchRefusalResponse(input);
774
+ const preDispatchRateRefusal = isPreDispatchRateRefusalResponse(input);
772
775
  const edgeGatewayFailure = isEdgeGatewayFailureResponse(input);
773
776
  const executionFenced = input.executionFenced === true;
774
777
  const explicitRetryable = readExplicitToolHttpRetryability(input);
@@ -987,6 +990,6 @@ export function classifyToolExecuteHttpFailure(input: {
987
990
  runtimeSchedulerCapacity ||
988
991
  concurrencyBackpressure ||
989
992
  providerPacingWait ||
990
- credentialDispatchRefusal,
993
+ preDispatchRateRefusal,
991
994
  };
992
995
  }
@@ -32,6 +32,12 @@ import {
32
32
  type JobChangeGetterValue,
33
33
  type JobChangeStatus,
34
34
  } from '../plays/extractor-targets';
35
+ import {
36
+ fieldOfName,
37
+ fieldPaths,
38
+ resolveFieldName,
39
+ type FieldBinding,
40
+ } from '../plays/field-catalog';
35
41
  import type {
36
42
  BasicToolExecuteResult,
37
43
  BasicToolResultListAccessor,
@@ -520,6 +526,10 @@ function parseExecuteToolMetadata(
520
526
  !Array.isArray(recordEntry.emailStatus)
521
527
  ? (recordEntry.emailStatus as EmailStatusExtractorConfig)
522
528
  : undefined;
529
+ const means =
530
+ typeof recordEntry.means === 'string'
531
+ ? recordEntry.means
532
+ : undefined;
523
533
  return [
524
534
  [
525
535
  key,
@@ -544,6 +554,7 @@ function parseExecuteToolMetadata(
544
554
  : {}),
545
555
  ...(overrides.length > 0 ? { overrides } : {}),
546
556
  ...(emailStatus ? { emailStatus } : {}),
557
+ ...(means !== undefined ? { means } : {}),
547
558
  },
548
559
  ],
549
560
  ];
@@ -1276,10 +1287,10 @@ function buildTargets(
1276
1287
  const declaredTargetPaths = new Map<string, readonly string[]>();
1277
1288
  const semanticStatusTargets = new Set<string>();
1278
1289
  for (const [target, descriptor] of Object.entries(extractors ?? {})) {
1279
- // Normal scalar getters are total: a declared but absent value reads null.
1280
- // Semantic status getters stay absent when their provider status did not
1281
- // resolve; manufacturing an "unknown" status would blur no signal with an
1282
- // observed provider verdict.
1290
+ // Declared getters are total: a declared but absent value reads null.
1291
+ // Semantic status getters never borrow a sibling key or manufacture an
1292
+ // "unknown" status, which would blur no signal with an observed provider
1293
+ // verdict; an unresolved status reads null like any other miss.
1283
1294
  const isSemanticStatus =
1284
1295
  descriptor.emailStatus !== undefined ||
1285
1296
  descriptor.transforms?.some((transform) =>
@@ -1288,7 +1299,7 @@ function buildTargets(
1288
1299
  ),
1289
1300
  ) === true;
1290
1301
  if (isSemanticStatus) semanticStatusTargets.add(target);
1291
- else declaredTargetPaths.set(target, descriptor.paths);
1302
+ declaredTargetPaths.set(target, descriptor.paths);
1292
1303
  const emailStatusTarget = buildEmailStatusTarget(result, descriptor);
1293
1304
  if (emailStatusTarget) {
1294
1305
  targets[target] = emailStatusTarget;
@@ -1448,8 +1459,18 @@ function applySerializedTargetValues(
1448
1459
  targetValues: Record<string, ToolResultTargetMetadata> | undefined,
1449
1460
  ): ToolExecuteResult {
1450
1461
  if (!targetValues || Object.keys(targetValues).length === 0) return result;
1451
- result._metadata.targets = targetValues;
1452
- result.extractedValues = buildExtractedAccessors(targetValues);
1462
+ // Receipts saved before status getters were total omit an unresolved
1463
+ // status. Keep every declared getter callable on replay: a target the
1464
+ // receipt did not save reads null, never a value recomputed here.
1465
+ const targets: Record<string, ToolResultTargetMetadata> = {};
1466
+ for (const [target, rebuilt] of Object.entries(result._metadata.targets)) {
1467
+ if (!Object.prototype.hasOwnProperty.call(targetValues, target)) {
1468
+ targets[target] = { path: rebuilt.path, value: null };
1469
+ }
1470
+ }
1471
+ Object.assign(targets, targetValues);
1472
+ result._metadata.targets = targets;
1473
+ result.extractedValues = buildExtractedAccessors(targets);
1453
1474
  return result;
1454
1475
  }
1455
1476
 
@@ -1530,6 +1551,71 @@ function listTableNamespace(
1530
1551
  }
1531
1552
  }
1532
1553
 
1554
+ /**
1555
+ * The outputs of a result that are catalog fields: declared extractors whose
1556
+ * meaning is known, from the tool's own `means` or the name's one meaning.
1557
+ * Values found by guessing at keys are never bindings.
1558
+ */
1559
+ function resultFieldBindings(
1560
+ result: ToolExecuteResult | BasicToolExecuteResult,
1561
+ ): FieldBinding[] {
1562
+ const extractors = result._metadata.extractors ?? {};
1563
+ return Object.entries(extractors).flatMap(([name, descriptor]) => {
1564
+ if (!result.extractedValues[name]) return [];
1565
+ const id = fieldOfName(name, descriptor.means);
1566
+ return id ? [{ name, id }] : [];
1567
+ });
1568
+ }
1569
+
1570
+ function resultOutputNames(
1571
+ result: ToolExecuteResult | BasicToolExecuteResult,
1572
+ ): string[] {
1573
+ return [
1574
+ ...Object.keys(result._metadata.extractors ?? {}),
1575
+ ...Object.keys(result.extractedLists),
1576
+ ];
1577
+ }
1578
+
1579
+ function readResultField(
1580
+ result: ToolExecuteResult | BasicToolExecuteResult,
1581
+ name: string,
1582
+ ): unknown {
1583
+ const bindings = resultFieldBindings(result);
1584
+ const binding = resolveFieldName(name, bindings, resultOutputNames(result));
1585
+ if (!binding) {
1586
+ const ids = [...new Set(bindings.map((known) => known.id))];
1587
+ throw new Error(
1588
+ `${result._metadata.toolId} has no field "${name}". ${ids.length > 0 ? `Its fields: ${ids.join(', ')}.` : 'It declares no catalog fields.'} Other values are in result.response.`,
1589
+ );
1590
+ }
1591
+ return result.extractedValues[binding.name]!.get();
1592
+ }
1593
+
1594
+ /** `result.fields`, laid out by `fieldPaths`; each value reads on access. */
1595
+ function buildResultFields(
1596
+ result: ToolExecuteResult | BasicToolExecuteResult,
1597
+ ): Record<string, unknown> {
1598
+ const tree: Record<string, unknown> = {};
1599
+ const lists = Object.keys(result.extractedLists);
1600
+ for (const entry of fieldPaths(
1601
+ resultFieldBindings(result),
1602
+ resultOutputNames(result),
1603
+ lists,
1604
+ )) {
1605
+ let node = tree;
1606
+ for (const key of entry.path.slice(0, -1)) {
1607
+ node = (node[key] ??= {}) as Record<string, unknown>;
1608
+ }
1609
+ Object.defineProperty(node, entry.path[entry.path.length - 1]!, {
1610
+ get: entry.list
1611
+ ? () => result.extractedLists[entry.name]!.get()
1612
+ : () => readResultField(result, entry.name),
1613
+ enumerable: true,
1614
+ });
1615
+ }
1616
+ return tree;
1617
+ }
1618
+
1533
1619
  export function createToolExecuteResult<TResult = unknown>(input: {
1534
1620
  status: string;
1535
1621
  jobId?: string;
@@ -1604,11 +1690,33 @@ export function createToolExecuteResult<TResult = unknown>(input: {
1604
1690
  extractedValues,
1605
1691
  extractedLists,
1606
1692
  } as ToolExecuteResult<TResult>;
1693
+ // Read through `this`, so copies made from these descriptors (the edition
1694
+ // projection, native batch views) read their own values.
1607
1695
  Object.defineProperties(wrapper, {
1608
1696
  toolOutput: {
1609
1697
  value: toolResponse,
1610
1698
  enumerable: false,
1611
1699
  },
1700
+ response: {
1701
+ get(this: ToolExecuteResult) {
1702
+ return Object.hasOwn(this.toolResponse, 'rawV2')
1703
+ ? this.toolResponse.rawV2
1704
+ : this.toolResponse.raw;
1705
+ },
1706
+ enumerable: false,
1707
+ },
1708
+ fields: {
1709
+ get(this: ToolExecuteResult) {
1710
+ return buildResultFields(this);
1711
+ },
1712
+ enumerable: false,
1713
+ },
1714
+ field: {
1715
+ value(this: ToolExecuteResult, name: string) {
1716
+ return readResultField(this, name);
1717
+ },
1718
+ enumerable: false,
1719
+ },
1612
1720
  });
1613
1721
  Object.defineProperty(wrapper, '_metadata', {
1614
1722
  value: metadata,