deepline 0.3.228 → 0.3.229
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/play-data-plane/contracts.ts +12 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +252 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/sheet-contract.ts +29 -8
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +250 -37
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +380 -183
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +1 -0
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +16 -2
- package/dist/bundling-sources/shared_libs/plays/execution-pipeline.ts +72 -0
- package/dist/bundling-sources/shared_libs/plays/launch/prepare.ts +1 -3
- package/dist/bundling-sources/shared_libs/plays/sheet-filter.ts +9 -13
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +28 -31
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/{compiler-manifest-Dpd2hEet.d.mts → compiler-manifest-n8ZtPv2h.d.mts} +31 -21
- package/dist/{compiler-manifest-Dpd2hEet.d.ts → compiler-manifest-n8ZtPv2h.d.ts} +31 -21
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -1
- package/dist/index.mjs +6 -1
- package/dist/install-integrity.json +4 -2
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- 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
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
serializePlayDatasetCell,
|
|
27
27
|
} from '../plays/dataset';
|
|
28
28
|
import type { PlayDataset, PlayDatasetInput } from '../plays/dataset';
|
|
29
|
+
import type { PlayDatasetColumnTypes } from '../play-data-plane/contracts';
|
|
29
30
|
import {
|
|
30
31
|
compileRequestsWithStrategy,
|
|
31
32
|
executeChunkedRequests,
|
|
@@ -203,6 +204,10 @@ import {
|
|
|
203
204
|
TOOL_EXECUTE_PROVIDER_RATE_RETRY_SNAPSHOT_HEADER,
|
|
204
205
|
classifyToolExecuteHttpFailure,
|
|
205
206
|
createToolExecuteHttpFailureAttemptTracker,
|
|
207
|
+
TOOL_EXECUTE_BARE_RATE_LIMIT_MAX_ATTEMPTS,
|
|
208
|
+
TOOL_EXECUTE_RATE_LIMIT_MAX_ATTEMPTS,
|
|
209
|
+
TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS,
|
|
210
|
+
TOOL_EXECUTE_RATE_LIMIT_RETRY_DELAY_MAX_MS,
|
|
206
211
|
parseToolExecuteRetryAfterMs,
|
|
207
212
|
parseToolExecuteRetryAtMs,
|
|
208
213
|
parseToolExecuteAuthScopeChangedError,
|
|
@@ -680,7 +685,7 @@ async function runCtxFetchPhase<T>(input: {
|
|
|
680
685
|
callerSignal?: AbortSignal | null;
|
|
681
686
|
controller: AbortController;
|
|
682
687
|
deadline: CtxFetchDeadline;
|
|
683
|
-
phase: 'headers' | 'body';
|
|
688
|
+
phase: 'headers' | 'body' | 'total';
|
|
684
689
|
run: () => Promise<T>;
|
|
685
690
|
}): Promise<T> {
|
|
686
691
|
const remainingMs = remainingCtxFetchMs(input.deadline);
|
|
@@ -695,7 +700,9 @@ async function runCtxFetchPhase<T>(input: {
|
|
|
695
700
|
const phaseLimitMs =
|
|
696
701
|
input.phase === 'headers'
|
|
697
702
|
? input.deadline.headersMs
|
|
698
|
-
: input.
|
|
703
|
+
: input.phase === 'body'
|
|
704
|
+
? input.deadline.bodyMs
|
|
705
|
+
: remainingMs;
|
|
699
706
|
const timeoutMs = Math.min(phaseLimitMs, remainingMs);
|
|
700
707
|
const timeoutPhase = timeoutMs >= remainingMs ? 'total' : input.phase;
|
|
701
708
|
let timeout: ReturnType<typeof setTimeout> | null = null;
|
|
@@ -744,19 +751,42 @@ async function sleepWithinCtxFetchDeadline(input: {
|
|
|
744
751
|
delayMs: number;
|
|
745
752
|
}): Promise<void> {
|
|
746
753
|
const controller = new AbortController();
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
)
|
|
758
|
-
|
|
759
|
-
}
|
|
754
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
755
|
+
try {
|
|
756
|
+
await runCtxFetchPhase({
|
|
757
|
+
callerSignal: input.callerSignal,
|
|
758
|
+
controller,
|
|
759
|
+
deadline: input.deadline,
|
|
760
|
+
phase: 'total',
|
|
761
|
+
run: () =>
|
|
762
|
+
new Promise<void>((resolve) => {
|
|
763
|
+
timer = setTimeout(resolve, input.delayMs);
|
|
764
|
+
}),
|
|
765
|
+
});
|
|
766
|
+
} finally {
|
|
767
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function isCtxFetchBackpressure(response: Response, bodyText: string): boolean {
|
|
772
|
+
if (response.status === 429) return true;
|
|
773
|
+
if (response.status !== 503) return false;
|
|
774
|
+
// This Salesforce endpoint reports a rejected burst as 503. Match the final
|
|
775
|
+
// destination and exact response contract; arbitrary 503s remain failures.
|
|
776
|
+
try {
|
|
777
|
+
const destination = new URL(response.url);
|
|
778
|
+
const body: unknown = JSON.parse(bodyText);
|
|
779
|
+
return (
|
|
780
|
+
destination.protocol === 'https:' &&
|
|
781
|
+
destination.hostname.endsWith('.salesforce-sites.com') &&
|
|
782
|
+
body !== null &&
|
|
783
|
+
typeof body === 'object' &&
|
|
784
|
+
!Array.isArray(body) &&
|
|
785
|
+
(body as Record<string, unknown>).status === 'burst_circuit_open'
|
|
786
|
+
);
|
|
787
|
+
} catch {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
760
790
|
}
|
|
761
791
|
|
|
762
792
|
async function readCtxFetchBody(input: {
|
|
@@ -1673,6 +1703,69 @@ function rowsFromUnknown(value: unknown): Record<string, unknown>[] {
|
|
|
1673
1703
|
);
|
|
1674
1704
|
}
|
|
1675
1705
|
|
|
1706
|
+
function customerDbColumnTypes(
|
|
1707
|
+
columns: unknown,
|
|
1708
|
+
rows: readonly Record<string, unknown>[],
|
|
1709
|
+
): PlayDatasetColumnTypes | undefined {
|
|
1710
|
+
if (!Array.isArray(columns)) return undefined;
|
|
1711
|
+
// Core PostgreSQL OIDs only. Extension/domain identities are database-local,
|
|
1712
|
+
// and source SQL types never authorize coercing the values returned by a tool.
|
|
1713
|
+
const coreValueTypes: Record<
|
|
1714
|
+
number,
|
|
1715
|
+
PlayDatasetColumnTypes[string]['valueType']
|
|
1716
|
+
> = {
|
|
1717
|
+
16: 'boolean',
|
|
1718
|
+
20: 'string',
|
|
1719
|
+
21: 'number',
|
|
1720
|
+
23: 'number',
|
|
1721
|
+
25: 'string',
|
|
1722
|
+
114: 'json',
|
|
1723
|
+
700: 'number',
|
|
1724
|
+
701: 'number',
|
|
1725
|
+
1042: 'string',
|
|
1726
|
+
1043: 'string',
|
|
1727
|
+
1082: 'string',
|
|
1728
|
+
1083: 'string',
|
|
1729
|
+
1114: 'string',
|
|
1730
|
+
1184: 'string',
|
|
1731
|
+
1266: 'string',
|
|
1732
|
+
1700: 'string',
|
|
1733
|
+
2950: 'string',
|
|
1734
|
+
3802: 'json',
|
|
1735
|
+
};
|
|
1736
|
+
const entries: Array<[string, PlayDatasetColumnTypes[string]]> = [];
|
|
1737
|
+
for (const value of columns) {
|
|
1738
|
+
const column = recordOrNull(value);
|
|
1739
|
+
const postgresTypeId = column?.data_type_id;
|
|
1740
|
+
if (
|
|
1741
|
+
typeof column?.name !== 'string' ||
|
|
1742
|
+
typeof postgresTypeId !== 'number' ||
|
|
1743
|
+
!Object.hasOwn(coreValueTypes, postgresTypeId)
|
|
1744
|
+
)
|
|
1745
|
+
continue;
|
|
1746
|
+
const observed = new Set<PlayDatasetColumnTypes[string]['valueType']>();
|
|
1747
|
+
for (const row of rows) {
|
|
1748
|
+
const cell = row[column.name];
|
|
1749
|
+
if (cell === null || cell === undefined) continue;
|
|
1750
|
+
observed.add(
|
|
1751
|
+
typeof cell === 'boolean'
|
|
1752
|
+
? 'boolean'
|
|
1753
|
+
: typeof cell === 'string'
|
|
1754
|
+
? 'string'
|
|
1755
|
+
: typeof cell === 'number' && Number.isFinite(cell)
|
|
1756
|
+
? 'number'
|
|
1757
|
+
: 'json',
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
const valueType =
|
|
1761
|
+
postgresTypeId === 114 || postgresTypeId === 3802 || observed.size > 1
|
|
1762
|
+
? 'json'
|
|
1763
|
+
: ([...observed][0] ?? coreValueTypes[postgresTypeId]!);
|
|
1764
|
+
entries.push([column.name, { postgresTypeId, valueType }]);
|
|
1765
|
+
}
|
|
1766
|
+
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1676
1769
|
function finiteNonNegativeInteger(value: unknown): number | null {
|
|
1677
1770
|
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
|
|
1678
1771
|
return null;
|
|
@@ -7914,6 +8007,9 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
7914
8007
|
rows.length >= effectiveCount ? rows.slice(0, effectiveCount) : null,
|
|
7915
8008
|
sourceLabel: 'query result rows',
|
|
7916
8009
|
tableNamespace: null,
|
|
8010
|
+
columnTypes: isCustomerDbDatasetTool(toolId)
|
|
8011
|
+
? customerDbColumnTypes(raw?.columns, rows)
|
|
8012
|
+
: undefined,
|
|
7917
8013
|
resolvers: {
|
|
7918
8014
|
count: async () => Math.min(totalRows, datasetLimit),
|
|
7919
8015
|
at: async (index) => (await fetchPage(index, 1))[0],
|
|
@@ -8472,6 +8568,18 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
8472
8568
|
let itemsToProcess: Array<Record<string, unknown>> = [];
|
|
8473
8569
|
let itemOriginalIndexes: number[] = [];
|
|
8474
8570
|
const datasetColumnNames = Object.keys(input);
|
|
8571
|
+
// Generated fields no longer describe the source column, even when they
|
|
8572
|
+
// retain its name. Every writer still validates the actual incoming values.
|
|
8573
|
+
const inputColumnTypes = isPlayDataset(items)
|
|
8574
|
+
? items.columnTypes
|
|
8575
|
+
: undefined;
|
|
8576
|
+
const unchangedColumnTypes = inputColumnTypes
|
|
8577
|
+
? Object.fromEntries(
|
|
8578
|
+
Object.entries(inputColumnTypes).filter(
|
|
8579
|
+
([field]) => !datasetColumnNames.includes(field),
|
|
8580
|
+
),
|
|
8581
|
+
)
|
|
8582
|
+
: undefined;
|
|
8475
8583
|
const stripFieldOutputs = (row: Record<string, unknown>) => {
|
|
8476
8584
|
const stripped = cloneCsvAliasedRow(row);
|
|
8477
8585
|
for (const fieldName of datasetColumnNames) {
|
|
@@ -8863,6 +8971,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
8863
8971
|
forceRefresh: this.#options.cachePolicy?.forceToolRefresh === true,
|
|
8864
8972
|
inputOffset: page.offset,
|
|
8865
8973
|
mode: options?.mode,
|
|
8974
|
+
columnTypes: unchangedColumnTypes,
|
|
8866
8975
|
},
|
|
8867
8976
|
);
|
|
8868
8977
|
resolvedTableNamespace = normalizeTableNamespace(
|
|
@@ -9424,6 +9533,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
9424
9533
|
? immediateMaterializedRows
|
|
9425
9534
|
: null,
|
|
9426
9535
|
tableNamespace: resolvedTableNamespace,
|
|
9536
|
+
columnTypes: unchangedColumnTypes,
|
|
9427
9537
|
workProgress: {
|
|
9428
9538
|
total: totalInputCount,
|
|
9429
9539
|
executed: executedCount,
|
|
@@ -9666,6 +9776,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
9666
9776
|
staticPipeline: this.currentStaticPipeline,
|
|
9667
9777
|
forceRefresh: this.#options.cachePolicy?.forceToolRefresh === true,
|
|
9668
9778
|
mode: options?.mode,
|
|
9779
|
+
columnTypes: unchangedColumnTypes,
|
|
9669
9780
|
},
|
|
9670
9781
|
);
|
|
9671
9782
|
resolvedTableNamespace = normalizeTableNamespace(
|
|
@@ -10175,6 +10286,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
10175
10286
|
.map((row) => this.toMaterializedOutputRow(row)),
|
|
10176
10287
|
residentRows: terminalRows,
|
|
10177
10288
|
tableNamespace: resolvedTableNamespace,
|
|
10289
|
+
columnTypes: unchangedColumnTypes,
|
|
10178
10290
|
workProgress: {
|
|
10179
10291
|
total: totalInputCount,
|
|
10180
10292
|
executed: executedCount,
|
|
@@ -14991,16 +15103,30 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
14991
15103
|
let response: Response | null = null;
|
|
14992
15104
|
let bodyText: string | null = null;
|
|
14993
15105
|
try {
|
|
14994
|
-
|
|
14995
|
-
|
|
14996
|
-
|
|
15106
|
+
// Only replay a body whose bytes are stable. In particular, a
|
|
15107
|
+
// consumed ReadableStream cannot be retried even with a write key.
|
|
15108
|
+
const replayableBody =
|
|
15109
|
+
init.body == null || typeof init.body === 'string';
|
|
15110
|
+
const canRetryTransport =
|
|
15111
|
+
replayableBody && ['GET', 'HEAD', 'OPTIONS'].includes(method);
|
|
14997
15112
|
const { safePublicFetch } = await loadSafeFetch();
|
|
14998
|
-
|
|
14999
|
-
|
|
15000
|
-
|
|
15001
|
-
attempt += 1
|
|
15002
|
-
) {
|
|
15113
|
+
let transportAttempt = 1;
|
|
15114
|
+
let rateLimitAttempt = 0;
|
|
15115
|
+
while (true) {
|
|
15003
15116
|
const attemptController = new AbortController();
|
|
15117
|
+
let permit: Awaited<
|
|
15118
|
+
ReturnType<RuntimeResourceGovernor['acquireProviderPermit']>
|
|
15119
|
+
> | null = null;
|
|
15120
|
+
let dispatched = false;
|
|
15121
|
+
const releasePhysicalPermit = async () => {
|
|
15122
|
+
const current = permit;
|
|
15123
|
+
permit = null;
|
|
15124
|
+
if (!current) return;
|
|
15125
|
+
if (dispatched) current.release();
|
|
15126
|
+
else await current.cancel();
|
|
15127
|
+
dispatched = false;
|
|
15128
|
+
};
|
|
15129
|
+
let transportRetry = false;
|
|
15004
15130
|
try {
|
|
15005
15131
|
const attemptInit = {
|
|
15006
15132
|
...fetchInit,
|
|
@@ -15012,10 +15138,53 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
15012
15138
|
callerSignal: init.signal,
|
|
15013
15139
|
controller: attemptController,
|
|
15014
15140
|
deadline: fetchDeadline,
|
|
15015
|
-
phase: '
|
|
15141
|
+
phase: 'total',
|
|
15016
15142
|
run: () =>
|
|
15017
15143
|
safePublicFetch(url, attemptInit, {
|
|
15018
|
-
|
|
15144
|
+
// safePublicFetch validates each URL before invoking this
|
|
15145
|
+
// wrapper. Redirect hops are physical dispatches too.
|
|
15146
|
+
fetchImpl: async (physicalUrl, physicalInit) => {
|
|
15147
|
+
await releasePhysicalPermit();
|
|
15148
|
+
const signal = attemptInit.signal;
|
|
15149
|
+
permit = await runCtxFetchPhase({
|
|
15150
|
+
callerSignal: init.signal,
|
|
15151
|
+
controller: attemptController,
|
|
15152
|
+
deadline: fetchDeadline,
|
|
15153
|
+
phase: 'total',
|
|
15154
|
+
run: async () => {
|
|
15155
|
+
for (;;) {
|
|
15156
|
+
const acquired =
|
|
15157
|
+
await this.resourceGovernor.acquireProviderPermit(
|
|
15158
|
+
{ toolId: CTX_FETCH_EGRESS_TOOL_ID, signal },
|
|
15159
|
+
);
|
|
15160
|
+
try {
|
|
15161
|
+
signal.throwIfAborted();
|
|
15162
|
+
const valid =
|
|
15163
|
+
!acquired.validate ||
|
|
15164
|
+
(await acquired.validate());
|
|
15165
|
+
signal.throwIfAborted();
|
|
15166
|
+
if (valid) return acquired;
|
|
15167
|
+
} catch (error) {
|
|
15168
|
+
await acquired.cancel();
|
|
15169
|
+
throw error;
|
|
15170
|
+
}
|
|
15171
|
+
await acquired.cancel();
|
|
15172
|
+
}
|
|
15173
|
+
},
|
|
15174
|
+
});
|
|
15175
|
+
return await runCtxFetchPhase({
|
|
15176
|
+
callerSignal: init.signal,
|
|
15177
|
+
controller: attemptController,
|
|
15178
|
+
deadline: fetchDeadline,
|
|
15179
|
+
phase: 'headers',
|
|
15180
|
+
run: () => {
|
|
15181
|
+
dispatched = true;
|
|
15182
|
+
return (
|
|
15183
|
+
this.#options.fetchImpl ?? globalThis.fetch
|
|
15184
|
+
)(physicalUrl, physicalInit);
|
|
15185
|
+
},
|
|
15186
|
+
});
|
|
15187
|
+
},
|
|
15019
15188
|
sensitiveHeaders: Object.keys(secretHeaderMarkers),
|
|
15020
15189
|
stripHeadersOnCrossOriginRedirect: true,
|
|
15021
15190
|
headersOnCrossOriginRedirect: {
|
|
@@ -15029,7 +15198,6 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
15029
15198
|
deadline: fetchDeadline,
|
|
15030
15199
|
response,
|
|
15031
15200
|
});
|
|
15032
|
-
break;
|
|
15033
15201
|
} catch (error) {
|
|
15034
15202
|
void response?.body?.cancel(error).catch(() => undefined);
|
|
15035
15203
|
response = null;
|
|
@@ -15045,22 +15213,67 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
15045
15213
|
error instanceof Error ? error.message : String(error);
|
|
15046
15214
|
if (
|
|
15047
15215
|
canRetryTransport &&
|
|
15048
|
-
|
|
15216
|
+
transportAttempt < FETCH_TRANSPORT_MAX_ATTEMPTS
|
|
15049
15217
|
) {
|
|
15050
15218
|
this.runtimeLog(
|
|
15051
|
-
`ctx.fetch(${method} ${url}) transport failed on attempt ${
|
|
15219
|
+
`ctx.fetch(${method} ${url}) transport failed on attempt ${transportAttempt}/${FETCH_TRANSPORT_MAX_ATTEMPTS}; retrying: ${message}`,
|
|
15220
|
+
);
|
|
15221
|
+
transportRetry = true;
|
|
15222
|
+
} else {
|
|
15223
|
+
throw new Error(
|
|
15224
|
+
`ctx.fetch(${method} ${url}) failed on attempt ${transportAttempt}/${FETCH_TRANSPORT_MAX_ATTEMPTS}: ${message}`,
|
|
15052
15225
|
);
|
|
15053
|
-
await sleepWithinCtxFetchDeadline({
|
|
15054
|
-
callerSignal: init.signal,
|
|
15055
|
-
deadline: fetchDeadline,
|
|
15056
|
-
delayMs: FETCH_TRANSPORT_RETRY_DELAY_MS * attempt,
|
|
15057
|
-
});
|
|
15058
|
-
continue;
|
|
15059
15226
|
}
|
|
15060
|
-
|
|
15061
|
-
|
|
15062
|
-
);
|
|
15227
|
+
} finally {
|
|
15228
|
+
await releasePhysicalPermit();
|
|
15063
15229
|
}
|
|
15230
|
+
if (transportRetry) {
|
|
15231
|
+
await sleepWithinCtxFetchDeadline({
|
|
15232
|
+
callerSignal: init.signal,
|
|
15233
|
+
deadline: fetchDeadline,
|
|
15234
|
+
delayMs: FETCH_TRANSPORT_RETRY_DELAY_MS * transportAttempt,
|
|
15235
|
+
});
|
|
15236
|
+
transportAttempt += 1;
|
|
15237
|
+
continue;
|
|
15238
|
+
}
|
|
15239
|
+
if (
|
|
15240
|
+
!response ||
|
|
15241
|
+
bodyText === null ||
|
|
15242
|
+
!replayableBody ||
|
|
15243
|
+
!isCtxFetchBackpressure(response, bodyText)
|
|
15244
|
+
)
|
|
15245
|
+
break;
|
|
15246
|
+
rateLimitAttempt += 1;
|
|
15247
|
+
const retryAfter = response.headers.get('retry-after');
|
|
15248
|
+
const attemptCap = retryAfter?.trim()
|
|
15249
|
+
? TOOL_EXECUTE_RATE_LIMIT_MAX_ATTEMPTS
|
|
15250
|
+
: TOOL_EXECUTE_BARE_RATE_LIMIT_MAX_ATTEMPTS;
|
|
15251
|
+
if (rateLimitAttempt >= attemptCap) break;
|
|
15252
|
+
const delayMs = Math.max(
|
|
15253
|
+
parseToolExecuteRetryAfterMs(retryAfter),
|
|
15254
|
+
Math.min(
|
|
15255
|
+
TOOL_EXECUTE_RATE_LIMIT_RETRY_DELAY_MAX_MS,
|
|
15256
|
+
TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS * rateLimitAttempt,
|
|
15257
|
+
),
|
|
15258
|
+
);
|
|
15259
|
+
this.runtimeLog(
|
|
15260
|
+
`[runtime.ctx_fetch_backpressure] ${JSON.stringify({
|
|
15261
|
+
key: normalizedKey,
|
|
15262
|
+
method,
|
|
15263
|
+
origin: new URL(response.url || url).origin,
|
|
15264
|
+
http_status: response.status,
|
|
15265
|
+
attempt: rateLimitAttempt,
|
|
15266
|
+
max_attempts: attemptCap,
|
|
15267
|
+
retry_delay_ms: delayMs,
|
|
15268
|
+
})}`,
|
|
15269
|
+
);
|
|
15270
|
+
// Destination feedback must not cool the shared generic_http
|
|
15271
|
+
// bucket used by unrelated websites. Pace this logical request.
|
|
15272
|
+
await sleepWithinCtxFetchDeadline({
|
|
15273
|
+
callerSignal: init.signal,
|
|
15274
|
+
deadline: fetchDeadline,
|
|
15275
|
+
delayMs,
|
|
15276
|
+
});
|
|
15064
15277
|
}
|
|
15065
15278
|
if (!response) {
|
|
15066
15279
|
throw new Error(
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
} from './cell-provenance';
|
|
8
8
|
import type { PlayBundleArtifact } from '../plays/artifact-types';
|
|
9
9
|
import type { PlayRunContractSnapshot } from '../plays/contracts';
|
|
10
|
+
import type { PlayDatasetColumnTypes } from '../play-data-plane/contracts';
|
|
10
11
|
import type { PlayStructuredDefinition } from '../plays/definition';
|
|
11
12
|
import type { PlayStaticPipeline } from '../plays/static-pipeline';
|
|
12
13
|
import type {
|
|
@@ -891,6 +892,7 @@ export interface ContextOptions {
|
|
|
891
892
|
forceRefresh?: boolean;
|
|
892
893
|
inputOffset?: number;
|
|
893
894
|
mode?: RuntimeDatasetRunOptions['mode'];
|
|
895
|
+
columnTypes?: PlayDatasetColumnTypes;
|
|
894
896
|
},
|
|
895
897
|
) => Promise<MapStartResult>;
|
|
896
898
|
/**
|
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
runtimeLimitExceededFailure,
|
|
42
42
|
} from '../run-failure';
|
|
43
43
|
import { createPlayContext } from '../context';
|
|
44
|
+
import { augmentSheetContractWithDatasetFields } from '../../play-data-plane/sheet-contract';
|
|
44
45
|
import type { RuntimeApiResponseMeta } from '../app-runtime-api';
|
|
45
46
|
import { onMemoryPressure } from '../memory-pressure-signal';
|
|
46
47
|
import {
|
|
@@ -2452,7 +2453,11 @@ async function run(
|
|
|
2452
2453
|
playName,
|
|
2453
2454
|
tableNamespace,
|
|
2454
2455
|
playInput: runtimeInputObject,
|
|
2455
|
-
sheetContract
|
|
2456
|
+
sheetContract: augmentSheetContractWithDatasetFields({
|
|
2457
|
+
contract: sheetContract,
|
|
2458
|
+
rows: items,
|
|
2459
|
+
columnTypes: mapContext.columnTypes,
|
|
2460
|
+
}),
|
|
2456
2461
|
rows: items,
|
|
2457
2462
|
inputOffset: mapContext.inputOffset,
|
|
2458
2463
|
mode: mapContext.mode,
|