deepline 0.3.304 → 0.3.306
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/cli-invocation-id.ts +14 -0
- package/dist/bundling-sources/sdk/src/client.ts +24 -1
- package/dist/bundling-sources/sdk/src/http.ts +11 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/tool-calls.ts +19 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +51 -25
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +10 -0
- package/dist/bundling-sources/shared_libs/product-notifications/billing-sales.ts +13 -0
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +69 -0
- package/dist/bundling-sources/shared_libs/product-notifications/default-policy.ts +26 -1
- package/dist/bundling-sources/shared_libs/product-notifications/events.ts +9 -1
- package/dist/cli/{auth-YKJHKHIQ.mjs → auth-WTC7LCQ6.mjs} +4 -4
- package/dist/cli/auth-ZT3UF33R.js +31 -0
- package/dist/cli/{billing-EOIKAZES.js → billing-3DYTHO32.js} +70 -70
- package/dist/cli/{billing-XEEW5SV2.mjs → billing-VQM65LVP.mjs} +4 -4
- package/dist/cli/chunk-2IKIG333.js +65 -0
- package/dist/cli/{chunk-NC4JXVVS.js → chunk-2KR56MPF.js} +2 -2
- package/dist/cli/{chunk-7QV545D7.mjs → chunk-4PSSDZQB.mjs} +7 -1
- package/dist/cli/{chunk-NW7I3LDU.mjs → chunk-5HS5EEFE.mjs} +3 -3
- package/dist/cli/{chunk-35SCWK4Y.mjs → chunk-5V56XCQN.mjs} +1 -1
- package/dist/cli/{chunk-JKY2QANB.mjs → chunk-6CRUYVU7.mjs} +4 -4
- package/dist/cli/{chunk-IHT6XITB.mjs → chunk-7XORS6WQ.mjs} +2 -2
- package/dist/cli/{chunk-7HYH533G.mjs → chunk-FJ3DANI4.mjs} +1 -1
- package/dist/cli/{chunk-KP5TOAI4.js → chunk-FZNO6B4W.js} +6 -6
- package/dist/cli/{chunk-JZWC4ES6.mjs → chunk-LLGF6V6I.mjs} +44 -8
- package/dist/cli/{chunk-DOCDA2YP.js → chunk-M6HCRRV2.js} +10 -4
- package/dist/cli/{chunk-BBXO7APG.js → chunk-MMNZ6GBT.js} +6 -6
- package/dist/cli/{chunk-INOSSTSG.js → chunk-OF7QP2XX.js} +15 -15
- package/dist/cli/{chunk-ZQSQCHG3.js → chunk-OZIFVQRY.js} +1 -1
- package/dist/cli/{chunk-FDEU7UY7.js → chunk-PHNAFCSB.js} +275 -239
- package/dist/cli/{chunk-TABL2Q6H.mjs → chunk-QDC4XTO3.mjs} +2 -2
- package/dist/cli/{chunk-DNBJRKVE.js → chunk-RODIZCGU.js} +60 -60
- package/dist/cli/{chunk-NJS3RHQO.js → chunk-SZQPJW2L.js} +6 -6
- package/dist/cli/{chunk-7NQJDQPH.js → chunk-U37SW6IK.js} +48 -48
- package/dist/cli/chunk-UABLQKTZ.mjs +65 -0
- package/dist/cli/{chunk-AOUGAM72.mjs → chunk-UT3VLSLM.mjs} +5 -5
- package/dist/cli/{chunk-USJBSNRI.js → chunk-W7ELTWDM.js} +26 -26
- package/dist/cli/{chunk-YJ2QYYB5.mjs → chunk-WV64SNDV.mjs} +1 -1
- package/dist/cli/{chunk-7OXXCRGZ.mjs → chunk-WWPI4GJI.mjs} +1 -1
- package/dist/cli/{client-FZPHVNWV.mjs → client-DCEK34D5.mjs} +3 -3
- package/dist/cli/client-UQXVU2T6.js +20 -0
- package/dist/cli/{csv-ANJ4KSHF.js → csv-H42JDJ6G.js} +12 -12
- package/dist/cli/{csv-CCHVZPRD.mjs → csv-LXBF5UIV.mjs} +3 -3
- package/dist/cli/{db-JFVR6STL.mjs → db-3O5CFLNP.mjs} +4 -4
- package/dist/cli/{db-AE3MLMRF.js → db-DP5GU4MU.js} +20 -20
- package/dist/cli/{executions-DGX53UEW.js → executions-5FFTPHEX.js} +6 -6
- package/dist/cli/{executions-WNXCURLN.mjs → executions-QC2UZKIP.mjs} +4 -4
- package/dist/cli/{feedback-L4A66OA2.mjs → feedback-JCGE6JFW.mjs} +3 -3
- package/dist/cli/{feedback-DGEFG6JI.js → feedback-XAU3FI5S.js} +6 -6
- package/dist/cli/git-CNO2UFZE.js +23 -0
- package/dist/cli/{git-LIZ3FGVR.mjs → git-S3Y3E2NL.mjs} +4 -4
- package/dist/cli/index.js +155 -121
- package/dist/cli/index.mjs +121 -87
- package/dist/cli/{legacy-noops-UCKGOSJA.mjs → legacy-noops-FQF2IRVS.mjs} +4 -4
- package/dist/cli/{legacy-noops-L7GGGAOR.js → legacy-noops-TXOUX4FX.js} +7 -7
- package/dist/cli/{monitors-NGACMMWV.js → monitors-4BQCO6B7.js} +85 -85
- package/dist/cli/{monitors-NLMFDD4C.mjs → monitors-F3PELPSH.mjs} +4 -4
- package/dist/cli/{org-2OW6TPHF.mjs → org-ER5J3ATG.mjs} +4 -4
- package/dist/cli/{org-FJSCZ6S3.js → org-VQM6OOLK.js} +60 -60
- package/dist/cli/{play-ZZ4AQLL5.mjs → play-B5H2RN4N.mjs} +6 -6
- package/dist/cli/{play-GJC4AIAX.js → play-WKZPAOW3.js} +200 -200
- package/dist/cli/{providers-D7KLXB4S.js → providers-5TEA2FJG.js} +7 -7
- package/dist/cli/{providers-6BJNJUSG.mjs → providers-6ODEAYC2.mjs} +4 -4
- package/dist/cli/{quickstart-FH4NGHEJ.mjs → quickstart-BCYT7BCY.mjs} +3 -3
- package/dist/cli/{quickstart-6WYRYZJZ.js → quickstart-GJYCNMFC.js} +5 -5
- package/dist/cli/{search-KOSJMN3U.js → search-KKJ535OX.js} +6 -6
- package/dist/cli/{search-SUT5XFI6.mjs → search-RY547KOT.mjs} +5 -5
- package/dist/cli/{secrets-Y2OI2P7O.js → secrets-RFGDXSEW.js} +13 -13
- package/dist/cli/{secrets-QK5QP4YU.mjs → secrets-U42ZEYIU.mjs} +4 -4
- package/dist/cli/{sessions-VQKZHOQJ.mjs → sessions-YWEFB62D.mjs} +4 -4
- package/dist/cli/{sessions-MLDROWXY.js → sessions-ZRTWHMIH.js} +5 -5
- package/dist/cli/{settings-SPUINZYG.mjs → settings-AS4U6NVP.mjs} +7 -7
- package/dist/cli/{settings-6WOSPHBC.js → settings-XUWFXIL7.js} +74 -74
- package/dist/cli/{setup-ZE2SDMC4.mjs → setup-2GUIV2EW.mjs} +6 -6
- package/dist/cli/{setup-E2UJV6PW.js → setup-2QPWP2FI.js} +41 -41
- package/dist/cli/skills-4E5KYW2Y.js +28 -0
- package/dist/cli/{skills-OJYRPY2N.mjs → skills-5QS7ERVF.mjs} +4 -4
- package/dist/cli/{tools-BNHRVKLA.js → tools-J47LIO2H.js} +120 -87
- package/dist/cli/{tools-O6EIDEKW.mjs → tools-PVWSGCZD.mjs} +76 -43
- package/dist/cli/update-GZKGOMKD.js +28 -0
- package/dist/cli/{update-NWESWMYF.mjs → update-KS4TRSZI.mjs} +6 -6
- package/dist/cli/{workflow-SAJAOPYE.js → workflow-HQRUUTTL.js} +15 -15
- package/dist/cli/{workflow-YJHXDD57.mjs → workflow-QCLR7GVC.mjs} +5 -5
- package/dist/{client-Me88eH3z.d.mts → client-Dj8MAkDc.d.mts} +91 -1
- package/dist/{client-DjJfoW8r.d.ts → client-DsrFGXJf.d.ts} +91 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -6
- package/dist/index.mjs +3 -3
- package/dist/install-integrity.json +74 -70
- package/dist/plays/run-request.d.mts +1 -1
- package/dist/plays/run-request.d.ts +1 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli/auth-UBWZC26A.js +0 -31
- package/dist/cli/client-IMFLPCD7.js +0 -20
- package/dist/cli/git-6QWUB6CR.js +0 -23
- package/dist/cli/skills-J3QIHO5L.js +0 -28
- package/dist/cli/update-TDOIF3C4.js +0 -28
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DeeplineError } from './errors.js';
|
|
2
|
+
|
|
3
|
+
const CLI_INVOCATION_ID_PATTERN =
|
|
4
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
5
|
+
|
|
6
|
+
export function validateCliInvocationId(value: string): void {
|
|
7
|
+
if (!CLI_INVOCATION_ID_PATTERN.test(value)) {
|
|
8
|
+
throw new DeeplineError(
|
|
9
|
+
'CLI invocation IDs must be UUID v4 values.',
|
|
10
|
+
undefined,
|
|
11
|
+
'CLI_INVOCATION_ID_INVALID',
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
type ExecutionByKeyResult,
|
|
58
58
|
type ToolExecution,
|
|
59
59
|
} from './tool-calls.js';
|
|
60
|
+
import { validateCliInvocationId } from './cli-invocation-id.js';
|
|
60
61
|
export type {
|
|
61
62
|
ExecutionRecovery,
|
|
62
63
|
ExecutionByKeyResult,
|
|
@@ -3263,7 +3264,13 @@ export class DeeplineClient {
|
|
|
3263
3264
|
* console.log(`Input schema:`, meta.inputSchema);
|
|
3264
3265
|
* ```
|
|
3265
3266
|
*/
|
|
3266
|
-
async getTool(
|
|
3267
|
+
async getTool(
|
|
3268
|
+
toolId: string,
|
|
3269
|
+
options?: { cliInvocationId?: string },
|
|
3270
|
+
): Promise<ToolMetadata> {
|
|
3271
|
+
if (options?.cliInvocationId !== undefined) {
|
|
3272
|
+
validateCliInvocationId(options.cliInvocationId);
|
|
3273
|
+
}
|
|
3267
3274
|
return this.http.request<ToolMetadata>(
|
|
3268
3275
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/get`,
|
|
3269
3276
|
{
|
|
@@ -3274,6 +3281,9 @@ export class DeeplineClient {
|
|
|
3274
3281
|
retryApiErrors: true,
|
|
3275
3282
|
headers: {
|
|
3276
3283
|
'x-deepline-tool-meta-only': '1',
|
|
3284
|
+
...(options?.cliInvocationId !== undefined
|
|
3285
|
+
? { 'x-deepline-cli-invocation-id': options.cliInvocationId }
|
|
3286
|
+
: {}),
|
|
3277
3287
|
},
|
|
3278
3288
|
},
|
|
3279
3289
|
);
|
|
@@ -5427,7 +5437,11 @@ export class DeeplineClient {
|
|
|
5427
5437
|
query: string;
|
|
5428
5438
|
compact?: boolean;
|
|
5429
5439
|
scope?: 'prebuilt' | 'owned' | 'all';
|
|
5440
|
+
cliInvocationId?: string;
|
|
5430
5441
|
}): Promise<PlayDescription[]> {
|
|
5442
|
+
if (options.cliInvocationId !== undefined) {
|
|
5443
|
+
validateCliInvocationId(options.cliInvocationId);
|
|
5444
|
+
}
|
|
5431
5445
|
const params = new URLSearchParams();
|
|
5432
5446
|
params.set('search', options.query.trim());
|
|
5433
5447
|
const scope = options.scope ?? 'prebuilt';
|
|
@@ -5436,6 +5450,15 @@ export class DeeplineClient {
|
|
|
5436
5450
|
}
|
|
5437
5451
|
const response = await this.http.get<{ plays: PlayListItem[] }>(
|
|
5438
5452
|
`/api/v2/plays?${params.toString()}`,
|
|
5453
|
+
{
|
|
5454
|
+
...(options.cliInvocationId !== undefined
|
|
5455
|
+
? {
|
|
5456
|
+
headers: {
|
|
5457
|
+
'x-deepline-cli-invocation-id': options.cliInvocationId,
|
|
5458
|
+
},
|
|
5459
|
+
}
|
|
5460
|
+
: {}),
|
|
5461
|
+
},
|
|
5439
5462
|
);
|
|
5440
5463
|
const plays = (response.plays ?? []).map((play) =>
|
|
5441
5464
|
this.summarizePlayListItem(play, options),
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* - **Max attempts**: `1 + maxRetries` (default: 4 total attempts)
|
|
10
10
|
* - **Backoff**: exponential — 1s, 2s, 4s, 8s, ... capped at 30s
|
|
11
|
+
* - **Total automatic retry wait**: 30s per request; a longer upstream
|
|
12
|
+
* `Retry-After` is returned to the caller instead of blocking the request
|
|
11
13
|
* - **Retryable**: network errors, timeouts, HTTP 429 (rate limit)
|
|
12
14
|
* - **Not retryable**: HTTP 401 (auth error), HTTP 403 and other 4xx API errors
|
|
13
15
|
*
|
|
@@ -54,6 +56,7 @@ const COWORK_NETWORK_HINT =
|
|
|
54
56
|
'Claude Cowork appears to be running Deepline in a network-restricted sandbox. In Claude Desktop, open Settings > Capabilities, turn on Allow network egress, and set Domain allowlist to All domains for the Cowork session.';
|
|
55
57
|
const REQUEST_TIMEOUT_MARKER = Symbol('deeplineRequestTimeout');
|
|
56
58
|
const REQUEST_ABORT_MARKER = Symbol('deeplineRequestAbort');
|
|
59
|
+
const MAX_AUTOMATIC_RETRY_WAIT_MS = 30_000;
|
|
57
60
|
|
|
58
61
|
interface RequestOptions {
|
|
59
62
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
@@ -431,6 +434,7 @@ export class HttpClient {
|
|
|
431
434
|
? [url]
|
|
432
435
|
: buildCandidateUrls(url);
|
|
433
436
|
let retryAfterDelayMs: number | null = null;
|
|
437
|
+
let totalRetryWaitMs = 0;
|
|
434
438
|
|
|
435
439
|
const maxRetries = options?.maxRetries ?? this.config.maxRetries;
|
|
436
440
|
|
|
@@ -447,6 +451,13 @@ export class HttpClient {
|
|
|
447
451
|
? backoffMs
|
|
448
452
|
: Math.max(backoffMs, retryAfterDelayMs);
|
|
449
453
|
retryAfterDelayMs = null;
|
|
454
|
+
if (totalRetryWaitMs + delayMs > MAX_AUTOMATIC_RETRY_WAIT_MS) {
|
|
455
|
+
// Honor the upstream delay by returning its original error. Never
|
|
456
|
+
// retry sooner than requested, and never let automatic retries hold
|
|
457
|
+
// the caller for an unbounded series of Retry-After sleeps.
|
|
458
|
+
break requestAttempts;
|
|
459
|
+
}
|
|
460
|
+
totalRetryWaitMs += delayMs;
|
|
450
461
|
networkPhase = 'retry_wait';
|
|
451
462
|
try {
|
|
452
463
|
await sleep(delayMs, options?.signal);
|
|
@@ -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.306',
|
|
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: {
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
|
|
19
19
|
import { DeeplineError, ToolExecutionError } from './errors.js';
|
|
20
20
|
import type { HttpClient } from './http.js';
|
|
21
|
+
import { validateCliInvocationId } from './cli-invocation-id.js';
|
|
21
22
|
|
|
22
23
|
const INCLUDE_TOOL_METADATA_HEADER = 'x-deepline-include-tool-metadata';
|
|
23
24
|
const EXECUTE_RESPONSE_CONTRACT_HEADER = 'x-deepline-execute-response-contract';
|
|
@@ -132,6 +133,8 @@ export type ExecuteToolRawOptions = {
|
|
|
132
133
|
recoveryTimeoutMs?: number;
|
|
133
134
|
/** The `search_ref` of the tools search that found this tool. */
|
|
134
135
|
searchRef?: string;
|
|
136
|
+
/** Correlates one CLI command with its execute request and server telemetry. */
|
|
137
|
+
cliInvocationId?: string;
|
|
135
138
|
};
|
|
136
139
|
|
|
137
140
|
/** Durable state returned for a keyed tool execution. */
|
|
@@ -327,6 +330,9 @@ export class ToolCalls {
|
|
|
327
330
|
input: Record<string, unknown>,
|
|
328
331
|
options?: ExecuteToolRawOptions,
|
|
329
332
|
): Promise<ToolExecution<TData, TMeta>> {
|
|
333
|
+
if (options?.cliInvocationId !== undefined) {
|
|
334
|
+
validateCliInvocationId(options.cliInvocationId);
|
|
335
|
+
}
|
|
330
336
|
// Snapshot JSON input before the caller's awaited onExecution callback and
|
|
331
337
|
// before any retry, so every POST is byte-equivalent in meaning.
|
|
332
338
|
const inputSnapshot = JSON.parse(JSON.stringify(input)) as Record<
|
|
@@ -365,7 +371,11 @@ export class ToolCalls {
|
|
|
365
371
|
this.configuredRequestTimeoutMs,
|
|
366
372
|
);
|
|
367
373
|
if (idempotencyKey !== undefined) {
|
|
368
|
-
await this.lookupExecutionByKey(
|
|
374
|
+
await this.lookupExecutionByKey(
|
|
375
|
+
idempotencyKey,
|
|
376
|
+
timeoutMs,
|
|
377
|
+
options?.cliInvocationId,
|
|
378
|
+
);
|
|
369
379
|
}
|
|
370
380
|
const isApifySync = toolId.trim().toLowerCase() === 'apify_run_actor_sync';
|
|
371
381
|
const headers = {
|
|
@@ -384,6 +394,9 @@ export class ToolCalls {
|
|
|
384
394
|
...(options?.searchRef
|
|
385
395
|
? { 'x-deepline-search-ref': options.searchRef }
|
|
386
396
|
: {}),
|
|
397
|
+
...(options?.cliInvocationId !== undefined
|
|
398
|
+
? { 'x-deepline-cli-invocation-id': options.cliInvocationId }
|
|
399
|
+
: {}),
|
|
387
400
|
};
|
|
388
401
|
const request = (requestTimeoutMs: number | undefined) =>
|
|
389
402
|
this.http.post<ToolExecution<TData, TMeta>>(
|
|
@@ -434,6 +447,7 @@ export class ToolCalls {
|
|
|
434
447
|
this.defaultRequestTimeoutMs,
|
|
435
448
|
remainingMs,
|
|
436
449
|
),
|
|
450
|
+
options?.cliInvocationId,
|
|
437
451
|
);
|
|
438
452
|
} catch (error) {
|
|
439
453
|
if (!isRecoverableExecutionLookupError(error)) throw error;
|
|
@@ -525,6 +539,7 @@ export class ToolCalls {
|
|
|
525
539
|
private async lookupExecutionByKey(
|
|
526
540
|
idempotencyKey: string,
|
|
527
541
|
timeoutMs?: number,
|
|
542
|
+
cliInvocationId?: string,
|
|
528
543
|
): Promise<ExecutionByKeyResult | null> {
|
|
529
544
|
validateExecutionIdempotencyKey(idempotencyKey);
|
|
530
545
|
let supported = false;
|
|
@@ -536,6 +551,9 @@ export class ToolCalls {
|
|
|
536
551
|
timeout: timeoutMs,
|
|
537
552
|
idempotencyKey,
|
|
538
553
|
allowNotFound: true,
|
|
554
|
+
...(cliInvocationId !== undefined
|
|
555
|
+
? { headers: { 'x-deepline-cli-invocation-id': cliInvocationId } }
|
|
556
|
+
: {}),
|
|
539
557
|
onResponse: (response) => {
|
|
540
558
|
supported =
|
|
541
559
|
response.headers.get('X-Deepline-Idempotency-Supported') === 'true';
|
|
@@ -1070,7 +1070,7 @@ export async function withRuntimeSchedulerClient<T>(
|
|
|
1070
1070
|
let queryCount = 0;
|
|
1071
1071
|
let queryMs = 0;
|
|
1072
1072
|
try {
|
|
1073
|
-
if (!entry.databasePoolAttached) {
|
|
1073
|
+
if (process.env.VERCEL?.trim() && !entry.databasePoolAttached) {
|
|
1074
1074
|
attachDatabasePool(entry.pool);
|
|
1075
1075
|
entry.databasePoolAttached = true;
|
|
1076
1076
|
}
|
|
@@ -14701,8 +14701,10 @@ function terminalLogProjectionForOutbox(
|
|
|
14701
14701
|
metadata: PlayLogMetadata | null;
|
|
14702
14702
|
entryId: string | null;
|
|
14703
14703
|
} => entry !== null,
|
|
14704
|
-
)
|
|
14705
|
-
|
|
14704
|
+
);
|
|
14705
|
+
// This carrier is consumed into the paginated log store by the terminal
|
|
14706
|
+
// statement. The runner already bounds its envelope by bytes; applying the
|
|
14707
|
+
// status tail here loses retained lines when live delivery was interrupted.
|
|
14706
14708
|
return {
|
|
14707
14709
|
lines: entries.map((entry) => entry.line),
|
|
14708
14710
|
lineContexts: entries.map((entry) => entry.context),
|
|
@@ -18091,10 +18093,10 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
18091
18093
|
? `owned_run AS MATERIALIZED (
|
|
18092
18094
|
SELECT run_id FROM ${tableName('runs', options)}
|
|
18093
18095
|
WHERE run_id = $2
|
|
18094
|
-
--
|
|
18095
|
-
--
|
|
18096
|
-
--
|
|
18097
|
-
FOR UPDATE
|
|
18096
|
+
-- The head is already owned. Wait for the producer, then revalidate
|
|
18097
|
+
-- its lease below; initial selection still skips unrelated busy runs.
|
|
18098
|
+
-- Child-row foreign-key share locks can coexist with this fence.
|
|
18099
|
+
FOR NO KEY UPDATE
|
|
18098
18100
|
),`
|
|
18099
18101
|
: ''
|
|
18100
18102
|
} head AS MATERIALIZED (
|
|
@@ -18117,7 +18119,7 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
18117
18119
|
${
|
|
18118
18120
|
input.extendOwnedHead
|
|
18119
18121
|
? `AND candidate.event_id = $5
|
|
18120
|
-
AND candidate.lease_owner = $3 AND candidate.lease_expires_at >
|
|
18122
|
+
AND candidate.lease_owner = $3 AND candidate.lease_expires_at > clock_timestamp()`
|
|
18121
18123
|
: ''
|
|
18122
18124
|
}
|
|
18123
18125
|
AND candidate.failed_at IS NULL
|
|
@@ -20340,23 +20342,47 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
20340
20342
|
events.length === 1 &&
|
|
20341
20343
|
first.eventType === RUN_SCHEDULER_OUTBOX_EVENT_TYPE.runEvents
|
|
20342
20344
|
) {
|
|
20343
|
-
const widened = await withClient((client) =>
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20355
|
-
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20345
|
+
const widened = await withClient(async (client) => {
|
|
20346
|
+
await client.query('BEGIN');
|
|
20347
|
+
try {
|
|
20348
|
+
await client.query(
|
|
20349
|
+
`SELECT set_config('lock_timeout', $1, true),
|
|
20350
|
+
set_config('statement_timeout', $2, true)`,
|
|
20351
|
+
[
|
|
20352
|
+
`${RUNTIME_SCHEDULER_CANCEL_LOCK_TIMEOUT_MS}ms`,
|
|
20353
|
+
`${RUNTIME_SCHEDULER_CANCEL_STATEMENT_TIMEOUT_MS}ms`,
|
|
20354
|
+
],
|
|
20355
|
+
);
|
|
20356
|
+
// An owned head must extend from a fresh snapshot after the producer
|
|
20357
|
+
// commits. Keep the wait inside the existing SQL budget and permit
|
|
20358
|
+
// child-row foreign-key share locks under the ingress fence.
|
|
20359
|
+
await client.query(
|
|
20360
|
+
`SELECT run_id FROM ${tableName('runs', options)} WHERE run_id = $1 FOR NO KEY UPDATE`,
|
|
20361
|
+
[first.runId],
|
|
20362
|
+
);
|
|
20363
|
+
const prefix = await readPendingPostgresSchedulerOutboxEvents(
|
|
20364
|
+
client,
|
|
20365
|
+
{
|
|
20366
|
+
runId: first.runId,
|
|
20367
|
+
leaseOwner,
|
|
20368
|
+
leaseSeconds: input.leaseSeconds ?? 120,
|
|
20369
|
+
limit: Math.min(
|
|
20370
|
+
RUN_LEDGER_PROJECTION_PREFIX_MAX_FACTS,
|
|
20371
|
+
remainingEvents ?? RUN_LEDGER_PROJECTION_PREFIX_MAX_FACTS,
|
|
20372
|
+
),
|
|
20373
|
+
allowIngressPrefix: true,
|
|
20374
|
+
extendOwnedHead: first.eventId,
|
|
20375
|
+
inTransaction: true,
|
|
20376
|
+
},
|
|
20377
|
+
options,
|
|
20378
|
+
);
|
|
20379
|
+
await client.query('COMMIT');
|
|
20380
|
+
return prefix;
|
|
20381
|
+
} catch (error) {
|
|
20382
|
+
await client.query('ROLLBACK');
|
|
20383
|
+
throw error;
|
|
20384
|
+
}
|
|
20385
|
+
});
|
|
20360
20386
|
if (widened[0]?.eventId !== first.eventId) {
|
|
20361
20387
|
throw new RunLedgerProjectionLeaseLostError(
|
|
20362
20388
|
'head_lease_owner_mismatch',
|
|
@@ -20729,7 +20755,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
20729
20755
|
}
|
|
20730
20756
|
const failure = runLedgerDeliveryFailure({ error });
|
|
20731
20757
|
console.warn('[run-ledger-outbox.batch_dispatch_failed]', {
|
|
20732
|
-
runId: input.runId ?? null,
|
|
20758
|
+
runId: input.runId ?? events[0]?.runId ?? null,
|
|
20733
20759
|
eventIds: events.map((event) => event.eventId),
|
|
20734
20760
|
error: error instanceof Error ? error.message : String(error),
|
|
20735
20761
|
code: failure.code,
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts
CHANGED
|
@@ -2793,6 +2793,16 @@ export async function hasRuntimeEventLogPositionIndex(
|
|
|
2793
2793
|
return true;
|
|
2794
2794
|
}
|
|
2795
2795
|
|
|
2796
|
+
/** Deployment-only check for all supported legacy and current log reads. */
|
|
2797
|
+
export async function hasRuntimeEventQueryIndexes(
|
|
2798
|
+
client: PostgresSchedulerQueryClient,
|
|
2799
|
+
): Promise<boolean> {
|
|
2800
|
+
for (const expected of RUNTIME_EVENT_QUERY_INDEXES) {
|
|
2801
|
+
if (!(await hasRuntimeEventQueryIndex(client, expected))) return false;
|
|
2802
|
+
}
|
|
2803
|
+
return true;
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2796
2806
|
/** Prepare old and new position indexes before replacing the projection body. */
|
|
2797
2807
|
export async function prepareRuntimeEventLogPositionIndex(
|
|
2798
2808
|
client: PostgresSchedulerQueryClient,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const BILLING_SALES_GROUP_KEY = 'shadow.billing-sales';
|
|
2
|
+
export const BILLING_SALES_DESTINATION_KEY = 'shadow.billing-sales.slack';
|
|
3
|
+
export const BILLING_SALES_SLACK_CHANNEL_ID = 'C0AGWVD2TNK';
|
|
4
|
+
export const BILLING_SALES_CONNECTION_ID = 'platform-reporting-bot';
|
|
5
|
+
export const BILLING_SALES_CREDIT_PURCHASE_MINIMUM_CENTS = 15_000;
|
|
6
|
+
export const BILLING_SALES_RULE_KEYS: readonly string[] = [
|
|
7
|
+
'internal.billing.credit_purchase',
|
|
8
|
+
'internal.billing.paid_plan',
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
export function isPlatformNotificationGroup(groupKey: string): boolean {
|
|
12
|
+
return groupKey === 'shadow' || groupKey === BILLING_SALES_GROUP_KEY;
|
|
13
|
+
}
|
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
} from './events';
|
|
14
14
|
import { legacySlackNotificationType } from './legacy-slack';
|
|
15
15
|
import type { NotificationText } from './content';
|
|
16
|
+
import {
|
|
17
|
+
BILLING_SALES_CREDIT_PURCHASE_MINIMUM_CENTS,
|
|
18
|
+
BILLING_SALES_GROUP_KEY,
|
|
19
|
+
} from './billing-sales';
|
|
16
20
|
|
|
17
21
|
type NotificationTypeDefinition = {
|
|
18
22
|
id: string;
|
|
@@ -734,6 +738,71 @@ const PRODUCT_NOTIFICATION_TYPE_REGISTRY = [
|
|
|
734
738
|
}),
|
|
735
739
|
},
|
|
736
740
|
},
|
|
741
|
+
{
|
|
742
|
+
id: 'internal.billing.credit_purchase',
|
|
743
|
+
eventName: ProductNotificationEvent.CreditsPurchaseCompleted,
|
|
744
|
+
requiredFilter: { currency: 'usd' },
|
|
745
|
+
allowedTriggers: ['threshold_crossing'],
|
|
746
|
+
catalog: undefined,
|
|
747
|
+
shadow: true,
|
|
748
|
+
rule: {
|
|
749
|
+
default: {
|
|
750
|
+
ruleKey: 'internal.billing.credit_purchase',
|
|
751
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
752
|
+
},
|
|
753
|
+
create: (_input, base) => ({
|
|
754
|
+
...base,
|
|
755
|
+
repeatMode: 'every_match',
|
|
756
|
+
trigger: {
|
|
757
|
+
kind: 'threshold_crossing',
|
|
758
|
+
direction: 'at_or_above',
|
|
759
|
+
threshold: BILLING_SALES_CREDIT_PURCHASE_MINIMUM_CENTS,
|
|
760
|
+
unit: 'usd_cents',
|
|
761
|
+
},
|
|
762
|
+
}),
|
|
763
|
+
present: ({ payload }) => ({
|
|
764
|
+
title: `Credit purchase: $${(Number(payload.amountPaidCents) / 100).toFixed(2)}`,
|
|
765
|
+
summary: [
|
|
766
|
+
{ workspace: true },
|
|
767
|
+
` purchased ${formatCredits(Number(payload.credits))} credits.`,
|
|
768
|
+
],
|
|
769
|
+
details: [],
|
|
770
|
+
targetUrl: String(payload.targetUrl),
|
|
771
|
+
subjectKind: 'workspace',
|
|
772
|
+
subjectId: String(payload.accountId),
|
|
773
|
+
}),
|
|
774
|
+
},
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
id: 'internal.billing.paid_plan',
|
|
778
|
+
eventName: ProductNotificationEvent.BillingPlanPurchased,
|
|
779
|
+
requiredFilter: {},
|
|
780
|
+
allowedTriggers: ['each_match'],
|
|
781
|
+
catalog: undefined,
|
|
782
|
+
shadow: true,
|
|
783
|
+
rule: {
|
|
784
|
+
default: {
|
|
785
|
+
ruleKey: 'internal.billing.paid_plan',
|
|
786
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
787
|
+
},
|
|
788
|
+
create: (_input, base) => ({
|
|
789
|
+
...base,
|
|
790
|
+
repeatMode: 'every_match',
|
|
791
|
+
trigger: { kind: 'each_match' },
|
|
792
|
+
}),
|
|
793
|
+
present: ({ payload }) => ({
|
|
794
|
+
title: 'New paid plan signup',
|
|
795
|
+
summary: [
|
|
796
|
+
{ workspace: true },
|
|
797
|
+
` signed up for the ${payload.planName} plan.`,
|
|
798
|
+
],
|
|
799
|
+
details: [],
|
|
800
|
+
targetUrl: String(payload.targetUrl),
|
|
801
|
+
subjectKind: 'workspace',
|
|
802
|
+
subjectId: String(payload.accountId),
|
|
803
|
+
}),
|
|
804
|
+
},
|
|
805
|
+
},
|
|
737
806
|
{
|
|
738
807
|
id: 'play.failed',
|
|
739
808
|
eventName: ProductNotificationEvent.PlayRunCompleted,
|
|
@@ -8,13 +8,19 @@ import {
|
|
|
8
8
|
validateProductNotificationDeliveryTiming,
|
|
9
9
|
type ProductNotificationDefaultPolicy,
|
|
10
10
|
} from './configuration';
|
|
11
|
+
import {
|
|
12
|
+
BILLING_SALES_CONNECTION_ID,
|
|
13
|
+
BILLING_SALES_DESTINATION_KEY,
|
|
14
|
+
BILLING_SALES_GROUP_KEY,
|
|
15
|
+
BILLING_SALES_SLACK_CHANNEL_ID,
|
|
16
|
+
} from './billing-sales';
|
|
11
17
|
|
|
12
18
|
/**
|
|
13
19
|
* Product defaults stay in code. Workspaces see these rows synthetically until
|
|
14
20
|
* they create sparse copy-on-write overrides.
|
|
15
21
|
*/
|
|
16
22
|
export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
|
|
17
|
-
version:
|
|
23
|
+
version: 9,
|
|
18
24
|
groups: [
|
|
19
25
|
{
|
|
20
26
|
groupKey: 'default',
|
|
@@ -32,6 +38,12 @@ export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
|
|
|
32
38
|
enabled: true,
|
|
33
39
|
deliveryTiming: DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
|
|
34
40
|
},
|
|
41
|
+
{
|
|
42
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
43
|
+
name: 'Billing sales alerts',
|
|
44
|
+
enabled: true,
|
|
45
|
+
deliveryTiming: { mode: 'immediate' },
|
|
46
|
+
},
|
|
35
47
|
],
|
|
36
48
|
destinations: [
|
|
37
49
|
{
|
|
@@ -48,6 +60,19 @@ export const CURRENT_PRODUCT_NOTIFICATION_DEFAULT_POLICY = {
|
|
|
48
60
|
enabled: true,
|
|
49
61
|
settings: { kind: 'email_roles', roles: ['owner'] },
|
|
50
62
|
},
|
|
63
|
+
{
|
|
64
|
+
destinationKey: BILLING_SALES_DESTINATION_KEY,
|
|
65
|
+
groupKey: BILLING_SALES_GROUP_KEY,
|
|
66
|
+
name: 'Deepline signup channel',
|
|
67
|
+
enabled: true,
|
|
68
|
+
settings: {
|
|
69
|
+
kind: 'slack',
|
|
70
|
+
targetKind: 'channel',
|
|
71
|
+
targetId: BILLING_SALES_SLACK_CHANNEL_ID,
|
|
72
|
+
targetName: 'Deepline signup channel',
|
|
73
|
+
oauthConnectionId: BILLING_SALES_CONNECTION_ID,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
51
76
|
],
|
|
52
77
|
rules: PRODUCT_NOTIFICATION_DEFAULT_RULES,
|
|
53
78
|
} satisfies ProductNotificationDefaultPolicy;
|
|
@@ -206,9 +206,10 @@ export const PRODUCT_NOTIFICATION_EVENT_DEFINITIONS: readonly ProductNotificatio
|
|
|
206
206
|
credits: 'number',
|
|
207
207
|
targetUrl: 'string',
|
|
208
208
|
},
|
|
209
|
+
optionalFacts: { amountPaidCents: 'number', currency: 'string' },
|
|
209
210
|
orderingSubjectFact: 'accountId',
|
|
210
211
|
allowedTriggers: ['threshold_crossing'],
|
|
211
|
-
allowedThresholdUnits: ['credits'],
|
|
212
|
+
allowedThresholdUnits: ['credits', 'usd_cents'],
|
|
212
213
|
},
|
|
213
214
|
{
|
|
214
215
|
// The workspace moved onto a paid acquisition offer.
|
|
@@ -451,6 +452,13 @@ export function adaptProductNotificationObservation(input: {
|
|
|
451
452
|
};
|
|
452
453
|
}
|
|
453
454
|
if (event.eventName === ProductNotificationEvent.CreditsPurchaseCompleted) {
|
|
455
|
+
if (trigger.kind === 'threshold_crossing' && trigger.unit === 'usd_cents') {
|
|
456
|
+
return {
|
|
457
|
+
kind: 'threshold_state',
|
|
458
|
+
currentValue: Number(event.payload.amountPaidCents ?? 0),
|
|
459
|
+
unit: 'usd_cents',
|
|
460
|
+
};
|
|
461
|
+
}
|
|
454
462
|
return {
|
|
455
463
|
kind: 'threshold_state',
|
|
456
464
|
currentValue: Number(event.payload.credits),
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
registerAuthCommands,
|
|
10
10
|
reportSetupCompleted,
|
|
11
11
|
resolvePendingAuthClaimForResume
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-7XORS6WQ.mjs";
|
|
13
|
+
import "./chunk-5V56XCQN.mjs";
|
|
14
|
+
import "./chunk-4PSSDZQB.mjs";
|
|
15
15
|
import "./chunk-DLIRSHV6.mjs";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-WWPI4GJI.mjs";
|
|
17
17
|
import "./chunk-NXGCO4JB.mjs";
|
|
18
18
|
import "./chunk-WZYKRD7T.mjs";
|
|
19
19
|
import "./chunk-KRD6H754.mjs";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var _chunkU37SW6IKjs = require('./chunk-U37SW6IK.js');
|
|
13
|
+
require('./chunk-MMNZ6GBT.js');
|
|
14
|
+
require('./chunk-M6HCRRV2.js');
|
|
15
|
+
require('./chunk-XNYIZMNQ.js');
|
|
16
|
+
require('./chunk-OZIFVQRY.js');
|
|
17
|
+
require('./chunk-7P5AA3SN.js');
|
|
18
|
+
require('./chunk-OG64RBAC.js');
|
|
19
|
+
require('./chunk-COGTRVWW.js');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
exports.EXIT_WORKSPACE_MISMATCH = _chunkU37SW6IKjs.EXIT_WORKSPACE_MISMATCH; exports.clearPendingClaim = _chunkU37SW6IKjs.clearPendingClaim; exports.clearSatisfiedPendingClaim = _chunkU37SW6IKjs.clearSatisfiedPendingClaim; exports.handleRegister = _chunkU37SW6IKjs.handleRegister; exports.handleStatus = _chunkU37SW6IKjs.handleStatus; exports.handleWait = _chunkU37SW6IKjs.handleWait; exports.readPendingAuthClaim = _chunkU37SW6IKjs.readPendingAuthClaim; exports.registerAuthCommands = _chunkU37SW6IKjs.registerAuthCommands; exports.reportSetupCompleted = _chunkU37SW6IKjs.reportSetupCompleted; exports.resolvePendingAuthClaimForResume = _chunkU37SW6IKjs.resolvePendingAuthClaimForResume;
|