deepline 0.3.251 → 0.3.253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/observability/scheduled-work-control.ts +25 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +85 -11
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +23 -5
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -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.
|
|
203
|
+
version: '0.3.253',
|
|
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: {
|
|
@@ -7,7 +7,19 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export const SCHEDULED_WORK_CONTROL_CONTRACT_VERSION = 1 as const;
|
|
9
9
|
|
|
10
|
-
export
|
|
10
|
+
export const SCHEDULED_WORK_CONTROL_ACTIONS = [
|
|
11
|
+
'run',
|
|
12
|
+
'start',
|
|
13
|
+
'pause',
|
|
14
|
+
'resume',
|
|
15
|
+
'retry',
|
|
16
|
+
'verify',
|
|
17
|
+
'activate',
|
|
18
|
+
'rollback',
|
|
19
|
+
] as const;
|
|
20
|
+
|
|
21
|
+
export type ScheduledWorkControlAction =
|
|
22
|
+
(typeof SCHEDULED_WORK_CONTROL_ACTIONS)[number];
|
|
11
23
|
|
|
12
24
|
export type ScheduledWorkControlContext = {
|
|
13
25
|
readonly jobId: string;
|
|
@@ -38,6 +50,10 @@ export type ScheduledWorkControlConnector = {
|
|
|
38
50
|
run?: (
|
|
39
51
|
context: ScheduledWorkControlContext,
|
|
40
52
|
) => Promise<ScheduledWorkRunResult>;
|
|
53
|
+
execute?: (
|
|
54
|
+
context: ScheduledWorkControlContext,
|
|
55
|
+
action: Exclude<ScheduledWorkControlAction, 'run'>,
|
|
56
|
+
) => Promise<ScheduledWorkRunResult>;
|
|
41
57
|
};
|
|
42
58
|
|
|
43
59
|
export type ScheduledWorkControlRegisterOptions = {
|
|
@@ -88,6 +104,14 @@ export class ScheduledWorkControlRegistry {
|
|
|
88
104
|
`Scheduled-work connector ${connector.id} declares run without an implementation.`,
|
|
89
105
|
);
|
|
90
106
|
}
|
|
107
|
+
if (
|
|
108
|
+
connector.actions.some((action) => action !== 'run') &&
|
|
109
|
+
typeof connector.execute !== 'function'
|
|
110
|
+
) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Scheduled-work connector ${connector.id} declares lifecycle controls without an implementation.`,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
91
115
|
if (
|
|
92
116
|
connector.actions.length === 0 &&
|
|
93
117
|
Object.keys(connector.unavailableActions ?? {}).length === 0
|
|
@@ -6426,16 +6426,11 @@ export async function repairPostgresSchedulerCronFire(
|
|
|
6426
6426
|
};
|
|
6427
6427
|
}
|
|
6428
6428
|
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
admissionEpoch: number;
|
|
6435
|
-
environment?: 'preview' | 'production';
|
|
6436
|
-
},
|
|
6437
|
-
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
6438
|
-
): Promise<void> {
|
|
6429
|
+
function runtimeReleaseAdmissionKeys(input: {
|
|
6430
|
+
releaseId: string;
|
|
6431
|
+
admissionEpoch: number;
|
|
6432
|
+
environment?: 'preview' | 'production';
|
|
6433
|
+
}) {
|
|
6439
6434
|
const releaseId = input.releaseId.trim();
|
|
6440
6435
|
const environment = input.environment ?? 'production';
|
|
6441
6436
|
const releaseAdmissionKey = `${environment}:${releaseId}`;
|
|
@@ -6458,6 +6453,21 @@ export async function setPostgresSchedulerRuntimeReleaseAdmission(
|
|
|
6458
6453
|
'Runtime release admission requires a non-negative safe-integer admissionEpoch.',
|
|
6459
6454
|
);
|
|
6460
6455
|
}
|
|
6456
|
+
return { releaseAdmissionLockKeys, releaseAdmissionWriteKeys };
|
|
6457
|
+
}
|
|
6458
|
+
|
|
6459
|
+
export async function setPostgresSchedulerRuntimeReleaseAdmission(
|
|
6460
|
+
client: PostgresSchedulerQueryClient,
|
|
6461
|
+
input: {
|
|
6462
|
+
releaseId: string;
|
|
6463
|
+
accepting: boolean;
|
|
6464
|
+
admissionEpoch: number;
|
|
6465
|
+
environment?: 'preview' | 'production';
|
|
6466
|
+
},
|
|
6467
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
6468
|
+
): Promise<void> {
|
|
6469
|
+
const { releaseAdmissionLockKeys, releaseAdmissionWriteKeys } =
|
|
6470
|
+
runtimeReleaseAdmissionKeys(input);
|
|
6461
6471
|
await client.query(
|
|
6462
6472
|
`
|
|
6463
6473
|
WITH admission_lock AS MATERIALIZED (
|
|
@@ -6493,6 +6503,61 @@ export async function setPostgresSchedulerRuntimeReleaseAdmission(
|
|
|
6493
6503
|
);
|
|
6494
6504
|
}
|
|
6495
6505
|
|
|
6506
|
+
/**
|
|
6507
|
+
* Keep a retired lane's final PostgreSQL-only cleanup ordered with admission
|
|
6508
|
+
* and Preview reclaim. The callback must not await remote control-plane work.
|
|
6509
|
+
* A separate statement after the lock wait sees any epoch committed by the
|
|
6510
|
+
* preceding owner; a lock and check in one CTE would retain the old snapshot.
|
|
6511
|
+
*/
|
|
6512
|
+
export async function withPostgresSchedulerClosedReleaseAdmission<T>(
|
|
6513
|
+
client: PostgresSchedulerQueryClient,
|
|
6514
|
+
input: {
|
|
6515
|
+
releaseId: string;
|
|
6516
|
+
admissionEpoch: number;
|
|
6517
|
+
environment: 'preview' | 'production';
|
|
6518
|
+
},
|
|
6519
|
+
operation: () => Promise<T>,
|
|
6520
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
6521
|
+
): Promise<{ guarded: false } | { guarded: true; value: T }> {
|
|
6522
|
+
const { releaseAdmissionLockKeys } = runtimeReleaseAdmissionKeys(input);
|
|
6523
|
+
await client.query('BEGIN ISOLATION LEVEL READ COMMITTED');
|
|
6524
|
+
try {
|
|
6525
|
+
await client.query(
|
|
6526
|
+
`SELECT pg_advisory_xact_lock(
|
|
6527
|
+
${POSTGRES_SCHEDULER_RELEASE_ADMISSION_LOCK_NAMESPACE},
|
|
6528
|
+
${quoteIdent(schemaName(options))}.runtime_release_admission_lock_id(lock_key)
|
|
6529
|
+
)
|
|
6530
|
+
FROM unnest($1::text[]) AS lock_key
|
|
6531
|
+
ORDER BY lock_key`,
|
|
6532
|
+
[releaseAdmissionLockKeys],
|
|
6533
|
+
);
|
|
6534
|
+
const admission = await client.query<{ closed: boolean }>(
|
|
6535
|
+
`SELECT count(*)::integer = cardinality($1::text[])
|
|
6536
|
+
AND coalesce(bool_and(NOT accepting AND admission_epoch = $2::bigint), false) AS closed
|
|
6537
|
+
FROM ${tableName('runtime_release_admission', options)}
|
|
6538
|
+
WHERE release_id = ANY($1::text[])`,
|
|
6539
|
+
[releaseAdmissionLockKeys, input.admissionEpoch],
|
|
6540
|
+
);
|
|
6541
|
+
if (admission.rows[0]?.closed !== true) {
|
|
6542
|
+
await client.query('COMMIT');
|
|
6543
|
+
return { guarded: false };
|
|
6544
|
+
}
|
|
6545
|
+
const value = await operation();
|
|
6546
|
+
await client.query('COMMIT');
|
|
6547
|
+
return { guarded: true, value };
|
|
6548
|
+
} catch (error) {
|
|
6549
|
+
try {
|
|
6550
|
+
await client.query('ROLLBACK');
|
|
6551
|
+
} catch (rollbackError) {
|
|
6552
|
+
throw new AggregateError(
|
|
6553
|
+
[error, rollbackError],
|
|
6554
|
+
'Retired release cleanup failed and its transaction could not roll back.',
|
|
6555
|
+
);
|
|
6556
|
+
}
|
|
6557
|
+
throw error;
|
|
6558
|
+
}
|
|
6559
|
+
}
|
|
6560
|
+
|
|
6496
6561
|
/**
|
|
6497
6562
|
* Scheduler-run statuses and suspension kinds a newer release lane may adopt.
|
|
6498
6563
|
*
|
|
@@ -18026,6 +18091,9 @@ export async function listPostgresSchedulerOutboxMaterializationPlans(
|
|
|
18026
18091
|
*/
|
|
18027
18092
|
export type RunLedgerOutboxTokenAuthority = 'local_mint' | 'gateway';
|
|
18028
18093
|
|
|
18094
|
+
/** Cross-run service policy; causal order within a run is always unchanged. */
|
|
18095
|
+
export type RunLedgerOutboxHeadPriority = 'admission_first' | 'oldest_ready';
|
|
18096
|
+
|
|
18029
18097
|
const POSTGRES_SCHEDULER_CANCELLATION_OUTBOX_LEASE_SECONDS =
|
|
18030
18098
|
// The direct projection can run for the full app-runtime request deadline.
|
|
18031
18099
|
// Keep another 30 seconds for dispatch setup and acknowledgement so a
|
|
@@ -18067,6 +18135,8 @@ export type RunLedgerOutboxDispatchInput = {
|
|
|
18067
18135
|
runId?: string | null;
|
|
18068
18136
|
leaseOwner?: string | null;
|
|
18069
18137
|
leaseSeconds?: number;
|
|
18138
|
+
/** Defaults to the compatible admission-first claim order. */
|
|
18139
|
+
headPriority?: RunLedgerOutboxHeadPriority;
|
|
18070
18140
|
/**
|
|
18071
18141
|
* Token authority for the outbox dispatch. Defaults to `local_mint` for the
|
|
18072
18142
|
* app-side authoritative projector. The Fly worker MUST pass `gateway`.
|
|
@@ -18328,7 +18398,11 @@ export async function dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope(
|
|
|
18328
18398
|
AND active.lease_owner IS NOT NULL
|
|
18329
18399
|
AND active.lease_expires_at > now()
|
|
18330
18400
|
)
|
|
18331
|
-
ORDER BY
|
|
18401
|
+
ORDER BY ${
|
|
18402
|
+
input.headPriority === 'oldest_ready'
|
|
18403
|
+
? ''
|
|
18404
|
+
: "CASE WHEN head.event_type = 'run.created' THEN 0 ELSE 1 END,"
|
|
18405
|
+
}
|
|
18332
18406
|
head.created_at, runs.run_id
|
|
18333
18407
|
FOR UPDATE OF runs SKIP LOCKED LIMIT 1
|
|
18334
18408
|
`);
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
readPostgresSchedulerOutboxNextDueAt,
|
|
15
15
|
type PostgresSchedulerOptions,
|
|
16
16
|
type PostgresSchedulerOutboxProjectionResult,
|
|
17
|
+
type RunLedgerOutboxHeadPriority,
|
|
17
18
|
} from './postgres';
|
|
18
19
|
import {
|
|
19
20
|
acquirePgNotifyHub,
|
|
@@ -59,6 +60,11 @@ export const RUN_LEDGER_OUTBOX_RECOVERY_MAX_IN_FLIGHT = 32;
|
|
|
59
60
|
// The higher exported ceiling remains available to isolated recovery callers,
|
|
60
61
|
// but it is not the steady-state production setting.
|
|
61
62
|
const RUN_LEDGER_OUTBOX_RECOVERY_PRODUCTION_IN_FLIGHT = 8;
|
|
63
|
+
// Admissions retain three of four claim opportunities. The fourth selects
|
|
64
|
+
// the oldest eligible causal head across all runs, preventing terminal work
|
|
65
|
+
// from starving behind continuous new admissions. An empty class never costs
|
|
66
|
+
// another query: either order can select any eligible run.
|
|
67
|
+
const ADMISSION_TURNS_PER_OLDEST_READY_TURN = 3;
|
|
62
68
|
|
|
63
69
|
type RecoveryTimer = ReturnType<typeof setTimeout>;
|
|
64
70
|
|
|
@@ -66,7 +72,9 @@ export type RunLedgerOutboxRecoveryLogger = Pick<Console, 'info' | 'warn'>;
|
|
|
66
72
|
|
|
67
73
|
export type RunLedgerOutboxRecoveryDeps = {
|
|
68
74
|
/** One bounded durable claim/delivery attempt. */
|
|
69
|
-
dispatchOnce: (
|
|
75
|
+
dispatchOnce: (
|
|
76
|
+
headPriority: RunLedgerOutboxHeadPriority,
|
|
77
|
+
) => Promise<PostgresSchedulerOutboxProjectionResult>;
|
|
70
78
|
/** Earliest pending retry time or active lease expiry in the durable outbox. */
|
|
71
79
|
readNextDueAt: () => Promise<Date | null>;
|
|
72
80
|
/** A direct LISTEN connection. It is a hint only; a null lease is safe. */
|
|
@@ -131,6 +139,14 @@ export function startRunLedgerOutboxRecovery(
|
|
|
131
139
|
let unsubscribeNotify: (() => void) | undefined;
|
|
132
140
|
let unsubscribeState: (() => void) | undefined;
|
|
133
141
|
let requestDrain: (reason: string) => void = () => undefined;
|
|
142
|
+
let admissionTurns = 0;
|
|
143
|
+
|
|
144
|
+
const dispatchOnce = () => {
|
|
145
|
+
const oldestReady =
|
|
146
|
+
admissionTurns === ADMISSION_TURNS_PER_OLDEST_READY_TURN;
|
|
147
|
+
admissionTurns = oldestReady ? 0 : admissionTurns + 1;
|
|
148
|
+
return deps.dispatchOnce(oldestReady ? 'oldest_ready' : 'admission_first');
|
|
149
|
+
};
|
|
134
150
|
|
|
135
151
|
const clearWakeTimer = () => {
|
|
136
152
|
if (!timer) return;
|
|
@@ -254,7 +270,9 @@ export function startRunLedgerOutboxRecovery(
|
|
|
254
270
|
const drain = async (reason: string): Promise<void> => {
|
|
255
271
|
type Delivery = {
|
|
256
272
|
id: symbol;
|
|
257
|
-
result:
|
|
273
|
+
result:
|
|
274
|
+
| PromiseSettledResult<PostgresSchedulerOutboxProjectionResult>
|
|
275
|
+
| { status: 'skipped' };
|
|
258
276
|
};
|
|
259
277
|
const pending = new Set<symbol>();
|
|
260
278
|
const deliveries: Delivery[] = [];
|
|
@@ -303,7 +321,7 @@ export function startRunLedgerOutboxRecovery(
|
|
|
303
321
|
return;
|
|
304
322
|
}
|
|
305
323
|
try {
|
|
306
|
-
settle({ status: 'fulfilled', value: await
|
|
324
|
+
settle({ status: 'fulfilled', value: await dispatchOnce() });
|
|
307
325
|
} catch (reason) {
|
|
308
326
|
settle({ status: 'rejected', reason });
|
|
309
327
|
}
|
|
@@ -410,10 +428,10 @@ export function startRunLedgerOutboxRecoveryController(input: {
|
|
|
410
428
|
schedulerOptions,
|
|
411
429
|
}),
|
|
412
430
|
),
|
|
413
|
-
dispatchOnce: () =>
|
|
431
|
+
dispatchOnce: (headPriority) =>
|
|
414
432
|
dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope(
|
|
415
433
|
(operation) => withRuntimeSchedulerClient(input.poolOptions, operation),
|
|
416
|
-
{ tokenAuthority: 'gateway', limit: 8 },
|
|
434
|
+
{ tokenAuthority: 'gateway', limit: 8, headPriority },
|
|
417
435
|
schedulerOptions,
|
|
418
436
|
),
|
|
419
437
|
// `dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope` releases each
|
package/dist/cli/index.js
CHANGED
|
@@ -3507,7 +3507,7 @@ var SDK_RELEASE = {
|
|
|
3507
3507
|
// getters keep their established compatibility behavior.
|
|
3508
3508
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3509
3509
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3510
|
-
version: "0.3.
|
|
3510
|
+
version: "0.3.253",
|
|
3511
3511
|
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.",
|
|
3512
3512
|
packageCapabilities: {
|
|
3513
3513
|
updatePreferences: 1
|
package/dist/cli/index.mjs
CHANGED
|
@@ -3502,7 +3502,7 @@ var SDK_RELEASE = {
|
|
|
3502
3502
|
// getters keep their established compatibility behavior.
|
|
3503
3503
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3504
3504
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3505
|
-
version: "0.3.
|
|
3505
|
+
version: "0.3.253",
|
|
3506
3506
|
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.",
|
|
3507
3507
|
packageCapabilities: {
|
|
3508
3508
|
updatePreferences: 1
|
package/dist/index.js
CHANGED
|
@@ -1320,7 +1320,7 @@ var SDK_RELEASE = {
|
|
|
1320
1320
|
// getters keep their established compatibility behavior.
|
|
1321
1321
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1322
1322
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
1323
|
-
version: "0.3.
|
|
1323
|
+
version: "0.3.253",
|
|
1324
1324
|
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.",
|
|
1325
1325
|
packageCapabilities: {
|
|
1326
1326
|
updatePreferences: 1
|
package/dist/index.mjs
CHANGED
|
@@ -1224,7 +1224,7 @@ var SDK_RELEASE = {
|
|
|
1224
1224
|
// getters keep their established compatibility behavior.
|
|
1225
1225
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1226
1226
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
1227
|
-
version: "0.3.
|
|
1227
|
+
version: "0.3.253",
|
|
1228
1228
|
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.",
|
|
1229
1229
|
packageCapabilities: {
|
|
1230
1230
|
updatePreferences: 1
|
package/dist/release.d.mts
CHANGED
|
@@ -149,7 +149,7 @@ type SdkRelease = {
|
|
|
149
149
|
supportPolicy: SdkSupportPolicy;
|
|
150
150
|
};
|
|
151
151
|
declare const SDK_RELEASE: {
|
|
152
|
-
readonly version: "0.3.
|
|
152
|
+
readonly version: "0.3.253";
|
|
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.
|
|
152
|
+
readonly version: "0.3.253";
|
|
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.
|
|
77
|
+
version: "0.3.253",
|
|
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.
|
|
51
|
+
version: "0.3.253",
|
|
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
|