@runtypelabs/cli 2.24.0 → 2.25.0
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/index.js +955 -229
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -549,7 +549,7 @@ import { RuntypeApiError } from "@runtypelabs/sdk";
|
|
|
549
549
|
// src/lib/sdk-client.ts
|
|
550
550
|
import { createClient } from "@runtypelabs/sdk";
|
|
551
551
|
|
|
552
|
-
// ../shared/dist/chunk-
|
|
552
|
+
// ../shared/dist/chunk-6FWWIIGE.mjs
|
|
553
553
|
var travrseConfig = {
|
|
554
554
|
name: "Travrse",
|
|
555
555
|
nameLower: "travrse",
|
|
@@ -573,7 +573,7 @@ var runtypeConfig = {
|
|
|
573
573
|
name: "Runtype",
|
|
574
574
|
nameLower: "runtype",
|
|
575
575
|
tagline: "Your AI Product Platform",
|
|
576
|
-
description: "
|
|
576
|
+
description: "The fastest way to ship agentic products. Prototype in minutes, prove it with evals, and ship to every surface on our cloud or yours.",
|
|
577
577
|
url: "https://www.runtype.com",
|
|
578
578
|
website: "https://runtype.com",
|
|
579
579
|
domain: "runtype.com",
|
|
@@ -3060,9 +3060,9 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
3060
3060
|
$ZodStringFormat.init(inst, def);
|
|
3061
3061
|
inst._zod.check = (payload) => {
|
|
3062
3062
|
try {
|
|
3063
|
-
const
|
|
3063
|
+
const trimmed2 = payload.value.trim();
|
|
3064
3064
|
if (!def.normalize && def.protocol?.source === httpProtocol.source) {
|
|
3065
|
-
if (!/^https?:\/\//i.test(
|
|
3065
|
+
if (!/^https?:\/\//i.test(trimmed2)) {
|
|
3066
3066
|
payload.issues.push({
|
|
3067
3067
|
code: "invalid_format",
|
|
3068
3068
|
format: "url",
|
|
@@ -3074,7 +3074,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
3074
3074
|
return;
|
|
3075
3075
|
}
|
|
3076
3076
|
}
|
|
3077
|
-
const url2 = new URL(
|
|
3077
|
+
const url2 = new URL(trimmed2);
|
|
3078
3078
|
if (def.hostname) {
|
|
3079
3079
|
def.hostname.lastIndex = 0;
|
|
3080
3080
|
if (!def.hostname.test(url2.hostname)) {
|
|
@@ -3106,7 +3106,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
|
|
|
3106
3106
|
if (def.normalize) {
|
|
3107
3107
|
payload.value = url2.href;
|
|
3108
3108
|
} else {
|
|
3109
|
-
payload.value =
|
|
3109
|
+
payload.value = trimmed2;
|
|
3110
3110
|
}
|
|
3111
3111
|
return;
|
|
3112
3112
|
} catch (_2) {
|
|
@@ -15181,7 +15181,7 @@ var edgeContextPayloadSchema = external_exports.object({
|
|
|
15181
15181
|
exp: external_exports.number().int().positive()
|
|
15182
15182
|
});
|
|
15183
15183
|
|
|
15184
|
-
// ../shared/dist/chunk-
|
|
15184
|
+
// ../shared/dist/chunk-OOL23ALD.mjs
|
|
15185
15185
|
function getNestedValue(obj, path19) {
|
|
15186
15186
|
let normalizedPath = path19;
|
|
15187
15187
|
normalizedPath = normalizedPath.replace(/^\$\.?/, "");
|
|
@@ -15257,8 +15257,8 @@ var RUNTIME_PREFIXES = {
|
|
|
15257
15257
|
};
|
|
15258
15258
|
var PREFIX_PATTERN = /^([A-Za-z][A-Za-z0-9_-]*):(.*)$/s;
|
|
15259
15259
|
function classifyVariableReference(token) {
|
|
15260
|
-
const
|
|
15261
|
-
const prefixMatch = PREFIX_PATTERN.exec(
|
|
15260
|
+
const trimmed2 = token.trim();
|
|
15261
|
+
const prefixMatch = PREFIX_PATTERN.exec(trimmed2);
|
|
15262
15262
|
if (prefixMatch) {
|
|
15263
15263
|
const prefix = `${prefixMatch[1]}:`;
|
|
15264
15264
|
const rest = prefixMatch[2] ?? "";
|
|
@@ -15266,12 +15266,12 @@ function classifyVariableReference(token) {
|
|
|
15266
15266
|
if (spec) {
|
|
15267
15267
|
return { namespace: spec.namespace, baseName: rest.trim() };
|
|
15268
15268
|
}
|
|
15269
|
-
return { namespace: "unknown", raw:
|
|
15269
|
+
return { namespace: "unknown", raw: trimmed2 };
|
|
15270
15270
|
}
|
|
15271
|
-
if (isSystemVariable(
|
|
15272
|
-
return { namespace: "system", baseName:
|
|
15271
|
+
if (isSystemVariable(trimmed2)) {
|
|
15272
|
+
return { namespace: "system", baseName: trimmed2 };
|
|
15273
15273
|
}
|
|
15274
|
-
return { namespace: "plain", baseName:
|
|
15274
|
+
return { namespace: "plain", baseName: trimmed2 };
|
|
15275
15275
|
}
|
|
15276
15276
|
function isSystemVariable(varName) {
|
|
15277
15277
|
const rootSegment = varName.split(".")[0] || "";
|
|
@@ -15287,15 +15287,15 @@ function parseTemplateExpression(expr) {
|
|
|
15287
15287
|
operands: tokens.rawOperands.map(parseOperand)
|
|
15288
15288
|
};
|
|
15289
15289
|
}
|
|
15290
|
-
const
|
|
15291
|
-
const pipeIndex =
|
|
15290
|
+
const trimmed2 = expr.trim();
|
|
15291
|
+
const pipeIndex = trimmed2.indexOf("|");
|
|
15292
15292
|
if (pipeIndex === -1) {
|
|
15293
|
-
return { kind: "legacy", variable:
|
|
15293
|
+
return { kind: "legacy", variable: trimmed2 };
|
|
15294
15294
|
}
|
|
15295
15295
|
return {
|
|
15296
15296
|
kind: "legacy",
|
|
15297
|
-
variable:
|
|
15298
|
-
defaultValue:
|
|
15297
|
+
variable: trimmed2.slice(0, pipeIndex).trim(),
|
|
15298
|
+
defaultValue: trimmed2.slice(pipeIndex + 1).trim()
|
|
15299
15299
|
};
|
|
15300
15300
|
}
|
|
15301
15301
|
function tokenizeFallbackExpression(expr) {
|
|
@@ -15566,7 +15566,7 @@ function resolveFallback(parsed, context, tracking) {
|
|
|
15566
15566
|
}
|
|
15567
15567
|
var templateEngine = new SimpleTemplateEngine();
|
|
15568
15568
|
|
|
15569
|
-
// ../shared/dist/chunk-
|
|
15569
|
+
// ../shared/dist/chunk-CNO2UJFO.mjs
|
|
15570
15570
|
var tokensSchema = external_exports.object({ input: external_exports.number(), output: external_exports.number() });
|
|
15571
15571
|
var wireStopReasonSchema = external_exports.enum([
|
|
15572
15572
|
"end_turn",
|
|
@@ -15641,7 +15641,13 @@ var unifiedExecutionErrorEventSchema = external_exports.object({
|
|
|
15641
15641
|
error: unifiedErrorPayloadSchema,
|
|
15642
15642
|
completedAt: external_exports.string().optional(),
|
|
15643
15643
|
code: external_exports.string().optional(),
|
|
15644
|
-
upgradeUrl: external_exports.string().optional()
|
|
15644
|
+
upgradeUrl: external_exports.string().optional(),
|
|
15645
|
+
// Structured discriminant for a platform-key spend block (credit_exhausted |
|
|
15646
|
+
// trial_expired | auto_topup_failed) so the dashboard paywall can render
|
|
15647
|
+
// differentiated copy. The `PlatformKeyBlockReason` union lives in
|
|
15648
|
+
// `@runtypelabs/model-execution`, which `shared` cannot import — typed as a
|
|
15649
|
+
// string to mirror the sibling `code` / `upgradeUrl` fields.
|
|
15650
|
+
blockReason: external_exports.string().optional()
|
|
15645
15651
|
});
|
|
15646
15652
|
var unifiedTurnStartEventSchema = external_exports.object({
|
|
15647
15653
|
...unifiedBase,
|
|
@@ -15867,7 +15873,11 @@ var unifiedToolCompleteEventSchema = external_exports.object({
|
|
|
15867
15873
|
});
|
|
15868
15874
|
var unifiedSubagentAttributionSchema = external_exports.object({
|
|
15869
15875
|
toolName: external_exports.string(),
|
|
15870
|
-
agentName: external_exports.string().optional()
|
|
15876
|
+
agentName: external_exports.string().optional(),
|
|
15877
|
+
// Parent-stream correlation id: the subagent tool bubble the client already
|
|
15878
|
+
// saw (the approval's own `toolCallId` is the muted child's never-streamed
|
|
15879
|
+
// tool_use id).
|
|
15880
|
+
parentToolCallId: external_exports.string().optional()
|
|
15871
15881
|
});
|
|
15872
15882
|
var unifiedApprovalStartEventSchema = external_exports.object({
|
|
15873
15883
|
...unifiedBase,
|
|
@@ -15904,7 +15914,17 @@ var unifiedAwaitEventSchema = external_exports.object({
|
|
|
15904
15914
|
parameters: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
15905
15915
|
awaitedAt: external_exports.string().optional(),
|
|
15906
15916
|
origin: external_exports.enum(["webmcp", "sdk"]).optional(),
|
|
15907
|
-
pageOrigin: external_exports.string().optional()
|
|
15917
|
+
pageOrigin: external_exports.string().optional(),
|
|
15918
|
+
// Discriminates an AUTO-RESUMING durable pause (`crawl_pending` /
|
|
15919
|
+
// `durable_poll`, resumed server-side by the crawl / wait-until
|
|
15920
|
+
// Workflow) from a CLIENT-RESOLVABLE local-tool / WebMCP await (absent), so a
|
|
15921
|
+
// streaming consumer does not render a "resume" prompt for a pause that
|
|
15922
|
+
// resumes itself. Mirrors the JSON `pausedReason` discriminator
|
|
15923
|
+
// (execution-pipeline.ts); the server-resumed pauses carry `crawlId` /
|
|
15924
|
+
// `stepId` instead of the tool fields. UX context; never a control signal.
|
|
15925
|
+
awaitReason: external_exports.string().optional(),
|
|
15926
|
+
crawlId: external_exports.string().optional(),
|
|
15927
|
+
stepId: external_exports.string().optional()
|
|
15908
15928
|
});
|
|
15909
15929
|
var unifiedErrorEventSchema = external_exports.object({
|
|
15910
15930
|
...unifiedBase,
|
|
@@ -16024,7 +16044,8 @@ var externalAgentContextSchema = external_exports.object({
|
|
|
16024
16044
|
});
|
|
16025
16045
|
var subagentAttributionSchema = external_exports.object({
|
|
16026
16046
|
toolName: external_exports.string(),
|
|
16027
|
-
agentName: external_exports.string().optional()
|
|
16047
|
+
agentName: external_exports.string().optional(),
|
|
16048
|
+
parentToolCallId: external_exports.string().optional()
|
|
16028
16049
|
});
|
|
16029
16050
|
var tokensSchema2 = external_exports.object({ input: external_exports.number(), output: external_exports.number() });
|
|
16030
16051
|
var wireStopReasonSchema2 = external_exports.enum([
|
|
@@ -16383,6 +16404,11 @@ var flowErrorEventSchema = external_exports.object({
|
|
|
16383
16404
|
// Spread only on platform-key spend errors (api raw-write).
|
|
16384
16405
|
code: external_exports.string().optional(),
|
|
16385
16406
|
upgradeUrl: external_exports.string().optional(),
|
|
16407
|
+
// Structured discriminant for a platform-key spend block (credit_exhausted |
|
|
16408
|
+
// trial_expired | auto_topup_failed). Typed as a string here because the
|
|
16409
|
+
// `PlatformKeyBlockReason` union lives in `@runtypelabs/model-execution`,
|
|
16410
|
+
// which `shared` cannot import — mirrors the sibling `code` / `upgradeUrl`.
|
|
16411
|
+
blockReason: external_exports.string().optional(),
|
|
16386
16412
|
timestamp: external_exports.string().optional(),
|
|
16387
16413
|
flowId: external_exports.string().optional(),
|
|
16388
16414
|
toolContext: toolContextSchema.optional()
|
|
@@ -16400,7 +16426,23 @@ var flowAwaitEventSchema = external_exports.object({
|
|
|
16400
16426
|
parameters: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
16401
16427
|
awaitedAt: external_exports.string(),
|
|
16402
16428
|
origin: external_exports.enum(["webmcp", "sdk"]).optional(),
|
|
16403
|
-
pageOrigin: external_exports.string().optional()
|
|
16429
|
+
pageOrigin: external_exports.string().optional(),
|
|
16430
|
+
// Discriminates an AUTO-RESUMING durable pause (`crawl_pending` /
|
|
16431
|
+
// `durable_poll`, resumed server-side by the crawl / wait-until
|
|
16432
|
+
// Workflow) from a CLIENT-RESOLVABLE local-tool / WebMCP await (absent). The
|
|
16433
|
+
// server-resumed pauses carry `crawlId` / `stepId` instead of the tool fields.
|
|
16434
|
+
// Open `z.string()` (not an enum) for forward-compat — kept in lockstep with
|
|
16435
|
+
// the JSON `pausedReason` discriminator in execution-pipeline.ts. UX context;
|
|
16436
|
+
// never a control signal.
|
|
16437
|
+
awaitReason: external_exports.string().optional(),
|
|
16438
|
+
crawlId: external_exports.string().optional(),
|
|
16439
|
+
stepId: external_exports.string().optional(),
|
|
16440
|
+
// Approval pauses (`awaitReason: 'approval_required'`) carry the approval
|
|
16441
|
+
// handle + configured timeout (ms). The flow→agent bridges and the unified
|
|
16442
|
+
// translator key on `approvalId` to surface the pause as an approval event
|
|
16443
|
+
// instead of a local-tool await.
|
|
16444
|
+
approvalId: external_exports.string().optional(),
|
|
16445
|
+
timeout: external_exports.number().optional()
|
|
16404
16446
|
});
|
|
16405
16447
|
var stepStartEventSchema = external_exports.object({
|
|
16406
16448
|
...baseFlowEvent,
|
|
@@ -16691,6 +16733,7 @@ var AGENT_CONTENT_CONFIG_KEYS = {
|
|
|
16691
16733
|
errorHandling: true,
|
|
16692
16734
|
artifacts: true,
|
|
16693
16735
|
loggingPolicy: true,
|
|
16736
|
+
piiRedaction: true,
|
|
16694
16737
|
temporal: true,
|
|
16695
16738
|
memory: true,
|
|
16696
16739
|
sandbox: true,
|
|
@@ -17604,6 +17647,51 @@ var retrieveRecordConfigSchema = external_exports.object({
|
|
|
17604
17647
|
includeMetadata: external_exports.boolean().optional(),
|
|
17605
17648
|
streamOutput: external_exports.boolean().optional()
|
|
17606
17649
|
});
|
|
17650
|
+
var LIST_RECORDS_MAX_LIMIT = 1e3;
|
|
17651
|
+
var hasNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
17652
|
+
var getRecordConfigSchema = external_exports.object({
|
|
17653
|
+
recordId: external_exports.string().optional(),
|
|
17654
|
+
recordType: external_exports.string().optional(),
|
|
17655
|
+
recordName: external_exports.string().optional(),
|
|
17656
|
+
recordFilter: recordFilterSchema.optional(),
|
|
17657
|
+
fieldsToInclude: external_exports.string().optional(),
|
|
17658
|
+
fieldsToExclude: external_exports.string().optional(),
|
|
17659
|
+
availableFields: external_exports.array(external_exports.string()).optional(),
|
|
17660
|
+
includeMetadata: external_exports.boolean().optional(),
|
|
17661
|
+
streamOutput: external_exports.boolean().optional(),
|
|
17662
|
+
outputVariable: external_exports.string().min(1, "Output variable is required")
|
|
17663
|
+
}).superRefine((config3, ctx) => {
|
|
17664
|
+
const hasFilterType = hasNonEmptyString(config3.recordFilter?.type);
|
|
17665
|
+
if (!hasNonEmptyString(config3.recordId) && !hasNonEmptyString(config3.recordType) && !hasNonEmptyString(config3.recordName) && !hasFilterType) {
|
|
17666
|
+
ctx.addIssue({
|
|
17667
|
+
code: "custom",
|
|
17668
|
+
path: ["recordId"],
|
|
17669
|
+
message: "get-record step requires at least one of 'recordId', 'recordType', 'recordName', or 'recordFilter'"
|
|
17670
|
+
});
|
|
17671
|
+
}
|
|
17672
|
+
});
|
|
17673
|
+
var listRecordsConfigSchema = external_exports.object({
|
|
17674
|
+
recordType: external_exports.string().optional(),
|
|
17675
|
+
recordName: external_exports.string().optional(),
|
|
17676
|
+
recordFilter: recordFilterSchema.optional(),
|
|
17677
|
+
limit: external_exports.number().int().min(1).max(LIST_RECORDS_MAX_LIMIT).optional(),
|
|
17678
|
+
onEmpty: external_exports.enum(["succeed", "fail"]).optional(),
|
|
17679
|
+
fieldsToInclude: external_exports.string().optional(),
|
|
17680
|
+
fieldsToExclude: external_exports.string().optional(),
|
|
17681
|
+
availableFields: external_exports.array(external_exports.string()).optional(),
|
|
17682
|
+
includeMetadata: external_exports.boolean().optional(),
|
|
17683
|
+
streamOutput: external_exports.boolean().optional(),
|
|
17684
|
+
outputVariable: external_exports.string().min(1, "Output variable is required")
|
|
17685
|
+
}).superRefine((config3, ctx) => {
|
|
17686
|
+
const hasFilterType = hasNonEmptyString(config3.recordFilter?.type);
|
|
17687
|
+
if (!hasNonEmptyString(config3.recordType) && !hasNonEmptyString(config3.recordName) && !hasFilterType) {
|
|
17688
|
+
ctx.addIssue({
|
|
17689
|
+
code: "custom",
|
|
17690
|
+
path: ["recordType"],
|
|
17691
|
+
message: "list-records step requires at least one of 'recordType', 'recordName', or 'recordFilter'"
|
|
17692
|
+
});
|
|
17693
|
+
}
|
|
17694
|
+
});
|
|
17607
17695
|
var updateRecordConfigSchema = external_exports.object({
|
|
17608
17696
|
recordId: external_exports.string().optional(),
|
|
17609
17697
|
recordType: external_exports.string().optional(),
|
|
@@ -17832,6 +17920,8 @@ var sharedStepConfigSchemas = {
|
|
|
17832
17920
|
"send-email": sendEmailConfigSchema,
|
|
17833
17921
|
"paginate-api": paginateApiConfigSchema,
|
|
17834
17922
|
"retrieve-record": retrieveRecordConfigSchema,
|
|
17923
|
+
"get-record": getRecordConfigSchema,
|
|
17924
|
+
"list-records": listRecordsConfigSchema,
|
|
17835
17925
|
"update-record": updateRecordConfigSchema,
|
|
17836
17926
|
"transform-data": transformDataConfigSchema,
|
|
17837
17927
|
prompt: promptConfigSchema,
|
|
@@ -17859,6 +17949,8 @@ var CONTEXT_STEP_TYPES = [
|
|
|
17859
17949
|
"crawl",
|
|
17860
17950
|
"fetch-url",
|
|
17861
17951
|
"retrieve-record",
|
|
17952
|
+
"get-record",
|
|
17953
|
+
"list-records",
|
|
17862
17954
|
"fetch-github",
|
|
17863
17955
|
"api-call",
|
|
17864
17956
|
"transform-data",
|
|
@@ -17950,6 +18042,52 @@ function isCustomSendFromAddressOnManagedDomain(configuredFrom, preferredManaged
|
|
|
17950
18042
|
preferredManagedDomain
|
|
17951
18043
|
);
|
|
17952
18044
|
}
|
|
18045
|
+
function isPlainObject9(value) {
|
|
18046
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18047
|
+
}
|
|
18048
|
+
function trimmed(value) {
|
|
18049
|
+
return typeof value === "string" ? value.trim() : "";
|
|
18050
|
+
}
|
|
18051
|
+
function retrieveRecordProducesArray(config3) {
|
|
18052
|
+
const recordId = trimmed(config3.recordId);
|
|
18053
|
+
if (recordId) return false;
|
|
18054
|
+
if (config3.retrievalMode && config3.retrievalMode !== "query") return false;
|
|
18055
|
+
const recordType = trimmed(config3.recordType);
|
|
18056
|
+
const recordName = trimmed(config3.recordName);
|
|
18057
|
+
const filter = config3.recordFilter;
|
|
18058
|
+
const filterType = isPlainObject9(filter) ? trimmed(filter.type) : "";
|
|
18059
|
+
return !!(recordType || recordName || filterType);
|
|
18060
|
+
}
|
|
18061
|
+
function resolveRetrieveRecordAlias(config3) {
|
|
18062
|
+
const common = {
|
|
18063
|
+
recordType: config3.recordType,
|
|
18064
|
+
recordName: config3.recordName,
|
|
18065
|
+
recordFilter: config3.recordFilter,
|
|
18066
|
+
fieldsToInclude: config3.fieldsToInclude,
|
|
18067
|
+
fieldsToExclude: config3.fieldsToExclude,
|
|
18068
|
+
availableFields: config3.availableFields,
|
|
18069
|
+
includeMetadata: config3.includeMetadata,
|
|
18070
|
+
streamOutput: config3.streamOutput,
|
|
18071
|
+
outputVariable: config3.outputVariable
|
|
18072
|
+
};
|
|
18073
|
+
if (retrieveRecordProducesArray(config3)) {
|
|
18074
|
+
return {
|
|
18075
|
+
type: "list-records",
|
|
18076
|
+
config: {
|
|
18077
|
+
...common,
|
|
18078
|
+
limit: LIST_RECORDS_MAX_LIMIT,
|
|
18079
|
+
onEmpty: "fail"
|
|
18080
|
+
}
|
|
18081
|
+
};
|
|
18082
|
+
}
|
|
18083
|
+
return {
|
|
18084
|
+
type: "get-record",
|
|
18085
|
+
config: {
|
|
18086
|
+
recordId: config3.recordId,
|
|
18087
|
+
...common
|
|
18088
|
+
}
|
|
18089
|
+
};
|
|
18090
|
+
}
|
|
17953
18091
|
var NormalizationError = class extends Error {
|
|
17954
18092
|
constructor(message, stepType, fieldName, expectedType, actualValue) {
|
|
17955
18093
|
super(message);
|
|
@@ -18152,6 +18290,8 @@ function normalizeContextStep(apiStep, options = {}) {
|
|
|
18152
18290
|
"crawl",
|
|
18153
18291
|
"fetch-url",
|
|
18154
18292
|
"retrieve-record",
|
|
18293
|
+
"get-record",
|
|
18294
|
+
"list-records",
|
|
18155
18295
|
"fetch-github",
|
|
18156
18296
|
"api-call",
|
|
18157
18297
|
"transform-data",
|
|
@@ -18208,11 +18348,26 @@ function normalizeContextStep(apiStep, options = {}) {
|
|
|
18208
18348
|
type: "fetch-url",
|
|
18209
18349
|
config: normalizeFetchUrlConfig(apiStep.config)
|
|
18210
18350
|
};
|
|
18211
|
-
case "retrieve-record":
|
|
18351
|
+
case "retrieve-record": {
|
|
18352
|
+
const legacyConfig = normalizeRetrieveRecordConfig(apiStep.config);
|
|
18353
|
+
const aliased = resolveRetrieveRecordAlias(legacyConfig);
|
|
18354
|
+
return {
|
|
18355
|
+
...baseStep,
|
|
18356
|
+
type: aliased.type,
|
|
18357
|
+
config: aliased.config
|
|
18358
|
+
};
|
|
18359
|
+
}
|
|
18360
|
+
case "get-record":
|
|
18212
18361
|
return {
|
|
18213
18362
|
...baseStep,
|
|
18214
|
-
type: "
|
|
18215
|
-
config:
|
|
18363
|
+
type: "get-record",
|
|
18364
|
+
config: normalizeGetRecordConfig(apiStep.config)
|
|
18365
|
+
};
|
|
18366
|
+
case "list-records":
|
|
18367
|
+
return {
|
|
18368
|
+
...baseStep,
|
|
18369
|
+
type: "list-records",
|
|
18370
|
+
config: normalizeListRecordsConfig(apiStep.config)
|
|
18216
18371
|
};
|
|
18217
18372
|
case "fetch-github":
|
|
18218
18373
|
return {
|
|
@@ -18612,6 +18767,84 @@ function normalizeRetrieveRecordConfig(config3) {
|
|
|
18612
18767
|
outputVariable: config3.outputVariable
|
|
18613
18768
|
};
|
|
18614
18769
|
}
|
|
18770
|
+
function normalizeGetRecordConfig(config3) {
|
|
18771
|
+
validateConfig(config3, "get-record");
|
|
18772
|
+
const filter = config3.recordFilter;
|
|
18773
|
+
const hasFilter = filter && typeof filter === "object" && typeof filter.type === "string" && filter.type.length > 0;
|
|
18774
|
+
if (!config3.recordId && !config3.recordType && !config3.recordName && !hasFilter) {
|
|
18775
|
+
throw new NormalizationError(
|
|
18776
|
+
`get-record step requires at least one of 'recordId', 'recordType', 'recordName', or 'recordFilter'`,
|
|
18777
|
+
"get-record",
|
|
18778
|
+
"recordId/recordType/recordName/recordFilter",
|
|
18779
|
+
"at least one identification field",
|
|
18780
|
+
void 0
|
|
18781
|
+
);
|
|
18782
|
+
}
|
|
18783
|
+
validateString(config3.outputVariable, "outputVariable", "get-record", true);
|
|
18784
|
+
if (config3.fieldsToInclude)
|
|
18785
|
+
validateString(config3.fieldsToInclude, "fieldsToInclude", "get-record");
|
|
18786
|
+
if (config3.fieldsToExclude)
|
|
18787
|
+
validateString(config3.fieldsToExclude, "fieldsToExclude", "get-record");
|
|
18788
|
+
if (config3.availableFields)
|
|
18789
|
+
validateArray(config3.availableFields, "availableFields", "get-record");
|
|
18790
|
+
if (config3.includeMetadata !== void 0)
|
|
18791
|
+
validateBoolean(config3.includeMetadata, "includeMetadata", "get-record");
|
|
18792
|
+
if (config3.streamOutput !== void 0)
|
|
18793
|
+
validateBoolean(config3.streamOutput, "streamOutput", "get-record");
|
|
18794
|
+
return {
|
|
18795
|
+
recordId: config3.recordId,
|
|
18796
|
+
recordType: config3.recordType,
|
|
18797
|
+
recordName: config3.recordName,
|
|
18798
|
+
recordFilter: config3.recordFilter,
|
|
18799
|
+
fieldsToInclude: config3.fieldsToInclude,
|
|
18800
|
+
fieldsToExclude: config3.fieldsToExclude,
|
|
18801
|
+
availableFields: config3.availableFields,
|
|
18802
|
+
includeMetadata: config3.includeMetadata,
|
|
18803
|
+
streamOutput: config3.streamOutput,
|
|
18804
|
+
outputVariable: config3.outputVariable
|
|
18805
|
+
};
|
|
18806
|
+
}
|
|
18807
|
+
function normalizeListRecordsConfig(config3) {
|
|
18808
|
+
validateConfig(config3, "list-records");
|
|
18809
|
+
const filter = config3.recordFilter;
|
|
18810
|
+
const hasFilter = filter && typeof filter === "object" && typeof filter.type === "string" && filter.type.length > 0;
|
|
18811
|
+
if (!config3.recordType && !config3.recordName && !hasFilter) {
|
|
18812
|
+
throw new NormalizationError(
|
|
18813
|
+
`list-records step requires at least one of 'recordType', 'recordName', or 'recordFilter'`,
|
|
18814
|
+
"list-records",
|
|
18815
|
+
"recordType/recordName/recordFilter",
|
|
18816
|
+
"at least one query field",
|
|
18817
|
+
void 0
|
|
18818
|
+
);
|
|
18819
|
+
}
|
|
18820
|
+
validateString(config3.outputVariable, "outputVariable", "list-records", true);
|
|
18821
|
+
if (config3.limit !== void 0) validateNumber(config3.limit, "limit", "list-records");
|
|
18822
|
+
if (config3.onEmpty !== void 0)
|
|
18823
|
+
validateEnum(config3.onEmpty, ["succeed", "fail"], "onEmpty", "list-records");
|
|
18824
|
+
if (config3.fieldsToInclude)
|
|
18825
|
+
validateString(config3.fieldsToInclude, "fieldsToInclude", "list-records");
|
|
18826
|
+
if (config3.fieldsToExclude)
|
|
18827
|
+
validateString(config3.fieldsToExclude, "fieldsToExclude", "list-records");
|
|
18828
|
+
if (config3.availableFields)
|
|
18829
|
+
validateArray(config3.availableFields, "availableFields", "list-records");
|
|
18830
|
+
if (config3.includeMetadata !== void 0)
|
|
18831
|
+
validateBoolean(config3.includeMetadata, "includeMetadata", "list-records");
|
|
18832
|
+
if (config3.streamOutput !== void 0)
|
|
18833
|
+
validateBoolean(config3.streamOutput, "streamOutput", "list-records");
|
|
18834
|
+
return {
|
|
18835
|
+
recordType: config3.recordType,
|
|
18836
|
+
recordName: config3.recordName,
|
|
18837
|
+
recordFilter: config3.recordFilter,
|
|
18838
|
+
limit: normalizeOptionalNumber(config3.limit),
|
|
18839
|
+
onEmpty: config3.onEmpty,
|
|
18840
|
+
fieldsToInclude: config3.fieldsToInclude,
|
|
18841
|
+
fieldsToExclude: config3.fieldsToExclude,
|
|
18842
|
+
availableFields: config3.availableFields,
|
|
18843
|
+
includeMetadata: config3.includeMetadata,
|
|
18844
|
+
streamOutput: config3.streamOutput,
|
|
18845
|
+
outputVariable: config3.outputVariable
|
|
18846
|
+
};
|
|
18847
|
+
}
|
|
18615
18848
|
function normalizeFetchGithubConfig(config3) {
|
|
18616
18849
|
validateConfig(config3, "fetch-github");
|
|
18617
18850
|
validateString(config3.repository, "repository", "fetch-github", true);
|
|
@@ -19842,6 +20075,7 @@ function sanitizeCodeToolIdentifier(name) {
|
|
|
19842
20075
|
if (/^[0-9]/.test(safe)) safe = "_" + safe;
|
|
19843
20076
|
return safe;
|
|
19844
20077
|
}
|
|
20078
|
+
var MAX_DURABLE_POLL_ATTEMPTS = 1e3;
|
|
19845
20079
|
var flowStepValidationSchema = external_exports.object({
|
|
19846
20080
|
// Optional stable client-supplied identifier. Preserved across saves so that
|
|
19847
20081
|
// `flow_step_results.stepId` references stay valid and dashboard UI state
|
|
@@ -19907,7 +20141,12 @@ var LEGACY_TOOL_KEY_SUGGESTIONS = {
|
|
|
19907
20141
|
function isObjectRecord(value) {
|
|
19908
20142
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19909
20143
|
}
|
|
19910
|
-
var NETWORK_ISOLATED_SANDBOX_PROVIDERS = /* @__PURE__ */ new Set([
|
|
20144
|
+
var NETWORK_ISOLATED_SANDBOX_PROVIDERS = /* @__PURE__ */ new Set([
|
|
20145
|
+
"cloudflare-worker",
|
|
20146
|
+
"quickjs",
|
|
20147
|
+
"runtype-sandbox",
|
|
20148
|
+
"cloudflare-sandbox"
|
|
20149
|
+
]);
|
|
19911
20150
|
var MAX_CONDITIONAL_NESTING_DEPTH = 10;
|
|
19912
20151
|
var FETCH_CALL_PATTERN = /\bfetch\s*\(/;
|
|
19913
20152
|
function validateSandboxNetworkAccess(config3, stepIndex, stepRef, buckets) {
|
|
@@ -20515,6 +20754,134 @@ function validateConditionExpressions(flowSteps, buckets, conditionalStepsExceed
|
|
|
20515
20754
|
walkStepConditionExpressions(step, `flowSteps[${stepIndex}]`, stepRef, buckets, 1);
|
|
20516
20755
|
}
|
|
20517
20756
|
}
|
|
20757
|
+
var TOOL_STRATEGY_REQUIRED_MULTISTEP_CODE = "TOOL_STRATEGY_REQUIRED_MULTISTEP";
|
|
20758
|
+
function isRequiredMultiStepFootgun(input) {
|
|
20759
|
+
if (input.toolCallStrategy !== "required") return false;
|
|
20760
|
+
if (typeof input.maxTurns === "number" && input.maxTurns > 1) return true;
|
|
20761
|
+
return input.maxToolCalls !== 1;
|
|
20762
|
+
}
|
|
20763
|
+
function toolStrategyRequiredMultiStepMessage() {
|
|
20764
|
+
return 'Tool call strategy "required" forces the model to call a tool on every step. Unless the turn is capped to a single tool call (maxToolCalls of 1), the model can never return a final text answer and the output comes back empty \u2014 the runtime default allows multiple tool calls, so leaving maxToolCalls unset (or above 1), or running a multi-turn loop, triggers this. Use "auto" (recommended) so the model decides when to call tools and can finish with text, or keep "required" only for a single forced tool call (maxToolCalls of 1, no loop).';
|
|
20765
|
+
}
|
|
20766
|
+
function validateToolCallStrategyMultiStep(flowSteps, buckets) {
|
|
20767
|
+
for (const [stepIndex, step] of flowSteps.entries()) {
|
|
20768
|
+
if (step.enabled === false) continue;
|
|
20769
|
+
if (step.type !== "prompt") continue;
|
|
20770
|
+
if (!isObjectRecord(step.config)) continue;
|
|
20771
|
+
const tools = step.config.tools;
|
|
20772
|
+
if (!isObjectRecord(tools)) continue;
|
|
20773
|
+
const toolCallStrategy = tools.toolCallStrategy ?? tools.tool_call_strategy;
|
|
20774
|
+
const maxToolCallsRaw = tools.maxToolCalls ?? tools.max_tool_calls;
|
|
20775
|
+
const maxToolCalls = typeof maxToolCallsRaw === "number" ? maxToolCallsRaw : void 0;
|
|
20776
|
+
if (isRequiredMultiStepFootgun({ toolCallStrategy, maxToolCalls })) {
|
|
20777
|
+
addIssue(
|
|
20778
|
+
"warning",
|
|
20779
|
+
{
|
|
20780
|
+
code: TOOL_STRATEGY_REQUIRED_MULTISTEP_CODE,
|
|
20781
|
+
message: toolStrategyRequiredMultiStepMessage(),
|
|
20782
|
+
path: `flowSteps[${stepIndex}].config.tools`,
|
|
20783
|
+
step: { index: stepIndex, name: step.name, type: step.type },
|
|
20784
|
+
details: { toolCallStrategy: "required", maxToolCalls }
|
|
20785
|
+
},
|
|
20786
|
+
buckets
|
|
20787
|
+
);
|
|
20788
|
+
}
|
|
20789
|
+
}
|
|
20790
|
+
}
|
|
20791
|
+
var WAIT_UNTIL_MAX_ATTEMPTS_CLAMPED_CODE = "WAIT_UNTIL_MAX_ATTEMPTS_CLAMPED";
|
|
20792
|
+
function validateWaitUntilPollBudget(flowSteps, buckets) {
|
|
20793
|
+
for (const [stepIndex, step] of flowSteps.entries()) {
|
|
20794
|
+
if (step.enabled === false) continue;
|
|
20795
|
+
if (step.type !== "wait-until") continue;
|
|
20796
|
+
if (!isObjectRecord(step.config)) continue;
|
|
20797
|
+
const poll = step.config.poll;
|
|
20798
|
+
if (!isObjectRecord(poll)) continue;
|
|
20799
|
+
const maxAttempts = poll.maxAttempts;
|
|
20800
|
+
if (typeof maxAttempts !== "number" || maxAttempts <= MAX_DURABLE_POLL_ATTEMPTS) continue;
|
|
20801
|
+
addIssue(
|
|
20802
|
+
"warning",
|
|
20803
|
+
{
|
|
20804
|
+
code: WAIT_UNTIL_MAX_ATTEMPTS_CLAMPED_CODE,
|
|
20805
|
+
message: `poll.maxAttempts (${maxAttempts}) exceeds the durable poll budget of ${MAX_DURABLE_POLL_ATTEMPTS} attempts; when this step runs as a durable Workflow poll the attempt count is clamped to ${MAX_DURABLE_POLL_ATTEMPTS}. To cover the same wall-clock window, increase poll.intervalMs instead of adding attempts.`,
|
|
20806
|
+
path: `flowSteps[${stepIndex}].config.poll.maxAttempts`,
|
|
20807
|
+
step: { index: stepIndex, name: step.name, type: step.type },
|
|
20808
|
+
details: { maxAttempts, maxDurablePollAttempts: MAX_DURABLE_POLL_ATTEMPTS }
|
|
20809
|
+
},
|
|
20810
|
+
buckets
|
|
20811
|
+
);
|
|
20812
|
+
}
|
|
20813
|
+
}
|
|
20814
|
+
var LIST_RECORDS_OBJECT_ACCESS_CODE = "LIST_RECORDS_OBJECT_ACCESS";
|
|
20815
|
+
var DEPRECATED_STEP_TYPE_CODE = "DEPRECATED_STEP_TYPE";
|
|
20816
|
+
function stepProducesRecordArray(type, config3) {
|
|
20817
|
+
if (type === "list-records") return true;
|
|
20818
|
+
if (type === "retrieve-record") {
|
|
20819
|
+
return resolveRetrieveRecordAlias(config3).type === "list-records";
|
|
20820
|
+
}
|
|
20821
|
+
return false;
|
|
20822
|
+
}
|
|
20823
|
+
function validateListRecordsArrayAccess(flowSteps, buckets) {
|
|
20824
|
+
const arrayOutputs = /* @__PURE__ */ new Map();
|
|
20825
|
+
for (const [stepIndex, step] of flowSteps.entries()) {
|
|
20826
|
+
if (step.enabled === false) continue;
|
|
20827
|
+
if (!isObjectRecord(step.config)) continue;
|
|
20828
|
+
const config3 = step.config;
|
|
20829
|
+
for (const { variable, fieldPath } of extractVariableReferences(config3)) {
|
|
20830
|
+
const classification = classifyVariableReference(variable);
|
|
20831
|
+
if (classification.namespace !== "plain" && classification.namespace !== "flow") continue;
|
|
20832
|
+
const segments = classification.baseName.split(".");
|
|
20833
|
+
const root = segments[0] || "";
|
|
20834
|
+
const origin = arrayOutputs.get(root);
|
|
20835
|
+
if (!origin) continue;
|
|
20836
|
+
if (segments.length < 2) continue;
|
|
20837
|
+
const field = segments[1] || "";
|
|
20838
|
+
if (/^\d+$/.test(field) || field === "length") continue;
|
|
20839
|
+
addIssue(
|
|
20840
|
+
"warning",
|
|
20841
|
+
{
|
|
20842
|
+
code: LIST_RECORDS_OBJECT_ACCESS_CODE,
|
|
20843
|
+
message: `Variable "{{${variable}}}" reads field "${field}" on "${root}", but step "${origin.name}" returns an ARRAY of records (even when a single record matches). Object-style access resolves to undefined at runtime. Index into the array first \u2014 e.g. "{{${root}.0.${field}}}" for the first record \u2014 or loop over "${root}". To get a single record object, use a get-record step.`,
|
|
20844
|
+
path: `flowSteps[${stepIndex}].config.${fieldPath}`,
|
|
20845
|
+
step: { index: stepIndex, name: step.name, type: step.type },
|
|
20846
|
+
details: {
|
|
20847
|
+
variable,
|
|
20848
|
+
rootVariable: root,
|
|
20849
|
+
field,
|
|
20850
|
+
originStepIndex: origin.index,
|
|
20851
|
+
originStepName: origin.name
|
|
20852
|
+
}
|
|
20853
|
+
},
|
|
20854
|
+
buckets
|
|
20855
|
+
);
|
|
20856
|
+
}
|
|
20857
|
+
const outputVar = getStepOutputVariable(step);
|
|
20858
|
+
if (outputVar) {
|
|
20859
|
+
if (stepProducesRecordArray(step.type, config3)) {
|
|
20860
|
+
arrayOutputs.set(outputVar, { index: stepIndex, name: step.name });
|
|
20861
|
+
} else {
|
|
20862
|
+
arrayOutputs.delete(outputVar);
|
|
20863
|
+
}
|
|
20864
|
+
}
|
|
20865
|
+
}
|
|
20866
|
+
}
|
|
20867
|
+
function validateDeprecatedStepTypes(flowSteps, buckets) {
|
|
20868
|
+
for (const [stepIndex, step] of flowSteps.entries()) {
|
|
20869
|
+
if (step.type !== "retrieve-record") continue;
|
|
20870
|
+
const config3 = isObjectRecord(step.config) ? step.config : {};
|
|
20871
|
+
const resolvedType = resolveRetrieveRecordAlias(config3).type;
|
|
20872
|
+
addIssue(
|
|
20873
|
+
"warning",
|
|
20874
|
+
{
|
|
20875
|
+
code: DEPRECATED_STEP_TYPE_CODE,
|
|
20876
|
+
message: `The "retrieve-record" step is deprecated. Use "get-record" (returns a single record object) or "list-records" (returns an array of records) instead \u2014 this config resolves to "${resolvedType}".`,
|
|
20877
|
+
path: `flowSteps[${stepIndex}].type`,
|
|
20878
|
+
step: { index: stepIndex, name: step.name, type: step.type },
|
|
20879
|
+
details: { deprecatedType: "retrieve-record", resolvedType }
|
|
20880
|
+
},
|
|
20881
|
+
buckets
|
|
20882
|
+
);
|
|
20883
|
+
}
|
|
20884
|
+
}
|
|
20518
20885
|
function collectAccountScopedReferences(step, stepIndex, pendingChecks) {
|
|
20519
20886
|
const stepRef = {
|
|
20520
20887
|
index: stepIndex,
|
|
@@ -21098,6 +21465,10 @@ function collectFlowStructureIssues(flowData, deps, buckets) {
|
|
|
21098
21465
|
validateUpsertRecordSourceShape(flowData.flowSteps, buckets);
|
|
21099
21466
|
validateStoreVectorSource(flowData.flowSteps, buckets, deps.declaredFlowInputs);
|
|
21100
21467
|
validateConditionExpressions(flowData.flowSteps, buckets, conditionalStepsExceedingDepth);
|
|
21468
|
+
validateToolCallStrategyMultiStep(flowData.flowSteps, buckets);
|
|
21469
|
+
validateListRecordsArrayAccess(flowData.flowSteps, buckets);
|
|
21470
|
+
validateWaitUntilPollBudget(flowData.flowSteps, buckets);
|
|
21471
|
+
validateDeprecatedStepTypes(flowData.flowSteps, buckets);
|
|
21101
21472
|
return { pendingChecks };
|
|
21102
21473
|
}
|
|
21103
21474
|
function validateFlowStructure(flowData, deps = {}) {
|
|
@@ -33327,7 +33698,7 @@ var CORE_BUILTIN_TOOLS_REGISTRY = [
|
|
|
33327
33698
|
{
|
|
33328
33699
|
id: "exa",
|
|
33329
33700
|
name: "Exa",
|
|
33330
|
-
description: "Search the web using neural and keyword algorithms. Returns relevant content with optional summaries, highlights, and full text.",
|
|
33701
|
+
description: "Search the web using neural and keyword algorithms. Returns relevant content with optional summaries, highlights, and full text. Tuned for retrieval and not blocked by anti-bot defenses, so prefer this over the raw fetch-url/crawl flow steps for research against sites that block datacenter traffic.",
|
|
33331
33702
|
category: BuiltInToolCategory.WEB_SEARCH,
|
|
33332
33703
|
providers: [BuiltInToolProvider.MULTI],
|
|
33333
33704
|
parametersSchema: {
|
|
@@ -33402,7 +33773,7 @@ var CORE_BUILTIN_TOOLS_REGISTRY = [
|
|
|
33402
33773
|
{
|
|
33403
33774
|
id: "firecrawl",
|
|
33404
33775
|
name: "Firecrawl",
|
|
33405
|
-
description: "Scrape and extract content from a URL as markdown. Provide a url and optional formats array.",
|
|
33776
|
+
description: "Scrape and extract content from a URL as markdown. Provide a url and optional formats array. Handles rendering and anti-bot measures, so prefer this over a raw HTTP fetch when a site blocks, rate-limits, or challenges datacenter (non-human) traffic.",
|
|
33406
33777
|
category: BuiltInToolCategory.WEB_SCRAPING,
|
|
33407
33778
|
providers: [BuiltInToolProvider.MULTI],
|
|
33408
33779
|
parametersSchema: {
|
|
@@ -37589,7 +37960,11 @@ var BUILT_IN_GRADER_IDS = [
|
|
|
37589
37960
|
"followsInstructions",
|
|
37590
37961
|
"grounded",
|
|
37591
37962
|
"rightTone",
|
|
37592
|
-
"safeToSend"
|
|
37963
|
+
"safeToSend",
|
|
37964
|
+
"staysOnTask",
|
|
37965
|
+
"sameLanguage",
|
|
37966
|
+
"refusesWhenItShould",
|
|
37967
|
+
"noPersonalData"
|
|
37593
37968
|
];
|
|
37594
37969
|
var graderSeveritySchema = external_exports.enum(["gate", "soft"]);
|
|
37595
37970
|
var severityFields = { severity: graderSeveritySchema.optional() };
|
|
@@ -37695,39 +38070,137 @@ var caseExpectedSchema = external_exports.object({
|
|
|
37695
38070
|
});
|
|
37696
38071
|
var DEFAULT_MODELS_FOR_NEW_ACCOUNTS = [
|
|
37697
38072
|
// Mixlayer models
|
|
37698
|
-
{
|
|
37699
|
-
|
|
37700
|
-
|
|
37701
|
-
|
|
38073
|
+
{
|
|
38074
|
+
provider: "runtype",
|
|
38075
|
+
modelId: "qwen/qwen3.6-27b",
|
|
38076
|
+
isDefault: false,
|
|
38077
|
+
strengths: "Fast, low-cost open-weight workhorse with reasoning, tool-use, and vision \u2014 good for high-volume extraction, classification, and simple transforms.",
|
|
38078
|
+
bestFor: ["fast-cheap", "vision"]
|
|
38079
|
+
},
|
|
37702
38080
|
// Routed models - benefit from automatic provider optimization
|
|
37703
38081
|
// OpenAI models (routed via OpenAI direct, with Vercel fallback)
|
|
37704
|
-
{
|
|
37705
|
-
|
|
37706
|
-
|
|
38082
|
+
{
|
|
38083
|
+
provider: "runtype",
|
|
38084
|
+
modelId: "gpt-5.5",
|
|
38085
|
+
isDefault: false,
|
|
38086
|
+
strengths: "Top-tier general reasoning and tool-use with excellent structured-output reliability, vision, and a 1M context \u2014 a strong pick for complex, correctness-sensitive steps.",
|
|
38087
|
+
bestFor: ["default", "deep-reasoning", "agentic-tools", "vision", "long-context"]
|
|
38088
|
+
},
|
|
38089
|
+
{
|
|
38090
|
+
provider: "runtype",
|
|
38091
|
+
modelId: "gpt-5.4-mini",
|
|
38092
|
+
isDefault: false,
|
|
38093
|
+
strengths: "Fast and affordable with dependable JSON formatting \u2014 a good fit for mid-complexity task steps.",
|
|
38094
|
+
bestFor: ["fast-cheap", "default"]
|
|
38095
|
+
},
|
|
38096
|
+
{
|
|
38097
|
+
provider: "runtype",
|
|
38098
|
+
modelId: "gpt-5.4-nano",
|
|
38099
|
+
isDefault: false,
|
|
38100
|
+
strengths: "Cheapest and fastest GPT-5 tier \u2014 reserve for trivial deterministic transforms, routing, and classification, not complex authoring.",
|
|
38101
|
+
bestFor: ["fast-cheap"]
|
|
38102
|
+
},
|
|
37707
38103
|
// Anthropic models (routed via Anthropic direct, with Vertex/Bedrock fallback)
|
|
37708
|
-
{
|
|
37709
|
-
|
|
37710
|
-
|
|
38104
|
+
{
|
|
38105
|
+
provider: "runtype",
|
|
38106
|
+
modelId: "claude-haiku-4-5",
|
|
38107
|
+
isDefault: false,
|
|
38108
|
+
strengths: "Fast and inexpensive while retaining real reasoning, tool-use, and vision \u2014 great for high-volume task steps that still need some judgment.",
|
|
38109
|
+
bestFor: ["fast-cheap", "agentic-tools", "vision"]
|
|
38110
|
+
},
|
|
38111
|
+
{
|
|
38112
|
+
provider: "runtype",
|
|
38113
|
+
modelId: "claude-sonnet-5",
|
|
38114
|
+
isDefault: false,
|
|
38115
|
+
strengths: "Balanced all-rounder: strong reasoning, very reliable multi-round tool loops, vision, and a 1M context \u2014 an excellent choice for agentic and structured work.",
|
|
38116
|
+
bestFor: ["default", "agentic-tools", "vision", "long-context"]
|
|
38117
|
+
},
|
|
38118
|
+
{
|
|
38119
|
+
provider: "runtype",
|
|
38120
|
+
modelId: "claude-opus-4-8",
|
|
38121
|
+
isDefault: false,
|
|
38122
|
+
strengths: "Deepest reasoning and planning for hard analysis and multi-constraint synthesis, with vision and a 1M context \u2014 premium-priced, so reserve for genuinely difficult steps.",
|
|
38123
|
+
bestFor: ["deep-reasoning", "vision", "long-context"]
|
|
38124
|
+
},
|
|
37711
38125
|
// Google models (routed via Google direct, with Vertex/Vercel fallback)
|
|
37712
|
-
{
|
|
37713
|
-
|
|
37714
|
-
|
|
37715
|
-
|
|
38126
|
+
{
|
|
38127
|
+
provider: "runtype",
|
|
38128
|
+
modelId: "gemini-3-1-flash-lite",
|
|
38129
|
+
isDefault: false,
|
|
38130
|
+
strengths: "Very fast and very cheap with full multimodal input (vision and audio), good structured output, and a 1M context \u2014 ideal for high-volume, simple steps.",
|
|
38131
|
+
bestFor: ["fast-cheap", "vision", "long-context"]
|
|
38132
|
+
},
|
|
38133
|
+
{
|
|
38134
|
+
provider: "runtype",
|
|
38135
|
+
modelId: "gemini-3.5-flash",
|
|
38136
|
+
isDefault: false,
|
|
38137
|
+
strengths: "Fast, low-cost, and natively multimodal with good reasoning, tool-use, and a 1M context \u2014 a strong choice for vision and high-throughput steps.",
|
|
38138
|
+
bestFor: ["default", "vision", "fast-cheap", "agentic-tools", "long-context"]
|
|
38139
|
+
},
|
|
38140
|
+
{
|
|
38141
|
+
provider: "runtype",
|
|
38142
|
+
modelId: "gemini-3-1-flash-image",
|
|
38143
|
+
isDefault: false,
|
|
38144
|
+
strengths: "Specialised for image generation and editing (image output) \u2014 use for steps that produce images, not text reasoning.",
|
|
38145
|
+
bestFor: ["image-generation"]
|
|
38146
|
+
},
|
|
38147
|
+
{
|
|
38148
|
+
provider: "runtype",
|
|
38149
|
+
modelId: "gemini-3.1-pro",
|
|
38150
|
+
isDefault: false,
|
|
38151
|
+
strengths: "Google's frontier tier: strong reasoning, a 1M context, and multimodal input \u2014 for complex analytical or long-document steps.",
|
|
38152
|
+
bestFor: ["deep-reasoning", "vision", "long-context"]
|
|
38153
|
+
},
|
|
37716
38154
|
// Inception models (routed via Vercel)
|
|
37717
|
-
{
|
|
38155
|
+
{
|
|
38156
|
+
provider: "runtype",
|
|
38157
|
+
modelId: "mercury-2",
|
|
38158
|
+
isDefault: false,
|
|
38159
|
+
strengths: "Diffusion-based LLM optimised for very low latency \u2014 good when speed matters more than deep reasoning.",
|
|
38160
|
+
bestFor: ["fast-cheap"]
|
|
38161
|
+
},
|
|
37718
38162
|
// Moonshot models (routed via Vercel)
|
|
37719
38163
|
// Kimi K2.6 is the default model: a reasoning + tool-use + vision model
|
|
37720
38164
|
// already trusted as the product-generator default.
|
|
37721
|
-
{
|
|
38165
|
+
{
|
|
38166
|
+
provider: "runtype",
|
|
38167
|
+
modelId: "kimi-k2.6",
|
|
38168
|
+
isDefault: true,
|
|
38169
|
+
strengths: "Capable open agentic model with reasoning, tool-use, and vision at strong value \u2014 the current account default and a dependable general workhorse.",
|
|
38170
|
+
bestFor: ["default", "agentic-tools", "vision"]
|
|
38171
|
+
},
|
|
37722
38172
|
// NVIDIA Nemotron Ultra (reasoning + tool-use flagship, routed via Vercel)
|
|
37723
|
-
{
|
|
38173
|
+
{
|
|
38174
|
+
provider: "runtype",
|
|
38175
|
+
modelId: "nemotron-3-ultra-550b-a55b",
|
|
38176
|
+
isDefault: false,
|
|
38177
|
+
strengths: "Large open-weight reasoning and tool-use flagship with a 1M context at a low price \u2014 strong analytical depth where an open model is preferred.",
|
|
38178
|
+
bestFor: ["deep-reasoning", "agentic-tools", "long-context"]
|
|
38179
|
+
},
|
|
37724
38180
|
// Google models (routed via Cloudflare Workers AI)
|
|
37725
|
-
{
|
|
38181
|
+
{
|
|
38182
|
+
provider: "runtype",
|
|
38183
|
+
modelId: "gemma-4-26b-a4b-it",
|
|
38184
|
+
isDefault: false,
|
|
38185
|
+
strengths: "Lightweight open-weight instruct model served free on Workers AI \u2014 fine for straightforward general tasks at zero cost.",
|
|
38186
|
+
bestFor: ["fast-cheap"]
|
|
38187
|
+
},
|
|
37726
38188
|
// Z.ai GLM-5.2 (agentic coding flagship, routed via Cloudflare Workers AI,
|
|
37727
38189
|
// Vercel fallback). The bare routed name resolves to `@cf/zai-org/glm-5.2`.
|
|
37728
|
-
{
|
|
38190
|
+
{
|
|
38191
|
+
provider: "runtype",
|
|
38192
|
+
modelId: "glm-5.2",
|
|
38193
|
+
isDefault: false,
|
|
38194
|
+
strengths: "Agentic flagship \u2014 best-in-class at long, multi-round tool-call loops and coding/agent workflows, with a 1M context; well suited to tool-heavy agent steps.",
|
|
38195
|
+
bestFor: ["agentic-tools", "default", "deep-reasoning", "long-context"]
|
|
38196
|
+
}
|
|
37729
38197
|
];
|
|
37730
38198
|
var DEFAULT_MODEL_ID = DEFAULT_MODELS_FOR_NEW_ACCOUNTS.find((m2) => m2.isDefault)?.modelId ?? "kimi-k2.6";
|
|
38199
|
+
function renderDefaultModelStrengthsGuide() {
|
|
38200
|
+
return DEFAULT_MODELS_FOR_NEW_ACCOUNTS.map(
|
|
38201
|
+
(m2) => `- \`${m2.modelId}\`${m2.isDefault ? " (account default)" : ""} \u2014 ${m2.strengths}`
|
|
38202
|
+
).join("\n");
|
|
38203
|
+
}
|
|
37731
38204
|
var userProfileFeaturesSchema = external_exports.object({
|
|
37732
38205
|
enableAgentSkills: external_exports.boolean(),
|
|
37733
38206
|
// Gates the WebMCP-powered dashboard assistant (copilot panel + chat
|
|
@@ -37748,9 +38221,21 @@ var userProfileFeaturesSchema = external_exports.object({
|
|
|
37748
38221
|
// `POST /v1/skills/scan` verdict UI). Driven by the `enable-skill-scanner`
|
|
37749
38222
|
// boolean flag (fail-closed until a rule enables it). The scan ROUTE stays
|
|
37750
38223
|
// reachable; this only hides the UI while the scanner rollout completes.
|
|
37751
|
-
enableSkillScanner: external_exports.boolean()
|
|
38224
|
+
enableSkillScanner: external_exports.boolean(),
|
|
38225
|
+
// Gates the usage-based-pricing dashboard surfaces (card-centric paywall /
|
|
38226
|
+
// slow-mode copy, trial-expired alerts, CTAs to the credit-card entry page).
|
|
38227
|
+
// Driven by the `usage-based-pricing` boolean flag (fail-closed in
|
|
38228
|
+
// production until Lane 1 is live and a rule ramps a cohort). Off renders
|
|
38229
|
+
// today's UI byte-identically.
|
|
38230
|
+
usageBasedPricing: external_exports.boolean()
|
|
37752
38231
|
});
|
|
37753
38232
|
var MODEL_FAMILY_PROVIDER_IDS = {
|
|
38233
|
+
"arrow-1-1": {
|
|
38234
|
+
"vercel": "quiverai/arrow-1.1"
|
|
38235
|
+
},
|
|
38236
|
+
"arrow-1.1": {
|
|
38237
|
+
"vercel": "quiverai/arrow-1.1"
|
|
38238
|
+
},
|
|
37754
38239
|
"claude-fable-5": {
|
|
37755
38240
|
"anthropic": "claude-fable-5"
|
|
37756
38241
|
},
|
|
@@ -37842,6 +38327,10 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
37842
38327
|
"claude-sonnet-4.6": {
|
|
37843
38328
|
"vercel": "anthropic/claude-sonnet-4.6"
|
|
37844
38329
|
},
|
|
38330
|
+
"claude-sonnet-5": {
|
|
38331
|
+
"anthropic": "claude-sonnet-5",
|
|
38332
|
+
"vercel": "anthropic/claude-sonnet-5"
|
|
38333
|
+
},
|
|
37845
38334
|
"codestral": {
|
|
37846
38335
|
"vercel": "mistral/codestral"
|
|
37847
38336
|
},
|
|
@@ -38026,6 +38515,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38026
38515
|
"google": "gemini-3.1-flash-lite",
|
|
38027
38516
|
"vercel": "google/gemini-3.1-flash-lite"
|
|
38028
38517
|
},
|
|
38518
|
+
"gemini-3-1-flash-lite-image": {
|
|
38519
|
+
"vercel": "google/gemini-3.1-flash-lite-image"
|
|
38520
|
+
},
|
|
38029
38521
|
"gemini-3-1-pro": {
|
|
38030
38522
|
"google": "gemini-3.1-pro-preview",
|
|
38031
38523
|
"vercel": "google/gemini-3.1-pro-preview"
|
|
@@ -38058,6 +38550,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38058
38550
|
"google": "gemini-3.1-flash-lite",
|
|
38059
38551
|
"vercel": "google/gemini-3.1-flash-lite"
|
|
38060
38552
|
},
|
|
38553
|
+
"gemini-3.1-flash-lite-image": {
|
|
38554
|
+
"vercel": "google/gemini-3.1-flash-lite-image"
|
|
38555
|
+
},
|
|
38061
38556
|
"gemini-3.1-pro-preview": {
|
|
38062
38557
|
"google": "gemini-3.1-pro-preview",
|
|
38063
38558
|
"vercel": "google/gemini-3.1-pro-preview"
|
|
@@ -38085,89 +38580,19 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38085
38580
|
"togetherai": "togetherai/pearl-ai/gemma-4-31b-it",
|
|
38086
38581
|
"vercel": "google/gemma-4-31b-it"
|
|
38087
38582
|
},
|
|
38088
|
-
"glm-4-5": {
|
|
38089
|
-
"vercel": "zai/glm-4.5"
|
|
38090
|
-
},
|
|
38091
|
-
"glm-4-5-air": {
|
|
38092
|
-
"vercel": "zai/glm-4.5-air"
|
|
38093
|
-
},
|
|
38094
|
-
"glm-4-5v": {
|
|
38095
|
-
"vercel": "zai/glm-4.5v"
|
|
38096
|
-
},
|
|
38097
|
-
"glm-4-6": {
|
|
38098
|
-
"vercel": "zai/glm-4.6"
|
|
38099
|
-
},
|
|
38100
|
-
"glm-4-6v": {
|
|
38101
|
-
"vercel": "zai/glm-4.6v"
|
|
38102
|
-
},
|
|
38103
|
-
"glm-4-6v-flash": {
|
|
38104
|
-
"vercel": "zai/glm-4.6v-flash"
|
|
38105
|
-
},
|
|
38106
|
-
"glm-4-7": {
|
|
38107
|
-
"vercel": "zai/glm-4.7"
|
|
38108
|
-
},
|
|
38109
|
-
"glm-4-7-flash": {
|
|
38110
|
-
"vercel": "zai/glm-4.7-flash"
|
|
38111
|
-
},
|
|
38112
|
-
"glm-4-7-flashx": {
|
|
38113
|
-
"vercel": "zai/glm-4.7-flashx"
|
|
38114
|
-
},
|
|
38115
|
-
"glm-4.5": {
|
|
38116
|
-
"vercel": "zai/glm-4.5"
|
|
38117
|
-
},
|
|
38118
|
-
"glm-4.5-air": {
|
|
38119
|
-
"vercel": "zai/glm-4.5-air"
|
|
38120
|
-
},
|
|
38121
|
-
"glm-4.5v": {
|
|
38122
|
-
"vercel": "zai/glm-4.5v"
|
|
38123
|
-
},
|
|
38124
|
-
"glm-4.6": {
|
|
38125
|
-
"vercel": "zai/glm-4.6"
|
|
38126
|
-
},
|
|
38127
|
-
"glm-4.6v": {
|
|
38128
|
-
"vercel": "zai/glm-4.6v"
|
|
38129
|
-
},
|
|
38130
|
-
"glm-4.6v-flash": {
|
|
38131
|
-
"vercel": "zai/glm-4.6v-flash"
|
|
38132
|
-
},
|
|
38133
|
-
"glm-4.7": {
|
|
38134
|
-
"vercel": "zai/glm-4.7"
|
|
38135
|
-
},
|
|
38136
|
-
"glm-4.7-flash": {
|
|
38137
|
-
"vercel": "zai/glm-4.7-flash"
|
|
38138
|
-
},
|
|
38139
|
-
"glm-4.7-flashx": {
|
|
38140
|
-
"vercel": "zai/glm-4.7-flashx"
|
|
38141
|
-
},
|
|
38142
|
-
"glm-5": {
|
|
38143
|
-
"togetherai": "togetherai/zai-org/GLM-5",
|
|
38144
|
-
"vercel": "zai/glm-5"
|
|
38145
|
-
},
|
|
38146
|
-
"glm-5-1": {
|
|
38147
|
-
"togetherai": "togetherai/zai-org/GLM-5.1",
|
|
38148
|
-
"vercel": "zai/glm-5.1"
|
|
38149
|
-
},
|
|
38150
38583
|
"glm-5-2": {
|
|
38584
|
+
"togetherai": "togetherai/zai-org/GLM-5.2",
|
|
38151
38585
|
"vercel": "zai/glm-5.2"
|
|
38152
38586
|
},
|
|
38153
38587
|
"glm-5-2-fast": {
|
|
38154
38588
|
"vercel": "zai/glm-5.2-fast"
|
|
38155
38589
|
},
|
|
38156
|
-
"glm-5-turbo": {
|
|
38157
|
-
"vercel": "zai/glm-5-turbo"
|
|
38158
|
-
},
|
|
38159
|
-
"glm-5.1": {
|
|
38160
|
-
"vercel": "zai/glm-5.1"
|
|
38161
|
-
},
|
|
38162
38590
|
"glm-5.2": {
|
|
38163
38591
|
"vercel": "zai/glm-5.2"
|
|
38164
38592
|
},
|
|
38165
38593
|
"glm-5.2-fast": {
|
|
38166
38594
|
"vercel": "zai/glm-5.2-fast"
|
|
38167
38595
|
},
|
|
38168
|
-
"glm-5v-turbo": {
|
|
38169
|
-
"vercel": "zai/glm-5v-turbo"
|
|
38170
|
-
},
|
|
38171
38596
|
"google/gemma-4-31B-it": {
|
|
38172
38597
|
"togetherai": "togetherai/google/gemma-4-31B-it"
|
|
38173
38598
|
},
|
|
@@ -38499,6 +38924,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38499
38924
|
"grok-imagine-video-1-5": {
|
|
38500
38925
|
"vercel": "xai/grok-imagine-video-1.5-preview"
|
|
38501
38926
|
},
|
|
38927
|
+
"grok-imagine-video-1.5": {
|
|
38928
|
+
"vercel": "xai/grok-imagine-video-1.5"
|
|
38929
|
+
},
|
|
38502
38930
|
"grok-imagine-video-1.5-preview": {
|
|
38503
38931
|
"vercel": "xai/grok-imagine-video-1.5-preview"
|
|
38504
38932
|
},
|
|
@@ -38715,22 +39143,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38715
39143
|
"mimo-v2.5-pro": {
|
|
38716
39144
|
"vercel": "xiaomi/mimo-v2.5-pro"
|
|
38717
39145
|
},
|
|
38718
|
-
"minimax-m2": {
|
|
38719
|
-
"vercel": "minimax/minimax-m2"
|
|
38720
|
-
},
|
|
38721
|
-
"minimax-m2-1": {
|
|
38722
|
-
"vercel": "minimax/minimax-m2.1"
|
|
38723
|
-
},
|
|
38724
|
-
"minimax-m2-1-lightning": {
|
|
38725
|
-
"vercel": "minimax/minimax-m2.1-lightning"
|
|
38726
|
-
},
|
|
38727
|
-
"minimax-m2-5": {
|
|
38728
|
-
"togetherai": "togetherai/MiniMaxAI/MiniMax-M2.5",
|
|
38729
|
-
"vercel": "minimax/minimax-m2.5"
|
|
38730
|
-
},
|
|
38731
|
-
"minimax-m2-5-highspeed": {
|
|
38732
|
-
"vercel": "minimax/minimax-m2.5-highspeed"
|
|
38733
|
-
},
|
|
38734
39146
|
"minimax-m2-7": {
|
|
38735
39147
|
"general-compute": "general-compute/minimax-m2.7",
|
|
38736
39148
|
"togetherai": "togetherai/MiniMaxAI/MiniMax-M2.7",
|
|
@@ -38739,18 +39151,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38739
39151
|
"minimax-m2-7-highspeed": {
|
|
38740
39152
|
"vercel": "minimax/minimax-m2.7-highspeed"
|
|
38741
39153
|
},
|
|
38742
|
-
"minimax-m2.1": {
|
|
38743
|
-
"vercel": "minimax/minimax-m2.1"
|
|
38744
|
-
},
|
|
38745
|
-
"minimax-m2.1-lightning": {
|
|
38746
|
-
"vercel": "minimax/minimax-m2.1-lightning"
|
|
38747
|
-
},
|
|
38748
|
-
"minimax-m2.5": {
|
|
38749
|
-
"vercel": "minimax/minimax-m2.5"
|
|
38750
|
-
},
|
|
38751
|
-
"minimax-m2.5-highspeed": {
|
|
38752
|
-
"vercel": "minimax/minimax-m2.5-highspeed"
|
|
38753
|
-
},
|
|
38754
39154
|
"minimax-m2.7": {
|
|
38755
39155
|
"general-compute": "general-compute/minimax-m2.7",
|
|
38756
39156
|
"vercel": "minimax/minimax-m2.7"
|
|
@@ -38762,9 +39162,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
38762
39162
|
"togetherai": "togetherai/MiniMaxAI/MiniMax-M3",
|
|
38763
39163
|
"vercel": "minimax/minimax-m3"
|
|
38764
39164
|
},
|
|
38765
|
-
"MiniMaxAI/MiniMax-M2.5": {
|
|
38766
|
-
"togetherai": "togetherai/MiniMaxAI/MiniMax-M2.5"
|
|
38767
|
-
},
|
|
38768
39165
|
"MiniMaxAI/MiniMax-M2.7": {
|
|
38769
39166
|
"togetherai": "togetherai/MiniMaxAI/MiniMax-M2.7"
|
|
38770
39167
|
},
|
|
@@ -39352,11 +39749,8 @@ var MODEL_FAMILY_PROVIDER_IDS = {
|
|
|
39352
39749
|
"whisper-1": {
|
|
39353
39750
|
"vercel": "openai/whisper-1"
|
|
39354
39751
|
},
|
|
39355
|
-
"zai-org/GLM-5": {
|
|
39356
|
-
"togetherai": "togetherai/zai-org/GLM-5"
|
|
39357
|
-
},
|
|
39358
|
-
"zai-org/GLM-5.1": {
|
|
39359
|
-
"togetherai": "togetherai/zai-org/GLM-5.1"
|
|
39752
|
+
"zai-org/GLM-5.2": {
|
|
39753
|
+
"togetherai": "togetherai/zai-org/GLM-5.2"
|
|
39360
39754
|
}
|
|
39361
39755
|
};
|
|
39362
39756
|
var PLATFORM_KEY_PROVIDER_MAP = {
|
|
@@ -40342,10 +40736,12 @@ var sandboxConfigSchema = external_exports.object({
|
|
|
40342
40736
|
instanceType: external_exports.enum(["standard-1", "standard-2", "standard-3", "standard-4"]).optional(),
|
|
40343
40737
|
networkAccess: sandboxNetworkAccessSchema.optional(),
|
|
40344
40738
|
ttl: external_exports.enum(["5m", "1h", "24h", "unlimited"]).optional(),
|
|
40345
|
-
sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional()
|
|
40346
|
-
//
|
|
40347
|
-
//
|
|
40348
|
-
|
|
40739
|
+
sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional()
|
|
40740
|
+
// NOTE: a `requireApprovalForBash` knob was forward-declared here for Phase 3
|
|
40741
|
+
// but never wired to any runtime gate, so it was REMOVED from the public
|
|
40742
|
+
// schema rather than ship a misleading, inert control (post-Fable handoff 05,
|
|
40743
|
+
// F3). To gate `bash` today use the generic `tools.approval` config, which
|
|
40744
|
+
// matches the tool by name. Re-add the dedicated knob only with its wiring.
|
|
40349
40745
|
});
|
|
40350
40746
|
var agentRuntimeConfigSchema = external_exports.object({
|
|
40351
40747
|
model: external_exports.string().optional(),
|
|
@@ -40474,6 +40870,10 @@ var agentRuntimeConfigSchema = external_exports.object({
|
|
|
40474
40870
|
}).optional(),
|
|
40475
40871
|
errorHandling: errorHandlingSchema,
|
|
40476
40872
|
loggingPolicy: external_exports.enum(["default", "on", "off"]).optional(),
|
|
40873
|
+
// Opt-in PII redaction for tail-log and telemetry payloads. `'default'`
|
|
40874
|
+
// defers to a lower layer (surface/product) or the resolver default (off).
|
|
40875
|
+
// Mirrors `loggingPolicy`.
|
|
40876
|
+
piiRedaction: external_exports.enum(["default", "off", "redact"]).optional(),
|
|
40477
40877
|
// Opt-in temporal awareness. `injectElapsed` turns on the automatic
|
|
40478
40878
|
// "time has passed" decorator (a `<temporal_context>` block prepended to
|
|
40479
40879
|
// the user turn at dispatch, gated on turn ≥ 2 and a gap ≥
|
|
@@ -40499,6 +40899,142 @@ var agentRuntimeConfigSchema = external_exports.object({
|
|
|
40499
40899
|
// `./tenancy-strategy`; the expansion + gate logic lives in apps/api.
|
|
40500
40900
|
tenancyStrategy: tenancyStrategySchema.optional()
|
|
40501
40901
|
});
|
|
40902
|
+
var identityAdapterKindSchema = external_exports.enum(["oidc-jwt", "session", "custom"]);
|
|
40903
|
+
var ASYMMETRIC_JWT_ALGORITHMS = [
|
|
40904
|
+
"RS256",
|
|
40905
|
+
"RS384",
|
|
40906
|
+
"RS512",
|
|
40907
|
+
"PS256",
|
|
40908
|
+
"PS384",
|
|
40909
|
+
"PS512",
|
|
40910
|
+
"ES256",
|
|
40911
|
+
"ES384",
|
|
40912
|
+
"ES512",
|
|
40913
|
+
"EdDSA"
|
|
40914
|
+
];
|
|
40915
|
+
var asymmetricAlgorithmSchema = external_exports.enum(ASYMMETRIC_JWT_ALGORITHMS);
|
|
40916
|
+
var httpsUrlSchema = external_exports.string().url().refine((value) => value.startsWith("https://"), {
|
|
40917
|
+
message: "must be an https:// URL (plaintext http is not accepted)."
|
|
40918
|
+
});
|
|
40919
|
+
var claimMapSchema = external_exports.object({
|
|
40920
|
+
/** JSON path (dot notation) to the end-user id, e.g. `sub`. */
|
|
40921
|
+
subject: external_exports.string().min(1),
|
|
40922
|
+
/** JSON path to the tenant id, e.g. `org_id` / `o.id` / `organizationId`. Optional. */
|
|
40923
|
+
tenant: external_exports.string().min(1).optional(),
|
|
40924
|
+
/** JSON path to the end-user email. Optional. */
|
|
40925
|
+
email: external_exports.string().min(1).optional(),
|
|
40926
|
+
/** JSON path to a roles claim. Optional, display/authz context only. */
|
|
40927
|
+
roles: external_exports.string().min(1).optional(),
|
|
40928
|
+
/** JSON path to a permissions claim. Optional. */
|
|
40929
|
+
permissions: external_exports.string().min(1).optional()
|
|
40930
|
+
});
|
|
40931
|
+
var oboModeSchema = external_exports.enum([
|
|
40932
|
+
"token-exchange-8693",
|
|
40933
|
+
// Okta / Auth0 Custom Token Exchange (RFC 8693)
|
|
40934
|
+
"federated-token-vault",
|
|
40935
|
+
// Auth0 Token Vault, WorkOS Pipes, Clerk OAuth tokens
|
|
40936
|
+
"customer-endpoint"
|
|
40937
|
+
// Better Auth / custom escape hatch
|
|
40938
|
+
]);
|
|
40939
|
+
var baseDescriptorShape = {
|
|
40940
|
+
/** Stable integration id (surface-scoped). Also the isolation namespace (C1). */
|
|
40941
|
+
id: external_exports.string().min(1),
|
|
40942
|
+
kind: identityAdapterKindSchema,
|
|
40943
|
+
claimMap: claimMapSchema,
|
|
40944
|
+
/**
|
|
40945
|
+
* The strongest assurance this integration may confer. Bounded ABOVE by the
|
|
40946
|
+
* kind ceiling ({@link assuranceCeilingForKind}) — may only lower it, never
|
|
40947
|
+
* raise it. A `custom`/`session` descriptor cannot declare `verified`.
|
|
40948
|
+
*/
|
|
40949
|
+
maxAssurance: tenancyAssuranceLevelSchema.optional(),
|
|
40950
|
+
capabilities: external_exports.object({
|
|
40951
|
+
obo: external_exports.boolean().default(false),
|
|
40952
|
+
oboMode: oboModeSchema.optional()
|
|
40953
|
+
}).default({ obo: false })
|
|
40954
|
+
};
|
|
40955
|
+
var verifiableDescriptorShape = {
|
|
40956
|
+
/** Expected `iss`. REQUIRED, non-empty, non-wildcard. */
|
|
40957
|
+
issuer: httpsUrlSchema,
|
|
40958
|
+
/** JWKS endpoint for the issuer's public keys. REQUIRED. */
|
|
40959
|
+
jwksUri: httpsUrlSchema,
|
|
40960
|
+
/** Expected `aud`. REQUIRED, non-empty, non-wildcard (see refinement). */
|
|
40961
|
+
audience: external_exports.union([external_exports.string().min(1), external_exports.array(external_exports.string().min(1)).nonempty()]),
|
|
40962
|
+
/** Non-empty subset of {@link ASYMMETRIC_JWT_ALGORITHMS}. */
|
|
40963
|
+
allowedAlgorithms: external_exports.array(asymmetricAlgorithmSchema).nonempty(),
|
|
40964
|
+
clockSkewSec: external_exports.number().int().min(0).max(120).optional()
|
|
40965
|
+
};
|
|
40966
|
+
var identityAdapterDescriptorSchema = external_exports.discriminatedUnion("kind", [
|
|
40967
|
+
external_exports.object({
|
|
40968
|
+
...baseDescriptorShape,
|
|
40969
|
+
...verifiableDescriptorShape,
|
|
40970
|
+
kind: external_exports.literal("oidc-jwt"),
|
|
40971
|
+
/** `azp` allowlist (Clerk CSRF/origin guard, Auth0 authorized party). */
|
|
40972
|
+
authorizedParties: external_exports.array(external_exports.string().min(1)).optional(),
|
|
40973
|
+
/** Provider-specific post-verify policy toggles. */
|
|
40974
|
+
claimPolicy: external_exports.object({
|
|
40975
|
+
rejectImpersonation: external_exports.boolean().optional(),
|
|
40976
|
+
// Clerk `act`
|
|
40977
|
+
rejectPendingOrg: external_exports.boolean().optional(),
|
|
40978
|
+
// Clerk `sts:pending`
|
|
40979
|
+
rejectAudienceEqualsAzp: external_exports.boolean().optional(),
|
|
40980
|
+
// Auth0 ID-vs-access-token
|
|
40981
|
+
requireIssuerPathSegment: external_exports.string().min(1).optional()
|
|
40982
|
+
// Okta `/oauth2/{id}`
|
|
40983
|
+
}).optional()
|
|
40984
|
+
}),
|
|
40985
|
+
external_exports.object({
|
|
40986
|
+
...baseDescriptorShape,
|
|
40987
|
+
...verifiableDescriptorShape,
|
|
40988
|
+
kind: external_exports.literal("session")
|
|
40989
|
+
}),
|
|
40990
|
+
external_exports.object({
|
|
40991
|
+
...baseDescriptorShape,
|
|
40992
|
+
kind: external_exports.literal("custom"),
|
|
40993
|
+
/** The customer verify endpoint (HTTPS). Egress is SSRF-guarded at call time. */
|
|
40994
|
+
verifyEndpoint: httpsUrlSchema
|
|
40995
|
+
})
|
|
40996
|
+
]).superRefine((descriptor, ctx) => {
|
|
40997
|
+
if (descriptor.kind === "oidc-jwt" || descriptor.kind === "session") {
|
|
40998
|
+
const auds = Array.isArray(descriptor.audience) ? descriptor.audience : [descriptor.audience];
|
|
40999
|
+
if (auds.some((a) => a.trim() === "*" || a.trim() === "")) {
|
|
41000
|
+
ctx.addIssue({
|
|
41001
|
+
code: external_exports.ZodIssueCode.custom,
|
|
41002
|
+
path: ["audience"],
|
|
41003
|
+
message: "audience must name a specific relying party (no wildcard / empty value)."
|
|
41004
|
+
});
|
|
41005
|
+
}
|
|
41006
|
+
}
|
|
41007
|
+
if (descriptor.maxAssurance) {
|
|
41008
|
+
const ceiling = assuranceCeilingForKind(descriptor.kind);
|
|
41009
|
+
if (assuranceRank(descriptor.maxAssurance) === 0) {
|
|
41010
|
+
ctx.addIssue({
|
|
41011
|
+
code: external_exports.ZodIssueCode.custom,
|
|
41012
|
+
path: ["maxAssurance"],
|
|
41013
|
+
message: "maxAssurance cannot be 'anonymous' \u2014 it is a ceiling; omit the field or use 'asserted' / 'verified'."
|
|
41014
|
+
});
|
|
41015
|
+
} else if (assuranceRank(descriptor.maxAssurance) > assuranceRank(ceiling)) {
|
|
41016
|
+
ctx.addIssue({
|
|
41017
|
+
code: external_exports.ZodIssueCode.custom,
|
|
41018
|
+
path: ["maxAssurance"],
|
|
41019
|
+
message: `maxAssurance '${descriptor.maxAssurance}' exceeds the '${descriptor.kind}' kind ceiling '${ceiling}'.`
|
|
41020
|
+
});
|
|
41021
|
+
}
|
|
41022
|
+
}
|
|
41023
|
+
});
|
|
41024
|
+
function assuranceRank(level) {
|
|
41025
|
+
return level === "verified" ? 2 : level === "asserted" ? 1 : 0;
|
|
41026
|
+
}
|
|
41027
|
+
function assuranceCeilingForKind(kind) {
|
|
41028
|
+
return kind === "oidc-jwt" ? "verified" : "asserted";
|
|
41029
|
+
}
|
|
41030
|
+
var identityProofSchema = external_exports.object({
|
|
41031
|
+
/** Which configured integration the token claims to come from (hint only). */
|
|
41032
|
+
provider: external_exports.string().min(1).max(64),
|
|
41033
|
+
/** The customer-native proof (JWT / opaque session token). */
|
|
41034
|
+
token: external_exports.string().min(1).max(8192)
|
|
41035
|
+
}).describe(
|
|
41036
|
+
"Customer-native auth proof for the Identity Exchange. When present and the surface has a matching integration, the verified tenant/end-user replace any body-asserted tenant/endUser (which are never trusted for web-embedded callers). Ignored until the Identity Exchange admission upgrade ships."
|
|
41037
|
+
);
|
|
40502
41038
|
function extractSecretReferences(template) {
|
|
40503
41039
|
const keys = /* @__PURE__ */ new Set();
|
|
40504
41040
|
let match;
|
|
@@ -42074,10 +42610,22 @@ var FLOW_STEP_TYPE_METADATA = {
|
|
|
42074
42610
|
configHints: "http, auth, requestTemplate, responseMapping, outputVariable"
|
|
42075
42611
|
},
|
|
42076
42612
|
"retrieve-record": {
|
|
42077
|
-
description: "
|
|
42613
|
+
description: "DEPRECATED \u2014 use get-record (single object) or list-records (array) instead. Loads records from the Runtype record store; its return shape is inferred from the lookup method (an id lookup returns one object, a type/name/filter query returns an array even for a single match), which is the ambiguity the successor step types remove.",
|
|
42078
42614
|
category: "data",
|
|
42079
42615
|
isPrompt: false,
|
|
42080
|
-
configHints: "recordType, recordName, recordFilter ({ type, where: { field, op, value } }), outputVariable"
|
|
42616
|
+
configHints: "DEPRECATED. Prefer get-record / list-records. recordType, recordName, recordFilter ({ type, where: { field, op, value } }), outputVariable"
|
|
42617
|
+
},
|
|
42618
|
+
"get-record": {
|
|
42619
|
+
description: "Load a SINGLE record object from the Runtype record store by ID, by type+name, or by a chip-style recordFilter (first match, ordered by updated_at desc). Access fields directly in templates ({{var.field}}). Fails if no record matches.",
|
|
42620
|
+
category: "data",
|
|
42621
|
+
isPrompt: false,
|
|
42622
|
+
configHints: "recordId, recordType, recordName, recordFilter ({ type, where: { field, op, value } }), outputVariable (returns one object \u2014 access as {{var.field}})"
|
|
42623
|
+
},
|
|
42624
|
+
"list-records": {
|
|
42625
|
+
description: "Load an ARRAY of records from the Runtype record store by type, name, or a chip-style recordFilter (metadata + top-level columns: id, name, createdAt, updatedAt), ordered by updated_at desc. Always returns an array \u2014 even for a single match \u2014 so index it in templates ({{var.0.field}}). Default limit 50 (max 1000).",
|
|
42626
|
+
category: "data",
|
|
42627
|
+
isPrompt: false,
|
|
42628
|
+
configHints: "recordType, recordName, recordFilter ({ type, where: { field, op, value } }), limit (default 50, max 1000), onEmpty (succeed|fail), outputVariable (returns an array \u2014 index as {{var.0.field}})"
|
|
42081
42629
|
},
|
|
42082
42630
|
"upsert-record": {
|
|
42083
42631
|
description: "Create or update a record. The sourceVariable must point to a JSON object.",
|
|
@@ -42146,10 +42694,10 @@ var FLOW_STEP_TYPE_METADATA = {
|
|
|
42146
42694
|
configHints: "vectorsSource, destination, idTemplate, outputVariable"
|
|
42147
42695
|
},
|
|
42148
42696
|
crawl: {
|
|
42149
|
-
description: "Crawl a website and extract content
|
|
42697
|
+
description: "Crawl a website with Cloudflare Browser Rendering and extract page content as markdown. Renders the SEED page fully; at depth >= 1 it enumerates child links WITHOUT rendering them (1 rendered seed record + N empty-markdown child records) and follows only ABSOLUTE link hrefs (relative links like item?id= are never followed). Writes { crawlId, status, result, resultPages[] } to outputVariable \u2014 flatten resultPages[].records[] (each { url, status, markdown?, metadata? }) to read every page. GOTCHA: the URL query string is DROPPED (https://site/item?id=42 crawls https://site/item) \u2014 for query-string URLs, JSON APIs, SPAs, or single detail/comment pages use fetch-url or the builtin:firecrawl scrape tool instead (firecrawl preserves query strings). ASYNC by default: with no streaming consumer (MCP run_flow/dispatch) the flow durably PAUSES while a Workflow polls; if the crawl exceeds completionTimeoutMs (default 120000 = 2 min) the step SILENTLY resumes with output = null. For real crawls raise completionTimeoutMs (e.g. 600000) and set pollIntervalMs (e.g. 5000), or set asyncCrawl:false to poll inline within the request (good for smoke tests).",
|
|
42150
42698
|
category: "integration",
|
|
42151
42699
|
isPrompt: false,
|
|
42152
|
-
configHints:
|
|
42700
|
+
configHints: 'url (required; query string is dropped), outputVariable (required), depth (0 = seed-only render, recommended), limit, formats (e.g. ["markdown"]), render, options ({ includePatterns, excludePatterns, allowSubdomains, allowExternalLinks, ignoreSitemap, sitemapOnly }), waitForSelector, completionTimeoutMs (default 120000; raise for slow crawls), pollIntervalMs, asyncCrawl (false = synchronous inline polling), errorHandling ({ onError: "continue"|"fail" } OBJECT, not a bare string), defaultValue. Pattern for "index + detail/comment pages": crawl the index with depth 0, transform-data to extract the links/ids from result markdown, then an agent prompt step (mode: "agent") with tools.toolIds ["builtin:firecrawl"] to fetch each query-string detail URL.'
|
|
42153
42701
|
},
|
|
42154
42702
|
"paginate-api": {
|
|
42155
42703
|
description: "Fetch paginated data from an API endpoint across multiple pages.",
|
|
@@ -42782,7 +43330,8 @@ ${lines.join("\n")}`;
|
|
|
42782
43330
|
var PLATFORM_FEATURES_SUMMARY = (() => {
|
|
42783
43331
|
const integrations = PLATFORM_CATALOG.availableIntegrations.map((i) => i.provider).join(", ");
|
|
42784
43332
|
const stepTypes = FLOW_STEP_TYPES.filter((t) => t !== "prompt").join(", ");
|
|
42785
|
-
const models =
|
|
43333
|
+
const models = `use ONLY these routed IDs (never dated/legacy IDs like gpt-4.1 or gpt-4o), matched to the work:
|
|
43334
|
+
${renderDefaultModelStrengthsGuide()}`;
|
|
42786
43335
|
return `## Available Platform Features
|
|
42787
43336
|
|
|
42788
43337
|
- **Built-in tools**: GPT Image 2 image generation, provider-native web search (OpenAI web search, Anthropic web search/fetch, xAI Live Search for Grok-3 series, xAI X Search / Web Search agentic tools for Grok-4 series), Exa (AI search), Firecrawl (simple web scraping), Browser Run tools (rendered markdown, HTML, screenshots, snapshots, selector scraping, JSON extraction, link harvesting \u2014 stateless), Browser Session tools (persistent interactive browsing: open, navigate, click, type, scroll, screenshot, evaluate, close), Browser Agent (autonomous higher-level alternative \u2014 give a natural-language goal plus a startUrl or sessionId and the agent navigates/clicks/extracts on its own), Store Asset (host any file from a URL or base64 inline content \u2014 returns a permanent public or signed private URL, downloads as attachment), Publish Page (host HTML that renders inline in the browser at a shareable 7-day /preview/ URL under a locked-down CSP), vector search, UCP commerce tools (discovery, catalog, cart, checkout, orders for any UCP-enabled merchant)
|
|
@@ -42792,6 +43341,113 @@ var PLATFORM_FEATURES_SUMMARY = (() => {
|
|
|
42792
43341
|
- **Available models**: ${models}
|
|
42793
43342
|
- **Surface types**: ${PLATFORM_CATALOG.availableSurfaceTypes.join(", ")}`;
|
|
42794
43343
|
})();
|
|
43344
|
+
var FLOW_GENERATION_GUIDE = `## Flow Generation Guide
|
|
43345
|
+
|
|
43346
|
+
### Step Types
|
|
43347
|
+
|
|
43348
|
+
- **prompt**: AI model call. Config: model, systemPrompt, userPrompt, responseFormat (text|json), outputVariable, tools
|
|
43349
|
+
- **transform-data**: Code execution in a sandboxed environment. **Use sparingly** \u2014 most agent-built flows over-use transform-data for work the platform already does natively. Before adding one, check the Transform-Data Anti-Patterns section: leading "Parse Input" steps duplicate the surface's \`parametersSchema\`; trailing "Final Output" reshapers add a dead hop; pre-cleaning data before a prompt step does the prompt's job in the wrong place; \`map().join()\` to format prompt input ignores that \`{{variable}}\` auto-stringifies; retrieving then plucking the first record ignores that \`recordFilter\` + \`{{records[0]}}\` work. Reach for transform-data only when the work is genuinely deterministic (record-name templating, JSON-shape coercion, math). Config: script, outputVariable, sandboxProvider (optional, default \`cloudflare-worker\`), language (required when sandboxProvider is \`runtype-sandbox\`). Sandbox providers: \`cloudflare-worker\` (default, JS only, strict mode ES module), \`runtype-sandbox\` (full container \u2014 supports \`javascript\`, \`typescript\`, and \`python\` via the \`language\` field), \`daytona\` (remote VM). For the default \`cloudflare-worker\` sandbox: always declare variables with const/let, access context variables via the \`input\` object (e.g., \`input.varName\`), use \`return { key: value }\` pattern. For \`runtype-sandbox\`: JS/TS use the same return pattern; Python uses \`print(json.dumps(...))\` to emit JSON output. Parameters are injected as a \`parameters\` object in all languages
|
|
43350
|
+
- **template**: Render a Liquid template into HTML, email-html, markdown, PDF, or text. **Prefer this over a prompt step when the output is a structured document** (invoice, receipt, email body, report) \u2014 keeps the LLM focused on producing data, not authoring HTML.
|
|
43351
|
+
|
|
43352
|
+
**Config fields:**
|
|
43353
|
+
- \`template\` (required): Liquid template body
|
|
43354
|
+
- \`outputFormat\` (required): \`html\` | \`email-html\` | \`markdown\` | \`pdf\` | \`text\`
|
|
43355
|
+
- \`outputVariable\` (required): variable name to store the rendered output
|
|
43356
|
+
- \`inputs\` (optional): map of logical name \u2192 expression resolving against flow context. If omitted, the entire flow context is available as template variables
|
|
43357
|
+
- \`partials\` (optional): named partial templates referenceable via \`{% include 'name' %}\`
|
|
43358
|
+
- \`pdfOptions\` (optional, pdf only): \`{ format?: 'A4' | 'Letter', landscape?: boolean, margin?: { top, bottom, left, right } }\`. PDF output returns \`{ contentType, bytes (base64), byteLength }\`
|
|
43359
|
+
- \`asArtifact\` (optional): emit a Persona artifact event for chat surfaces \u2014 renders inline in the conversation
|
|
43360
|
+
- \`streamOutput\` (optional): stream the rendered output via SSE
|
|
43361
|
+
- \`sampleData\` (optional): array of \`{ name, data }\` scenarios for the dashboard template editor preview
|
|
43362
|
+
|
|
43363
|
+
**Liquid syntax quick reference:**
|
|
43364
|
+
- Variables: \`{{ name }}\`, \`{{ object.field }}\`, \`{{ array[0] }}\`
|
|
43365
|
+
- Filters: \`{{ name | upcase }}\`, \`{{ price | round: 2 }}\`, \`{{ title | default: "Untitled" }}\`
|
|
43366
|
+
- Loops: \`{% for item in items %} ... {% endfor %}\`
|
|
43367
|
+
- Conditionals: \`{% if condition %} ... {% elsif other %} ... {% else %} ... {% endif %}\`
|
|
43368
|
+
- Partials: \`{% include 'partial_name' %}\` (references \`partials\` map keys)
|
|
43369
|
+
- Assignment: \`{% assign total = 0 %}\`, \`{% capture greeting %}Hello {{ name }}{% endcapture %}\`
|
|
43370
|
+
- Common filters: upcase, downcase, capitalize, strip, truncate, replace, split, join, size, round, date, default, escape, url_encode, newline_to_br
|
|
43371
|
+
|
|
43372
|
+
**Output format notes:**
|
|
43373
|
+
- \`html\` / \`email-html\`: Raw HTML string. \`email-html\` is identical today but semantically marks output destined for send-email steps
|
|
43374
|
+
- \`markdown\`: Plain markdown text
|
|
43375
|
+
- \`pdf\`: Renders the Liquid body as HTML, then converts to PDF. Result is \`{ contentType: "application/pdf", bytes: "<base64>", byteLength: N }\`
|
|
43376
|
+
- \`text\`: Plain text, no HTML processing
|
|
43377
|
+
|
|
43378
|
+
**Inputs map vs. full context:**
|
|
43379
|
+
- With \`inputs\`: only the declared names are available inside the template. Example: \`inputs: { "customer": "{{order_data}}" }\` exposes \`order_data\` as \`{{ customer }}\` in the template. Preferred for clarity and safety
|
|
43380
|
+
- Without \`inputs\`: the entire flow variable scope is available. Convenient for simple templates but risks name collisions
|
|
43381
|
+
|
|
43382
|
+
**Example \u2014 prompt produces JSON, template renders HTML:**
|
|
43383
|
+
\`\`\`
|
|
43384
|
+
Step 1 (prompt): model: "claude-sonnet-4-6", responseFormat: "json", outputVariable: "invoice"
|
|
43385
|
+
\u2192 AI generates { "company": "Acme", "items": [{...}], "total": "1,234.56" }
|
|
43386
|
+
Step 2 (template):
|
|
43387
|
+
template: "<h1>Invoice for {{ data.company }}</h1>{% for item in data.items %}<p>{{ item.desc }}: \${{ item.price }}</p>{% endfor %}<p>Total: \${{ data.total }}</p>"
|
|
43388
|
+
inputs: { "data": "{{invoice}}" }
|
|
43389
|
+
outputFormat: "html"
|
|
43390
|
+
outputVariable: "invoice_html"
|
|
43391
|
+
\`\`\`
|
|
43392
|
+
- **conditional**: Branch logic. Either the binary shape (condition (JS expression), trueSteps, falseSteps) or N-way named branches (branches: [{ id, name, condition, steps }], evaluated first-match-wins, with otherwiseSteps as the fallback). Set outputVariable to merge whichever branch ran into one named result.
|
|
43393
|
+
- **fetch-url**: HTTP request. Config: http (url, method, headers, body), responseType, outputVariable
|
|
43394
|
+
- **api-call**: Structured API call. Config: http, auth, requestTemplate, responseMapping, outputVariable
|
|
43395
|
+
- **get-record**: Load a SINGLE record OBJECT. Config: recordId, OR recordType + recordName, OR recordFilter ({ type, where: { field, op, value } }) for richer metadata-aware queries; outputVariable. Reachable filter columns include id, name, createdAt, updatedAt plus any metadata key. Returns one object \u2014 access fields directly in templates (\`{{record.field}}\`). On multiple matches the first by updated_at desc wins; fails if none match.
|
|
43396
|
+
- **list-records**: Load an ARRAY of records. Config: recordType, recordName, OR recordFilter ({ type, where: { field, op, value } }); limit (default 50, max 1000), onEmpty (succeed|fail, default succeed), outputVariable. Ordered by updated_at desc. Always writes an array \u2014 even for a single match \u2014 so index it in templates (\`{{records.0.field}}\` or \`{{records[0].field}}\`); object-style access (\`{{records.field}}\`) on the array resolves to undefined.
|
|
43397
|
+
- **retrieve-record**: DEPRECATED \u2014 use get-record (single object) or list-records (array). Still accepted at write and aliased at execution onto one of them; its return shape is inferred from the lookup method (recordId \u2192 object, type/name/filter \u2192 array), which is the ambiguity the successors remove.
|
|
43398
|
+
- **upsert-record**: Create/update a record keyed by \`(recordType, recordName)\` per owner. Config: recordType, **recordName** (REQUIRED for upsert semantics \u2014 without it each run creates a fresh \`\${recordType}-\${Date.now()}\` record), sourceVariable (the JSON metadata payload only \u2014 do NOT wrap as \`{ name, type, metadata }\`; the wrapper gets stored verbatim), outputVariable. See "Record-Keyed Upsert Patterns" in the build-product instructions for the full anti-pattern list (silent timestamped fallback, wrapped-source footgun, JSONB-blob aggregate races).
|
|
43399
|
+
- **update-record**: Update record fields. Config: recordId, OR recordFilter ({ type, where }) for first-match-wins by predicate; updates, mergeStrategy (merge|replace|deep-merge), outputVariable.
|
|
43400
|
+
- **set-variable**: Set a variable. Config: variableName, value
|
|
43401
|
+
- **send-email**: Send email. Config: from, to, subject, html, outputVariable
|
|
43402
|
+
- **send-text**: Send SMS. Config: from, to, message, outputVariable
|
|
43403
|
+
- **search**: Web/AI search. Config: provider, query, maxResults, outputVariable
|
|
43404
|
+
- **generate-embedding**: Create vector embedding. Config: inputSource, text, embeddingModel, outputVariable
|
|
43405
|
+
- **vector-search**: Search vectors. Config: query, limit, threshold, outputVariable
|
|
43406
|
+
- **crawl**: Multi-page web crawl via Cloudflare Browser Rendering \u2192 markdown. Config: url (required; **query string is DROPPED** \u2014 \`item?id=42\` crawls \`/item\`), outputVariable (required), depth (0 = render seed only, recommended), limit, completionTimeoutMs (default 120000; a slower crawl SILENTLY resumes with output **null** \u2014 raise to e.g. 600000 + set pollIntervalMs), asyncCrawl (false = inline polling for smoke tests), errorHandling ({ onError } OBJECT, not a bare string). Output: \`{ crawlId, status, result, resultPages[] }\` \u2014 flatten \`resultPages[].records[]\` (each \`{ url, status, markdown? }\`). Renders the seed fully but at depth \u2265 1 enumerates child links WITHOUT rendering them and follows only ABSOLUTE hrefs. For query-string URLs / single detail or comment pages use **fetch-url** or **builtin:firecrawl** (preserves query strings) instead.
|
|
43407
|
+
- **paginate-api**: Paginated API fetch. Config: url, paginationType, entityPath, outputVariable
|
|
43408
|
+
- **store-vector**: Store embeddings. Config: vectorsSource, destination, outputVariable
|
|
43409
|
+
- **execute-agent**: Run an existing agent. Config: agentId, message, outputVariable
|
|
43410
|
+
- **save-memory**: Persist a fact or observation to Cloudflare Agent Memory. Config: profileTemplate (e.g. \`{{_user.id}}\`), contentVariable, sessionId?, outputVariable?
|
|
43411
|
+
- **recall-memory**: Query long-term memory for a synthesized answer. Config: profileTemplate, queryTemplate, thinkingLevel? (low|medium|high), responseLength? (short|medium|long), outputVariable
|
|
43412
|
+
- **memory-summary**: Fetch a Markdown summary of what the agent has stored. Config: profileTemplate, sessionId?, outputVariable
|
|
43413
|
+
|
|
43414
|
+
> **Subagent tools** are not flow step types \u2014 they are runtime tools attached to prompt steps via \`tools.runtimeTools[]\` with \`toolType: 'subagent'\`. Use them when an agent should delegate focused sub-tasks with tool subsetting and context isolation. See the Subagent Delegation Guide.
|
|
43415
|
+
|
|
43416
|
+
> **Agent-level memory shortcut:** if the memory belongs to an agent (not a standalone flow), prefer the agent's \`memory: { enabled: true }\` config over threading the three steps through a flow. The agent gets the same three operations as tools (\`save_memory\`, \`recall_memory\`, \`memory_summary\`) and auto-ingests each exchange. Use the flow steps only when the memory operation must run deterministically at a fixed point in the flow.
|
|
43417
|
+
|
|
43418
|
+
### Tool Usage Best Practice
|
|
43419
|
+
|
|
43420
|
+
Prefer registering tools on **prompt** or **execute-agent** steps via \`tools: { toolIds: [...] }\` rather than using standalone \`tool-call\` steps. When tools are registered on a prompt step, the AI model autonomously decides when and how to invoke them, producing more natural and adaptive flows.
|
|
43421
|
+
|
|
43422
|
+
Only use a \`tool-call\` step when the tool must run deterministically at a fixed point in the flow (e.g., always store an asset, always send a notification) regardless of model judgment.
|
|
43423
|
+
|
|
43424
|
+
> **Platform limits:** max 50 runtime tools per dispatch request, 30s tool timeout cap, and tool search auto-activates at 20+ tools (deferred tools become search-loaded). Fetch the \`limits\` documentation topic for the full list.
|
|
43425
|
+
|
|
43426
|
+
### Variable System
|
|
43427
|
+
|
|
43428
|
+
- System variables (read-only): \`{{_flow.id}}\`, \`{{_flow.name}}\`, \`{{_user.id}}\`, \`{{_organization.id}}\`, \`{{_agent.id}}\`, \`{{_execution.id}}\`, \`{{_execution.conversationId}}\`
|
|
43429
|
+
- Temporal: \`{{_now.date}}\` (YYYY-MM-DD), \`{{_now.time}}\` (HH:mm:ss), \`{{_now.weekday}}\`, \`{{_now.iso}}\`, \`{{_now.year|month|day|unix|timezone}}\` \u2014 rendered in the schedule's tz on schedule-fired runs, UTC otherwise
|
|
43430
|
+
- End-user variables (populated when the caller passes \`endUser\` on dispatch \u2014 Persona widget, SDK \`executeAgent\`, or top-level \`endUser: { id, email?, ... }\` on the dispatch body): \`{{_endUser.id}}\`, \`{{_endUser.email}}\`, plus any additional fields the caller provides under \`_endUser.*\`. Use these for memory sharding in SaaS products where your customer's users are not Runtype account holders.
|
|
43431
|
+
- Product Tenant variables (populated when the caller passes \`tenant\` on dispatch or \`agents/:id/execute\` \u2014 top-level \`tenant: { id, ... }\` on the body): \`{{_tenant.id}}\`, plus any additional fields under \`_tenant.*\`. The Product Tenant is the builder's customer/account *inside* a Product (nested under the Builder Org \`_user\` and above the individual End User \`_endUser\`). Use \`{{_tenant.id}}\` to address account-level scope shared by all of a tenant's end-users (e.g. shard shared memory by \`{{_tenant.id}}\` while sharding per-user memory by \`{{_endUser.id}}\`).
|
|
43432
|
+
- Record variables: \`{{_record.id}}\`, \`{{_record.name}}\`, \`{{_record.type}}\`, \`{{_record.metadata.field}}\`
|
|
43433
|
+
- Schedule (schedule-fired runs only): \`{{_schedule.id}}\`, \`{{_schedule.name}}\`, \`{{_schedule.cron}}\`, \`{{_schedule.timezone}}\`, \`{{_schedule.lastRunAt}}\`, \`{{_schedule.nextRunAt}}\` \u2014 useful for incremental-window patterns: \`{{_schedule.lastRunAt || "24h ago"}}\`
|
|
43434
|
+
- Message variables: \`{{messages}}\`, \`{{userMessage}}\`, \`{{lastMessage}}\`, \`{{messageCount}}\`
|
|
43435
|
+
- Step outputs: Use the outputVariable name from previous steps, e.g., \`{{result}}\`, \`{{analysis}}\`
|
|
43436
|
+
- **One distinct \`outputVariable\` per step \u2014 never share one across \`when\`-guarded steps.** A \`when\`-skipped step does not no-op; the engine writes \`null\` to its \`outputVariable\`. With last-writer-wins, if several steps point at the SAME output name (e.g. five HTTP-method steps all writing \`response\`), the skipped ones null out the value the one that ran produced, and every downstream read sees \`null\`. Give each step its own name (\`response_get\`, \`response_post\`, \u2026) and coalesce them in a final step (\`{{response_get || response_post || ...}}\`, or a transform-data returning the first non-null).
|
|
43437
|
+
- Custom inputs: \`{{input_name}}\` \u2014 top-level variables passed via dispatch inputs
|
|
43438
|
+
- Defaults & fallbacks:
|
|
43439
|
+
- Legacy literal default: \`{{name|Anonymous}}\` \u2014 uses \`Anonymous\` if \`name\` is unset
|
|
43440
|
+
- Truthy fallback: \`{{primary || fallback}}\` \u2014 first truthy operand wins (skips empty strings, 0, false)
|
|
43441
|
+
- Nullish fallback: \`{{count ?? 0}}\` \u2014 keeps 0 / "" / false (only null/undefined fall through)
|
|
43442
|
+
- Chains: \`{{a || b || "default"}}\` \u2014 supports paths and string/number/boolean/null literals; do NOT mix \`||\` and \`??\` in one expression
|
|
43443
|
+
|
|
43444
|
+
### Model Selection
|
|
43445
|
+
|
|
43446
|
+
Use ONLY routed model IDs from the list below (platform-key compatible). Never
|
|
43447
|
+
emit dated or legacy IDs (e.g. \`gpt-4.1\`, \`gpt-4o\`, \`claude-sonnet-4\`) \u2014 they
|
|
43448
|
+
are not enabled for new accounts. Match the model to the step's actual work:
|
|
43449
|
+
|
|
43450
|
+
${renderDefaultModelStrengthsGuide()}`;
|
|
42795
43451
|
var CATEGORY_DISPLAY_NAMES = {
|
|
42796
43452
|
[BuiltInToolCategory.IMAGE_GENERATION]: "Image Generation",
|
|
42797
43453
|
[BuiltInToolCategory.WEB_SEARCH]: "Web Search",
|
|
@@ -42867,6 +43523,7 @@ ${orthogonalLines.join("\n")}
|
|
|
42867
43523
|
- **Web search (provider-native, inline citations)** \u2192 see Provider-Native Search section above
|
|
42868
43524
|
- **Web search (standalone, AI-powered)** \u2192 \`builtin:exa\`
|
|
42869
43525
|
- **Simple web scraping to markdown** \u2192 \`builtin:firecrawl\`
|
|
43526
|
+
- **Research/scraping a site that blocks bots** \u2192 prefer \`builtin:firecrawl\` or \`builtin:exa\` over the raw \`fetch-url\`/\`crawl\` flow steps. Those steps request from datacenter IPs flagged as non-human traffic, so sites behind a WAF/anti-bot service often return a 403, CAPTCHA, or empty body. A mixed approach (fetch first, fall back to Firecrawl/Exa on a block) is the most reliable.
|
|
42870
43527
|
- **Rendered web pages, screenshots, structured extraction, or link harvesting** \u2192 \`builtin:browser:markdown\`, \`builtin:browser:snapshot\`, \`builtin:browser:json\`, \`builtin:browser:scrape\`, \`builtin:browser:links\` (stateless, one-shot \u2014 cheap, no session overhead)
|
|
42871
43528
|
- **Autonomous browsing (just want the outcome \u2014 extract data, complete a form, find info on a page)** \u2192 \`builtin:browser:agent\` with a natural-language \`goal\` plus \`startUrl\` (fresh browser) or \`sessionId\` (continue an existing session). Stagehand handles observe/act/extract; you get back text or, with an \`outputSchema\`, structured JSON. Try this BEFORE reaching for the manual session tools below.
|
|
42872
43529
|
- **Interactive browsing (precise control over individual actions)** \u2192 \`builtin:browser:open\` to start a session, then \`builtin:browser:click\`, \`builtin:browser:type\`, \`builtin:browser:scroll\`, \`builtin:browser:session-screenshot\`, \`builtin:browser:evaluate\`, \`builtin:browser:navigate\`, and \`builtin:browser:close\` when done. Session tools maintain cookies and page state across calls but cost more than stateless tools \u2014 prefer stateless tools when a single page read suffices.
|
|
@@ -42932,6 +43589,7 @@ Tools are added to prompt steps via \`tools: { toolIds: ["<id>"] }\`. The AI mod
|
|
|
42932
43589
|
- **Web search (provider-native, inline citations)** \u2192 see the Provider-Native Search section
|
|
42933
43590
|
- **Web search (standalone, AI-powered)** \u2192 \`builtin:exa\`
|
|
42934
43591
|
- **Simple web scraping to markdown** \u2192 \`builtin:firecrawl\`
|
|
43592
|
+
- **Research/scraping a site that blocks bots** \u2192 prefer \`builtin:firecrawl\` or \`builtin:exa\` over the raw \`fetch-url\`/\`crawl\` flow steps. Those steps request from datacenter IPs flagged as non-human traffic, so sites behind a WAF/anti-bot service often return a 403, CAPTCHA, or empty body. A mixed approach (fetch first, fall back to Firecrawl/Exa on a block) is the most reliable.
|
|
42935
43593
|
- **Rendered web pages, screenshots, structured extraction, or link harvesting** \u2192 \`builtin:browser:markdown\`, \`builtin:browser:snapshot\`, \`builtin:browser:json\`, \`builtin:browser:scrape\`, \`builtin:browser:links\` (stateless, one-shot)
|
|
42936
43594
|
- **Autonomous browsing (just want the outcome)** \u2192 \`builtin:browser:agent\` with a natural-language \`goal\` plus \`startUrl\` or \`sessionId\` \u2014 try this BEFORE the manual session tools
|
|
42937
43595
|
- **Interactive browsing (precise control)** \u2192 \`builtin:browser:open\`, then \`builtin:browser:click\` / \`type\` / \`scroll\` / \`session-screenshot\` / \`evaluate\` / \`navigate\`, and \`builtin:browser:close\` when done
|
|
@@ -43606,6 +44264,22 @@ function selectAccountId(params) {
|
|
|
43606
44264
|
if (isValidAccountId(params.userId)) return params.userId;
|
|
43607
44265
|
return void 0;
|
|
43608
44266
|
}
|
|
44267
|
+
function flattenTextContent(content) {
|
|
44268
|
+
if (typeof content === "string") return content;
|
|
44269
|
+
return content.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
|
|
44270
|
+
}
|
|
44271
|
+
function hasUsableClaudeManagedSeed(messages) {
|
|
44272
|
+
let lastUserIndex = -1;
|
|
44273
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
44274
|
+
if (messages[i]?.role === "user") {
|
|
44275
|
+
lastUserIndex = i;
|
|
44276
|
+
break;
|
|
44277
|
+
}
|
|
44278
|
+
}
|
|
44279
|
+
if (lastUserIndex === -1) return false;
|
|
44280
|
+
if (lastUserIndex > 0) return true;
|
|
44281
|
+
return flattenTextContent(messages[lastUserIndex].content).length > 0;
|
|
44282
|
+
}
|
|
43609
44283
|
var RecordInputSchema = external_exports.object({
|
|
43610
44284
|
id: external_exports.string().min(1).optional(),
|
|
43611
44285
|
name: external_exports.string().min(1).optional(),
|
|
@@ -43866,6 +44540,12 @@ var DispatchRequestSchema = external_exports.object({
|
|
|
43866
44540
|
tenant: external_exports.object({
|
|
43867
44541
|
id: external_exports.string().min(1)
|
|
43868
44542
|
}).passthrough().optional(),
|
|
44543
|
+
// Identity Exchange proof (design §4.1): a customer-native auth token the
|
|
44544
|
+
// broker will verify server-side and admit as `verified` tenant/end-user.
|
|
44545
|
+
// Wire contract only for now — parsed here, consumed by NOTHING until the
|
|
44546
|
+
// admission slice wires verification into the tenancy seam. The token is a
|
|
44547
|
+
// live credential: never log or persist it (see identityProofSchema docs).
|
|
44548
|
+
identityProof: identityProofSchema.optional(),
|
|
43869
44549
|
options: external_exports.object({
|
|
43870
44550
|
streamResponse: external_exports.boolean().optional().default(true),
|
|
43871
44551
|
modelOverride: external_exports.string().optional(),
|
|
@@ -43901,6 +44581,15 @@ var DispatchRequestSchema = external_exports.object({
|
|
|
43901
44581
|
})
|
|
43902
44582
|
}).refine((data) => data.flow || data.agent, {
|
|
43903
44583
|
message: "Either 'flow' or 'agent' configuration must be provided"
|
|
44584
|
+
}).superRefine((data, ctx) => {
|
|
44585
|
+
if (data.agent?.agentType !== "claude_managed") return;
|
|
44586
|
+
if (!hasUsableClaudeManagedSeed(data.messages ?? [])) {
|
|
44587
|
+
ctx.addIssue({
|
|
44588
|
+
code: "custom",
|
|
44589
|
+
path: ["messages"],
|
|
44590
|
+
message: "messages with a non-empty user message is required for Claude Managed agents"
|
|
44591
|
+
});
|
|
44592
|
+
}
|
|
43904
44593
|
});
|
|
43905
44594
|
var RunFlowOptionsSchema = external_exports.object({
|
|
43906
44595
|
recordId: external_exports.string().optional(),
|
|
@@ -43952,6 +44641,15 @@ var RuntimeProxyToolConfigSchema = external_exports.object({
|
|
|
43952
44641
|
toolCallStrategy: external_exports.enum(["auto", "required", "none"]).optional(),
|
|
43953
44642
|
onToolError: external_exports.enum(["fail", "continue", "retry"]).optional()
|
|
43954
44643
|
});
|
|
44644
|
+
var RuntimeProxyProviderTransportSchema = external_exports.object({
|
|
44645
|
+
mixlayer: external_exports.object({
|
|
44646
|
+
modelApi: external_exports.enum(["chat", "responses"]).optional(),
|
|
44647
|
+
responsesTransport: external_exports.enum(["http", "websocket"]).optional()
|
|
44648
|
+
}).optional(),
|
|
44649
|
+
openai: external_exports.object({
|
|
44650
|
+
responsesTransport: external_exports.enum(["http", "websocket"]).optional()
|
|
44651
|
+
}).optional()
|
|
44652
|
+
});
|
|
43955
44653
|
var RuntimeProxyRequestSchema = external_exports.object({
|
|
43956
44654
|
model: external_exports.string().min(1),
|
|
43957
44655
|
prompt: external_exports.string().default(""),
|
|
@@ -43968,6 +44666,7 @@ var RuntimeProxyRequestSchema = external_exports.object({
|
|
|
43968
44666
|
seed: external_exports.number().int().optional(),
|
|
43969
44667
|
tools: external_exports.array(RuntimeProxyToolSchema).optional(),
|
|
43970
44668
|
providerTools: external_exports.array(RuntimeProxyProviderToolSchema).optional(),
|
|
44669
|
+
providerTransport: RuntimeProxyProviderTransportSchema.optional(),
|
|
43971
44670
|
toolConfiguration: RuntimeProxyToolConfigSchema.optional()
|
|
43972
44671
|
}).optional().default({})
|
|
43973
44672
|
});
|
|
@@ -44952,11 +45651,11 @@ async function promptConfirm(message, options) {
|
|
|
44952
45651
|
return new Promise((resolve12) => {
|
|
44953
45652
|
rl.question(chalk3.cyan(`${message} (${hint}): `), (answer) => {
|
|
44954
45653
|
rl.close();
|
|
44955
|
-
const
|
|
44956
|
-
if (
|
|
45654
|
+
const trimmed2 = answer.trim().toLowerCase();
|
|
45655
|
+
if (trimmed2 === "") {
|
|
44957
45656
|
resolve12(defaultYes);
|
|
44958
45657
|
} else {
|
|
44959
|
-
resolve12(
|
|
45658
|
+
resolve12(trimmed2 === "y" || trimmed2 === "yes");
|
|
44960
45659
|
}
|
|
44961
45660
|
});
|
|
44962
45661
|
});
|
|
@@ -47338,7 +48037,13 @@ secretsCommand.command("get <id>").description("Get secret metadata (value is ne
|
|
|
47338
48037
|
const { waitUntilExit } = render6(React6.createElement(App));
|
|
47339
48038
|
await waitUntilExit();
|
|
47340
48039
|
});
|
|
47341
|
-
secretsCommand.command("create").description("Create a new secret (provide the value via --value or stdin)").requiredOption("-k, --key <key>", "Secret key (alphanumeric/underscore, starts with a letter)").option("--value <value>", "Secret value (omit to read from stdin without echo)").option("-d, --description <text>", "Secret description").option(
|
|
48040
|
+
secretsCommand.command("create").description("Create a new secret (provide the value via --value or stdin)").requiredOption("-k, --key <key>", "Secret key (alphanumeric/underscore, starts with a letter)").option("--value <value>", "Secret value (omit to read from stdin without echo)").option("-d, --description <text>", "Secret description").option(
|
|
48041
|
+
"--product-tenant-id <id>",
|
|
48042
|
+
"Scope the secret to a Product Tenant (tnt_*). Omit for an org-level secret; a scoped secret requires a value."
|
|
48043
|
+
).option(
|
|
48044
|
+
"--end-user-id <id>",
|
|
48045
|
+
"Scope the secret to an End User (eu_*); its enclosing tenant is derived server-side. Omit for an org-level secret; a scoped secret requires a value."
|
|
48046
|
+
).option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(
|
|
47342
48047
|
async (options) => {
|
|
47343
48048
|
const apiKey = await ensureAuth();
|
|
47344
48049
|
if (!apiKey) return;
|
|
@@ -47358,6 +48063,8 @@ secretsCommand.command("create").description("Create a new secret (provide the v
|
|
|
47358
48063
|
description: options.description
|
|
47359
48064
|
};
|
|
47360
48065
|
if (value !== void 0) body.value = value;
|
|
48066
|
+
if (options.productTenantId !== void 0) body.productTenantId = options.productTenantId;
|
|
48067
|
+
if (options.endUserId !== void 0) body.endUserId = options.endUserId;
|
|
47361
48068
|
if (!isTTY(options) || options.json) {
|
|
47362
48069
|
try {
|
|
47363
48070
|
const data = await client.post("/secrets", body);
|
|
@@ -50469,9 +51176,9 @@ ${delta}` : `${content}${delta}`;
|
|
|
50469
51176
|
}
|
|
50470
51177
|
function getVisibleReasoningLines(reasoning, maxLines) {
|
|
50471
51178
|
if (maxLines <= 0) return [];
|
|
50472
|
-
const
|
|
50473
|
-
if (!
|
|
50474
|
-
return
|
|
51179
|
+
const trimmed2 = reasoning.trimEnd();
|
|
51180
|
+
if (!trimmed2) return [];
|
|
51181
|
+
return trimmed2.split("\n").slice(-maxLines);
|
|
50475
51182
|
}
|
|
50476
51183
|
|
|
50477
51184
|
// src/ink/marathon/useMarathonStream.ts
|
|
@@ -52874,12 +53581,12 @@ function parseSandboxTimeout(value, provider) {
|
|
|
52874
53581
|
}
|
|
52875
53582
|
function parseDaytonaExecutionResult(value) {
|
|
52876
53583
|
if (typeof value !== "string") return value;
|
|
52877
|
-
const
|
|
52878
|
-
if (!
|
|
53584
|
+
const trimmed2 = value.trim();
|
|
53585
|
+
if (!trimmed2) return "";
|
|
52879
53586
|
try {
|
|
52880
|
-
return JSON.parse(
|
|
53587
|
+
return JSON.parse(trimmed2);
|
|
52881
53588
|
} catch {
|
|
52882
|
-
const lines =
|
|
53589
|
+
const lines = trimmed2.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
52883
53590
|
const lastLine = lines[lines.length - 1];
|
|
52884
53591
|
if (!lastLine) return value;
|
|
52885
53592
|
try {
|
|
@@ -54998,9 +55705,9 @@ function CheckpointPrompt({
|
|
|
54998
55705
|
onSubmit
|
|
54999
55706
|
]);
|
|
55000
55707
|
const handleSubmit = (text) => {
|
|
55001
|
-
const
|
|
55002
|
-
const modelArg =
|
|
55003
|
-
if (
|
|
55708
|
+
const trimmed2 = text.trim();
|
|
55709
|
+
const modelArg = trimmed2.startsWith("/model") ? trimmed2.slice("/model".length).trim() : "";
|
|
55710
|
+
if (trimmed2.startsWith("/model")) {
|
|
55004
55711
|
clearInputDraft();
|
|
55005
55712
|
if (modelArg) {
|
|
55006
55713
|
setPendingModel(modelArg);
|
|
@@ -55009,53 +55716,53 @@ function CheckpointPrompt({
|
|
|
55009
55716
|
}
|
|
55010
55717
|
return;
|
|
55011
55718
|
}
|
|
55012
|
-
if (
|
|
55719
|
+
if (trimmed2.startsWith("/reflect")) {
|
|
55013
55720
|
setShowReflectEditor(true);
|
|
55014
55721
|
clearInputDraft();
|
|
55015
55722
|
return;
|
|
55016
55723
|
}
|
|
55017
|
-
if (
|
|
55724
|
+
if (trimmed2 === "/tree") {
|
|
55018
55725
|
setTreePanelRows(onLoadTreeView?.() ?? []);
|
|
55019
55726
|
clearInputDraft();
|
|
55020
55727
|
return;
|
|
55021
55728
|
}
|
|
55022
|
-
if (
|
|
55729
|
+
if (trimmed2 === "/fork") {
|
|
55023
55730
|
setForkCandidates(onLoadForkCandidates?.() ?? []);
|
|
55024
55731
|
clearInputDraft();
|
|
55025
55732
|
return;
|
|
55026
55733
|
}
|
|
55027
|
-
if (
|
|
55734
|
+
if (trimmed2 === "/copy") {
|
|
55028
55735
|
onCopySession?.();
|
|
55029
55736
|
clearInputDraft();
|
|
55030
55737
|
return;
|
|
55031
55738
|
}
|
|
55032
|
-
if (
|
|
55739
|
+
if (trimmed2 === "/copy-trimmed") {
|
|
55033
55740
|
onCopySessionTrimmed?.();
|
|
55034
55741
|
clearInputDraft();
|
|
55035
55742
|
return;
|
|
55036
55743
|
}
|
|
55037
|
-
if (
|
|
55744
|
+
if (trimmed2 === "/open") {
|
|
55038
55745
|
onOpenStateFile?.();
|
|
55039
55746
|
clearInputDraft();
|
|
55040
55747
|
return;
|
|
55041
55748
|
}
|
|
55042
|
-
if (
|
|
55749
|
+
if (trimmed2.startsWith("/help")) {
|
|
55043
55750
|
onToggleHelp();
|
|
55044
55751
|
clearInputDraft();
|
|
55045
55752
|
return;
|
|
55046
55753
|
}
|
|
55047
|
-
if (
|
|
55754
|
+
if (trimmed2.startsWith("/tools")) {
|
|
55048
55755
|
setPendingToolsToggle((prev) => !prev);
|
|
55049
55756
|
clearInputDraft();
|
|
55050
55757
|
return;
|
|
55051
55758
|
}
|
|
55052
|
-
if (
|
|
55053
|
-
const arg =
|
|
55759
|
+
if (trimmed2.startsWith("/sandbox")) {
|
|
55760
|
+
const arg = trimmed2.slice("/sandbox".length).trim();
|
|
55054
55761
|
setPendingSandbox(arg ? arg : false);
|
|
55055
55762
|
clearInputDraft();
|
|
55056
55763
|
return;
|
|
55057
55764
|
}
|
|
55058
|
-
if (
|
|
55765
|
+
if (trimmed2.startsWith("/stop")) {
|
|
55059
55766
|
setPendingStop((prev) => !prev);
|
|
55060
55767
|
clearInputDraft();
|
|
55061
55768
|
return;
|
|
@@ -55064,11 +55771,11 @@ function CheckpointPrompt({
|
|
|
55064
55771
|
submitStagedResult("stop");
|
|
55065
55772
|
return;
|
|
55066
55773
|
}
|
|
55067
|
-
if (
|
|
55774
|
+
if (trimmed2 === "") {
|
|
55068
55775
|
submitStagedResult("continue");
|
|
55069
55776
|
return;
|
|
55070
55777
|
}
|
|
55071
|
-
submitStagedResult("steer",
|
|
55778
|
+
submitStagedResult("steer", trimmed2);
|
|
55072
55779
|
};
|
|
55073
55780
|
const handleModelSelect = (model) => {
|
|
55074
55781
|
setShowModelPicker(false);
|
|
@@ -55079,11 +55786,11 @@ function CheckpointPrompt({
|
|
|
55079
55786
|
};
|
|
55080
55787
|
const handleReflectSubmit = (message) => {
|
|
55081
55788
|
setShowReflectEditor(false);
|
|
55082
|
-
const
|
|
55083
|
-
if (
|
|
55789
|
+
const trimmed2 = message.trim();
|
|
55790
|
+
if (trimmed2) {
|
|
55084
55791
|
setValue((prev) => prev.trim() ? `${prev}
|
|
55085
55792
|
|
|
55086
|
-
${
|
|
55793
|
+
${trimmed2}` : trimmed2);
|
|
55087
55794
|
setIsTyping(true);
|
|
55088
55795
|
}
|
|
55089
55796
|
};
|
|
@@ -55219,12 +55926,12 @@ function SteerComposer({ initialDraft = "", onSubmit, onCancel }) {
|
|
|
55219
55926
|
}
|
|
55220
55927
|
});
|
|
55221
55928
|
const handleSubmit = (text) => {
|
|
55222
|
-
const
|
|
55223
|
-
if (!
|
|
55929
|
+
const trimmed2 = text.trim();
|
|
55930
|
+
if (!trimmed2) {
|
|
55224
55931
|
onCancel("");
|
|
55225
55932
|
return;
|
|
55226
55933
|
}
|
|
55227
|
-
onSubmit(
|
|
55934
|
+
onSubmit(trimmed2, kind);
|
|
55228
55935
|
};
|
|
55229
55936
|
const kindLabel = kind === "steer" ? "deliver: next turn" : "deliver: after all work";
|
|
55230
55937
|
return /* @__PURE__ */ jsxs23(
|
|
@@ -57229,8 +57936,8 @@ function MarathonApp({
|
|
|
57229
57936
|
adjustedContentHeight - reasoningHintRows - reasoningBodyRows - reasoningLiveRows - thinkingRows - compactionIndicatorRows
|
|
57230
57937
|
);
|
|
57231
57938
|
const reasoningDetailLineCount = useMemo11(() => {
|
|
57232
|
-
const
|
|
57233
|
-
return
|
|
57939
|
+
const trimmed2 = displayedReasoning.trimEnd();
|
|
57940
|
+
return trimmed2 ? getReasoningLines(trimmed2, terminalWidth).length : 0;
|
|
57234
57941
|
}, [displayedReasoning, terminalWidth]);
|
|
57235
57942
|
const fileDetailRenderedLineCount = useMemo11(
|
|
57236
57943
|
() => detailFile && detailFileContent ? getFileRenderedLineCount(detailFile.path, detailFileContent, terminalWidth) : 0,
|
|
@@ -58462,10 +59169,10 @@ var ALLOWED_VERIFICATION_COMMANDS = [
|
|
|
58462
59169
|
/^(?:make|just)\s+(?:test|lint|build|check|typecheck)\b/i
|
|
58463
59170
|
];
|
|
58464
59171
|
function isSafeVerificationCommand(command) {
|
|
58465
|
-
const
|
|
58466
|
-
if (!
|
|
58467
|
-
if (BLOCKED_VERIFICATION_PATTERNS.some((pattern) => pattern.test(
|
|
58468
|
-
return ALLOWED_VERIFICATION_COMMANDS.some((pattern) => pattern.test(
|
|
59172
|
+
const trimmed2 = command.trim();
|
|
59173
|
+
if (!trimmed2) return false;
|
|
59174
|
+
if (BLOCKED_VERIFICATION_PATTERNS.some((pattern) => pattern.test(trimmed2))) return false;
|
|
59175
|
+
return ALLOWED_VERIFICATION_COMMANDS.some((pattern) => pattern.test(trimmed2));
|
|
58469
59176
|
}
|
|
58470
59177
|
var SCRIPT_COMMAND_PATTERNS = [
|
|
58471
59178
|
{
|
|
@@ -58482,9 +59189,9 @@ var SCRIPT_COMMAND_PATTERNS = [
|
|
|
58482
59189
|
}
|
|
58483
59190
|
];
|
|
58484
59191
|
function getScriptConfigFiles(command) {
|
|
58485
|
-
const
|
|
59192
|
+
const trimmed2 = command.trim();
|
|
58486
59193
|
for (const { pattern, files } of SCRIPT_COMMAND_PATTERNS) {
|
|
58487
|
-
if (pattern.test(
|
|
59194
|
+
if (pattern.test(trimmed2)) return files;
|
|
58488
59195
|
}
|
|
58489
59196
|
return [];
|
|
58490
59197
|
}
|
|
@@ -60480,12 +61187,12 @@ function resolveModelContextLength(modelId, configuredModels, availableModels) {
|
|
|
60480
61187
|
}
|
|
60481
61188
|
function resolveAutoCompactTokenThreshold(modelContextLength, rawThreshold, strategy = "summary_fallback") {
|
|
60482
61189
|
const effectiveBudget = resolveEffectiveInputBudgetTokens(modelContextLength);
|
|
60483
|
-
const
|
|
60484
|
-
if (!
|
|
61190
|
+
const trimmed2 = rawThreshold?.trim();
|
|
61191
|
+
if (!trimmed2) {
|
|
60485
61192
|
const ratio = strategy === "provider_native" ? DEFAULT_PROVIDER_NATIVE_COMPACT_THRESHOLD_RATIO : DEFAULT_AUTO_COMPACT_THRESHOLD_RATIO;
|
|
60486
61193
|
return typeof effectiveBudget === "number" && effectiveBudget > 0 ? Math.max(1, Math.floor(effectiveBudget * ratio)) : void 0;
|
|
60487
61194
|
}
|
|
60488
|
-
const percentMatch =
|
|
61195
|
+
const percentMatch = trimmed2.match(/^(\d+(?:\.\d+)?)%$/);
|
|
60489
61196
|
if (percentMatch) {
|
|
60490
61197
|
const percentValue = Number(percentMatch[1]);
|
|
60491
61198
|
if (!Number.isFinite(percentValue) || percentValue <= 0 || percentValue > 100) {
|
|
@@ -60495,7 +61202,7 @@ function resolveAutoCompactTokenThreshold(modelContextLength, rawThreshold, stra
|
|
|
60495
61202
|
}
|
|
60496
61203
|
return typeof effectiveBudget === "number" && effectiveBudget > 0 ? Math.max(1, Math.floor(effectiveBudget * (percentValue / 100))) : void 0;
|
|
60497
61204
|
}
|
|
60498
|
-
const numericValue = Number(
|
|
61205
|
+
const numericValue = Number(trimmed2);
|
|
60499
61206
|
if (!Number.isFinite(numericValue) || numericValue <= 0) {
|
|
60500
61207
|
throw new Error(
|
|
60501
61208
|
`Invalid --compact-threshold value "${rawThreshold}". Use a percentage (e.g. 80%) or absolute token count (e.g. 120000).`
|
|
@@ -60965,9 +61672,9 @@ function formatBytes(bytes) {
|
|
|
60965
61672
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
60966
61673
|
}
|
|
60967
61674
|
function normalizeStartupModelOptionValue(value) {
|
|
60968
|
-
const
|
|
60969
|
-
if (!
|
|
60970
|
-
const withoutProvider =
|
|
61675
|
+
const trimmed2 = value?.trim().toLowerCase().replace(/^model\//, "") ?? "";
|
|
61676
|
+
if (!trimmed2) return "";
|
|
61677
|
+
const withoutProvider = trimmed2.includes(":") ? trimmed2.split(":").slice(1).join(":") : trimmed2;
|
|
60971
61678
|
if (withoutProvider.includes("/")) {
|
|
60972
61679
|
return withoutProvider.split("/").pop() ?? withoutProvider;
|
|
60973
61680
|
}
|
|
@@ -61049,8 +61756,8 @@ function buildMarathonClientHeaders(devPlanOverride) {
|
|
|
61049
61756
|
};
|
|
61050
61757
|
}
|
|
61051
61758
|
function normalizeMarathonAgentArgument(agent) {
|
|
61052
|
-
const
|
|
61053
|
-
if (
|
|
61759
|
+
const trimmed2 = agent.trim();
|
|
61760
|
+
if (trimmed2.length < 2) return trimmed2;
|
|
61054
61761
|
const matchingQuotePairs = [
|
|
61055
61762
|
['"', '"'],
|
|
61056
61763
|
["'", "'"],
|
|
@@ -61058,12 +61765,12 @@ function normalizeMarathonAgentArgument(agent) {
|
|
|
61058
61765
|
["\u2018", "\u2019"]
|
|
61059
61766
|
];
|
|
61060
61767
|
for (const [openQuote, closeQuote] of matchingQuotePairs) {
|
|
61061
|
-
if (
|
|
61062
|
-
const unwrapped =
|
|
61063
|
-
return unwrapped ||
|
|
61768
|
+
if (trimmed2.startsWith(openQuote) && trimmed2.endsWith(closeQuote)) {
|
|
61769
|
+
const unwrapped = trimmed2.slice(openQuote.length, trimmed2.length - closeQuote.length).trim();
|
|
61770
|
+
return unwrapped || trimmed2;
|
|
61064
61771
|
}
|
|
61065
61772
|
}
|
|
61066
|
-
return
|
|
61773
|
+
return trimmed2;
|
|
61067
61774
|
}
|
|
61068
61775
|
function buildMarathonAutoCreatedAgentBootstrap(agentName, options = {}) {
|
|
61069
61776
|
const normalizedModel = options.model?.trim();
|
|
@@ -64325,7 +65032,10 @@ function printSuiteResult(rootDir, outcome) {
|
|
|
64325
65032
|
const rel = relative6(rootDir, outcome.file) || outcome.file;
|
|
64326
65033
|
const badge = result.passed ? chalk27.green("PASS") : chalk27.red("FAIL");
|
|
64327
65034
|
const score = `${result.passedCases}/${result.totalCases}`;
|
|
64328
|
-
|
|
65035
|
+
const runRef = result.runId ? ` \xB7 run ${result.runId}` : "";
|
|
65036
|
+
console.log(
|
|
65037
|
+
`${badge} ${chalk27.bold(definition.name)} ${chalk27.gray(`(${score} cases \xB7 ${rel}${runRef})`)}`
|
|
65038
|
+
);
|
|
64329
65039
|
for (const testCase of result.cases) {
|
|
64330
65040
|
const caseBadge = testCase.passed ? chalk27.green(" \u2713") : chalk27.red(" \u2717");
|
|
64331
65041
|
console.log(`${caseBadge} ${testCase.name}`);
|
|
@@ -66545,11 +67255,11 @@ async function promptLine(rl, question, defaultValue) {
|
|
|
66545
67255
|
const answer = await new Promise((resolve12) => {
|
|
66546
67256
|
rl.question(`${question}${hint}: `, resolve12);
|
|
66547
67257
|
});
|
|
66548
|
-
const
|
|
66549
|
-
if (!
|
|
67258
|
+
const trimmed2 = answer.trim();
|
|
67259
|
+
if (!trimmed2 && defaultValue !== void 0) {
|
|
66550
67260
|
return defaultValue;
|
|
66551
67261
|
}
|
|
66552
|
-
return
|
|
67262
|
+
return trimmed2;
|
|
66553
67263
|
}
|
|
66554
67264
|
async function promptConfirm2(rl, message, defaultYes = false) {
|
|
66555
67265
|
const hint = defaultYes ? chalk30.dim(" (Y/n)") : chalk30.dim(" (y/N)");
|
|
@@ -68334,9 +69044,9 @@ async function readInput(input) {
|
|
|
68334
69044
|
if (!input || input === "-") {
|
|
68335
69045
|
return await readStdin();
|
|
68336
69046
|
}
|
|
68337
|
-
const
|
|
68338
|
-
if (
|
|
68339
|
-
return
|
|
69047
|
+
const trimmed2 = input.trim();
|
|
69048
|
+
if (trimmed2.startsWith("{") || trimmed2.startsWith("[")) {
|
|
69049
|
+
return trimmed2;
|
|
68340
69050
|
}
|
|
68341
69051
|
return readFileSync18(input, "utf-8");
|
|
68342
69052
|
}
|
|
@@ -70255,6 +70965,19 @@ function maybeNotifyAboutCliUpdate(args, options = {}) {
|
|
|
70255
70965
|
void refreshCliUpdateMetadata(options);
|
|
70256
70966
|
}
|
|
70257
70967
|
|
|
70968
|
+
// src/lib/global-option-forwarding.ts
|
|
70969
|
+
function registerGlobalOptionForwarding(program2) {
|
|
70970
|
+
program2.hook("preAction", (_thisCommand, actionCommand) => {
|
|
70971
|
+
const globals = program2.opts();
|
|
70972
|
+
if (typeof globals.apiUrl === "string" && globals.apiUrl.length > 0) {
|
|
70973
|
+
process.env.RUNTYPE_API_URL = globals.apiUrl;
|
|
70974
|
+
}
|
|
70975
|
+
if (globals.json === true && actionCommand.getOptionValue("json") === void 0) {
|
|
70976
|
+
actionCommand.setOptionValue("json", true);
|
|
70977
|
+
}
|
|
70978
|
+
});
|
|
70979
|
+
}
|
|
70980
|
+
|
|
70258
70981
|
// src/index.ts
|
|
70259
70982
|
loadEnv();
|
|
70260
70983
|
setCliTitle();
|
|
@@ -70293,6 +71016,7 @@ program.addCommand(validateProductCommand);
|
|
|
70293
71016
|
program.addCommand(deployCommand);
|
|
70294
71017
|
program.addCommand(skillsCommand);
|
|
70295
71018
|
program.addCommand(appsCommand);
|
|
71019
|
+
registerGlobalOptionForwarding(program);
|
|
70296
71020
|
program.exitOverride();
|
|
70297
71021
|
async function run() {
|
|
70298
71022
|
const userArgs = process.argv.slice(2);
|
|
@@ -70315,7 +71039,9 @@ run().catch((error51) => {
|
|
|
70315
71039
|
} else if (commanderError.code === "commander.unknownOption") {
|
|
70316
71040
|
console.error(chalk42.red(`Error: ${commanderError.message}`));
|
|
70317
71041
|
process.exit(1);
|
|
70318
|
-
} else if (commanderError.code === "commander.
|
|
71042
|
+
} else if (commanderError.code === "commander.unknownCommand") {
|
|
71043
|
+
process.exit(1);
|
|
71044
|
+
} else if (commanderError.code === "commander.help" || commanderError.code === "commander.helpDisplayed" || commanderError.code === "commander.version") {
|
|
70319
71045
|
process.exit(0);
|
|
70320
71046
|
} else {
|
|
70321
71047
|
console.error(chalk42.red("An unexpected error occurred:"));
|