deepline 0.3.287 → 0.3.289

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.287',
203
+ version: '0.3.289',
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: {
@@ -371,6 +371,7 @@ import {
371
371
  type PlayExecutionSuspension,
372
372
  } from './suspension';
373
373
  import {
374
+ createRequestHeaderSecretRedactionContext,
374
375
  createSecretRedactionContext,
375
376
  type SecretRedactionContext,
376
377
  } from './secret-redaction';
@@ -14669,6 +14670,10 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
14669
14670
  if (headers['user-agent'] === undefined) {
14670
14671
  headers['user-agent'] = 'Deepline Play Runtime';
14671
14672
  }
14673
+ const requestRedactor = createRequestHeaderSecretRedactionContext(
14674
+ headers,
14675
+ Object.keys(secretHeaderMarkers),
14676
+ );
14672
14677
  const fetchInit = { ...init, headers };
14673
14678
  delete fetchInit.auth;
14674
14679
  const boundaryId = this.durableBoundaryId(
@@ -14755,18 +14760,18 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
14755
14760
  log: (message) => this.runtimeLog(message),
14756
14761
  });
14757
14762
  const rawJson = parseJsonOrNull(bodyText);
14758
- const redactedBodyText = this.secretRedactor.redactString(bodyText);
14759
- const output: PlayFetchResponse = {
14760
- ok: response.ok,
14761
- status: response.status,
14762
- statusText: response.statusText,
14763
- url: response.url,
14764
- headers: this.secretRedactor.redact(
14765
- Object.fromEntries(response.headers.entries()),
14766
- ) as Record<string, string>,
14767
- bodyText: redactedBodyText,
14768
- json: this.secretRedactor.redactKnownSecrets(rawJson),
14769
- };
14763
+ const output: PlayFetchResponse =
14764
+ this.secretRedactor.redactKnownSecrets(
14765
+ requestRedactor.redactKnownSecrets({
14766
+ ok: response.ok,
14767
+ status: response.status,
14768
+ statusText: response.statusText,
14769
+ url: response.url,
14770
+ headers: Object.fromEntries(response.headers.entries()),
14771
+ bodyText,
14772
+ json: rawJson,
14773
+ }),
14774
+ );
14770
14775
 
14771
14776
  if (!output.ok) {
14772
14777
  this.logCtxFetchHttpFailure({
@@ -73,7 +73,7 @@ export type PlayDocflowNodeIoState = {
73
73
  };
74
74
 
75
75
  type PreviewOptions = {
76
- redactor?: SecretRedactionContext;
76
+ redactor?: Pick<SecretRedactionContext, 'redactRegisteredSecrets'>;
77
77
  };
78
78
 
79
79
  const utf8Encoder = new TextEncoder();
@@ -132,26 +132,13 @@ function truncateUtf8(value: string, maxBytes: number): string {
132
132
  return `${output}…`;
133
133
  }
134
134
 
135
- function redactString(
136
- redactor: SecretRedactionContext,
137
- value: string,
138
- key?: string,
139
- ): string {
140
- if (!key) return redactor.redactString(value);
141
- const wrapped = redactor.redact({ [key]: value }) as Record<string, unknown>;
142
- return typeof wrapped[key] === 'string'
143
- ? wrapped[key]
144
- : redactor.redactString(value);
145
- }
146
-
147
135
  function safeString(
148
136
  value: unknown,
149
- redactor: SecretRedactionContext,
150
- key?: string,
137
+ redactor?: PreviewOptions['redactor'],
151
138
  ): string | undefined {
152
139
  if (typeof value !== 'string') return undefined;
153
140
  return truncateUtf8(
154
- redactString(redactor, value, key),
141
+ redactor?.redactRegisteredSecrets(value) ?? value,
155
142
  DOCFLOW_NODE_IO_LIMITS.maxStringBytes,
156
143
  );
157
144
  }
@@ -161,8 +148,7 @@ function previewValue(
161
148
  input: {
162
149
  depth: number;
163
150
  ancestors: WeakSet<object>;
164
- redactor: SecretRedactionContext;
165
- key?: string;
151
+ redactor?: PreviewOptions['redactor'];
166
152
  },
167
153
  ): PlayDocflowNodeValuePreview {
168
154
  if (value === null) return { kind: 'null' };
@@ -170,7 +156,7 @@ function previewValue(
170
156
  if (typeof value === 'string') {
171
157
  return {
172
158
  kind: 'scalar',
173
- value: safeString(value, input.redactor, input.key) ?? '',
159
+ value: safeString(value, input.redactor) ?? '',
174
160
  };
175
161
  }
176
162
  if (typeof value === 'number') {
@@ -207,18 +193,13 @@ function previewValue(
207
193
  ) {
208
194
  return {
209
195
  kind: 'dataset',
210
- datasetId:
211
- safeString(datasetId.value, input.redactor, 'datasetId') ?? 'dataset',
196
+ datasetId: safeString(datasetId.value, input.redactor) ?? 'dataset',
212
197
  datasetKind: datasetKind.value,
213
198
  tableNamespace:
214
199
  tableNamespace.ok && tableNamespace.value === null
215
200
  ? null
216
201
  : tableNamespace.ok
217
- ? safeString(
218
- tableNamespace.value,
219
- input.redactor,
220
- 'tableNamespace',
221
- )
202
+ ? safeString(tableNamespace.value, input.redactor)
222
203
  : undefined,
223
204
  };
224
205
  }
@@ -239,18 +220,13 @@ function previewValue(
239
220
  ) {
240
221
  return {
241
222
  kind: 'dataset',
242
- datasetId:
243
- safeString(datasetId.value, input.redactor, 'datasetId') ?? 'dataset',
223
+ datasetId: safeString(datasetId.value, input.redactor) ?? 'dataset',
244
224
  datasetKind: datasetKind.value,
245
225
  tableNamespace:
246
226
  tableNamespace.ok && tableNamespace.value === null
247
227
  ? null
248
228
  : tableNamespace.ok
249
- ? safeString(
250
- tableNamespace.value,
251
- input.redactor,
252
- 'tableNamespace',
253
- )
229
+ ? safeString(tableNamespace.value, input.redactor)
254
230
  : undefined,
255
231
  rowCount: Math.max(0, Math.floor(count.value)),
256
232
  };
@@ -309,7 +285,9 @@ function previewValue(
309
285
  const fields: Record<string, PlayDocflowNodeValuePreview> = {};
310
286
  for (const [key, descriptor] of selected) {
311
287
  const safeKey = truncateUtf8(
312
- ledgerSafeDocflowPreviewKey(input.redactor.redactString(key)),
288
+ ledgerSafeDocflowPreviewKey(
289
+ input.redactor?.redactRegisteredSecrets(key) ?? key,
290
+ ),
313
291
  DOCFLOW_NODE_IO_LIMITS.maxStringBytes,
314
292
  );
315
293
  fields[safeKey] =
@@ -317,7 +295,6 @@ function previewValue(
317
295
  ? previewValue(descriptor.value, {
318
296
  ...input,
319
297
  depth: input.depth + 1,
320
- key,
321
298
  })
322
299
  : { kind: 'unavailable', reason: 'access_error' };
323
300
  }
@@ -338,7 +315,6 @@ export function buildPlayDocflowNodeIoPreviewMap(
338
315
  values: Record<string, unknown>,
339
316
  options: PreviewOptions = {},
340
317
  ): { values: PlayDocflowNodeIoPreviewMap; truncated: boolean } {
341
- const redactor = options.redactor ?? createSecretRedactionContext();
342
318
  const previews: PlayDocflowNodeIoPreviewMap = {};
343
319
  let truncated = false;
344
320
  let entries: Array<[string, unknown]>;
@@ -356,14 +332,15 @@ export function buildPlayDocflowNodeIoPreviewMap(
356
332
  break;
357
333
  }
358
334
  const safePath = truncateUtf8(
359
- ledgerSafeDocflowPreviewKey(redactor.redactString(path)),
335
+ ledgerSafeDocflowPreviewKey(
336
+ options.redactor?.redactRegisteredSecrets(path) ?? path,
337
+ ),
360
338
  DOCFLOW_NODE_IO_LIMITS.maxStringBytes,
361
339
  );
362
340
  const preview = previewValue(value, {
363
341
  depth: 0,
364
342
  ancestors: new WeakSet(),
365
- redactor,
366
- key: path.split('.').at(-1),
343
+ redactor: options.redactor,
367
344
  });
368
345
  const candidate = { ...previews, [safePath]: preview };
369
346
  if (
@@ -413,7 +390,6 @@ export function buildPlayDocflowNodeInputPreviewMap(
413
390
  captures: readonly PlayDocflowNodeInputCapture[],
414
391
  options: PreviewOptions = {},
415
392
  ): { values: PlayDocflowNodeIoPreviewMap; truncated: boolean } {
416
- const redactor = options.redactor ?? createSecretRedactionContext();
417
393
  const values: PlayDocflowNodeIoPreviewMap = {};
418
394
  let truncated = false;
419
395
  for (const capture of captures.slice(0, DOCFLOW_NODE_IO_LIMITS.maxPaths)) {
@@ -435,15 +411,16 @@ export function buildPlayDocflowNodeInputPreviewMap(
435
411
  }
436
412
  }
437
413
  const safePath = truncateUtf8(
438
- ledgerSafeDocflowPreviewKey(redactor.redactString(capture.path)),
414
+ ledgerSafeDocflowPreviewKey(
415
+ options.redactor?.redactRegisteredSecrets(capture.path) ?? capture.path,
416
+ ),
439
417
  DOCFLOW_NODE_IO_LIMITS.maxStringBytes,
440
418
  );
441
419
  const preview: PlayDocflowNodeValuePreview = available
442
420
  ? previewValue(current, {
443
421
  depth: 0,
444
422
  ancestors: new WeakSet(),
445
- redactor,
446
- key: capture.properties.at(-1) ?? capture.path,
423
+ redactor: options.redactor,
447
424
  })
448
425
  : { kind: 'unavailable', reason: 'access_error' };
449
426
  const candidate = { ...values, [safePath]: preview };
@@ -494,7 +471,6 @@ function normalizePreview(
494
471
  return previewValue(value.value, {
495
472
  depth: 0,
496
473
  ancestors: new WeakSet(),
497
- redactor: createSecretRedactionContext(),
498
474
  });
499
475
  }
500
476
  return null;
@@ -523,11 +499,7 @@ function normalizePreview(
523
499
  : null;
524
500
  }
525
501
  if (value.kind === 'dataset') {
526
- const datasetId = safeString(
527
- value.datasetId,
528
- createSecretRedactionContext(),
529
- 'datasetId',
530
- );
502
+ const datasetId = safeString(value.datasetId);
531
503
  if (
532
504
  !datasetId ||
533
505
  (value.datasetKind !== 'csv' && value.datasetKind !== 'map')
@@ -542,11 +514,7 @@ function normalizePreview(
542
514
  ? { tableNamespace: null }
543
515
  : typeof value.tableNamespace === 'string'
544
516
  ? {
545
- tableNamespace: safeString(
546
- value.tableNamespace,
547
- createSecretRedactionContext(),
548
- 'tableNamespace',
549
- ),
517
+ tableNamespace: safeString(value.tableNamespace),
550
518
  }
551
519
  : {}),
552
520
  ...(typeof value.rowCount === 'number' && Number.isFinite(value.rowCount)
@@ -59,52 +59,33 @@ export function sanitizeOpaqueLedgerPayload(value: unknown): unknown {
59
59
  return redactedIssue ? opaqueLedgerPayloadSummary(redactedIssue) : redacted;
60
60
  }
61
61
 
62
- /** A receipt payload redacted once, serialized once, and measured from that text. */
62
+ /** A customer receipt value serialized once and measured from the stored text. */
63
63
  export type SanitizedRuntimeReceiptPayload = {
64
- /** The redacted value. Callers return or re-project this, never the source. */
65
64
  value: unknown;
66
- /**
67
- * Canonical Postgres JSON text for `value`, byte-identical to what
68
- * `stringifyPostgresJson(value ?? null)` produces. `jsonb` accepts this text
69
- * directly, so the completion path never re-serializes the same output.
70
- */
65
+ /** Canonical Postgres JSON text, passed directly to the jsonb completion write. */
71
66
  serialized: string;
72
- /** UTF-8 byte length of `serialized`; the measured size the limit is enforced on. */
67
+ /** UTF-8 byte length of `serialized`. */
73
68
  bytes: number;
74
69
  };
75
70
 
76
- /**
77
- * Secret-redact a receipt payload without coupling its 10 MiB cell limit to the
78
- * ledger, and serialize it exactly once.
79
- *
80
- * The limit is enforced on the redacted, serialized value that is actually
81
- * persisted. Redaction normally shrinks credential-shaped values but can expand
82
- * short matched strings, so measuring the source instead would be wrong in both
83
- * directions.
84
- *
85
- * Redaction is identity-preserving: a payload carrying no credential comes back
86
- * as the very object that was passed in, with no deep clone, and is serialized
87
- * exactly once. Only a payload that actually redacts pays for a rebuilt value.
88
- */
89
71
  export function sanitizeRuntimeReceiptPayloadForStorage(
90
72
  value: unknown,
91
73
  ): SanitizedRuntimeReceiptPayload {
92
- const redacted = ledgerIngressRedactor.redact(value);
93
74
  // `undefined` is not JSON. The receipt contract stores it as jsonb `null`,
94
75
  // which is exactly what the previous `stringifyPostgresJson(output ?? null)`
95
76
  // parameter produced.
96
- const serialized = stringifyPostgresJson(redacted ?? null);
77
+ const serialized = stringifyPostgresJson(value ?? null);
97
78
  if (serialized === undefined) {
98
79
  throw new TypeError('Runtime receipt output is not JSON-serializable.');
99
80
  }
100
81
  const bytes = assertSerializedRuntimeReceiptOutputWithinLimit({
101
82
  serialized,
102
- path: 'runtime receipt output after secret redaction',
83
+ path: 'runtime receipt output',
103
84
  });
104
- return { value: redacted, serialized, bytes };
85
+ return { value, serialized, bytes };
105
86
  }
106
87
 
107
- /** Secret-redact a receipt payload without coupling its 10 MiB cell limit to the ledger. */
88
+ /** Enforce the customer receipt byte limit without altering its values. */
108
89
  export function sanitizeRuntimeReceiptPayload(value: unknown): unknown {
109
90
  return sanitizeRuntimeReceiptPayloadForStorage(value).value;
110
91
  }
@@ -188,6 +188,7 @@ export type SecretRedactionContext = {
188
188
  /** Redacts only values registered by the secret resolver, preserving safe diagnostics. */
189
189
  redactRegisteredSecrets(value: string): string;
190
190
  redactString(value: string): string;
191
+ /** Redacts registered credential values recursively, without guessing from field names or patterns. */
191
192
  redactKnownSecrets<T>(value: T): T;
192
193
  redact<T>(value: T): T;
193
194
  };
@@ -335,7 +336,7 @@ export function createSecretRedactionContext(
335
336
  }
336
337
 
337
338
  function redactKnownSecrets<T>(value: T): T {
338
- if (typeof value === 'string') return redactString(value) as T;
339
+ if (typeof value === 'string') return redactRegisteredSecrets(value) as T;
339
340
  if (Array.isArray(value)) {
340
341
  return value.map((entry) => redactKnownSecrets(entry)) as T;
341
342
  }
@@ -360,3 +361,48 @@ export function createSecretRedactionContext(
360
361
  redact,
361
362
  };
362
363
  }
364
+
365
+ const REQUEST_CREDENTIAL_HEADER_NAMES = new Set([
366
+ 'authorization',
367
+ 'cookie',
368
+ 'proxy-authorization',
369
+ 'x-api-key',
370
+ 'api-key',
371
+ 'apikey',
372
+ 'x-auth',
373
+ 'auth-token',
374
+ 'access-token',
375
+ 'refresh-token',
376
+ 'session-token',
377
+ 'x-auth-token',
378
+ 'x-access-token',
379
+ 'x-refresh-token',
380
+ 'x-session-token',
381
+ ]);
382
+
383
+ export function createRequestHeaderSecretRedactionContext(
384
+ headers: Readonly<Record<string, string>>,
385
+ sensitiveHeaders: readonly string[] = [],
386
+ ): SecretRedactionContext {
387
+ const redactor = createSecretRedactionContext();
388
+ const declared = new Set(sensitiveHeaders.map((name) => name.toLowerCase()));
389
+ for (const [name, value] of Object.entries(headers)) {
390
+ const normalizedName = name.toLowerCase();
391
+ if (
392
+ !REQUEST_CREDENTIAL_HEADER_NAMES.has(normalizedName) &&
393
+ !declared.has(normalizedName)
394
+ ) {
395
+ continue;
396
+ }
397
+ redactor.register(value);
398
+ const auth = /^(?:bearer|basic)\s+(.+)$/i.exec(value.trim());
399
+ if (auth?.[1]) redactor.register(auth[1]);
400
+ if (normalizedName === 'cookie') {
401
+ for (const pair of value.split(';')) {
402
+ const separator = pair.indexOf('=');
403
+ if (separator > 0) redactor.register(pair.slice(separator + 1).trim());
404
+ }
405
+ }
406
+ }
407
+ return redactor;
408
+ }
@@ -6,7 +6,6 @@ type SecretRedactionOptions = {
6
6
  keyPolicy?: 'strict' | 'public-result';
7
7
  /** Replace sample cursor values with a non-capability-bearing placeholder. */
8
8
  placeholderContinuationValues?: boolean;
9
- redactJsonStrings?: boolean;
10
9
  };
11
10
 
12
11
  const SENSITIVE_KEY_PATTERNS = [
@@ -400,83 +399,12 @@ function maybeRedactString(value: string, options: SecretRedactionOptions) {
400
399
  : redacted.replace(HIGH_ENTROPY_VALUE_PATTERN, REDACTED_VALUE);
401
400
  }
402
401
 
403
- function parseJsonContainerText(value: unknown): unknown {
404
- if (typeof value !== 'string') return value;
405
- const trimmed = value.trim();
406
- if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return value;
407
- try {
408
- return JSON.parse(value);
409
- } catch {
410
- return value;
411
- }
412
- }
413
-
414
- function jsonStringContainsSecrets(
415
- value: string,
416
- options: SecretRedactionOptions,
417
- parentKey?: string,
418
- path: readonly string[] = [],
419
- ): boolean {
420
- // Inspect parsed values, but never reserialize SQL text and round its numeric literals.
421
- const parsed = parseJsonContainerText(value);
422
- if (!parsed || typeof parsed !== 'object') return false;
423
- const pending = [
424
- {
425
- value: parsed,
426
- parentKey,
427
- path: [...path],
428
- },
429
- ];
430
- const textOptions = { ...options, redactJsonStrings: false };
431
- while (pending.length > 0) {
432
- const current = pending.pop()!;
433
- const sourceIsArray = Array.isArray(current.value);
434
- for (const [key, rawItem] of Object.entries(current.value)) {
435
- const item = parseJsonContainerText(rawItem);
436
- const parentKey = sourceIsArray ? current.parentKey : key;
437
- if (
438
- !sourceIsArray &&
439
- options.keyPolicy === 'public-result' &&
440
- isPublicResultSafeTokenKey(key, current.path, item) &&
441
- (!item || typeof item !== 'object')
442
- ) {
443
- if (
444
- typeof item === 'string' &&
445
- maybeRedactString(item, textOptions) !== item
446
- )
447
- return true;
448
- continue;
449
- }
450
- if (!sourceIsArray && shouldRedactKey(key)) return true;
451
- if (item && typeof item === 'object') {
452
- pending.push({
453
- value: item,
454
- parentKey,
455
- path: sourceIsArray ? current.path : [...current.path, key],
456
- });
457
- } else if (
458
- typeof item === 'string' &&
459
- redactSecretsInValue(item, parentKey, textOptions) !== item
460
- ) {
461
- return true;
462
- }
463
- }
464
- }
465
- return false;
466
- }
467
-
468
402
  export function redactSecretsInValue<T>(
469
403
  value: T,
470
404
  parentKey?: string,
471
405
  options: SecretRedactionOptions = {},
472
406
  ): T {
473
407
  if (typeof value === 'string') {
474
- if (
475
- options.redactJsonStrings &&
476
- jsonStringContainsSecrets(value, options, parentKey)
477
- ) {
478
- return REDACTED_VALUE as T;
479
- }
480
408
  if (hasExplicitSecretValue(value, options)) {
481
409
  return REDACTED_VALUE as T;
482
410
  }
@@ -519,15 +447,8 @@ export function redactSecretsInValue<T>(
519
447
  const redactNestedValue = (
520
448
  item: unknown,
521
449
  itemParentKey: string | undefined,
522
- path: readonly string[],
523
450
  ): unknown => {
524
451
  if (typeof item !== 'string') return item;
525
- if (
526
- options.redactJsonStrings &&
527
- jsonStringContainsSecrets(item, options, itemParentKey, path)
528
- ) {
529
- return REDACTED_VALUE;
530
- }
531
452
  if (hasExplicitSecretValue(item, options)) {
532
453
  return REDACTED_VALUE;
533
454
  }
@@ -552,15 +473,7 @@ export function redactSecretsInValue<T>(
552
473
  (!item || typeof item !== 'object')
553
474
  ) {
554
475
  const redacted =
555
- typeof item === 'string'
556
- ? options.redactJsonStrings &&
557
- jsonStringContainsSecrets(item, options, itemParentKey, [
558
- ...current.path,
559
- key,
560
- ])
561
- ? REDACTED_VALUE
562
- : maybeRedactString(item, options)
563
- : item;
476
+ typeof item === 'string' ? maybeRedactString(item, options) : item;
564
477
  (current.target as Record<string, unknown>)[key] =
565
478
  options.placeholderContinuationValues &&
566
479
  isPublicResultCursorKey(key, current.path) &&
@@ -589,7 +502,6 @@ export function redactSecretsInValue<T>(
589
502
  (current.target as Record<string, unknown>)[key] = redactNestedValue(
590
503
  item,
591
504
  itemParentKey,
592
- sourceIsArray ? current.path : [...current.path, key],
593
505
  );
594
506
  }
595
507
  }
package/dist/cli/index.js CHANGED
@@ -3515,7 +3515,7 @@ var SDK_RELEASE = {
3515
3515
  // getters keep their established compatibility behavior.
3516
3516
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3517
3517
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3518
- version: "0.3.287",
3518
+ version: "0.3.289",
3519
3519
  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.",
3520
3520
  packageCapabilities: {
3521
3521
  updatePreferences: 1
@@ -5217,7 +5217,7 @@ function createSecretRedactionContext(initialValues = []) {
5217
5217
  return value;
5218
5218
  }
5219
5219
  function redactKnownSecrets(value) {
5220
- if (typeof value === "string") return redactString(value);
5220
+ if (typeof value === "string") return redactRegisteredSecrets(value);
5221
5221
  if (Array.isArray(value)) {
5222
5222
  return value.map((entry) => redactKnownSecrets(entry));
5223
5223
  }
@@ -46644,16 +46644,27 @@ function resolvePersistentGlobalCommand(dependencies = {}) {
46644
46644
  const pathClis = dependencies.pathClis ?? resolvePathCommands("deepline");
46645
46645
  const homebrewCommand = pathClis.find(isHomebrewFormulaCommand);
46646
46646
  if (homebrewCommand) return homebrewCommand;
46647
- const plan = resolveShellSpawn("npm", ["prefix", "-g"], platform3);
46648
- const prefix = run(plan.command, plan.args, {
46649
- encoding: "utf8",
46650
- shell: plan.shell
46651
- });
46652
- if (prefix.status !== 0) return null;
46653
- const root = String(prefix.stdout ?? "").trim();
46654
- if (!root) return null;
46655
- const candidates = platform3 === "win32" ? [(0, import_node_path27.join)(root, "deepline.cmd"), (0, import_node_path27.join)(root, "deepline")] : [(0, import_node_path27.join)(root, "bin", "deepline")];
46656
- return candidates.find((candidate) => pathExists(candidate)) ?? null;
46647
+ for (const manager of ["npm", "pnpm"]) {
46648
+ const plan = resolveShellSpawn(
46649
+ manager,
46650
+ manager === "npm" ? ["prefix", "-g"] : ["bin", "-g"],
46651
+ platform3
46652
+ );
46653
+ const result = run(plan.command, plan.args, {
46654
+ encoding: "utf8",
46655
+ shell: plan.shell,
46656
+ cwd: manager === "pnpm" ? (0, import_node_os14.homedir)() : void 0,
46657
+ timeout: 1e4
46658
+ });
46659
+ if (result.status !== 0) continue;
46660
+ const root = String(result.stdout ?? "").trim();
46661
+ if (!root) continue;
46662
+ const bin = manager === "npm" && platform3 !== "win32" ? (0, import_node_path27.join)(root, "bin") : root;
46663
+ const candidates = platform3 === "win32" ? [(0, import_node_path27.join)(bin, "deepline.cmd"), (0, import_node_path27.join)(bin, "deepline")] : [(0, import_node_path27.join)(bin, "deepline")];
46664
+ const command = candidates.find((candidate) => pathExists(candidate));
46665
+ if (command) return command;
46666
+ }
46667
+ return null;
46657
46668
  }
46658
46669
  function inspectGlobalCliAvailability(input2) {
46659
46670
  const pathClis = input2?.pathClis ?? resolvePathCommands("deepline");
@@ -3510,7 +3510,7 @@ var SDK_RELEASE = {
3510
3510
  // getters keep their established compatibility behavior.
3511
3511
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3512
3512
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3513
- version: "0.3.287",
3513
+ version: "0.3.289",
3514
3514
  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.",
3515
3515
  packageCapabilities: {
3516
3516
  updatePreferences: 1
@@ -5212,7 +5212,7 @@ function createSecretRedactionContext(initialValues = []) {
5212
5212
  return value;
5213
5213
  }
5214
5214
  function redactKnownSecrets(value) {
5215
- if (typeof value === "string") return redactString(value);
5215
+ if (typeof value === "string") return redactRegisteredSecrets(value);
5216
5216
  if (Array.isArray(value)) {
5217
5217
  return value.map((entry) => redactKnownSecrets(entry));
5218
5218
  }
@@ -46743,16 +46743,27 @@ function resolvePersistentGlobalCommand(dependencies = {}) {
46743
46743
  const pathClis = dependencies.pathClis ?? resolvePathCommands("deepline");
46744
46744
  const homebrewCommand = pathClis.find(isHomebrewFormulaCommand);
46745
46745
  if (homebrewCommand) return homebrewCommand;
46746
- const plan = resolveShellSpawn("npm", ["prefix", "-g"], platform3);
46747
- const prefix = run(plan.command, plan.args, {
46748
- encoding: "utf8",
46749
- shell: plan.shell
46750
- });
46751
- if (prefix.status !== 0) return null;
46752
- const root = String(prefix.stdout ?? "").trim();
46753
- if (!root) return null;
46754
- const candidates = platform3 === "win32" ? [join21(root, "deepline.cmd"), join21(root, "deepline")] : [join21(root, "bin", "deepline")];
46755
- return candidates.find((candidate) => pathExists(candidate)) ?? null;
46746
+ for (const manager of ["npm", "pnpm"]) {
46747
+ const plan = resolveShellSpawn(
46748
+ manager,
46749
+ manager === "npm" ? ["prefix", "-g"] : ["bin", "-g"],
46750
+ platform3
46751
+ );
46752
+ const result = run(plan.command, plan.args, {
46753
+ encoding: "utf8",
46754
+ shell: plan.shell,
46755
+ cwd: manager === "pnpm" ? homedir9() : void 0,
46756
+ timeout: 1e4
46757
+ });
46758
+ if (result.status !== 0) continue;
46759
+ const root = String(result.stdout ?? "").trim();
46760
+ if (!root) continue;
46761
+ const bin = manager === "npm" && platform3 !== "win32" ? join21(root, "bin") : root;
46762
+ const candidates = platform3 === "win32" ? [join21(bin, "deepline.cmd"), join21(bin, "deepline")] : [join21(bin, "deepline")];
46763
+ const command = candidates.find((candidate) => pathExists(candidate));
46764
+ if (command) return command;
46765
+ }
46766
+ return null;
46756
46767
  }
46757
46768
  function inspectGlobalCliAvailability(input2) {
46758
46769
  const pathClis = input2?.pathClis ?? resolvePathCommands("deepline");
package/dist/index.js CHANGED
@@ -1328,7 +1328,7 @@ var SDK_RELEASE = {
1328
1328
  // getters keep their established compatibility behavior.
1329
1329
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1330
1330
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
1331
- version: "0.3.287",
1331
+ version: "0.3.289",
1332
1332
  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.",
1333
1333
  packageCapabilities: {
1334
1334
  updatePreferences: 1
@@ -2968,7 +2968,7 @@ function createSecretRedactionContext(initialValues = []) {
2968
2968
  return value;
2969
2969
  }
2970
2970
  function redactKnownSecrets(value) {
2971
- if (typeof value === "string") return redactString(value);
2971
+ if (typeof value === "string") return redactRegisteredSecrets(value);
2972
2972
  if (Array.isArray(value)) {
2973
2973
  return value.map((entry) => redactKnownSecrets(entry));
2974
2974
  }
package/dist/index.mjs CHANGED
@@ -1232,7 +1232,7 @@ var SDK_RELEASE = {
1232
1232
  // getters keep their established compatibility behavior.
1233
1233
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1234
1234
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
1235
- version: "0.3.287",
1235
+ version: "0.3.289",
1236
1236
  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.",
1237
1237
  packageCapabilities: {
1238
1238
  updatePreferences: 1
@@ -2872,7 +2872,7 @@ function createSecretRedactionContext(initialValues = []) {
2872
2872
  return value;
2873
2873
  }
2874
2874
  function redactKnownSecrets(value) {
2875
- if (typeof value === "string") return redactString(value);
2875
+ if (typeof value === "string") return redactRegisteredSecrets(value);
2876
2876
  if (Array.isArray(value)) {
2877
2877
  return value.map((entry) => redactKnownSecrets(entry));
2878
2878
  }
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.287";
152
+ readonly version: "0.3.289";
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.287";
152
+ readonly version: "0.3.289";
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.287",
77
+ version: "0.3.289",
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.287",
51
+ version: "0.3.289",
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.287",
3
+ "version": "0.3.289",
4
4
  "description": "GTM data CLI and TypeScript SDK for coding agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://code.deepline.com",