deepline 0.1.120 → 0.1.122

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.
@@ -99,10 +99,10 @@ export const SDK_RELEASE = {
99
99
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
100
100
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
101
101
  // the SDK enrich generator's one-second stale policy.
102
- version: '0.1.120',
102
+ version: '0.1.122',
103
103
  apiContract: '2026-06-dataset-column-cell-stale-hard-cutover',
104
104
  supportPolicy: {
105
- latest: '0.1.120',
105
+ latest: '0.1.122',
106
106
  minimumSupported: '0.1.53',
107
107
  deprecatedBelow: '0.1.53',
108
108
  commandMinimumSupported: [
@@ -188,6 +188,8 @@ function isUnsafeOutboundUrlError(error: unknown): boolean {
188
188
 
189
189
  const EXECUTE_TOOL_METADATA_HEADER = 'x-deepline-include-tool-metadata';
190
190
  const EXECUTE_RESPONSE_CONTRACT_HEADER = 'x-deepline-execute-response-contract';
191
+ const AUTH_ACTIVITY_SUPPRESS_SLACK_HEADER =
192
+ 'x-deepline-suppress-auth-activity-slack';
191
193
  const V2_EXECUTE_RESPONSE_CONTRACT = 'v2-tool-response';
192
194
  const IN_MEMORY_STEP_RESULT_PREVIEW_LIMIT = 25;
193
195
  const WATERFALL_ROW_MATCH_LOG_SAMPLE_LIMIT = 10;
@@ -5338,6 +5340,7 @@ export class PlayContextImpl {
5338
5340
  [EXECUTE_RESPONSE_CONTRACT_HEADER]:
5339
5341
  V2_EXECUTE_RESPONSE_CONTRACT,
5340
5342
  [EXECUTE_TOOL_METADATA_HEADER]: 'true',
5343
+ [AUTH_ACTIVITY_SUPPRESS_SLACK_HEADER]: 'true',
5341
5344
  ...(this.#options.vercelProtectionBypassToken?.trim()
5342
5345
  ? {
5343
5346
  'x-vercel-protection-bypass':
@@ -217,6 +217,11 @@ type RuntimeApiActionRequest =
217
217
  alg: 'RSA-OAEP-256+A256GCM';
218
218
  publicKeyJwk: JsonWebKey;
219
219
  } | null;
220
+ }
221
+ | {
222
+ action: 'repair_runtime_storage_grants';
223
+ playName: string;
224
+ runId?: string | null;
220
225
  };
221
226
 
222
227
  type RuntimeApiRowRecord = MapRowOutcome & {
@@ -544,9 +549,28 @@ async function ensureRuntimeSheetForPreloadedSession(
544
549
  runtimeSheetEnsureCache.delete(cacheKey);
545
550
  }
546
551
  const checkStartedAt = Date.now();
547
- const ready = await isRuntimeSheetSchemaReady(input.session, {
548
- sheetContract: input.sheetContract,
549
- });
552
+ let ready: boolean;
553
+ try {
554
+ ready = await isRuntimeSheetSchemaReady(input.session, {
555
+ sheetContract: input.sheetContract,
556
+ });
557
+ } catch (error) {
558
+ if (!isPostgresPermissionDeniedError(error)) {
559
+ throw error;
560
+ }
561
+ const repairStartedAt = Date.now();
562
+ await repairRuntimeStorageGrants(context, {
563
+ playName: context.playName,
564
+ });
565
+ input.timings?.push({
566
+ phase: 'repair_storage_grants_after_schema_check_permission_error',
567
+ ms: Date.now() - repairStartedAt,
568
+ retried: true,
569
+ });
570
+ ready = await isRuntimeSheetSchemaReady(input.session, {
571
+ sheetContract: input.sheetContract,
572
+ });
573
+ }
550
574
  input.timings?.push({
551
575
  phase: 'schema_check_for_preloaded_session',
552
576
  ms: Date.now() - checkStartedAt,
@@ -1231,6 +1255,28 @@ function isMissingRelationError(error: unknown): boolean {
1231
1255
  );
1232
1256
  }
1233
1257
 
1258
+ function isPostgresPermissionDeniedError(error: unknown): boolean {
1259
+ return (
1260
+ error !== null &&
1261
+ typeof error === 'object' &&
1262
+ 'code' in error &&
1263
+ String(error.code) === '42501'
1264
+ );
1265
+ }
1266
+
1267
+ async function repairRuntimeStorageGrants(
1268
+ context: RuntimeApiContext,
1269
+ input: {
1270
+ playName: string;
1271
+ },
1272
+ ): Promise<void> {
1273
+ await postRuntimeApi<{ ok: true }>(context, {
1274
+ action: 'repair_runtime_storage_grants',
1275
+ playName: input.playName,
1276
+ runId: context.runId ?? null,
1277
+ });
1278
+ }
1279
+
1234
1280
  async function withRuntimeSheetProvisioningRetry<T>(
1235
1281
  context: RuntimeApiContext,
1236
1282
  input: {
@@ -1257,16 +1303,27 @@ async function withRuntimeSheetProvisioningRetry<T>(
1257
1303
  retried: false,
1258
1304
  error: error instanceof Error ? error.message : String(error),
1259
1305
  });
1260
- if (!isMissingRelationError(error)) {
1306
+ if (isMissingRelationError(error)) {
1307
+ const ensureStartedAt = Date.now();
1308
+ await ensureRuntimeSheet(context, input);
1309
+ input.timings?.push({
1310
+ phase: 'ensure_sheet_after_provisioning_error',
1311
+ ms: Date.now() - ensureStartedAt,
1312
+ retried: true,
1313
+ });
1314
+ } else if (isPostgresPermissionDeniedError(error)) {
1315
+ const repairStartedAt = Date.now();
1316
+ await repairRuntimeStorageGrants(context, {
1317
+ playName: input.playName,
1318
+ });
1319
+ input.timings?.push({
1320
+ phase: 'repair_storage_grants_after_permission_error',
1321
+ ms: Date.now() - repairStartedAt,
1322
+ retried: true,
1323
+ });
1324
+ } else {
1261
1325
  throw error;
1262
1326
  }
1263
- const ensureStartedAt = Date.now();
1264
- await ensureRuntimeSheet(context, input);
1265
- input.timings?.push({
1266
- phase: 'ensure_sheet_after_provisioning_error',
1267
- ms: Date.now() - ensureStartedAt,
1268
- retried: true,
1269
- });
1270
1327
  const retryStartedAt = Date.now();
1271
1328
  const result = await operation();
1272
1329
  input.timings?.push({
@@ -1458,13 +1515,18 @@ async function withRuntimeWorkReceiptClient<T>(
1458
1515
  try {
1459
1516
  return await operation(client);
1460
1517
  } catch (error) {
1461
- if (!isMissingRelationError(error)) {
1518
+ if (isMissingRelationError(error)) {
1519
+ runtimeWorkReceiptEnsureCache.delete(
1520
+ runtimeWorkReceiptEnsureCacheKey(session),
1521
+ );
1522
+ await ensureRuntimeWorkReceiptTable(session, client);
1523
+ } else if (isPostgresPermissionDeniedError(error)) {
1524
+ await repairRuntimeStorageGrants(context, {
1525
+ playName: context.playName?.trim() || session.playName,
1526
+ });
1527
+ } else {
1462
1528
  throw error;
1463
1529
  }
1464
- runtimeWorkReceiptEnsureCache.delete(
1465
- runtimeWorkReceiptEnsureCacheKey(session),
1466
- );
1467
- await ensureRuntimeWorkReceiptTable(session, client);
1468
1530
  return await operation(client);
1469
1531
  }
1470
1532
  };
@@ -13,6 +13,7 @@ import {
13
13
 
14
14
  type NodeSafeFetchOptions = {
15
15
  maxRedirects?: number;
16
+ maxResponseBytes?: number;
16
17
  sensitiveHeaders?: Iterable<string>;
17
18
  };
18
19
 
@@ -124,6 +125,7 @@ function createRequest(
124
125
  url: URL,
125
126
  init: RequestInit,
126
127
  prepared: PreparedBody,
128
+ maxResponseBytes: number | undefined,
127
129
  ): Promise<Response> {
128
130
  return new Promise((resolve, reject) => {
129
131
  const transport = url.protocol === 'https:' ? https : http;
@@ -137,9 +139,38 @@ function createRequest(
137
139
  signal: init.signal ?? undefined,
138
140
  },
139
141
  (response) => {
142
+ const contentLength = Number(response.headers['content-length']);
143
+ if (
144
+ maxResponseBytes !== undefined &&
145
+ Number.isFinite(contentLength) &&
146
+ contentLength > maxResponseBytes
147
+ ) {
148
+ response.resume();
149
+ reject(
150
+ new Error(
151
+ `Response body exceeds ${maxResponseBytes} byte limit.`,
152
+ ),
153
+ );
154
+ return;
155
+ }
156
+
140
157
  const chunks: Buffer[] = [];
158
+ let receivedBytes = 0;
141
159
  response.on('data', (chunk) => {
142
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
160
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
161
+ receivedBytes += buffer.byteLength;
162
+ if (
163
+ maxResponseBytes !== undefined &&
164
+ receivedBytes > maxResponseBytes
165
+ ) {
166
+ response.destroy(
167
+ new Error(
168
+ `Response body exceeds ${maxResponseBytes} byte limit.`,
169
+ ),
170
+ );
171
+ return;
172
+ }
173
+ chunks.push(buffer);
143
174
  });
144
175
  response.on('error', reject);
145
176
  response.on('end', () => {
@@ -208,6 +239,7 @@ export async function safeOutboundFetch(
208
239
  ): Promise<Response> {
209
240
  const redirectMode = init.redirect ?? 'follow';
210
241
  const maxRedirects = options.maxRedirects ?? 10;
242
+ const maxResponseBytes = options.maxResponseBytes;
211
243
  const sensitiveHeaders = options.sensitiveHeaders ?? [];
212
244
  let currentUrl = assertPublicHttpUrl(input);
213
245
  let currentInit: RequestInit = { ...init, redirect: 'manual' };
@@ -228,6 +260,7 @@ export async function safeOutboundFetch(
228
260
  currentUrl,
229
261
  currentInit,
230
262
  await prepareBody(currentInit),
263
+ maxResponseBytes,
231
264
  );
232
265
 
233
266
  Object.defineProperty(response, 'url', {
package/dist/cli/index.js CHANGED
@@ -403,10 +403,10 @@ var SDK_RELEASE = {
403
403
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
404
404
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
405
405
  // the SDK enrich generator's one-second stale policy.
406
- version: "0.1.120",
406
+ version: "0.1.122",
407
407
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
408
408
  supportPolicy: {
409
- latest: "0.1.120",
409
+ latest: "0.1.122",
410
410
  minimumSupported: "0.1.53",
411
411
  deprecatedBelow: "0.1.53",
412
412
  commandMinimumSupported: [
@@ -4342,10 +4342,8 @@ async function claimInstallBonus(baseUrl, apiKey) {
4342
4342
  apiKey,
4343
4343
  {}
4344
4344
  );
4345
- if (status !== 200) {
4346
- return;
4347
- }
4348
- const granted = Number(data.credits_granted ?? 0);
4345
+ if (status !== 200) return;
4346
+ const granted = typeof data.credits_granted === "number" ? data.credits_granted : 0;
4349
4347
  const alreadyGranted = data.already_granted === true;
4350
4348
  if (granted > 0) {
4351
4349
  console.log(`
@@ -380,10 +380,10 @@ var SDK_RELEASE = {
380
380
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
381
381
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
382
382
  // the SDK enrich generator's one-second stale policy.
383
- version: "0.1.120",
383
+ version: "0.1.122",
384
384
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
385
385
  supportPolicy: {
386
- latest: "0.1.120",
386
+ latest: "0.1.122",
387
387
  minimumSupported: "0.1.53",
388
388
  deprecatedBelow: "0.1.53",
389
389
  commandMinimumSupported: [
@@ -4331,10 +4331,8 @@ async function claimInstallBonus(baseUrl, apiKey) {
4331
4331
  apiKey,
4332
4332
  {}
4333
4333
  );
4334
- if (status !== 200) {
4335
- return;
4336
- }
4337
- const granted = Number(data.credits_granted ?? 0);
4334
+ if (status !== 200) return;
4335
+ const granted = typeof data.credits_granted === "number" ? data.credits_granted : 0;
4338
4336
  const alreadyGranted = data.already_granted === true;
4339
4337
  if (granted > 0) {
4340
4338
  console.log(`
package/dist/index.js CHANGED
@@ -274,10 +274,10 @@ var SDK_RELEASE = {
274
274
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
275
275
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
276
276
  // the SDK enrich generator's one-second stale policy.
277
- version: "0.1.120",
277
+ version: "0.1.122",
278
278
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
279
279
  supportPolicy: {
280
- latest: "0.1.120",
280
+ latest: "0.1.122",
281
281
  minimumSupported: "0.1.53",
282
282
  deprecatedBelow: "0.1.53",
283
283
  commandMinimumSupported: [
package/dist/index.mjs CHANGED
@@ -196,10 +196,10 @@ var SDK_RELEASE = {
196
196
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
197
197
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
198
198
  // the SDK enrich generator's one-second stale policy.
199
- version: "0.1.120",
199
+ version: "0.1.122",
200
200
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
201
201
  supportPolicy: {
202
- latest: "0.1.120",
202
+ latest: "0.1.122",
203
203
  minimumSupported: "0.1.53",
204
204
  deprecatedBelow: "0.1.53",
205
205
  commandMinimumSupported: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.120",
3
+ "version": "0.1.122",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {