@bike4mind/cli 3.4.0 → 4.0.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/README.md +139 -37
- package/bin/bike4mind-cli.mjs +55 -1
- package/bin/hearth-hook.mjs +53 -7
- package/dist/{AgentHistoryStore-ClO2zOn6.mjs → AgentHistoryStore-DgqmcVLN.mjs} +5429 -5543
- package/dist/ApiClient-_JrM_xWw.mjs +133 -0
- package/dist/{ConfigStore-CbVFLXMH.mjs → ConfigStore-BwqsQ0U9.mjs} +1254 -182
- package/dist/RemoteSkillSource-qTvRkaNA.mjs +455 -0
- package/dist/{WorkItemsClient-SeNbzvEw.mjs → WorkItemsClient-CERTDrhT.mjs} +1 -1
- package/dist/{buildAgent-BeaVbpzH.mjs → buildToolSearch-D9GEK91u.mjs} +406 -47
- package/dist/commands/acpCommand.mjs +13 -13
- package/dist/commands/apiCommand.mjs +1 -1
- package/dist/commands/doctorCommand.mjs +1 -1
- package/dist/commands/envCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +5 -4
- package/dist/commands/mcpCommand.mjs +4 -3
- package/dist/commands/pluginCommand.mjs +1 -1
- package/dist/commands/skillsCommand.mjs +259 -0
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/{dist-DlBq3wHu.mjs → dist-Ul2qwn5x.mjs} +17 -132
- package/dist/index.mjs +171 -48
- package/dist/{package-MoDZ9cGj.mjs → package-CQaam4Dq.mjs} +1 -1
- package/dist/{serve-zi-B2iUT.mjs → serve-CFxUhjml.mjs} +657 -27
- package/dist/store-BYeE0shc.mjs +2 -0
- package/dist/{store-BxmPEI3v.mjs → store-BbvSi3KK.mjs} +26 -2
- package/package.json +11 -10
- package/dist/store-BkMur6uk.mjs +0 -2
|
@@ -22,7 +22,7 @@ import { homedir as homedir$1 } from "node:os";
|
|
|
22
22
|
const APP_NAME = process.env.APP_NAME || "";
|
|
23
23
|
const WEBSITE_URL = process.env.WEBSITE_URL || "";
|
|
24
24
|
//#endregion
|
|
25
|
-
//#region ../../b4m-core/common/dist/skillMdSource-
|
|
25
|
+
//#region ../../b4m-core/common/dist/skillMdSource-CNWRf6Lw.mjs
|
|
26
26
|
/**
|
|
27
27
|
* The marker an exported SKILL.md carries so Bike4Mind can recognize its own exports. The B4M
|
|
28
28
|
* CLI/desktop loader (packages/cli CustomCommandStore) skips stamped files, and a future CLI sync
|
|
@@ -34,7 +34,7 @@ const WEBSITE_URL = process.env.WEBSITE_URL || "";
|
|
|
34
34
|
const SKILL_MD_SOURCE_MARKER = "Bike4Mind-Source:";
|
|
35
35
|
/** Opening `---<lang>` fence, the frontmatter text, then the closing `---` line. */
|
|
36
36
|
const FRONTMATTER = /^---([^\r\n]*)\r?\n(?:([\s\S]*?)\r?\n)?---[ \t]*(?:\r?\n|$)/;
|
|
37
|
-
const SOURCE_LINE = new RegExp(`^[ \\t]*#[ \\t]*${SKILL_MD_SOURCE_MARKER}[ \\t]*(\\S
|
|
37
|
+
const SOURCE_LINE = new RegExp(`^[ \\t]*#[ \\t]*${SKILL_MD_SOURCE_MARKER}[ \\t]*(\\S+)`);
|
|
38
38
|
/** Splits a SKILL.md into its raw frontmatter and the rest; null when there is no closed fence. */
|
|
39
39
|
function splitSkillMdFrontmatter(text) {
|
|
40
40
|
if (text.charCodeAt(0) === 65279) text = text.slice(1);
|
|
@@ -791,6 +791,22 @@ const CHAT_HISTORY_ITEM_TYPES = [
|
|
|
791
791
|
"system",
|
|
792
792
|
"voice_transcript"
|
|
793
793
|
];
|
|
794
|
+
/**
|
|
795
|
+
* Why a turn's LLM call was retried. Timeouts we raise ourselves are classified ahead of
|
|
796
|
+
* overload so they never read as a provider fault (older backends worded them "may be
|
|
797
|
+
* overloaded"). Must stay in sync with classifyTurnRetryReason in @bike4mind/services.
|
|
798
|
+
*/
|
|
799
|
+
const TURN_RETRY_REASONS = [
|
|
800
|
+
"stream_idle_timeout",
|
|
801
|
+
"stream_truncated",
|
|
802
|
+
"request_timeout",
|
|
803
|
+
"rate_limit",
|
|
804
|
+
"overloaded",
|
|
805
|
+
"server_error",
|
|
806
|
+
"transport",
|
|
807
|
+
"tool_pairing",
|
|
808
|
+
"other"
|
|
809
|
+
];
|
|
794
810
|
/** Where a session was created. Absent on sessions that predate the field; render those as 'web'. */
|
|
795
811
|
const SESSION_ORIGIN_CHANNELS = [
|
|
796
812
|
"web",
|
|
@@ -849,6 +865,12 @@ function parseClaudeModelId(modelId) {
|
|
|
849
865
|
minor: minor === void 0 ? null : Number(minor)
|
|
850
866
|
};
|
|
851
867
|
}
|
|
868
|
+
/** `opus-4-5` for `claude-opus-4-5-20251101` or `global.anthropic.claude-opus-4-5-...`; null otherwise. */
|
|
869
|
+
function claudeFamilyVersion(modelId) {
|
|
870
|
+
const parsed = parseClaudeModelId(modelId);
|
|
871
|
+
if (!parsed) return null;
|
|
872
|
+
return parsed.minor === null ? `${parsed.family}-${parsed.major}` : `${parsed.family}-${parsed.major}-${parsed.minor}`;
|
|
873
|
+
}
|
|
852
874
|
/**
|
|
853
875
|
* Model backends
|
|
854
876
|
*/
|
|
@@ -1022,6 +1044,7 @@ let ChatModels = /* @__PURE__ */ function(ChatModels) {
|
|
|
1022
1044
|
ChatModels["TINYLLAMA"] = "tinyllama";
|
|
1023
1045
|
ChatModels["DEEPSEEK_R1_BEDROCK"] = "us.deepseek.r1-v1:0";
|
|
1024
1046
|
ChatModels["DEEPSEEK_V3_1"] = "deepseek.v3-v1:0";
|
|
1047
|
+
ChatModels["NOVA_PRO_BEDROCK"] = "us.amazon.nova-pro-v1:0";
|
|
1025
1048
|
ChatModels["TITAN_TEXT_G1_LITE"] = "amazon.titan-text-lite-v1";
|
|
1026
1049
|
ChatModels["TITAN_TEXT_G1_EXPRESS"] = "amazon.titan-text-express-v1";
|
|
1027
1050
|
ChatModels["CLAUDE_3_HAIKU_BEDROCK"] = "anthropic.claude-3-haiku-20240307-v1:0";
|
|
@@ -1149,6 +1172,173 @@ z$1.enum({
|
|
|
1149
1172
|
...ImageModels,
|
|
1150
1173
|
...SpeechToTextModels
|
|
1151
1174
|
});
|
|
1175
|
+
let ApiKeyScope = /* @__PURE__ */ function(ApiKeyScope) {
|
|
1176
|
+
ApiKeyScope["READ_NOTEBOOKS"] = "notebooks:read";
|
|
1177
|
+
ApiKeyScope["WRITE_NOTEBOOKS"] = "notebooks:write";
|
|
1178
|
+
ApiKeyScope["READ_FILES"] = "files:read";
|
|
1179
|
+
ApiKeyScope["WRITE_FILES"] = "files:write";
|
|
1180
|
+
ApiKeyScope["AI_GENERATE"] = "ai:generate";
|
|
1181
|
+
/**
|
|
1182
|
+
* Only the Decisions API (`POST /api/v1/decisions`, `GET /api/v1/decision-models`): typed questions answered
|
|
1183
|
+
* with probabilities. `ai:generate` also opens these routes. Not confined, so like `me:read` it also passes
|
|
1184
|
+
* scope-less routes; an image sent by `file_id` additionally needs `files:read`.
|
|
1185
|
+
*/
|
|
1186
|
+
ApiKeyScope["AI_DECIDE"] = "ai:decide";
|
|
1187
|
+
ApiKeyScope["AI_CHAT"] = "ai:chat";
|
|
1188
|
+
ApiKeyScope["READ_PROJECTS"] = "projects:read";
|
|
1189
|
+
ApiKeyScope["WRITE_PROJECTS"] = "projects:write";
|
|
1190
|
+
/** List and read the key owner's agents (and agents shared with them). */
|
|
1191
|
+
ApiKeyScope["READ_AGENTS"] = "agents:read";
|
|
1192
|
+
/**
|
|
1193
|
+
* Create, update, delete and fund agents, manage their embed keys, and run the
|
|
1194
|
+
* agent-authoring assistants (description/avatar/system-prompt/field generation),
|
|
1195
|
+
* which spend the owner's credits on the agent's behalf.
|
|
1196
|
+
*/
|
|
1197
|
+
ApiKeyScope["WRITE_AGENTS"] = "agents:write";
|
|
1198
|
+
/** Authorizes only the cc-bridge WS actions (cc_agent_register /
|
|
1199
|
+
* cc_agent_event / cc_agent_disconnect). Keys with this scope CANNOT
|
|
1200
|
+
* call chat/completions - a leaked bridge key has the narrow blast
|
|
1201
|
+
* radius of a sprite-spawning credential, not a billable AI key. */
|
|
1202
|
+
ApiKeyScope["CC_BRIDGE"] = "cc-bridge:connect";
|
|
1203
|
+
/**
|
|
1204
|
+
* Read the key owner's OWN commercial state - tier, credit balance, entitlement
|
|
1205
|
+
* keys - via `GET /api/v1/me`. Split from the AI scopes on purpose: a key minted
|
|
1206
|
+
* to generate text has no business enumerating what its owner has paid for. It
|
|
1207
|
+
* reaches only `GET /api/v1/me` and its balance-only subset `GET /api/v1/credits`
|
|
1208
|
+
* (which the AI scopes also open, since spend needs a pre-flight check), so it
|
|
1209
|
+
* carries the `:read` suffix that puts it in the New-Key modal's read-only preset.
|
|
1210
|
+
*/
|
|
1211
|
+
ApiKeyScope["ME_READ"] = "me:read";
|
|
1212
|
+
ApiKeyScope["ADMIN"] = "admin:*";
|
|
1213
|
+
ApiKeyScope["MARKETING_REPORTS_READ"] = "marketing-reports:read";
|
|
1214
|
+
ApiKeyScope["MARKETING_REPORTS_WRITE"] = "marketing-reports:write";
|
|
1215
|
+
/** Server-to-server ingest scope for Overwatch analytics. Admin-provisioned only - never shown in user-facing key creation UI. */
|
|
1216
|
+
ApiKeyScope["OVERWATCH_INGEST_WRITE"] = "overwatch-ingest:write";
|
|
1217
|
+
/** Authorizes only embedded-widget chat against the single agent the key is
|
|
1218
|
+
* bound to (`agentId`). Like CC_BRIDGE, a leaked embed key has a narrow blast
|
|
1219
|
+
* radius: it can talk to one agent from allow-listed origins, nothing else. */
|
|
1220
|
+
ApiKeyScope["EMBED_CHAT"] = "embed:chat";
|
|
1221
|
+
/** Read a Hearth channel list and replay its events. Read-only: it cannot
|
|
1222
|
+
* advance an actor cursor, because consuming events out from under a
|
|
1223
|
+
* legitimate agent reader is a denial of context, not a read. */
|
|
1224
|
+
ApiKeyScope["HEARTH_READ"] = "hearth:read";
|
|
1225
|
+
/** Append Hearth events, create channels, and advance actor cursors. */
|
|
1226
|
+
ApiKeyScope["HEARTH_WRITE"] = "hearth:write";
|
|
1227
|
+
/**
|
|
1228
|
+
* Read OptiHashi problems, runs, and run artifacts. Deliberately split from
|
|
1229
|
+
* {@link OPTIHASHI_COMPUTE}: a key that only inspects results is structurally
|
|
1230
|
+
* unable to start a billable solve, so an agent-held key can be handed the
|
|
1231
|
+
* read half alone. Like every scope, it authorizes but never entitles - the
|
|
1232
|
+
* OptiHashi entitlement check still runs and can refuse on its own.
|
|
1233
|
+
*/
|
|
1234
|
+
ApiKeyScope["OPTIHASHI_READ"] = "optihashi:read";
|
|
1235
|
+
/**
|
|
1236
|
+
* Submit OptiHashi compute (solve/decompose/schedule) and cancel a run. This
|
|
1237
|
+
* is the spend half of the OptiHashi pair: it commissions external compute
|
|
1238
|
+
* that costs real money, so it is never implied by {@link OPTIHASHI_READ}.
|
|
1239
|
+
*/
|
|
1240
|
+
ApiKeyScope["OPTIHASHI_COMPUTE"] = "optihashi:compute";
|
|
1241
|
+
/**
|
|
1242
|
+
* Read data lakes and their contents: list/browse lakes (including keyword search over
|
|
1243
|
+
* articles), read a lake's health, spend, batches, and access view. Split from
|
|
1244
|
+
* {@link DATALAKE_WRITE} so a key handed to an agent can look at a lake without being able to
|
|
1245
|
+
* change one. A retrieval query that spends LLM/search budget (semantic search, the RLM answer
|
|
1246
|
+
* endpoint) needs {@link DATALAKE_QUERY} instead: this scope does not imply it, though a
|
|
1247
|
+
* {@link DATALAKE_QUERY} key does gain this one (it has to, to reach the read-gated routes its
|
|
1248
|
+
* own retrieval tools call back into).
|
|
1249
|
+
*/
|
|
1250
|
+
ApiKeyScope["DATALAKE_READ"] = "datalake:read";
|
|
1251
|
+
/**
|
|
1252
|
+
* Change what is IN a lake or how it behaves: create/update/archive a lake,
|
|
1253
|
+
* attach, detach, retag, or purge its files, run converge/rechunk/research,
|
|
1254
|
+
* and manage upload batches. Deliberately does NOT carry
|
|
1255
|
+
* {@link DATALAKE_SHARE}: adding files to a lake is a different privilege
|
|
1256
|
+
* from handing the lake to someone else.
|
|
1257
|
+
*/
|
|
1258
|
+
ApiKeyScope["DATALAKE_WRITE"] = "datalake:write";
|
|
1259
|
+
/**
|
|
1260
|
+
* Change WHO can reach a lake: its visibility and its ownership (and the
|
|
1261
|
+
* grant/revoke door). Never implied by {@link DATALAKE_WRITE} - re-sharing a
|
|
1262
|
+
* lake widens the blast radius of every document already in it, which is not
|
|
1263
|
+
* what a key minted to keep a lake's files current asked for.
|
|
1264
|
+
*/
|
|
1265
|
+
ApiKeyScope["DATALAKE_SHARE"] = "datalake:share";
|
|
1266
|
+
/**
|
|
1267
|
+
* Run a retrieval query that spends LLM/search budget against a lake: semantic search and the
|
|
1268
|
+
* RLM answer endpoint. Deliberately NOT suffixed `:read` - {@link DATALAKE_READ} feeds the
|
|
1269
|
+
* New-Key modal's "Read-only" preset (`s.value.endsWith(':read')`), and a key an operator mints
|
|
1270
|
+
* expecting that preset to be free must not auto-join a scope that commissions billable work.
|
|
1271
|
+
* Mirrors {@link OPTIHASHI_COMPUTE}'s split from {@link OPTIHASHI_READ}. Never implied by
|
|
1272
|
+
* {@link DATALAKE_READ} or {@link DATALAKE_WRITE} - spend on a lake is opt-in on its own. The
|
|
1273
|
+
* implication runs the other way for gating purposes: a key holding only this scope also passes
|
|
1274
|
+
* {@link DATALAKE_READ}'s gate, because the RLM answer endpoint's in-REPL tools call back into
|
|
1275
|
+
* read-gated routes (e.g. GET /api/data-lakes/articles) with the caller's own credential.
|
|
1276
|
+
*/
|
|
1277
|
+
ApiKeyScope["DATALAKE_QUERY"] = "datalake:query";
|
|
1278
|
+
/**
|
|
1279
|
+
* Read the Overwatch analytics surface - the cross-product overview, product
|
|
1280
|
+
* inventory and config, first-party metrics, product-stat history, funnel,
|
|
1281
|
+
* and pipeline freshness. Exists so an agent can be handed a credential that
|
|
1282
|
+
* can only *look*: it is deliberately NOT the read half of
|
|
1283
|
+
* {@link OVERWATCH_INGEST_WRITE}, which is a per-product ingest credential
|
|
1284
|
+
* bound to one `productId` and able to write that product's numbers. Handing
|
|
1285
|
+
* an explorer the ingest key would let it fabricate the very stats it reports
|
|
1286
|
+
* on, so the two are separate scopes rather than a read/write pair.
|
|
1287
|
+
*
|
|
1288
|
+
* Like every scope, it authorizes but never entitles - the Overwatch access
|
|
1289
|
+
* check (`requestHasOverwatchAccess`: admin OR developer OR `overwatch:pro`)
|
|
1290
|
+
* still runs against the key's owner and can refuse on its own. A key minted
|
|
1291
|
+
* with this scope by a user who does not hold Overwatch access opens nothing.
|
|
1292
|
+
* That check and the routes it guards live in the Overwatch overlay package;
|
|
1293
|
+
* neither has an implementation in this repository, so nothing here verifies
|
|
1294
|
+
* the claim - it is a property of the consumer, recorded for the reader.
|
|
1295
|
+
*/
|
|
1296
|
+
ApiKeyScope["OVERWATCH_READ"] = "overwatch:read";
|
|
1297
|
+
/**
|
|
1298
|
+
* CI-to-server ingest of Playwright runs for the admin /status page
|
|
1299
|
+
* (`POST /api/qa/uploads`, `POST /api/qa/runs`). Admin-provisioned only,
|
|
1300
|
+
* and confined like {@link OVERWATCH_INGEST_WRITE}: a leaked CI key reaches the
|
|
1301
|
+
* two ingest routes and nothing else. The routes also require the key's owner
|
|
1302
|
+
* to carry the `qa-ingest` user tag (QA_INGEST_USER_TAG in schemas/qa.ts).
|
|
1303
|
+
*/
|
|
1304
|
+
ApiKeyScope["QA_INGEST"] = "qa:ingest";
|
|
1305
|
+
/**
|
|
1306
|
+
* List and download the Claude Code plugin feed of an org's approved Skill Market listings
|
|
1307
|
+
* (`/api/v1/skills/market/*`). Confined: the key ends up in plaintext in `~/.claude/settings.json`,
|
|
1308
|
+
* so it must reach nothing else. Minted from the Skill Market's "Use in Claude Code" dialog.
|
|
1309
|
+
*/
|
|
1310
|
+
ApiKeyScope["SKILLS_READ"] = "skills:read";
|
|
1311
|
+
/**
|
|
1312
|
+
* Release-note automation: find a release note and set its video, and upload the What's New
|
|
1313
|
+
* media for it. Admin-provisioned and confined so the job needs no `admin:*`
|
|
1314
|
+
* key: it reaches only the routes that name it, and those still require a platform-admin owner.
|
|
1315
|
+
*/
|
|
1316
|
+
ApiKeyScope["RELEASE_NOTES_WRITE"] = "release-notes:write";
|
|
1317
|
+
/**
|
|
1318
|
+
* Read the key owner's own Bob results: single-site reads, two-site comparisons and
|
|
1319
|
+
* re-checks, the recent-reports list, and how many runs are left. It starts nothing and
|
|
1320
|
+
* spends nothing, so the `:read` suffix that puts it in the New-Key modal's Read-only
|
|
1321
|
+
* preset is deliberate, and safe there because every read is scoped to the key's owner.
|
|
1322
|
+
* Split from {@link BOB_RUN} so an agent can be handed the read half alone.
|
|
1323
|
+
*
|
|
1324
|
+
* Like every scope, it authorizes but never entitles. The Bob routes, and the gate that
|
|
1325
|
+
* decides which of the two scopes each one accepts, live in the Bob overlay package and
|
|
1326
|
+
* have no implementation in this repository, so nothing here verifies either claim.
|
|
1327
|
+
*/
|
|
1328
|
+
ApiKeyScope["BOB_READ"] = "bob:read";
|
|
1329
|
+
/**
|
|
1330
|
+
* Start a Bob site read, a two-site comparison or a re-check. This is the spend half of
|
|
1331
|
+
* the Bob pair: it spends the key owner's credits and publishes a report as them, so it
|
|
1332
|
+
* is never implied by {@link BOB_READ}, and it is deliberately unsuffixed so it stays out
|
|
1333
|
+
* of the Read-only and Read & write presets, as {@link OPTIHASHI_COMPUTE} does. Nor does
|
|
1334
|
+
* it imply {@link BOB_READ} at this repository's scope gate.
|
|
1335
|
+
*
|
|
1336
|
+
* Authorizes without entitling, like {@link BOB_READ}: the gate that enforces it lives in
|
|
1337
|
+
* the Bob overlay package, with no implementation here.
|
|
1338
|
+
*/
|
|
1339
|
+
ApiKeyScope["BOB_RUN"] = "bob:run";
|
|
1340
|
+
return ApiKeyScope;
|
|
1341
|
+
}({});
|
|
1152
1342
|
Object.freeze({
|
|
1153
1343
|
requestsPerMinute: 60,
|
|
1154
1344
|
requestsPerDay: 1e3
|
|
@@ -1280,6 +1470,42 @@ const GenericCreditAddTransaction = BaseCreditTransaction.extend({
|
|
|
1280
1470
|
transactionId: z$1.string().optional()
|
|
1281
1471
|
});
|
|
1282
1472
|
/**
|
|
1473
|
+
* Built-in reasons for generic credit deductions; they seed the registry below.
|
|
1474
|
+
* A package that needs a new reason registers it with registerGenericDeductReason
|
|
1475
|
+
* rather than extending this list.
|
|
1476
|
+
*/
|
|
1477
|
+
const GenericDeductReasons = [
|
|
1478
|
+
"dispute_clawback",
|
|
1479
|
+
"refund_clawback",
|
|
1480
|
+
"payment_failed_clawback",
|
|
1481
|
+
"notebook_curation",
|
|
1482
|
+
"manual",
|
|
1483
|
+
"admin_adjustment",
|
|
1484
|
+
"refund_adjustment",
|
|
1485
|
+
"optihashi_reservation",
|
|
1486
|
+
"optihashi_cost_chargeup",
|
|
1487
|
+
"credit_expiry"
|
|
1488
|
+
];
|
|
1489
|
+
const GENERIC_DEDUCT_REASON_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
1490
|
+
const GENERIC_DEDUCT_REASON_REGISTRY_KEY = Symbol.for("b4m.credit.genericDeductReasons");
|
|
1491
|
+
let seededRegistry;
|
|
1492
|
+
function genericDeductReasonRegistry() {
|
|
1493
|
+
const holder = globalThis;
|
|
1494
|
+
let registry = holder[GENERIC_DEDUCT_REASON_REGISTRY_KEY];
|
|
1495
|
+
if (!registry) {
|
|
1496
|
+
registry = /* @__PURE__ */ new Set();
|
|
1497
|
+
holder[GENERIC_DEDUCT_REASON_REGISTRY_KEY] = registry;
|
|
1498
|
+
}
|
|
1499
|
+
if (seededRegistry !== registry) {
|
|
1500
|
+
for (const reason of GenericDeductReasons) registry.add(reason);
|
|
1501
|
+
seededRegistry = registry;
|
|
1502
|
+
}
|
|
1503
|
+
return registry;
|
|
1504
|
+
}
|
|
1505
|
+
function isGenericDeductReason(value) {
|
|
1506
|
+
return typeof value === "string" && GENERIC_DEDUCT_REASON_PATTERN.test(value) && genericDeductReasonRegistry().has(value);
|
|
1507
|
+
}
|
|
1508
|
+
/**
|
|
1283
1509
|
* Generic credit deduction transaction for legacy data and flexible use cases
|
|
1284
1510
|
* Represents any credit deduction that doesn't fit specific categories
|
|
1285
1511
|
* (e.g., admin adjustments, legacy usage, manual deductions)
|
|
@@ -1291,20 +1517,10 @@ const GenericCreditDeductTransaction = BaseCreditTransaction.extend({
|
|
|
1291
1517
|
*/
|
|
1292
1518
|
userId: z$1.string().optional(),
|
|
1293
1519
|
/**
|
|
1294
|
-
* Reason/source for the transaction
|
|
1520
|
+
* Reason/source for the transaction: a built-in GenericDeductReasons value or one added with
|
|
1521
|
+
* registerGenericDeductReason.
|
|
1295
1522
|
*/
|
|
1296
|
-
reason: z$1.
|
|
1297
|
-
"dispute_clawback",
|
|
1298
|
-
"refund_clawback",
|
|
1299
|
-
"payment_failed_clawback",
|
|
1300
|
-
"notebook_curation",
|
|
1301
|
-
"manual",
|
|
1302
|
-
"admin_adjustment",
|
|
1303
|
-
"refund_adjustment",
|
|
1304
|
-
"optihashi_reservation",
|
|
1305
|
-
"optihashi_cost_chargeup",
|
|
1306
|
-
"credit_expiry"
|
|
1307
|
-
]).optional(),
|
|
1523
|
+
reason: z$1.custom(isGenericDeductReason, { error: (issue) => typeof issue.input === "string" ? "Unregistered generic deduct reason" : `Expected a generic deduct reason string, received ${issue.input === null ? "null" : typeof issue.input}` }).optional(),
|
|
1308
1524
|
/**
|
|
1309
1525
|
* Stripe dispute ID - set for dispute clawback transactions.
|
|
1310
1526
|
* Used for idempotency (unique sparse index prevents duplicate clawbacks).
|
|
@@ -1472,6 +1688,25 @@ const USAGE_EVENT_STATUSES = [
|
|
|
1472
1688
|
"refusal",
|
|
1473
1689
|
"degenerate"
|
|
1474
1690
|
];
|
|
1691
|
+
/** Where a UsageEvent's rates came from: a ModelPrice catalog row, or the adapter literal fallback. */
|
|
1692
|
+
const USAGE_PRICE_SOURCES = ["catalog", "literal"];
|
|
1693
|
+
/** USD per token for the pricing tier that priced a call (see AppliedRates in models.ts). */
|
|
1694
|
+
const UsageEventRates = z$1.object({
|
|
1695
|
+
/** The pricing-map key (input-token threshold) of the tier applied. */
|
|
1696
|
+
tierKey: z$1.number(),
|
|
1697
|
+
input: z$1.number(),
|
|
1698
|
+
output: z$1.number(),
|
|
1699
|
+
cacheRead: z$1.number().optional(),
|
|
1700
|
+
cacheWrite: z$1.number().optional()
|
|
1701
|
+
});
|
|
1702
|
+
/** One provider request of a multi-turn completion, with the tier it was priced on. */
|
|
1703
|
+
const UsageEventTurn = z$1.object({
|
|
1704
|
+
inputTokens: z$1.number(),
|
|
1705
|
+
outputTokens: z$1.number(),
|
|
1706
|
+
cacheReadTokens: z$1.number().optional(),
|
|
1707
|
+
cacheWriteTokens: z$1.number().optional(),
|
|
1708
|
+
tierKey: z$1.number()
|
|
1709
|
+
});
|
|
1475
1710
|
z$1.object({
|
|
1476
1711
|
id: z$1.string().optional(),
|
|
1477
1712
|
/** App-level correlation id: questId for chat/image/video, session/run id otherwise. */
|
|
@@ -1517,6 +1752,30 @@ z$1.object({
|
|
|
1517
1752
|
source: z$1.enum(COMPLETION_SOURCES).optional(),
|
|
1518
1753
|
/** API key that authed the call; present only for API-key-authed usage. */
|
|
1519
1754
|
apiKeyId: z$1.string().optional(),
|
|
1755
|
+
/** 'catalog' when a ModelPrice row priced the call, 'literal' when the adapter literal did. */
|
|
1756
|
+
priceSource: z$1.enum(USAGE_PRICE_SOURCES).optional(),
|
|
1757
|
+
/** The ModelPrice row in force; set only when priceSource is 'catalog'. */
|
|
1758
|
+
priceRowId: z$1.string().optional(),
|
|
1759
|
+
/**
|
|
1760
|
+
* Rates of the tier applied. A multi-turn row whose turns hit different tiers carries the
|
|
1761
|
+
* tier of its largest turn; turnUsage has each turn's own tierKey, but not that tier's rates,
|
|
1762
|
+
* so only a single-tier text charge is recomputable from its own fields. Provider-basis chat
|
|
1763
|
+
* rows use providerInputTokens/providerOutputTokens plus the cache buckets. Local-estimate chat
|
|
1764
|
+
* rows use input * (inputTokens - cachedInputTokens) + cacheRead * cachedInputTokens
|
|
1765
|
+
* + output * outputTokens. Operational and CLI rows use disjoint input/cache buckets instead:
|
|
1766
|
+
* input * inputTokens + cacheRead * cachedInputTokens + cacheWrite * cacheWriteTokens
|
|
1767
|
+
* + output * outputTokens, even when settledBasis is 'local' or unset.
|
|
1768
|
+
* Local-estimate chat rows are inexact when a fallback uses a different tokenEstimateMultiplier:
|
|
1769
|
+
* inputTokens remains in the requested model's units. Tool spend on other models is not covered.
|
|
1770
|
+
*/
|
|
1771
|
+
rates: UsageEventRates.optional(),
|
|
1772
|
+
/**
|
|
1773
|
+
* Per-turn usage, written only when the completion settled over more than one provider
|
|
1774
|
+
* request (tool loops bill turn by turn). Capped at USAGE_EVENT_TURN_USAGE_CAP entries.
|
|
1775
|
+
*/
|
|
1776
|
+
turnUsage: z$1.array(UsageEventTurn).optional(),
|
|
1777
|
+
/** True when turnUsage was capped: its last entry is the sum of every turn from there on. */
|
|
1778
|
+
turnUsageTruncated: z$1.boolean().optional(),
|
|
1520
1779
|
createdAt: z$1.date(),
|
|
1521
1780
|
updatedAt: z$1.date()
|
|
1522
1781
|
});
|
|
@@ -1589,6 +1848,7 @@ const ADAPTER_FAMILIES = [
|
|
|
1589
1848
|
"bedrock-moonshot",
|
|
1590
1849
|
"bedrock-jurassic",
|
|
1591
1850
|
"bedrock-titan",
|
|
1851
|
+
"bedrock-converse",
|
|
1592
1852
|
"gemini",
|
|
1593
1853
|
"xai",
|
|
1594
1854
|
"kimi",
|
|
@@ -1660,6 +1920,8 @@ const LIFECYCLE_STATUSES = [...[
|
|
|
1660
1920
|
"retired"
|
|
1661
1921
|
], "unlisted"];
|
|
1662
1922
|
const LifecycleWrite = z$1.strictObject({
|
|
1923
|
+
/** Absent on v1 rows means current; true folds the model without disabling it. */
|
|
1924
|
+
isSuperseded: z$1.boolean().optional(),
|
|
1663
1925
|
status: z$1.enum(LIFECYCLE_STATUSES),
|
|
1664
1926
|
deprecationDate: CALENDAR_DATE.optional(),
|
|
1665
1927
|
retirementDate: CALENDAR_DATE.optional(),
|
|
@@ -1843,6 +2105,7 @@ const MODEL_INFO_FIELD_GROUP_OF = {
|
|
|
1843
2105
|
supportsTools: "modalities",
|
|
1844
2106
|
supportsImageVariation: "modalities",
|
|
1845
2107
|
supportsSafetyTolerance: "modalities",
|
|
2108
|
+
isSuperseded: "lifecycle",
|
|
1846
2109
|
deprecationDate: "lifecycle",
|
|
1847
2110
|
replacedBy: "lifecycle",
|
|
1848
2111
|
adapterFamily: "dispatch",
|
|
@@ -2368,6 +2631,59 @@ z$1.object({
|
|
|
2368
2631
|
summary: z$1.string(),
|
|
2369
2632
|
counts: orgFeedbackSummaryCountsSchema
|
|
2370
2633
|
});
|
|
2634
|
+
const MODAL_MEDIA_HOST_SUFFIXES = [".amazonaws.com", ".cloudfront.net"];
|
|
2635
|
+
const MODAL_MEDIA_URL_MAX_LENGTH = 2048;
|
|
2636
|
+
const MODAL_MEDIA_URL_HINT = "Upload the file, or paste an https URL on amazonaws.com or cloudfront.net";
|
|
2637
|
+
function isAllowedModalMediaUrl(url, policy = {}) {
|
|
2638
|
+
if (url.length > MODAL_MEDIA_URL_MAX_LENGTH) return false;
|
|
2639
|
+
if (policy.allowedUrls?.has(url)) return true;
|
|
2640
|
+
try {
|
|
2641
|
+
const { protocol, hostname, origin, port } = new URL(url);
|
|
2642
|
+
if (policy.extraOrigins?.includes(origin)) return true;
|
|
2643
|
+
return protocol === "https:" && port === "" && MODAL_MEDIA_HOST_SUFFIXES.some((suffix) => hostname.endsWith(suffix));
|
|
2644
|
+
} catch {
|
|
2645
|
+
return false;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
/** Per-field problems with a modal video, empty when it is valid. Shared by the admin form and the API. */
|
|
2649
|
+
function getModalVideoErrors(video, policy = {}) {
|
|
2650
|
+
const errors = {};
|
|
2651
|
+
if (!video) return errors;
|
|
2652
|
+
for (const field of [
|
|
2653
|
+
"landscapeUrl",
|
|
2654
|
+
"landscapePosterUrl",
|
|
2655
|
+
"portraitUrl",
|
|
2656
|
+
"portraitPosterUrl"
|
|
2657
|
+
]) {
|
|
2658
|
+
const url = video[field];
|
|
2659
|
+
if (url && !isAllowedModalMediaUrl(url, policy)) errors[field] = MODAL_MEDIA_URL_HINT;
|
|
2660
|
+
}
|
|
2661
|
+
if (video.landscapePosterUrl && !video.landscapeUrl) errors.landscapePosterUrl ??= "A 16:9 poster needs its 16:9 video";
|
|
2662
|
+
if (video.portraitPosterUrl && !video.portraitUrl) errors.portraitPosterUrl ??= "A 9:16 poster needs its 9:16 video";
|
|
2663
|
+
return errors;
|
|
2664
|
+
}
|
|
2665
|
+
/** The video's fields with no host check, for reading stored or upstream data written under another policy. */
|
|
2666
|
+
const ModalVideoShapeSchema = z$1.object({
|
|
2667
|
+
landscapeUrl: z$1.string().nullable().optional(),
|
|
2668
|
+
landscapePosterUrl: z$1.string().nullable().optional(),
|
|
2669
|
+
portraitUrl: z$1.string().nullable().optional(),
|
|
2670
|
+
portraitPosterUrl: z$1.string().nullable().optional()
|
|
2671
|
+
});
|
|
2672
|
+
/**
|
|
2673
|
+
* Product video for a modal slide. Landscape is the 16:9 cut shown on desktop, portrait the 9:16 cut
|
|
2674
|
+
* shown on mobile; the slider falls back to the other orientation when one is missing. The API passes
|
|
2675
|
+
* its deployment's extra origins; the bare `ModalVideoSchema` allows only the static host list.
|
|
2676
|
+
*/
|
|
2677
|
+
function createModalVideoSchema(policy = {}) {
|
|
2678
|
+
return ModalVideoShapeSchema.superRefine((video, ctx) => {
|
|
2679
|
+
for (const [field, message] of Object.entries(getModalVideoErrors(video, policy))) ctx.addIssue({
|
|
2680
|
+
code: "custom",
|
|
2681
|
+
path: [field],
|
|
2682
|
+
message
|
|
2683
|
+
});
|
|
2684
|
+
});
|
|
2685
|
+
}
|
|
2686
|
+
createModalVideoSchema();
|
|
2371
2687
|
/**
|
|
2372
2688
|
* Check if a value is a placeholder (not configured or SST default).
|
|
2373
2689
|
* Uses case-insensitive comparison and trims whitespace to prevent bypass attempts.
|
|
@@ -2984,18 +3300,21 @@ const AuditChangeSchema = z$1.object({
|
|
|
2984
3300
|
before: z$1.unknown(),
|
|
2985
3301
|
after: z$1.unknown()
|
|
2986
3302
|
});
|
|
3303
|
+
/** Sources a stored AdminAuditLog row can carry; the write input and the filters stay inside this set. */
|
|
3304
|
+
const StoredAuditContextSourceSchema = z$1.enum([
|
|
3305
|
+
"admin_ui",
|
|
3306
|
+
"api_key",
|
|
3307
|
+
"script",
|
|
3308
|
+
"worker"
|
|
3309
|
+
]);
|
|
3310
|
+
/** Read-side context: 'user' is the account holder's own session, which only the security-store adapters emit. */
|
|
2987
3311
|
const AuditContextSchema = z$1.object({
|
|
2988
3312
|
ip: z$1.string().optional(),
|
|
2989
3313
|
userAgent: z$1.string().optional(),
|
|
2990
3314
|
requestId: z$1.string().optional(),
|
|
2991
|
-
source:
|
|
2992
|
-
"admin_ui",
|
|
2993
|
-
"api_key",
|
|
2994
|
-
"script",
|
|
2995
|
-
"worker"
|
|
2996
|
-
]),
|
|
3315
|
+
source: StoredAuditContextSourceSchema,
|
|
2997
3316
|
route: z$1.string().optional()
|
|
2998
|
-
});
|
|
3317
|
+
}).extend({ source: z$1.union([StoredAuditContextSourceSchema, z$1.literal("user")]) });
|
|
2999
3318
|
const AdminAuditCategorySchema = z$1.enum([
|
|
3000
3319
|
"credits",
|
|
3001
3320
|
"access",
|
|
@@ -3037,6 +3356,267 @@ z$1.object({
|
|
|
3037
3356
|
backfilled: z$1.boolean().optional()
|
|
3038
3357
|
});
|
|
3039
3358
|
z$1.string({ error: "A reason is required" }).trim().min(5, `A reason of at least 5 characters is required`).max(500);
|
|
3359
|
+
/** App defaults for the AdminSettings grant thresholds (AdminAuditCriticalGrantCredits / AdminAuditDailyGrantCredits). */
|
|
3360
|
+
const ADMIN_AUDIT_DEFAULT_CRITICAL_GRANT_CREDITS = 5e4;
|
|
3361
|
+
const ADMIN_AUDIT_DEFAULT_DAILY_GRANT_CREDITS = 2e5;
|
|
3362
|
+
const ADMIN_AUDIT_CATALOGUE = {
|
|
3363
|
+
"org.credits.granted": {
|
|
3364
|
+
category: "credits",
|
|
3365
|
+
severity: "notice",
|
|
3366
|
+
write: "strict",
|
|
3367
|
+
escalatesAboveGrantThreshold: true
|
|
3368
|
+
},
|
|
3369
|
+
"org.credits.topped_up": {
|
|
3370
|
+
category: "credits",
|
|
3371
|
+
severity: "notice",
|
|
3372
|
+
write: "strict",
|
|
3373
|
+
escalatesAboveGrantThreshold: true
|
|
3374
|
+
},
|
|
3375
|
+
"org.credits.adjusted": {
|
|
3376
|
+
category: "credits",
|
|
3377
|
+
severity: "notice",
|
|
3378
|
+
write: "strict",
|
|
3379
|
+
escalatesAboveGrantThreshold: true
|
|
3380
|
+
},
|
|
3381
|
+
"org.credits.refunded": {
|
|
3382
|
+
category: "credits",
|
|
3383
|
+
severity: "notice",
|
|
3384
|
+
write: "strict",
|
|
3385
|
+
escalatesAboveGrantThreshold: true
|
|
3386
|
+
},
|
|
3387
|
+
"user.subscription.granted": {
|
|
3388
|
+
category: "credits",
|
|
3389
|
+
severity: "notice",
|
|
3390
|
+
write: "strict"
|
|
3391
|
+
},
|
|
3392
|
+
"user.credits.adjusted": {
|
|
3393
|
+
category: "credits",
|
|
3394
|
+
severity: "notice",
|
|
3395
|
+
write: "strict",
|
|
3396
|
+
escalatesAboveGrantThreshold: true
|
|
3397
|
+
},
|
|
3398
|
+
"user.credits.denied": {
|
|
3399
|
+
category: "credits",
|
|
3400
|
+
severity: "critical",
|
|
3401
|
+
write: "bestEffort"
|
|
3402
|
+
},
|
|
3403
|
+
"user.subscription.denied": {
|
|
3404
|
+
category: "credits",
|
|
3405
|
+
severity: "critical",
|
|
3406
|
+
write: "bestEffort"
|
|
3407
|
+
},
|
|
3408
|
+
"user.role.admin_granted": {
|
|
3409
|
+
category: "access",
|
|
3410
|
+
severity: "critical",
|
|
3411
|
+
write: "strict"
|
|
3412
|
+
},
|
|
3413
|
+
"user.role.admin_revoked": {
|
|
3414
|
+
category: "access",
|
|
3415
|
+
severity: "critical",
|
|
3416
|
+
write: "strict"
|
|
3417
|
+
},
|
|
3418
|
+
"user.role.denied": {
|
|
3419
|
+
category: "access",
|
|
3420
|
+
severity: "critical",
|
|
3421
|
+
write: "bestEffort"
|
|
3422
|
+
},
|
|
3423
|
+
"user.impersonation.started": {
|
|
3424
|
+
category: "access",
|
|
3425
|
+
severity: "critical",
|
|
3426
|
+
write: "strict"
|
|
3427
|
+
},
|
|
3428
|
+
"user.impersonation.ended": {
|
|
3429
|
+
category: "access",
|
|
3430
|
+
severity: "info",
|
|
3431
|
+
write: "bestEffort"
|
|
3432
|
+
},
|
|
3433
|
+
"user.impersonation.denied": {
|
|
3434
|
+
category: "access",
|
|
3435
|
+
severity: "critical",
|
|
3436
|
+
write: "bestEffort"
|
|
3437
|
+
},
|
|
3438
|
+
"user.deleted": {
|
|
3439
|
+
category: "account",
|
|
3440
|
+
severity: "critical",
|
|
3441
|
+
write: "strict"
|
|
3442
|
+
},
|
|
3443
|
+
"user.deletion.denied": {
|
|
3444
|
+
category: "account",
|
|
3445
|
+
severity: "critical",
|
|
3446
|
+
write: "bestEffort"
|
|
3447
|
+
},
|
|
3448
|
+
"user.profile.updated": {
|
|
3449
|
+
category: "account",
|
|
3450
|
+
severity: "notice",
|
|
3451
|
+
write: "bestEffort"
|
|
3452
|
+
},
|
|
3453
|
+
"org.seats.changed": {
|
|
3454
|
+
category: "org",
|
|
3455
|
+
severity: "notice",
|
|
3456
|
+
write: "bestEffort"
|
|
3457
|
+
},
|
|
3458
|
+
"org.seats.ceiling_raised": {
|
|
3459
|
+
category: "org",
|
|
3460
|
+
severity: "info",
|
|
3461
|
+
write: "bestEffort"
|
|
3462
|
+
},
|
|
3463
|
+
"org.conversion.initiated": {
|
|
3464
|
+
category: "org",
|
|
3465
|
+
severity: "notice",
|
|
3466
|
+
write: "bestEffort"
|
|
3467
|
+
},
|
|
3468
|
+
"org.revoked": {
|
|
3469
|
+
category: "org",
|
|
3470
|
+
severity: "notice",
|
|
3471
|
+
write: "strict"
|
|
3472
|
+
},
|
|
3473
|
+
"org.group_types.updated": {
|
|
3474
|
+
category: "org",
|
|
3475
|
+
severity: "info",
|
|
3476
|
+
write: "bestEffort"
|
|
3477
|
+
},
|
|
3478
|
+
"org.admins.updated": {
|
|
3479
|
+
category: "org",
|
|
3480
|
+
severity: "notice",
|
|
3481
|
+
write: "bestEffort"
|
|
3482
|
+
},
|
|
3483
|
+
"org.group_member.assigned": {
|
|
3484
|
+
category: "org",
|
|
3485
|
+
severity: "info",
|
|
3486
|
+
write: "bestEffort"
|
|
3487
|
+
},
|
|
3488
|
+
"org.group_member.unassigned": {
|
|
3489
|
+
category: "org",
|
|
3490
|
+
severity: "info",
|
|
3491
|
+
write: "bestEffort"
|
|
3492
|
+
},
|
|
3493
|
+
"org.invite.created": {
|
|
3494
|
+
category: "org",
|
|
3495
|
+
severity: "info",
|
|
3496
|
+
write: "bestEffort"
|
|
3497
|
+
},
|
|
3498
|
+
"org.member_budget.updated": {
|
|
3499
|
+
category: "org",
|
|
3500
|
+
severity: "notice",
|
|
3501
|
+
write: "bestEffort"
|
|
3502
|
+
},
|
|
3503
|
+
"settings.admin_settings.updated": {
|
|
3504
|
+
category: "settings",
|
|
3505
|
+
severity: "notice",
|
|
3506
|
+
write: "strict"
|
|
3507
|
+
},
|
|
3508
|
+
"settings.whats_new.updated": {
|
|
3509
|
+
category: "settings",
|
|
3510
|
+
severity: "info",
|
|
3511
|
+
write: "bestEffort"
|
|
3512
|
+
},
|
|
3513
|
+
"settings.whats_new.synced": {
|
|
3514
|
+
category: "settings",
|
|
3515
|
+
severity: "info",
|
|
3516
|
+
write: "bestEffort"
|
|
3517
|
+
},
|
|
3518
|
+
"settings.whats_new.generation_triggered": {
|
|
3519
|
+
category: "settings",
|
|
3520
|
+
severity: "info",
|
|
3521
|
+
write: "bestEffort"
|
|
3522
|
+
},
|
|
3523
|
+
"settings.security_scan.enabled": {
|
|
3524
|
+
category: "settings",
|
|
3525
|
+
severity: "notice",
|
|
3526
|
+
write: "bestEffort"
|
|
3527
|
+
},
|
|
3528
|
+
"settings.security_scan.disabled": {
|
|
3529
|
+
category: "settings",
|
|
3530
|
+
severity: "notice",
|
|
3531
|
+
write: "bestEffort"
|
|
3532
|
+
},
|
|
3533
|
+
"settings.security_scan.triggered": {
|
|
3534
|
+
category: "settings",
|
|
3535
|
+
severity: "notice",
|
|
3536
|
+
write: "bestEffort"
|
|
3537
|
+
},
|
|
3538
|
+
"security.attack_simulation.run": {
|
|
3539
|
+
category: "settings",
|
|
3540
|
+
severity: "notice",
|
|
3541
|
+
write: "bestEffort"
|
|
3542
|
+
},
|
|
3543
|
+
"oauth_client.created": {
|
|
3544
|
+
category: "settings",
|
|
3545
|
+
severity: "notice",
|
|
3546
|
+
write: "bestEffort"
|
|
3547
|
+
},
|
|
3548
|
+
"oauth_client.secret_rotated": {
|
|
3549
|
+
category: "settings",
|
|
3550
|
+
severity: "notice",
|
|
3551
|
+
write: "bestEffort"
|
|
3552
|
+
},
|
|
3553
|
+
"oauth_client.updated": {
|
|
3554
|
+
category: "settings",
|
|
3555
|
+
severity: "notice",
|
|
3556
|
+
write: "bestEffort"
|
|
3557
|
+
},
|
|
3558
|
+
"oauth_client.activated": {
|
|
3559
|
+
category: "settings",
|
|
3560
|
+
severity: "notice",
|
|
3561
|
+
write: "bestEffort"
|
|
3562
|
+
},
|
|
3563
|
+
"oauth_client.deactivated": {
|
|
3564
|
+
category: "settings",
|
|
3565
|
+
severity: "notice",
|
|
3566
|
+
write: "bestEffort"
|
|
3567
|
+
},
|
|
3568
|
+
"system_health.test_run": {
|
|
3569
|
+
category: "settings",
|
|
3570
|
+
severity: "info",
|
|
3571
|
+
write: "bestEffort"
|
|
3572
|
+
},
|
|
3573
|
+
"user.email.verified": {
|
|
3574
|
+
category: "identity",
|
|
3575
|
+
severity: "info",
|
|
3576
|
+
write: "bestEffort"
|
|
3577
|
+
},
|
|
3578
|
+
"user.email.unverified": {
|
|
3579
|
+
category: "identity",
|
|
3580
|
+
severity: "info",
|
|
3581
|
+
write: "bestEffort"
|
|
3582
|
+
},
|
|
3583
|
+
"user.email.verification_resent": {
|
|
3584
|
+
category: "identity",
|
|
3585
|
+
severity: "info",
|
|
3586
|
+
write: "bestEffort"
|
|
3587
|
+
},
|
|
3588
|
+
"user.email.change_resent": {
|
|
3589
|
+
category: "identity",
|
|
3590
|
+
severity: "info",
|
|
3591
|
+
write: "bestEffort"
|
|
3592
|
+
},
|
|
3593
|
+
"user.email.change_cancelled": {
|
|
3594
|
+
category: "identity",
|
|
3595
|
+
severity: "info",
|
|
3596
|
+
write: "bestEffort"
|
|
3597
|
+
},
|
|
3598
|
+
"user.sessions.revoked": {
|
|
3599
|
+
category: "identity",
|
|
3600
|
+
severity: "notice",
|
|
3601
|
+
write: "bestEffort"
|
|
3602
|
+
},
|
|
3603
|
+
"user.mfa.reset": {
|
|
3604
|
+
category: "identity",
|
|
3605
|
+
severity: "notice",
|
|
3606
|
+
write: "strict"
|
|
3607
|
+
},
|
|
3608
|
+
"user.mfa.denied": {
|
|
3609
|
+
category: "identity",
|
|
3610
|
+
severity: "critical",
|
|
3611
|
+
write: "bestEffort"
|
|
3612
|
+
},
|
|
3613
|
+
"audit.exported": {
|
|
3614
|
+
category: "support",
|
|
3615
|
+
severity: "info",
|
|
3616
|
+
write: "bestEffort"
|
|
3617
|
+
}
|
|
3618
|
+
};
|
|
3619
|
+
Object.keys(ADMIN_AUDIT_CATALOGUE).filter((action) => "escalatesAboveGrantThreshold" in ADMIN_AUDIT_CATALOGUE[action]);
|
|
3040
3620
|
z$1.object({
|
|
3041
3621
|
category: AdminAuditCategorySchema.optional(),
|
|
3042
3622
|
severity: AdminAuditSeveritySchema.optional(),
|
|
@@ -3045,13 +3625,14 @@ z$1.object({
|
|
|
3045
3625
|
actorUserId: z$1.string().min(1).optional(),
|
|
3046
3626
|
targetKind: AuditTargetSchema.shape.kind.optional(),
|
|
3047
3627
|
targetId: z$1.string().min(1).optional(),
|
|
3048
|
-
source:
|
|
3628
|
+
source: StoredAuditContextSourceSchema.optional(),
|
|
3049
3629
|
actorScope: AuditActorSchema.shape.scope.optional(),
|
|
3050
3630
|
from: z$1.iso.datetime().optional(),
|
|
3051
3631
|
to: z$1.iso.datetime().optional(),
|
|
3052
3632
|
requestId: z$1.string().min(1).optional(),
|
|
3053
3633
|
impersonationSessionId: z$1.string().min(1).optional()
|
|
3054
3634
|
});
|
|
3635
|
+
z$1.enum(["target", "actor"]);
|
|
3055
3636
|
let SupportedFabFileMimeTypes = /* @__PURE__ */ function(SupportedFabFileMimeTypes) {
|
|
3056
3637
|
SupportedFabFileMimeTypes["PDF"] = "application/pdf";
|
|
3057
3638
|
SupportedFabFileMimeTypes["DOCX"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
@@ -3097,6 +3678,26 @@ let SupportedFabFileMimeTypes = /* @__PURE__ */ function(SupportedFabFileMimeTyp
|
|
|
3097
3678
|
return SupportedFabFileMimeTypes;
|
|
3098
3679
|
}({});
|
|
3099
3680
|
new Set(Object.values(SupportedFabFileMimeTypes));
|
|
3681
|
+
/**
|
|
3682
|
+
* Known MIME types emitted by the generated-audio endpoints (TTS + sound
|
|
3683
|
+
* effects). Deliberately SEPARATE from SupportedFabFileMimeTypes: that set is
|
|
3684
|
+
* the ingest pipeline's chunk+vectorize allowlist, and audio is intentionally
|
|
3685
|
+
* NOT vectorizable and NOT attachable to a chat completion (no model accepts
|
|
3686
|
+
* audio input). Kept only for extension mapping / documentation; the runtime
|
|
3687
|
+
* guard below matches any `audio/*` so unusual provider subtypes are still
|
|
3688
|
+
* treated as audio (i.e. still excluded from every LLM path).
|
|
3689
|
+
*/
|
|
3690
|
+
let AudioMimeType = /* @__PURE__ */ function(AudioMimeType) {
|
|
3691
|
+
AudioMimeType["MP3"] = "audio/mpeg";
|
|
3692
|
+
AudioMimeType["WAV"] = "audio/wav";
|
|
3693
|
+
AudioMimeType["OPUS"] = "audio/opus";
|
|
3694
|
+
AudioMimeType["AAC"] = "audio/aac";
|
|
3695
|
+
AudioMimeType["FLAC"] = "audio/flac";
|
|
3696
|
+
AudioMimeType["PCM"] = "audio/pcm";
|
|
3697
|
+
AudioMimeType["OGG"] = "audio/ogg";
|
|
3698
|
+
AudioMimeType["WEBM"] = "audio/webm";
|
|
3699
|
+
return AudioMimeType;
|
|
3700
|
+
}({});
|
|
3100
3701
|
/** Reads back the classifier set by the tagged-error helpers above; `undefined` for untagged errors. */
|
|
3101
3702
|
function getQuestErrorCode(error) {
|
|
3102
3703
|
const code = error?.additionalInfo?.errorCode;
|
|
@@ -3233,6 +3834,49 @@ const PROMPT_META_MODEL_TYPES = [
|
|
|
3233
3834
|
"image",
|
|
3234
3835
|
"video"
|
|
3235
3836
|
];
|
|
3837
|
+
/**
|
|
3838
|
+
* Native Anthropic tool capabilities, by Claude family and version. Allow-lists rather than a
|
|
3839
|
+
* version comparison, so an older or not-yet-reviewed id (a preview, a new family) reads false.
|
|
3840
|
+
* Sources: the tool search tool and mid-conversation system messages pages of the Claude docs.
|
|
3841
|
+
*/
|
|
3842
|
+
const TOOL_SEARCH_VERSIONS = /* @__PURE__ */ new Set([
|
|
3843
|
+
"opus-4-5",
|
|
3844
|
+
"opus-4-6",
|
|
3845
|
+
"opus-4-7",
|
|
3846
|
+
"opus-4-8",
|
|
3847
|
+
"opus-5",
|
|
3848
|
+
"opus-5-5",
|
|
3849
|
+
"sonnet-4-5",
|
|
3850
|
+
"sonnet-4-6",
|
|
3851
|
+
"sonnet-5",
|
|
3852
|
+
"sonnet-5-5",
|
|
3853
|
+
"haiku-4-5",
|
|
3854
|
+
"haiku-5-5",
|
|
3855
|
+
"fable-5",
|
|
3856
|
+
"fable-5-1",
|
|
3857
|
+
"mythos-5",
|
|
3858
|
+
"mythos-5-1"
|
|
3859
|
+
]);
|
|
3860
|
+
function servedNatively(model, versions) {
|
|
3861
|
+
if (model.backend !== "anthropic" && model.backend !== "bedrock") return false;
|
|
3862
|
+
const version = claudeFamilyVersion(model.id);
|
|
3863
|
+
return version !== null && versions.has(version);
|
|
3864
|
+
}
|
|
3865
|
+
/** Whether the model accepts the tool search server tool and `defer_loading` on tool definitions. */
|
|
3866
|
+
function supportsToolSearch(model) {
|
|
3867
|
+
return servedNatively(model, TOOL_SEARCH_VERSIONS);
|
|
3868
|
+
}
|
|
3869
|
+
function servedByDirectAnthropic(model) {
|
|
3870
|
+
return model.adapterFamily ? model.adapterFamily === "anthropic-messages" : model.backend === "anthropic";
|
|
3871
|
+
}
|
|
3872
|
+
function servedByClaudeAdapter(model) {
|
|
3873
|
+
if (servedByDirectAnthropic(model)) return true;
|
|
3874
|
+
return model.adapterFamily ? model.adapterFamily === "bedrock-anthropic" : model.backend === "bedrock";
|
|
3875
|
+
}
|
|
3876
|
+
/** supportsToolSearch, narrowed to models whose `/api/ai/v1/completions` adapter actually forwards it. */
|
|
3877
|
+
function completionsSupportsToolSearch(model) {
|
|
3878
|
+
return servedByClaudeAdapter(model) && supportsToolSearch(model);
|
|
3879
|
+
}
|
|
3236
3880
|
const DEFAULT_PRICE_MARGIN = 1.2;
|
|
3237
3881
|
const DEFAULT_USD_TO_CREDITS_RATE = 6e-4;
|
|
3238
3882
|
/**
|
|
@@ -3848,7 +4492,7 @@ const CompletionCustomToolSchema = z$1.object({
|
|
|
3848
4492
|
required: z$1.array(z$1.string()).optional()
|
|
3849
4493
|
}).passthrough(),
|
|
3850
4494
|
strict: z$1.boolean().optional(),
|
|
3851
|
-
defer_loading: z$1.boolean().optional().describe("Keep this definition out of the model context until the tool search server tool (or a `tool_reference`) loads it. Honoured only on models
|
|
4495
|
+
defer_loading: z$1.boolean().optional().describe("Keep this definition out of the model context until the tool search server tool (or a `tool_reference`) loads it. Honoured only on Claude models (direct Anthropic or Bedrock) whose `supports_tool_search` is true; on every other model it is ignored and the tool is sent as usual. At least one tool, or a `serverTool` entry, must stay non-deferred (`errorCode: \"all_tools_deferred\"`)."),
|
|
3852
4496
|
cache_control: z$1.unknown().optional().describe("Accepted for validation only and not forwarded. Rejected on a deferred tool (`errorCode: \"deferred_tool_cache_control\"`).")
|
|
3853
4497
|
}),
|
|
3854
4498
|
_isMcpTool: z$1.boolean().optional()
|
|
@@ -3861,7 +4505,7 @@ const ToolSearchServerToolSchema = z$1.discriminatedUnion("type", [z$1.object({
|
|
|
3861
4505
|
type: z$1.literal("tool_search_tool_bm25_20251119"),
|
|
3862
4506
|
name: z$1.literal("tool_search_tool_bm25")
|
|
3863
4507
|
})]);
|
|
3864
|
-
const CompletionServerToolSchema = z$1.object({ serverTool: ToolSearchServerToolSchema.describe("A provider-run tool, sent to the provider as `{ type, name }`. Only the Anthropic tool search tools exist today, and only on models
|
|
4508
|
+
const CompletionServerToolSchema = z$1.object({ serverTool: ToolSearchServerToolSchema.describe("A provider-run tool, sent to the provider as `{ type, name }`. Only the Anthropic tool search tools exist today, and only on Claude models (direct Anthropic or Bedrock) whose `supports_tool_search` is true; any other model is refused with `errorCode: \"tool_search_unsupported\"` rather than run without it.") });
|
|
3865
4509
|
/** One `tools[]` entry: a caller-defined tool, or a provider-run server tool. */
|
|
3866
4510
|
const CompletionToolSchema = z$1.union([CompletionCustomToolSchema, CompletionServerToolSchema]);
|
|
3867
4511
|
/**
|
|
@@ -3930,7 +4574,7 @@ const CompletionMessageSchema = z$1.object({
|
|
|
3930
4574
|
*/
|
|
3931
4575
|
const CompletionRequestSchema = z$1.object({
|
|
3932
4576
|
model: z$1.string().max(256),
|
|
3933
|
-
messages: z$1.array(CompletionMessageSchema),
|
|
4577
|
+
messages: z$1.array(CompletionMessageSchema).min(1),
|
|
3934
4578
|
response_format: ResponseFormatSchema.optional(),
|
|
3935
4579
|
stream: z$1.boolean().optional(),
|
|
3936
4580
|
tools: z$1.array(CompletionToolSchema).optional(),
|
|
@@ -3991,6 +4635,7 @@ const CompletionContentEventSchema = z$1.object({
|
|
|
3991
4635
|
*/
|
|
3992
4636
|
const COMPLETION_SSE_ERROR_CODES = [
|
|
3993
4637
|
...QUEST_ERROR_CODES,
|
|
4638
|
+
"invalid_request",
|
|
3994
4639
|
"provider_error",
|
|
3995
4640
|
"provider_rejected",
|
|
3996
4641
|
"content_blocked"
|
|
@@ -4001,9 +4646,9 @@ const COMPLETION_SSE_ERROR_CODES = [
|
|
|
4001
4646
|
* real status instead; see completions.contract.ts.
|
|
4002
4647
|
*
|
|
4003
4648
|
* `code` is the machine-readable classifier: a billing code when settlement runs out mid-generation,
|
|
4004
|
-
* `
|
|
4005
|
-
*
|
|
4006
|
-
* `message`.
|
|
4649
|
+
* `invalid_request` when the provider rejects caller-controlled input, `provider_rejected` /
|
|
4650
|
+
* `provider_error` when the model provider fails, `content_blocked` when the model's safety classifier
|
|
4651
|
+
* declined the request. Optional; callers must never match on the prose `message`.
|
|
4007
4652
|
*
|
|
4008
4653
|
* The field is `code` rather than the conventions' `errorCode` because this frame shipped that way
|
|
4009
4654
|
* and is a published wire shape.
|
|
@@ -5128,9 +5773,9 @@ const RetrievalSummarySchema = z$1.object({
|
|
|
5128
5773
|
* `citables` and `retrieval` - this field needs no merge case in applyQuestStatusChanges: a
|
|
5129
5774
|
* later tool-arm write that omits it is preserved by the one-level spread.
|
|
5130
5775
|
*
|
|
5131
|
-
* `reasons` is
|
|
5132
|
-
*
|
|
5133
|
-
*
|
|
5776
|
+
* `reasons` is reader-facing prose with no document ids or internal limits, shown behind a
|
|
5777
|
+
* disclosure in the chat notice. The diagnostic version (ids, caps, counts) lives only in the
|
|
5778
|
+
* `warnings` entry. A supersession collapse alone does not produce this field at all.
|
|
5134
5779
|
*/
|
|
5135
5780
|
const RetrievalCoverageSchema = z$1.object({
|
|
5136
5781
|
/** Always true - see the presence contract above. */
|
|
@@ -5460,10 +6105,14 @@ const StorageLimitErrorSchema = ApiErrorSchema.extend(StorageLimitErrorInfoSchem
|
|
|
5460
6105
|
/** 503 when this deployment has no usable key for a provider the request needs (data-lake search, voice). */
|
|
5461
6106
|
const ProviderNotConfiguredErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.literal("provider_not_configured").optional() });
|
|
5462
6107
|
/**
|
|
5463
|
-
* 400 for a `model` the caller cannot use, or a refused tool search
|
|
5464
|
-
* other 400s (e.g. malformed JSON).
|
|
6108
|
+
* 400 for provider-rejected caller input, a `model` the caller cannot use, or a refused tool search
|
|
6109
|
+
* request; `errorCode` is absent on the other 400s (e.g. malformed JSON).
|
|
5465
6110
|
*/
|
|
5466
|
-
const CompletionsBadRequestErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.enum([
|
|
6111
|
+
const CompletionsBadRequestErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.enum([
|
|
6112
|
+
"invalid_request",
|
|
6113
|
+
UNKNOWN_MODEL_ERROR_CODE,
|
|
6114
|
+
...COMPLETION_TOOL_ERROR_CODES
|
|
6115
|
+
]).optional() });
|
|
5467
6116
|
/**
|
|
5468
6117
|
* Error envelope for the 403 apiKeyAuth (apps/client/server/middlewares/apiKeyAuth.ts)
|
|
5469
6118
|
* throws when an API key lacks a route's scopes. It names what the ROUTE requires,
|
|
@@ -5491,10 +6140,11 @@ const voiceOutputFormatSchema = z.enum([
|
|
|
5491
6140
|
"flac",
|
|
5492
6141
|
"pcm"
|
|
5493
6142
|
]);
|
|
5494
|
-
const
|
|
6143
|
+
const TTS_MAX_INPUT_CHARS = {
|
|
5495
6144
|
openai: 4096,
|
|
5496
6145
|
elevenlabs: 1e4
|
|
5497
|
-
}
|
|
6146
|
+
};
|
|
6147
|
+
const TTS_ABSOLUTE_MAX_INPUT_CHARS = Math.max(...Object.values(TTS_MAX_INPUT_CHARS));
|
|
5498
6148
|
const ttsLanguageCodeSchema = z.string().regex(/^[a-z]{2}$/, "languageCode must be a lowercase ISO 639-1 code, e.g. \"en\" or \"ja\"");
|
|
5499
6149
|
const ttsRequestSchema = z.object({
|
|
5500
6150
|
text: z.string().min(1).max(TTS_ABSOLUTE_MAX_INPUT_CHARS),
|
|
@@ -5586,12 +6236,30 @@ const ttsResponseTooLargeSchema = generatedAudioTooLargeSchema.extend({
|
|
|
5586
6236
|
fabFileId: z.string().optional(),
|
|
5587
6237
|
fileUrl: z.string().optional()
|
|
5588
6238
|
});
|
|
6239
|
+
/**
|
|
6240
|
+
* The model each vendor's service synthesizes and bills with when the caller
|
|
6241
|
+
* names none. Read by OpenAIVoiceService / ElevenLabsVoiceService in
|
|
6242
|
+
* @bike4mind/utils, so a pre-flight estimate prices the model the charge will use
|
|
6243
|
+
* when the requested vendor serves the call. The TTS route reserves the highest
|
|
6244
|
+
* estimate across its candidate vendors, using these defaults for alternates,
|
|
6245
|
+
* then settles the actual vendor's cost and refunds the difference.
|
|
6246
|
+
*/
|
|
6247
|
+
const TTS_DEFAULT_MODEL = {
|
|
6248
|
+
openai: "tts-1",
|
|
6249
|
+
elevenlabs: "eleven_multilingual_v2"
|
|
6250
|
+
};
|
|
5589
6251
|
const GENERATION_OUTPUT_AVAILABILITIES = [
|
|
5590
6252
|
"ready",
|
|
5591
6253
|
"pending_scan",
|
|
5592
6254
|
"unavailable"
|
|
5593
6255
|
];
|
|
5594
6256
|
const VIDEO_MODES = ["text_to_video", "image_to_video"];
|
|
6257
|
+
const VIDEO_INPUT_ROLES = [
|
|
6258
|
+
"first_frame",
|
|
6259
|
+
"last_frame",
|
|
6260
|
+
"reference",
|
|
6261
|
+
"style"
|
|
6262
|
+
];
|
|
5595
6263
|
const ASPECT_RATIOS = [
|
|
5596
6264
|
"16:9",
|
|
5597
6265
|
"9:16",
|
|
@@ -5615,6 +6283,13 @@ const VideoModelIdSchema = z$1.enum([
|
|
|
5615
6283
|
"grok-imagine-video-1.5",
|
|
5616
6284
|
"veo-3.1-fast-generate-preview"
|
|
5617
6285
|
]);
|
|
6286
|
+
const VideoInputSchema = z$1.union([z$1.strictObject({
|
|
6287
|
+
role: z$1.enum(VIDEO_INPUT_ROLES),
|
|
6288
|
+
fileId: z$1.string().min(1)
|
|
6289
|
+
}), z$1.strictObject({
|
|
6290
|
+
role: z$1.enum(VIDEO_INPUT_ROLES),
|
|
6291
|
+
generatedImageKey: z$1.string().min(1)
|
|
6292
|
+
})]);
|
|
5618
6293
|
z$1.object({
|
|
5619
6294
|
model: VideoModelIdSchema,
|
|
5620
6295
|
mode: z$1.enum(VIDEO_MODES),
|
|
@@ -5622,6 +6297,7 @@ z$1.object({
|
|
|
5622
6297
|
durationSeconds: z$1.number().positive(),
|
|
5623
6298
|
aspectRatio: z$1.enum(ASPECT_RATIOS),
|
|
5624
6299
|
resolution: z$1.enum(RESOLUTION_TIERS),
|
|
6300
|
+
inputs: z$1.array(VideoInputSchema).max(8).optional(),
|
|
5625
6301
|
inputImageFileId: z$1.string().min(1).optional(),
|
|
5626
6302
|
inputGeneratedImageKey: z$1.string().min(1).optional(),
|
|
5627
6303
|
audio: z$1.boolean().optional()
|
|
@@ -5633,6 +6309,7 @@ const VIDEO_VALIDATION_ERROR_CODES = [
|
|
|
5633
6309
|
"unsupported_mode",
|
|
5634
6310
|
"missing_input_image",
|
|
5635
6311
|
"unexpected_input_image",
|
|
6312
|
+
"unsupported_input_role",
|
|
5636
6313
|
"unsupported_audio_option"
|
|
5637
6314
|
];
|
|
5638
6315
|
const MAX_MUSIC_LYRICS_CHARS = 1e4;
|
|
@@ -5854,6 +6531,7 @@ z$2.object({
|
|
|
5854
6531
|
]),
|
|
5855
6532
|
slackSettings: redactedSubdocument([
|
|
5856
6533
|
"slackUserId",
|
|
6534
|
+
"slackTeamId",
|
|
5857
6535
|
"defaultNotebookId",
|
|
5858
6536
|
"autoCreateNotebook",
|
|
5859
6537
|
"notebookNamePrefix",
|
|
@@ -5874,7 +6552,10 @@ z$2.object({
|
|
|
5874
6552
|
"connectedAt"
|
|
5875
6553
|
])
|
|
5876
6554
|
}).extend({
|
|
5877
|
-
securityQuestions:
|
|
6555
|
+
securityQuestions: z$2.array(z$2.object({
|
|
6556
|
+
question: z$2.string(),
|
|
6557
|
+
answer: z$2.literal("")
|
|
6558
|
+
})).nullable().optional(),
|
|
5878
6559
|
userNotes: passthroughField
|
|
5879
6560
|
});
|
|
5880
6561
|
/**
|
|
@@ -5894,7 +6575,6 @@ const INTEGRATION_IDS = [
|
|
|
5894
6575
|
"mcp-cli",
|
|
5895
6576
|
"atlassian",
|
|
5896
6577
|
"notion",
|
|
5897
|
-
"google-calendar",
|
|
5898
6578
|
"slack",
|
|
5899
6579
|
"email",
|
|
5900
6580
|
"linkedin",
|
|
@@ -6067,20 +6747,6 @@ const INTEGRATION_CATALOG = {
|
|
|
6067
6747
|
mcpServer: "notion"
|
|
6068
6748
|
}]
|
|
6069
6749
|
},
|
|
6070
|
-
"google-calendar": {
|
|
6071
|
-
name: "Google Calendar",
|
|
6072
|
-
description: "Book briefing calls into open slots on a shared Bike4Mind calendar, not your own.",
|
|
6073
|
-
category: "productivity",
|
|
6074
|
-
logo: "google-calendar",
|
|
6075
|
-
stage: "beta",
|
|
6076
|
-
flag: "enableGoogleCalendar",
|
|
6077
|
-
capabilities: [{
|
|
6078
|
-
id: "calendar-booking",
|
|
6079
|
-
label: "Book briefings on a shared calendar",
|
|
6080
|
-
kind: "notifications",
|
|
6081
|
-
stage: "beta"
|
|
6082
|
-
}]
|
|
6083
|
-
},
|
|
6084
6750
|
slack: {
|
|
6085
6751
|
name: "Slack",
|
|
6086
6752
|
description: "Chat with Bike4Mind in Slack and send threads and files to a data lake.",
|
|
@@ -6655,7 +7321,7 @@ let OllamaEmbeddingModel = /* @__PURE__ */ function(OllamaEmbeddingModel) {
|
|
|
6655
7321
|
*
|
|
6656
7322
|
* Deliberately answers from the ENVIRONMENT only, and deliberately does NOT try to answer "can this
|
|
6657
7323
|
* deployment actually reach that model". It cannot: on a hosted stage an SST secret arrives as a
|
|
6658
|
-
* linked Resource, never as process.env (see
|
|
7324
|
+
* linked Resource, never as process.env (see packages/server-utils/src/modelDiscovery/adapters.ts), so an
|
|
6659
7325
|
* absent OPENAI_API_KEY here means "unknown", not "no key" - it is absent on production too. This
|
|
6660
7326
|
* function is also bundled into the browser via settingsMap, where every env read is undefined, so
|
|
6661
7327
|
* any answer it gives must be one that is safe as a stage-neutral constant.
|
|
@@ -6764,6 +7430,7 @@ z$1.object({
|
|
|
6764
7430
|
status: ReleaseNoteStatusSchema,
|
|
6765
7431
|
publishAt: z$1.coerce.date(),
|
|
6766
7432
|
editedAt: z$1.coerce.date().nullable(),
|
|
7433
|
+
video: ModalVideoShapeSchema.nullable().optional(),
|
|
6767
7434
|
schemaVersion: z$1.number().int()
|
|
6768
7435
|
});
|
|
6769
7436
|
const ReleaseNotesJobPrSchema = z$1.object({
|
|
@@ -6791,6 +7458,22 @@ const ReleaseNotesConfigSchema = z$1.object({
|
|
|
6791
7458
|
slackTeamId: z$1.string().optional(),
|
|
6792
7459
|
slackChannelId: z$1.string().optional()
|
|
6793
7460
|
});
|
|
7461
|
+
/** A release note video on the public wire: ModalVideo with snake_case keys. */
|
|
7462
|
+
const PublicReleaseNoteVideoSchema = z$1.object({
|
|
7463
|
+
landscape_url: z$1.string().nullable().optional(),
|
|
7464
|
+
landscape_poster_url: z$1.string().nullable().optional(),
|
|
7465
|
+
portrait_url: z$1.string().nullable().optional(),
|
|
7466
|
+
portrait_poster_url: z$1.string().nullable().optional()
|
|
7467
|
+
});
|
|
7468
|
+
const ReleaseNoteMediaParamsSchema = z$1.object({
|
|
7469
|
+
id: z$1.string().min(1),
|
|
7470
|
+
asset: z$1.enum(Object.keys({
|
|
7471
|
+
landscape: "landscapeUrl",
|
|
7472
|
+
"landscape-poster": "landscapePosterUrl",
|
|
7473
|
+
portrait: "portraitUrl",
|
|
7474
|
+
"portrait-poster": "portraitPosterUrl"
|
|
7475
|
+
}))
|
|
7476
|
+
});
|
|
6794
7477
|
/**
|
|
6795
7478
|
* A release note as GET /api/v1/whats-new serves it. An allowlist: provenance (sourcePrs, deployedSha),
|
|
6796
7479
|
* workflow state (status, editedAt) and storage fields never reach the public wire.
|
|
@@ -6805,7 +7488,8 @@ const PublicReleaseNoteSchema = z$1.object({
|
|
|
6805
7488
|
category: ReleaseNoteCategorySchema,
|
|
6806
7489
|
text: z$1.string(),
|
|
6807
7490
|
importance: z$1.number().int().min(1).max(3)
|
|
6808
|
-
}))
|
|
7491
|
+
})),
|
|
7492
|
+
video: PublicReleaseNoteVideoSchema.nullable().optional()
|
|
6809
7493
|
});
|
|
6810
7494
|
/**
|
|
6811
7495
|
* The measured per-space floors, rendered for an admin-facing description (e.g. "75 for
|
|
@@ -7100,6 +7784,7 @@ z$1.enum([
|
|
|
7100
7784
|
"serverStatus",
|
|
7101
7785
|
"defaultSeats",
|
|
7102
7786
|
"CSMandCTAFlag",
|
|
7787
|
+
"showDesktopAppPromo",
|
|
7103
7788
|
"SystemFiles",
|
|
7104
7789
|
"OpenWeatherKey",
|
|
7105
7790
|
"SerperKey",
|
|
@@ -7115,6 +7800,9 @@ z$1.enum([
|
|
|
7115
7800
|
"MaxActiveDungeons",
|
|
7116
7801
|
"DungeonSpawnIntervalHeartbeats",
|
|
7117
7802
|
"DungeonTTLMinutes",
|
|
7803
|
+
"EnableStudioCreateV2",
|
|
7804
|
+
"EnableStudioImage",
|
|
7805
|
+
"EnableStudioProductions",
|
|
7118
7806
|
"VectorThreshold",
|
|
7119
7807
|
"bflApiKey",
|
|
7120
7808
|
"EnableMCPServer",
|
|
@@ -7148,10 +7836,6 @@ z$1.enum([
|
|
|
7148
7836
|
"teamPlanCreditsPerSeat",
|
|
7149
7837
|
"lowCreditsThreshold",
|
|
7150
7838
|
"syntheticUserEmailDomains",
|
|
7151
|
-
"enableGoogleCalendar",
|
|
7152
|
-
"googleCalendarServiceAccountEmail",
|
|
7153
|
-
"googleCalendarServiceAccountSecret",
|
|
7154
|
-
"googleCalendarOrganizerEmail",
|
|
7155
7839
|
"EnableWeatherService",
|
|
7156
7840
|
"WeatherUnits",
|
|
7157
7841
|
"defaultEmbeddingModel",
|
|
@@ -7197,6 +7881,9 @@ z$1.enum([
|
|
|
7197
7881
|
"SlackFeedbackWebhookUrl",
|
|
7198
7882
|
"SlackNonProdFeedbackWebhookUrl",
|
|
7199
7883
|
"SlackEmailAuditWebhookUrl",
|
|
7884
|
+
"SlackSecurityAlertsWebhookUrl",
|
|
7885
|
+
"AdminAuditCriticalGrantCredits",
|
|
7886
|
+
"AdminAuditDailyGrantCredits",
|
|
7200
7887
|
"slackSigningSecret",
|
|
7201
7888
|
"slackBotToken",
|
|
7202
7889
|
"enforceMFA",
|
|
@@ -7441,15 +8128,17 @@ function makeNumberSetting(config) {
|
|
|
7441
8128
|
schema: z$1.preprocess((val) => isBlankSettingValue(val) ? void 0 : val, numberSchema.prefault(config.defaultValue ?? 0))
|
|
7442
8129
|
};
|
|
7443
8130
|
}
|
|
7444
|
-
function makeBooleanSetting(config) {
|
|
8131
|
+
function makeBooleanSetting({ acceptNumeric = false, ...config }) {
|
|
7445
8132
|
return {
|
|
7446
8133
|
...config,
|
|
7447
8134
|
type: "boolean",
|
|
7448
8135
|
schema: z$1.preprocess((val) => {
|
|
7449
8136
|
if (typeof val === "string") {
|
|
7450
|
-
if (val.toLowerCase() === "true") return true;
|
|
7451
|
-
if (val.toLowerCase() === "false") return false;
|
|
8137
|
+
if (val.toLowerCase() === "true" || acceptNumeric && val === "1") return true;
|
|
8138
|
+
if (val.toLowerCase() === "false" || acceptNumeric && val === "0") return false;
|
|
7452
8139
|
}
|
|
8140
|
+
if (acceptNumeric && val === 1) return true;
|
|
8141
|
+
if (acceptNumeric && val === 0) return false;
|
|
7453
8142
|
return val;
|
|
7454
8143
|
}, z$1.boolean()).prefault(config.defaultValue ?? false)
|
|
7455
8144
|
};
|
|
@@ -8391,30 +9080,6 @@ const API_SERVICE_GROUPS = {
|
|
|
8391
9080
|
}
|
|
8392
9081
|
]
|
|
8393
9082
|
},
|
|
8394
|
-
CALENDAR: {
|
|
8395
|
-
id: "calendarAPIService",
|
|
8396
|
-
name: "Google Calendar",
|
|
8397
|
-
description: "Google Calendar integration settings",
|
|
8398
|
-
icon: "CalendarMonth",
|
|
8399
|
-
settings: [
|
|
8400
|
-
{
|
|
8401
|
-
key: "enableGoogleCalendar",
|
|
8402
|
-
order: 1
|
|
8403
|
-
},
|
|
8404
|
-
{
|
|
8405
|
-
key: "googleCalendarServiceAccountEmail",
|
|
8406
|
-
order: 2
|
|
8407
|
-
},
|
|
8408
|
-
{
|
|
8409
|
-
key: "googleCalendarServiceAccountSecret",
|
|
8410
|
-
order: 3
|
|
8411
|
-
},
|
|
8412
|
-
{
|
|
8413
|
-
key: "googleCalendarOrganizerEmail",
|
|
8414
|
-
order: 4
|
|
8415
|
-
}
|
|
8416
|
-
]
|
|
8417
|
-
},
|
|
8418
9083
|
FEEDBACK: {
|
|
8419
9084
|
id: "feedbackService",
|
|
8420
9085
|
name: "Feedback System",
|
|
@@ -8736,6 +9401,18 @@ const API_SERVICE_GROUPS = {
|
|
|
8736
9401
|
{
|
|
8737
9402
|
key: "DungeonTTLMinutes",
|
|
8738
9403
|
order: 293
|
|
9404
|
+
},
|
|
9405
|
+
{
|
|
9406
|
+
key: "EnableStudioCreateV2",
|
|
9407
|
+
order: 300
|
|
9408
|
+
},
|
|
9409
|
+
{
|
|
9410
|
+
key: "EnableStudioImage",
|
|
9411
|
+
order: 301
|
|
9412
|
+
},
|
|
9413
|
+
{
|
|
9414
|
+
key: "EnableStudioProductions",
|
|
9415
|
+
order: 302
|
|
8739
9416
|
}
|
|
8740
9417
|
]
|
|
8741
9418
|
},
|
|
@@ -8774,10 +9451,6 @@ const API_SERVICE_GROUPS = {
|
|
|
8774
9451
|
{
|
|
8775
9452
|
key: "defaultTags",
|
|
8776
9453
|
order: 5
|
|
8777
|
-
},
|
|
8778
|
-
{
|
|
8779
|
-
key: "enforceCredits",
|
|
8780
|
-
order: 6
|
|
8781
9454
|
}
|
|
8782
9455
|
]
|
|
8783
9456
|
},
|
|
@@ -8788,36 +9461,16 @@ const API_SERVICE_GROUPS = {
|
|
|
8788
9461
|
icon: "Payments",
|
|
8789
9462
|
settings: [
|
|
8790
9463
|
{
|
|
8791
|
-
key: "
|
|
9464
|
+
key: "billOperationalUsage",
|
|
8792
9465
|
order: 1
|
|
8793
9466
|
},
|
|
8794
9467
|
{
|
|
8795
|
-
key: "
|
|
9468
|
+
key: "blockDisposableEmails",
|
|
8796
9469
|
order: 2
|
|
8797
9470
|
},
|
|
8798
9471
|
{
|
|
8799
|
-
key: "
|
|
9472
|
+
key: "syntheticUserEmailDomains",
|
|
8800
9473
|
order: 3
|
|
8801
|
-
},
|
|
8802
|
-
{
|
|
8803
|
-
key: "enableTeamPlan",
|
|
8804
|
-
order: 4
|
|
8805
|
-
},
|
|
8806
|
-
{
|
|
8807
|
-
key: "teamPlanMinSeats",
|
|
8808
|
-
order: 5
|
|
8809
|
-
},
|
|
8810
|
-
{
|
|
8811
|
-
key: "teamPlanMaxSeats",
|
|
8812
|
-
order: 6
|
|
8813
|
-
},
|
|
8814
|
-
{
|
|
8815
|
-
key: "teamPlanCreditsPerSeat",
|
|
8816
|
-
order: 7
|
|
8817
|
-
},
|
|
8818
|
-
{
|
|
8819
|
-
key: "lowCreditsThreshold",
|
|
8820
|
-
order: 8
|
|
8821
9474
|
}
|
|
8822
9475
|
]
|
|
8823
9476
|
},
|
|
@@ -8895,6 +9548,10 @@ const API_SERVICE_GROUPS = {
|
|
|
8895
9548
|
{
|
|
8896
9549
|
key: "RedditLink",
|
|
8897
9550
|
order: 8
|
|
9551
|
+
},
|
|
9552
|
+
{
|
|
9553
|
+
key: "showDesktopAppPromo",
|
|
9554
|
+
order: 9
|
|
8898
9555
|
}
|
|
8899
9556
|
]
|
|
8900
9557
|
},
|
|
@@ -9590,7 +10247,7 @@ const settingsMap = {
|
|
|
9590
10247
|
key: "SkillMarketUrlAllowlist",
|
|
9591
10248
|
name: "Skill Market URL Allowlist",
|
|
9592
10249
|
defaultValue: "",
|
|
9593
|
-
description: "Comma-separated host names a Skill Market skill may reference without a finding (subdomains included). Any other URL holds a
|
|
10250
|
+
description: "Comma-separated host names a Skill Market skill may reference without a finding (subdomains included). Any other URL holds a listing for review at every visibility.",
|
|
9594
10251
|
category: "AI Moderation"
|
|
9595
10252
|
}),
|
|
9596
10253
|
SkillMarketClassifierMinConfidence: makeNumberSetting({
|
|
@@ -9725,9 +10382,7 @@ const settingsMap = {
|
|
|
9725
10382
|
name: "Price Per Credit",
|
|
9726
10383
|
defaultValue: 50,
|
|
9727
10384
|
description: `The price in USD of one credit bought pay-as-you-go. Cannot be set below ${formatUsdPerCredit(MIN_PRICE_PER_CREDIT_USD)}, the per-credit sale price including markup.`,
|
|
9728
|
-
category: "Users"
|
|
9729
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
9730
|
-
order: 1
|
|
10385
|
+
category: "Users"
|
|
9731
10386
|
}),
|
|
9732
10387
|
apiRateLimitFreePerMin: makeNumberSetting({
|
|
9733
10388
|
key: "apiRateLimitFreePerMin",
|
|
@@ -9933,6 +10588,32 @@ const settingsMap = {
|
|
|
9933
10588
|
order: 8,
|
|
9934
10589
|
isSensitive: true
|
|
9935
10590
|
}),
|
|
10591
|
+
SlackSecurityAlertsWebhookUrl: makeStringSetting({
|
|
10592
|
+
key: "SlackSecurityAlertsWebhookUrl",
|
|
10593
|
+
name: "Security Alerts Channel Webhook URL",
|
|
10594
|
+
defaultValue: "",
|
|
10595
|
+
description: "Incoming-webhook URL for the security Slack channel that receives critical Admin Audit Log entries and credit-grant bursts. Leave empty to turn alerts off; the Audit Log page then shows a banner. It never falls back to the default webhook.",
|
|
10596
|
+
category: "SecOps",
|
|
10597
|
+
isSensitive: true
|
|
10598
|
+
}),
|
|
10599
|
+
AdminAuditCriticalGrantCredits: makeNumberSetting({
|
|
10600
|
+
key: "AdminAuditCriticalGrantCredits",
|
|
10601
|
+
name: "Critical Single Credit Grant",
|
|
10602
|
+
defaultValue: ADMIN_AUDIT_DEFAULT_CRITICAL_GRANT_CREDITS,
|
|
10603
|
+
min: 1,
|
|
10604
|
+
int: true,
|
|
10605
|
+
description: "An admin credit grant above this many credits is recorded as critical in the Admin Audit Log and alerts the security channel.",
|
|
10606
|
+
category: "SecOps"
|
|
10607
|
+
}),
|
|
10608
|
+
AdminAuditDailyGrantCredits: makeNumberSetting({
|
|
10609
|
+
key: "AdminAuditDailyGrantCredits",
|
|
10610
|
+
name: "Critical Daily Credit Grants per Admin",
|
|
10611
|
+
defaultValue: ADMIN_AUDIT_DEFAULT_DAILY_GRANT_CREDITS,
|
|
10612
|
+
min: 1,
|
|
10613
|
+
int: true,
|
|
10614
|
+
description: "A grant that takes one admin past this many credits granted in the last 24 hours is recorded as critical in the Admin Audit Log and alerts the security channel.",
|
|
10615
|
+
category: "SecOps"
|
|
10616
|
+
}),
|
|
9936
10617
|
liveFeedbackEmail: makeStringSetting({
|
|
9937
10618
|
key: "liveFeedbackEmail",
|
|
9938
10619
|
name: "Live Feedback Email",
|
|
@@ -10071,51 +10752,12 @@ const settingsMap = {
|
|
|
10071
10752
|
description: "The default number of seats for new organizations.",
|
|
10072
10753
|
category: "Users"
|
|
10073
10754
|
}),
|
|
10074
|
-
enableGoogleCalendar: makeBooleanSetting({
|
|
10075
|
-
key: "enableGoogleCalendar",
|
|
10076
|
-
name: "Enable Google Calendar Integration",
|
|
10077
|
-
defaultValue: false,
|
|
10078
|
-
description: "Whether to enable scheduling of briefing/advisory using google calendar",
|
|
10079
|
-
category: "Calendar",
|
|
10080
|
-
group: API_SERVICE_GROUPS.CALENDAR.id,
|
|
10081
|
-
order: 1,
|
|
10082
|
-
userReadable: true
|
|
10083
|
-
}),
|
|
10084
|
-
googleCalendarServiceAccountEmail: makeStringSetting({
|
|
10085
|
-
key: "googleCalendarServiceAccountEmail",
|
|
10086
|
-
name: "Service Account Email",
|
|
10087
|
-
defaultValue: "",
|
|
10088
|
-
description: "The service account email address that has access to google calendar API.",
|
|
10089
|
-
category: "Calendar",
|
|
10090
|
-
group: API_SERVICE_GROUPS.CALENDAR.id,
|
|
10091
|
-
order: 2
|
|
10092
|
-
}),
|
|
10093
|
-
googleCalendarServiceAccountSecret: makeStringSetting({
|
|
10094
|
-
key: "googleCalendarServiceAccountSecret",
|
|
10095
|
-
name: "Service Account Secret",
|
|
10096
|
-
defaultValue: "",
|
|
10097
|
-
description: "The base64 encoded service account secret that is associated with the service account email.",
|
|
10098
|
-
category: "Calendar",
|
|
10099
|
-
group: API_SERVICE_GROUPS.CALENDAR.id,
|
|
10100
|
-
order: 3,
|
|
10101
|
-
isSensitive: true
|
|
10102
|
-
}),
|
|
10103
|
-
googleCalendarOrganizerEmail: makeStringSetting({
|
|
10104
|
-
key: "googleCalendarOrganizerEmail",
|
|
10105
|
-
name: "Organizer Email",
|
|
10106
|
-
defaultValue: "",
|
|
10107
|
-
description: "The organizer email for creating events.",
|
|
10108
|
-
category: "Calendar",
|
|
10109
|
-
group: API_SERVICE_GROUPS.CALENDAR.id,
|
|
10110
|
-
order: 4
|
|
10111
|
-
}),
|
|
10112
10755
|
enforceCredits: makeBooleanSetting({
|
|
10113
10756
|
key: "enforceCredits",
|
|
10114
10757
|
userReadable: true,
|
|
10115
10758
|
name: "Enforce Credits",
|
|
10116
10759
|
defaultValue: process.env.B4M_SELF_HOST === "true" ? false : true,
|
|
10117
10760
|
description: "Whether to enforce credits for users",
|
|
10118
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10119
10761
|
category: "Users"
|
|
10120
10762
|
}),
|
|
10121
10763
|
billOperationalUsage: makeBooleanSetting({
|
|
@@ -10127,12 +10769,12 @@ const settingsMap = {
|
|
|
10127
10769
|
category: "Users"
|
|
10128
10770
|
}),
|
|
10129
10771
|
enableTeamPlan: makeBooleanSetting({
|
|
10772
|
+
acceptNumeric: true,
|
|
10130
10773
|
key: "enableTeamPlan",
|
|
10131
10774
|
userReadable: true,
|
|
10132
10775
|
name: "Enable Team Plan",
|
|
10133
10776
|
defaultValue: false,
|
|
10134
10777
|
description: "Whether to enable team plans",
|
|
10135
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10136
10778
|
category: "Users"
|
|
10137
10779
|
}),
|
|
10138
10780
|
allowOpenRegistration: makeBooleanSetting({
|
|
@@ -10140,7 +10782,6 @@ const settingsMap = {
|
|
|
10140
10782
|
name: "Allow Open Registration",
|
|
10141
10783
|
defaultValue: false,
|
|
10142
10784
|
description: "Master switch for self-serve signup. When OFF (default), a valid invite code is required to register. When ON, users may register without an invite code; the Default Free Credits grant is then applied after they verify their email (anti-spam — see Default Free Credits). Safe to enable: the pre-request credit reservation caps every free user at the credits they are granted.",
|
|
10143
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10144
10785
|
category: "Users"
|
|
10145
10786
|
}),
|
|
10146
10787
|
blockDisposableEmails: makeBooleanSetting({
|
|
@@ -10157,7 +10798,6 @@ const settingsMap = {
|
|
|
10157
10798
|
name: "Default Free Credits",
|
|
10158
10799
|
defaultValue: 0,
|
|
10159
10800
|
description: "Base credits granted after email verification to a user who registers WITHOUT an invite code, including eligible partner signups when Allow Open Registration is OFF. Partner-rule credits are added on top of this amount. An unverified account receives no credits. A free user cannot spend beyond their total granted balance.",
|
|
10160
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10161
10801
|
category: "Users"
|
|
10162
10802
|
}),
|
|
10163
10803
|
teamPlanMinSeats: makeNumberSetting({
|
|
@@ -10169,7 +10809,6 @@ const settingsMap = {
|
|
|
10169
10809
|
min: 1,
|
|
10170
10810
|
max: TEAM_PLAN_SEATS_HARD_LIMIT,
|
|
10171
10811
|
description: "Fewest seats a paid team subscription can be bought with. Enforced at checkout, on seat changes from Stripe and on admin conversion to paid. Admin grants may still go down to 1. If set above the maximum seats, the maximum wins.",
|
|
10172
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10173
10812
|
category: "Users"
|
|
10174
10813
|
}),
|
|
10175
10814
|
teamPlanMaxSeats: makeNumberSetting({
|
|
@@ -10181,7 +10820,6 @@ const settingsMap = {
|
|
|
10181
10820
|
min: 1,
|
|
10182
10821
|
max: TEAM_PLAN_SEATS_HARD_LIMIT,
|
|
10183
10822
|
description: "Most seats any team can hold (owner + members + pending invites). Enforced at checkout, on every seat change, on admin grants and on the partner-signup auto-raise. Lowering it below a team that is already larger does not remove anyone; that team can only be set down to this cap.",
|
|
10184
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10185
10823
|
category: "Users"
|
|
10186
10824
|
}),
|
|
10187
10825
|
teamPlanCreditsPerSeat: makeNumberSetting({
|
|
@@ -10192,7 +10830,6 @@ const settingsMap = {
|
|
|
10192
10830
|
min: 0,
|
|
10193
10831
|
max: 1e8,
|
|
10194
10832
|
description: "Credits added to a team pool per paid seat each billing cycle (and per seat-month on admin team grants). Applies to invoices issued after the change; credits already granted are not adjusted.",
|
|
10195
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10196
10833
|
category: "Users",
|
|
10197
10834
|
userReadable: true
|
|
10198
10835
|
}),
|
|
@@ -10205,7 +10842,6 @@ const settingsMap = {
|
|
|
10205
10842
|
min: 0,
|
|
10206
10843
|
max: 1e8,
|
|
10207
10844
|
description: "Below this many credits a user sees the low-credit warning state. Set to 0 to show warnings only once credits run out.",
|
|
10208
|
-
group: API_SERVICE_GROUPS.CREDITS.id,
|
|
10209
10845
|
category: "Users"
|
|
10210
10846
|
}),
|
|
10211
10847
|
syntheticUserEmailDomains: makeStringSetting({
|
|
@@ -10284,6 +10920,16 @@ const settingsMap = {
|
|
|
10284
10920
|
group: API_SERVICE_GROUPS.USER_MANAGEMENT.id,
|
|
10285
10921
|
order: 3
|
|
10286
10922
|
}),
|
|
10923
|
+
showDesktopAppPromo: makeBooleanSetting({
|
|
10924
|
+
key: "showDesktopAppPromo",
|
|
10925
|
+
name: "Promote the Desktop App",
|
|
10926
|
+
defaultValue: true,
|
|
10927
|
+
description: "Show signed-in users the \"Try the desktop app\" button and the profile-menu link to the desktop download page. Turn off for deployments that do not want to point users at the published desktop builds.",
|
|
10928
|
+
category: "Branding",
|
|
10929
|
+
group: API_SERVICE_GROUPS.BRANDING.id,
|
|
10930
|
+
order: 9,
|
|
10931
|
+
userReadable: true
|
|
10932
|
+
}),
|
|
10287
10933
|
SystemFiles: makeStringSetting({
|
|
10288
10934
|
key: "SystemFiles",
|
|
10289
10935
|
name: "System Prompt Files",
|
|
@@ -10376,6 +11022,35 @@ const settingsMap = {
|
|
|
10376
11022
|
order: 4,
|
|
10377
11023
|
isSensitive: true
|
|
10378
11024
|
}),
|
|
11025
|
+
EnableStudioCreateV2: makeBooleanSetting({
|
|
11026
|
+
key: "EnableStudioCreateV2",
|
|
11027
|
+
name: "Enable Studio Create v2",
|
|
11028
|
+
defaultValue: false,
|
|
11029
|
+
description: "Admin-only preview of the restructured Studio Create area. Non-admins never see it, whatever this is set to.",
|
|
11030
|
+
category: "Experimental",
|
|
11031
|
+
group: API_SERVICE_GROUPS.EXPERIMENTAL.id,
|
|
11032
|
+
order: 300
|
|
11033
|
+
}),
|
|
11034
|
+
EnableStudioImage: makeBooleanSetting({
|
|
11035
|
+
key: "EnableStudioImage",
|
|
11036
|
+
name: "Enable Image in Studio",
|
|
11037
|
+
defaultValue: false,
|
|
11038
|
+
description: "Admin-only preview of the Image tab in Studio. Non-admins never see it, whatever this is set to.",
|
|
11039
|
+
category: "Experimental",
|
|
11040
|
+
group: API_SERVICE_GROUPS.EXPERIMENTAL.id,
|
|
11041
|
+
order: 301,
|
|
11042
|
+
dependsOn: "EnableStudioCreateV2"
|
|
11043
|
+
}),
|
|
11044
|
+
EnableStudioProductions: makeBooleanSetting({
|
|
11045
|
+
key: "EnableStudioProductions",
|
|
11046
|
+
name: "Enable Studio Productions",
|
|
11047
|
+
defaultValue: false,
|
|
11048
|
+
description: "Admin-only preview of Studio Productions (assembling many assets into one piece). Non-admins never see it, whatever this is set to.",
|
|
11049
|
+
category: "Experimental",
|
|
11050
|
+
group: API_SERVICE_GROUPS.EXPERIMENTAL.id,
|
|
11051
|
+
order: 302,
|
|
11052
|
+
dependsOn: "EnableStudioCreateV2"
|
|
11053
|
+
}),
|
|
10379
11054
|
EnablePotionQuest: makeBooleanSetting({
|
|
10380
11055
|
key: "EnablePotionQuest",
|
|
10381
11056
|
name: "Enable PotionQuest Tools",
|
|
@@ -12044,6 +12719,41 @@ const musicRequestSchema = z.object({
|
|
|
12044
12719
|
format: z.string().optional(),
|
|
12045
12720
|
...generatedAudioRequestFields
|
|
12046
12721
|
});
|
|
12722
|
+
const turnRetryShape = {
|
|
12723
|
+
reason: z$1.enum(TURN_RETRY_REASONS),
|
|
12724
|
+
status: z$1.number().optional(),
|
|
12725
|
+
retryAfterMs: z$1.number().optional(),
|
|
12726
|
+
requestId: z$1.string().optional(),
|
|
12727
|
+
delayMs: z$1.number(),
|
|
12728
|
+
model: z$1.string()
|
|
12729
|
+
};
|
|
12730
|
+
const turnTimingShape = {
|
|
12731
|
+
queueMs: z$1.number(),
|
|
12732
|
+
contextBuildMs: z$1.number().optional(),
|
|
12733
|
+
semaphoreWaitMs: z$1.number(),
|
|
12734
|
+
totalMs: z$1.number().optional(),
|
|
12735
|
+
fallbackHops: z$1.number()
|
|
12736
|
+
};
|
|
12737
|
+
/** Wire shape of ITurnTiming for the live chat frame; hydrates `at` into a Date server-side. */
|
|
12738
|
+
const TurnTimingSchema = z$1.object({
|
|
12739
|
+
...turnTimingShape,
|
|
12740
|
+
retries: z$1.array(z$1.object({
|
|
12741
|
+
...turnRetryShape,
|
|
12742
|
+
at: z$1.coerce.date()
|
|
12743
|
+
}))
|
|
12744
|
+
});
|
|
12745
|
+
/**
|
|
12746
|
+
* The same record for the public quest poll. `at` is an ISO string on the wire (a Date only
|
|
12747
|
+
* before JSON serialization). Not z.coerce.date() here: like the other public response schemas
|
|
12748
|
+
* (schemas/chat.ts, schemas/session.ts), it would document the field as nullable in OpenAPI.
|
|
12749
|
+
*/
|
|
12750
|
+
const TurnTimingPollSchema = z$1.object({
|
|
12751
|
+
...turnTimingShape,
|
|
12752
|
+
retries: z$1.array(z$1.object({
|
|
12753
|
+
...turnRetryShape,
|
|
12754
|
+
at: z$1.union([z$1.string().datetime(), z$1.date()])
|
|
12755
|
+
}))
|
|
12756
|
+
});
|
|
12047
12757
|
/**
|
|
12048
12758
|
* Canonical agent execution status tuple. Shared between the database model
|
|
12049
12759
|
* (`AgentExecutionModel`), the client store (`useAgentExecutionStore`), and
|
|
@@ -12228,7 +12938,7 @@ const CliCompletionRequestAction = z$1.object({
|
|
|
12228
12938
|
]),
|
|
12229
12939
|
content: z$1.union([z$1.string(), z$1.array(z$1.unknown())]),
|
|
12230
12940
|
cache: z$1.boolean().optional()
|
|
12231
|
-
})),
|
|
12941
|
+
})).min(1),
|
|
12232
12942
|
options: z$1.object({
|
|
12233
12943
|
temperature: z$1.number().optional(),
|
|
12234
12944
|
maxTokens: z$1.number().optional(),
|
|
@@ -12563,6 +13273,7 @@ const StreamedChatCompletionAction = z$1.object({
|
|
|
12563
13273
|
endTime: z$1.number().optional()
|
|
12564
13274
|
}).optional(),
|
|
12565
13275
|
fallbackInfo: FallbackInfoSchema.nullish(),
|
|
13276
|
+
turnTiming: TurnTimingSchema.optional(),
|
|
12566
13277
|
pendingAction: z$1.object({
|
|
12567
13278
|
tool: z$1.string(),
|
|
12568
13279
|
params: z$1.record(z$1.string(), z$1.unknown()),
|
|
@@ -13529,7 +14240,7 @@ const ConfidenceGateAction = z$1.object({
|
|
|
13529
14240
|
iteration: z$1.number(),
|
|
13530
14241
|
/** 0..1, the agent's reported confidence for the paused iteration. */
|
|
13531
14242
|
confidence: z$1.number(),
|
|
13532
|
-
/** Pre-formatted server copy, e.g. "
|
|
14243
|
+
/** Pre-formatted server copy, e.g. "2 iterations in a row below the 60% confidence threshold (latest 42%)". */
|
|
13533
14244
|
reason: z$1.string()
|
|
13534
14245
|
});
|
|
13535
14246
|
const ChildExecutionSnapshotSchema = z$1.lazy(() => z$1.object({
|
|
@@ -14438,7 +15149,9 @@ z.object({
|
|
|
14438
15149
|
/** Set to true if the file should be publicly accessible */
|
|
14439
15150
|
public: z.boolean().optional(),
|
|
14440
15151
|
/** The prefix to use for the file path */
|
|
14441
|
-
prefix: z.string().optional()
|
|
15152
|
+
prefix: z.string().optional(),
|
|
15153
|
+
/** Admin What's New media: the server stores it under its modal prefix and admits mp4 */
|
|
15154
|
+
purpose: z.literal("modal-media").optional()
|
|
14442
15155
|
});
|
|
14443
15156
|
/**
|
|
14444
15157
|
* Constants for BFL safety tolerance settings.
|
|
@@ -15040,6 +15753,7 @@ const QuestPollResponseSchema = ChatQuestPollResultSchema.extend({
|
|
|
15040
15753
|
promptMeta: z$1.record(z$1.string(), z$1.unknown()).optional(),
|
|
15041
15754
|
attachmentNotices: z$1.array(z$1.string()).optional(),
|
|
15042
15755
|
attachmentDelivery: z$1.record(z$1.string(), z$1.unknown()).optional(),
|
|
15756
|
+
turnTiming: TurnTimingPollSchema.optional(),
|
|
15043
15757
|
executionTracking: z$1.unknown().optional()
|
|
15044
15758
|
});
|
|
15045
15759
|
/**
|
|
@@ -15270,6 +15984,7 @@ z$2.object(passthroughShape({
|
|
|
15270
15984
|
pendingAction: true,
|
|
15271
15985
|
attachmentNotices: true,
|
|
15272
15986
|
attachmentDelivery: true,
|
|
15987
|
+
turnTiming: true,
|
|
15273
15988
|
navigationIntents: true,
|
|
15274
15989
|
suggestedChoices: true,
|
|
15275
15990
|
attachmentList: true,
|
|
@@ -15317,6 +16032,123 @@ z$2.object({
|
|
|
15317
16032
|
envVariables: envVariableResponseSchema,
|
|
15318
16033
|
metadata: metadataResponseSchema.nullish()
|
|
15319
16034
|
});
|
|
16035
|
+
const SAML_CONFIG_RESPONSE_FIELDS = {
|
|
16036
|
+
entryPoint: true,
|
|
16037
|
+
issuer: true,
|
|
16038
|
+
cert: true,
|
|
16039
|
+
callbackUrl: true,
|
|
16040
|
+
identifierFormat: true,
|
|
16041
|
+
acceptedClockSkewMs: true,
|
|
16042
|
+
attributeConsumingServiceIndex: true,
|
|
16043
|
+
disableRequestedAuthnContext: true,
|
|
16044
|
+
attributeMappings: true
|
|
16045
|
+
};
|
|
16046
|
+
const OKTA_CONFIG_RESPONSE_FIELDS = {
|
|
16047
|
+
audience: true,
|
|
16048
|
+
clientId: true,
|
|
16049
|
+
authServerId: true,
|
|
16050
|
+
useOrgAuthServer: true
|
|
16051
|
+
};
|
|
16052
|
+
/** An identity provider as the admin routes return it: configuration only, no credential values. */
|
|
16053
|
+
const identityProviderResponseSchema = z$2.object({
|
|
16054
|
+
...passthroughShape({
|
|
16055
|
+
id: true,
|
|
16056
|
+
name: true,
|
|
16057
|
+
emailDomain: true,
|
|
16058
|
+
type: true,
|
|
16059
|
+
isActive: true,
|
|
16060
|
+
samlConfig: true,
|
|
16061
|
+
oktaConfig: true,
|
|
16062
|
+
createdAt: true,
|
|
16063
|
+
updatedAt: true,
|
|
16064
|
+
createdBy: true
|
|
16065
|
+
}),
|
|
16066
|
+
samlConfig: z$2.object(passthroughShape(SAML_CONFIG_RESPONSE_FIELDS)).nullish(),
|
|
16067
|
+
oktaConfig: z$2.object(passthroughShape(OKTA_CONFIG_RESPONSE_FIELDS)).nullish()
|
|
16068
|
+
});
|
|
16069
|
+
/**
|
|
16070
|
+
* Which credentials an identity provider has stored: flags, never values. The single source for
|
|
16071
|
+
* the repository that computes them and the admin UI that reads them.
|
|
16072
|
+
*/
|
|
16073
|
+
const identityProviderSecretPresenceSchema = z$2.object({
|
|
16074
|
+
decryptionPvk: z$2.boolean(),
|
|
16075
|
+
privateCert: z$2.boolean(),
|
|
16076
|
+
clientSecret: z$2.boolean()
|
|
16077
|
+
});
|
|
16078
|
+
/** The admin list row: the provider plus which credentials are stored. */
|
|
16079
|
+
const identityProviderListItemResponseSchema = identityProviderResponseSchema.extend({ hasSecrets: identityProviderSecretPresenceSchema });
|
|
16080
|
+
z$2.array(identityProviderListItemResponseSchema);
|
|
16081
|
+
/** An API key as the admin routes return it: everything but the secret material. */
|
|
16082
|
+
const userApiKeyResponseSchema = z$2.object(passthroughShape({
|
|
16083
|
+
id: true,
|
|
16084
|
+
userId: true,
|
|
16085
|
+
name: true,
|
|
16086
|
+
keyPrefix: true,
|
|
16087
|
+
scopes: true,
|
|
16088
|
+
status: true,
|
|
16089
|
+
expiresAt: true,
|
|
16090
|
+
lastUsedAt: true,
|
|
16091
|
+
revokedAt: true,
|
|
16092
|
+
revokedBy: true,
|
|
16093
|
+
revokedReason: true,
|
|
16094
|
+
callbackSigningSecretCreatedAt: true,
|
|
16095
|
+
rateLimit: true,
|
|
16096
|
+
usage: true,
|
|
16097
|
+
metadata: true,
|
|
16098
|
+
productId: true,
|
|
16099
|
+
productName: true,
|
|
16100
|
+
billingOwnerType: true,
|
|
16101
|
+
organizationId: true,
|
|
16102
|
+
agentId: true,
|
|
16103
|
+
allowedOrigins: true,
|
|
16104
|
+
identifiedClientIds: true,
|
|
16105
|
+
preauthorizedLakeIds: true,
|
|
16106
|
+
branding: true,
|
|
16107
|
+
spendCap: true,
|
|
16108
|
+
ownerHasWhitelabel: true,
|
|
16109
|
+
createdAt: true,
|
|
16110
|
+
updatedAt: true
|
|
16111
|
+
}));
|
|
16112
|
+
/**
|
|
16113
|
+
* A key's live minute/day rate-limit counters. The single source for the server's
|
|
16114
|
+
* `RateLimitUsage` and the admin client's response type, so a new field cannot be stripped here
|
|
16115
|
+
* while the producer and the UI both expect it.
|
|
16116
|
+
*/
|
|
16117
|
+
const apiKeyRateLimitUsageSchema = z$2.object({
|
|
16118
|
+
minute: z$2.number(),
|
|
16119
|
+
day: z$2.number(),
|
|
16120
|
+
/** Epoch seconds when the current minute window ends; undefined when no window is open (count 0). */
|
|
16121
|
+
minuteResetAt: z$2.number().optional(),
|
|
16122
|
+
/** Epoch seconds when the current day window ends; undefined when no window is open (count 0). */
|
|
16123
|
+
dayResetAt: z$2.number().optional()
|
|
16124
|
+
});
|
|
16125
|
+
z$2.object({
|
|
16126
|
+
apiKeys: z$2.array(userApiKeyResponseSchema),
|
|
16127
|
+
liveUsage: z$2.record(z$2.string(), apiKeyRateLimitUsageSchema)
|
|
16128
|
+
});
|
|
16129
|
+
const emailVerificationUserResponseSchema = z$2.object(passthroughShape({
|
|
16130
|
+
_id: true,
|
|
16131
|
+
username: true,
|
|
16132
|
+
email: true,
|
|
16133
|
+
name: true,
|
|
16134
|
+
emailVerified: true,
|
|
16135
|
+
emailVerifiedAt: true,
|
|
16136
|
+
emailVerificationSentAt: true,
|
|
16137
|
+
emailVerificationExpires: true,
|
|
16138
|
+
pendingEmail: true,
|
|
16139
|
+
pendingEmailSentAt: true,
|
|
16140
|
+
pendingEmailExpires: true,
|
|
16141
|
+
createdAt: true
|
|
16142
|
+
}));
|
|
16143
|
+
z$2.object({
|
|
16144
|
+
users: z$2.array(emailVerificationUserResponseSchema),
|
|
16145
|
+
pagination: z$2.object({
|
|
16146
|
+
page: z$2.number(),
|
|
16147
|
+
limit: z$2.number(),
|
|
16148
|
+
totalPages: z$2.number(),
|
|
16149
|
+
totalCount: z$2.number()
|
|
16150
|
+
})
|
|
16151
|
+
});
|
|
15320
16152
|
const questMasterPlanResponseSchema = z$2.object(passthroughShape({
|
|
15321
16153
|
id: true,
|
|
15322
16154
|
createdAt: true,
|
|
@@ -15767,6 +16599,14 @@ const EmbeddingsErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.enum([
|
|
|
15767
16599
|
"provider_not_configured",
|
|
15768
16600
|
"provider_rejected"
|
|
15769
16601
|
]).optional() });
|
|
16602
|
+
const MAX_REFINE_TEXT_CHARS = 1e4;
|
|
16603
|
+
const MAX_REFINE_CONTEXT_CHARS = 1e4;
|
|
16604
|
+
const TextRefinementRequestSchema = z$1.object({
|
|
16605
|
+
text: z$1.string().min(1).max(MAX_REFINE_TEXT_CHARS),
|
|
16606
|
+
context: z$1.string().max(MAX_REFINE_CONTEXT_CHARS).optional()
|
|
16607
|
+
});
|
|
16608
|
+
const TextRefinementResponseSchema = z$1.object({ text: z$1.string() });
|
|
16609
|
+
const TextRefinementErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.enum(["provider_not_configured", "provider_rejected"]).optional() });
|
|
15770
16610
|
/**
|
|
15771
16611
|
* Every tool name in `b4mLLMTools`. Exhaustive by annotation - do not widen the type.
|
|
15772
16612
|
*/
|
|
@@ -15868,6 +16708,19 @@ const InternalTeamMemberSchema = z$1.object({
|
|
|
15868
16708
|
isActive: z$1.boolean().optional()
|
|
15869
16709
|
});
|
|
15870
16710
|
z$1.array(InternalTeamMemberSchema);
|
|
16711
|
+
/** An internal team member as the admin routes return it. */
|
|
16712
|
+
const internalTeamMemberResponseSchema = z$1.object(passthroughShape({
|
|
16713
|
+
id: true,
|
|
16714
|
+
name: true,
|
|
16715
|
+
phone: true,
|
|
16716
|
+
email: true,
|
|
16717
|
+
role: true,
|
|
16718
|
+
department: true,
|
|
16719
|
+
isActive: true,
|
|
16720
|
+
createdAt: true,
|
|
16721
|
+
updatedAt: true
|
|
16722
|
+
}));
|
|
16723
|
+
z$1.array(internalTeamMemberResponseSchema);
|
|
15871
16724
|
/**
|
|
15872
16725
|
* Lattice Zod Schemas
|
|
15873
16726
|
*
|
|
@@ -16654,6 +17507,32 @@ const UpdateProjectRequestSchema = z$1.object({
|
|
|
16654
17507
|
description: z$1.string().min(1).optional()
|
|
16655
17508
|
}).strict();
|
|
16656
17509
|
/**
|
|
17510
|
+
* Wire schemas for the Skill Market's Claude Code plugin feed
|
|
17511
|
+
* (api-contract/contracts/skillMarket.contract.ts). The 200 body is a Claude Code
|
|
17512
|
+
* `marketplace.json`, so its field names follow Claude Code, not this API's snake_case.
|
|
17513
|
+
*/
|
|
17514
|
+
const ClaudeMarketplaceQuerySchema = z$1.object({ orgId: z$1.string().min(1) });
|
|
17515
|
+
const ClaudePluginZipParamSchema = z$1.object({ id: z$1.string().min(1) });
|
|
17516
|
+
const ClaudePluginZipQuerySchema = z$1.object({ version: z$1.coerce.number().int().positive().optional() });
|
|
17517
|
+
const ClaudeMarketplacePluginSchema = z$1.object({
|
|
17518
|
+
name: z$1.string(),
|
|
17519
|
+
description: z$1.string(),
|
|
17520
|
+
/** The listing's approved version number; Claude Code offers an update when it changes. */
|
|
17521
|
+
version: z$1.string(),
|
|
17522
|
+
source: z$1.object({
|
|
17523
|
+
source: z$1.literal("archive"),
|
|
17524
|
+
url: z$1.string(),
|
|
17525
|
+
sha256: z$1.string()
|
|
17526
|
+
})
|
|
17527
|
+
});
|
|
17528
|
+
const ClaudeMarketplaceSchema = z$1.object({
|
|
17529
|
+
name: z$1.string(),
|
|
17530
|
+
owner: z$1.object({ name: z$1.string() }),
|
|
17531
|
+
/** Claude Code uninstalls installed plugins this feed stops listing, at the next session start. */
|
|
17532
|
+
forceRemoveDeletedPlugins: z$1.boolean(),
|
|
17533
|
+
plugins: z$1.array(ClaudeMarketplacePluginSchema)
|
|
17534
|
+
});
|
|
17535
|
+
/**
|
|
16657
17536
|
* The public projection of `ModelInfo` served by `GET /api/v1/models`.
|
|
16658
17537
|
*
|
|
16659
17538
|
* Deliberately narrower than `ModelInfo`: every field here is one an integrator can pin, so
|
|
@@ -16733,8 +17612,8 @@ const ListModelsResponseSchema = paginatedResponseSchema(z$1.object({
|
|
|
16733
17612
|
reasons_within_output_budget: z$1.boolean().describe("Whether reasoning tokens are spent inside `max_output_tokens` on every turn. When true, a small `max_tokens` can be used up by reasoning alone and return an empty reply, so leave room above the answer you expect."),
|
|
16734
17613
|
reasoning_efforts: z$1.array(CompletionReasoningEffortSchema).describe("The `reasoningEffort` levels this model acts on, lowest first; empty when it ignores the option. `none` is listed only where it turns reasoning off. Each level is mapped to the nearest one the provider offers. A listed level can still be dropped on one request: some OpenAI models drop it on tool turns, and Claude models with a fixed thinking budget drop it when `max_tokens` leaves no room for the budget plus the answer."),
|
|
16735
17614
|
supports_tools: z$1.boolean(),
|
|
16736
|
-
supports_tool_search: z$1.boolean().describe("Whether the model accepts the tool search server tool and `defer_loading: true` on tool definitions, so a large tool catalog is searched on demand instead of loaded into context up front. Describes the model: `/api/ai/v1/completions` honours it
|
|
16737
|
-
supports_tool_changes: z$1.boolean().describe("Whether a system-role message can carry `tool_addition` and `tool_removal` blocks, which add or remove a declared tool mid-conversation. Describes the model
|
|
17615
|
+
supports_tool_search: z$1.boolean().describe("Whether the model accepts the tool search server tool and `defer_loading: true` on tool definitions, so a large tool catalog is searched on demand instead of loaded into context up front. Describes the model: `/api/ai/v1/completions` honours it for every model with this flag set, whether its `backend` is `anthropic` or `bedrock`."),
|
|
17616
|
+
supports_tool_changes: z$1.boolean().describe("Whether a system-role message can carry `tool_addition` and `tool_removal` blocks, which add or remove a declared tool mid-conversation. Describes the model: `/api/ai/v1/completions` honours it only for models whose `backend` is `anthropic`; a `bedrock` model with this flag set is refused there with `errorCode: \"tool_changes_unsupported\"`."),
|
|
16738
17617
|
supports_vision: z$1.boolean(),
|
|
16739
17618
|
deprecation_date: z$1.string().nullable().describe("`YYYY-MM-DD`; null when no retirement is scheduled."),
|
|
16740
17619
|
replaced_by: z$1.string().nullable().describe("The id of the recommended successor, when there is one."),
|
|
@@ -16860,7 +17739,7 @@ const GenerateImageIvokeParamsSchema = OpenAIImageGenerationInput.extend({
|
|
|
16860
17739
|
referenceImageFabFileIds: z$1.array(z$1.string()).max(15).optional(),
|
|
16861
17740
|
tools: z$1.array(z$1.union([b4mLLMTools, z$1.string()])).optional(),
|
|
16862
17741
|
safety_tolerance: BFLSafetyToleranceSchema,
|
|
16863
|
-
prompt_upsampling: z$1.boolean().
|
|
17742
|
+
prompt_upsampling: z$1.boolean().prefault(false).describe("Let the provider rewrite and expand the prompt before rendering. Applies to Black Forest Labs (FLUX) models only; other models ignore it. Defaults to false."),
|
|
16864
17743
|
seed: z$1.number().nullable().optional(),
|
|
16865
17744
|
output_format: ImageOutputFormatSchema.nullable().optional(),
|
|
16866
17745
|
/** Resolved by the API route's prompt resolver. Defaults to 'fresh' for first-turn or sessions with no prior image. */
|
|
@@ -16990,7 +17869,13 @@ z$1.object({
|
|
|
16990
17869
|
"tool"
|
|
16991
17870
|
]),
|
|
16992
17871
|
content: z$1.union([z$1.string(), z$1.array(z$1.any())]),
|
|
16993
|
-
fabFileIds: z$1.array(z$1.string()).optional()
|
|
17872
|
+
fabFileIds: z$1.array(z$1.string()).optional(),
|
|
17873
|
+
/**
|
|
17874
|
+
* Send this message in the current user turn instead of the system prompt, keeping the
|
|
17875
|
+
* system prefix byte-stable for prompt caching. Only for content that changes every turn
|
|
17876
|
+
* (a view description, a per-send brief); a caller's actual system prompt must not set it.
|
|
17877
|
+
*/
|
|
17878
|
+
perTurn: z$1.boolean().optional()
|
|
16994
17879
|
})).optional(),
|
|
16995
17880
|
/** Dashboard related params */
|
|
16996
17881
|
dashboardParams: DashboardParamsSchema.optional(),
|
|
@@ -17179,11 +18064,15 @@ const VideoGenerationErrorResponseSchema = ApiErrorSchema.extend({ errorCode: z$
|
|
|
17179
18064
|
const CreateVideoGenerationBodySchema = z$1.strictObject({
|
|
17180
18065
|
model: z$1.string().min(1).describe("A model id from GET /api/v1/video-models."),
|
|
17181
18066
|
prompt: z$1.string().min(1).max(4e3),
|
|
17182
|
-
mode: z$1.enum(VIDEO_MODES).optional().describe("Defaults to image_to_video when input_image_file_id is set, else text_to_video."),
|
|
18067
|
+
mode: z$1.enum(VIDEO_MODES).optional().describe("Defaults to image_to_video when a first_frame input (or input_image_file_id) is set, else text_to_video."),
|
|
17183
18068
|
duration_seconds: z$1.number().positive().optional().describe("Defaults to the model's default duration."),
|
|
17184
18069
|
aspect_ratio: z$1.enum(ASPECT_RATIOS).optional(),
|
|
17185
18070
|
resolution: z$1.enum(RESOLUTION_TIERS).optional(),
|
|
17186
|
-
|
|
18071
|
+
inputs: z$1.array(z$1.strictObject({
|
|
18072
|
+
file_id: z$1.string().min(1),
|
|
18073
|
+
role: z$1.enum(VIDEO_INPUT_ROLES)
|
|
18074
|
+
})).max(8).optional().describe("Image files you own, each tagged with what it is for. image_to_video needs a first_frame. The roles a model accepts, and how many of each, are its input_roles in GET /api/v1/video-models."),
|
|
18075
|
+
input_image_file_id: z$1.string().min(1).optional().describe("Deprecated: send inputs with role first_frame instead. Cannot be combined with inputs."),
|
|
17187
18076
|
audio: z$1.boolean().optional(),
|
|
17188
18077
|
organization_id: BillingOrganizationIdSchema
|
|
17189
18078
|
});
|
|
@@ -17225,6 +18114,10 @@ const VideoModelSchema = z$1.object({
|
|
|
17225
18114
|
display_name: z$1.string(),
|
|
17226
18115
|
provider: z$1.string(),
|
|
17227
18116
|
modes: z$1.array(z$1.enum(VIDEO_MODES)),
|
|
18117
|
+
input_roles: z$1.array(z$1.object({
|
|
18118
|
+
role: z$1.string(),
|
|
18119
|
+
max: z$1.number().int().positive()
|
|
18120
|
+
})).optional().describe(`The inputs[] roles this model accepts and the most of each one request may carry. Roles today: ${VIDEO_INPUT_ROLES.join(", ")}; ignore any you do not know.`),
|
|
17228
18121
|
duration: z$1.union([z$1.object({
|
|
17229
18122
|
kind: z$1.literal("range"),
|
|
17230
18123
|
min: z$1.number(),
|
|
@@ -17802,7 +18695,7 @@ defineEndpoint({
|
|
|
17802
18695
|
path: "/api/ai/v1/completions",
|
|
17803
18696
|
operationId: "createCompletion",
|
|
17804
18697
|
summary: "Create a chat completion",
|
|
17805
|
-
description: "OpenAI-compatible completion. A successful request is ALWAYS answered with an SSE stream (`text/event-stream`), regardless of the `stream` flag: a `meta` event, then `content`/`tool_use` events carrying `usage`/`credits`, terminated by `data: [DONE]`. The terminal event carries `stopReason`; treat `max_tokens` as a TRUNCATED reply rather than a complete one, and note that omitting `max_tokens` on the request lets the server size the output ceiling for the model (recommended for reasoning models, which spend thinking tokens inside that ceiling). A message `content` may be a string or an array of parts; image parts are accepted in OpenAI Chat (`image_url`), OpenAI Responses (`input_image`) or Anthropic (`image` with a `source`) form and are translated to whatever the target model speaks. Authenticate with an API key (`b4m_live_`) or a JWT.\n\nTOOL SEARCH. On a model whose `GET /api/v1/models` row has `supports_tool_search: true`
|
|
18698
|
+
description: "OpenAI-compatible completion. A successful request is ALWAYS answered with an SSE stream (`text/event-stream`), regardless of the `stream` flag: a `meta` event, then `content`/`tool_use` events carrying `usage`/`credits`, terminated by `data: [DONE]`. The terminal event carries `stopReason`; treat `max_tokens` as a TRUNCATED reply rather than a complete one, and note that omitting `max_tokens` on the request lets the server size the output ceiling for the model (recommended for reasoning models, which spend thinking tokens inside that ceiling). A message `content` may be a string or an array of parts; image parts are accepted in OpenAI Chat (`image_url`), OpenAI Responses (`input_image`) or Anthropic (`image` with a `source`) form and are translated to whatever the target model speaks. Authenticate with an API key (`b4m_live_`) or a JWT.\n\nTOOL SEARCH. On a model whose `GET /api/v1/models` row has `supports_tool_search: true` (`backend` `\"anthropic\"` or `\"bedrock\"`), a `tools` entry may set `toolSchema.defer_loading: true`, and a `{ \"serverTool\": { \"type\": \"tool_search_tool_regex_20251119\", \"name\": \"tool_search_tool_regex\" } }` (or the `bm25` pair) entry adds Anthropic's tool search, so deferred definitions load only when the model searches for them. The stream then carries `provider_block` events (`{ type, provider: \"anthropic\", block }`) for the server-run search; echo each block back verbatim, in order, in the assistant `messages` content of the next request, and never answer one with a `tool_result`. When the server-run search loop hits its iteration limit the stream ends with `stopReason: \"pause_turn\"`; continue by re-sending the conversation with that assistant turn's provider blocks echoed. A client-side search may return `{ \"type\": \"tool_reference\", \"tool_name\": \"...\" }` blocks inside a `tool_result`'s content. On every other model `defer_loading` is ignored (every tool is sent as usual) and a server tool, a `tool_reference` or an echoed tool search block is refused with a `400` rather than run without it.\n\nERRORS. Everything checked before the model provider is called fails with a JSON error body and a real HTTP status, before any stream opens: an empty `messages` array, a conversation with no non-empty user or assistant message (system-only, or only blank content), a malformed request, or an unknown `model` `400` (`errorCode: \"unknown_model\"` for an unknown model), a bad credential `401`, a key without a required scope `403` (with `required_scopes`), a body over 25 MB `413`, any other body that fails schema validation `422`, insufficient credits `422` with `errorCode: \"insufficient_credits\"` (personal or org balance, or an org per-member credit cap), a rate limit `429` with `Retry-After`, and a catalogued model whose provider is not configured on this deployment, or a model that could only come from a self-hosted model server (Ollama, local image) that is currently unreachable, `503` with `errorCode: \"provider_not_configured\"` (retryable). A provider rejection of caller input that happens before the stream opens is also a JSON `400`, with `errorCode: \"invalid_request\"` (do not retry it unchanged). Once the stream has opened the status stays `200` and a failure arrives as one terminal in-band `error` event. Branch on that event's `code`, never on `message`, which is prose and may change: `insufficient_credits` (buy credits) when credits run out mid-generation, `invalid_request` when the provider rejects caller input (do not retry it unchanged), `provider_rejected` when the model provider refused our credentials, `content_blocked` when the model declined the request (do not retry it unchanged), and `provider_error` for any other provider failure. Treat `code` as optional.",
|
|
17806
18699
|
tags: ["AI"],
|
|
17807
18700
|
auth: "apiKeyOrJwt",
|
|
17808
18701
|
scopes: ["ai:chat", "ai:generate"],
|
|
@@ -17836,7 +18729,7 @@ defineEndpoint({
|
|
|
17836
18729
|
}
|
|
17837
18730
|
},
|
|
17838
18731
|
400: {
|
|
17839
|
-
description: "Malformed or otherwise invalid request (no `errorCode`), or a `model` the caller cannot use (`errorCode: \"unknown_model\"`): not in the catalog or not available to the caller. List valid ids with `GET /api/v1/models`. Tool search requests are refused with: `tool_search_unsupported` (a server tool, `tool_reference` or echoed tool search block on a model that cannot serve tool search here), `all_tools_deferred` (every tool deferred and no server tool), `deferred_tool_cache_control` (`cache_control` on a deferred tool), `unknown_tool_reference` (a `tool_reference` naming a tool not in `tools`, or carrying no string `tool_name`). Mid-conversation tool changes are refused with: `tool_changes_unsupported` (a `tool_addition` / `tool_removal` system message on a model that cannot serve it here), `invalid_tool_change` (a malformed block, or one placed where the provider does not accept it), and `unknown_tool_reference` (a changed tool not in `tools`).",
|
|
18732
|
+
description: "Malformed or otherwise invalid request (no `errorCode`), provider-rejected caller input (`errorCode: \"invalid_request\"`), or a `model` the caller cannot use (`errorCode: \"unknown_model\"`): not in the catalog or not available to the caller. List valid ids with `GET /api/v1/models`. Tool search requests are refused with: `tool_search_unsupported` (a server tool, `tool_reference` or echoed tool search block on a model that cannot serve tool search here), `all_tools_deferred` (every tool deferred and no server tool), `deferred_tool_cache_control` (`cache_control` on a deferred tool), `unknown_tool_reference` (a `tool_reference` naming a tool not in `tools`, or carrying no string `tool_name`). Mid-conversation tool changes are refused with: `tool_changes_unsupported` (a `tool_addition` / `tool_removal` system message on a model that cannot serve it here), `invalid_tool_change` (a malformed block, or one placed where the provider does not accept it), and `unknown_tool_reference` (a changed tool not in `tools`).",
|
|
17840
18733
|
schema: CompletionsBadRequestErrorSchema
|
|
17841
18734
|
},
|
|
17842
18735
|
413: {
|
|
@@ -17857,7 +18750,7 @@ defineEndpoint({
|
|
|
17857
18750
|
schema: ApiErrorSchema
|
|
17858
18751
|
},
|
|
17859
18752
|
503: {
|
|
17860
|
-
description: "Temporarily unavailable: the model's provider is not configured on this deployment (`errorCode: \"provider_not_configured\"`), or the database is unreachable (no `errorCode`). Retry later.",
|
|
18753
|
+
description: "Temporarily unavailable: the model's provider is not configured on this deployment, or the self-hosted model server that lists it (Ollama, local image) is unreachable (`errorCode: \"provider_not_configured\"`), or the database is unreachable (no `errorCode`). Retry later.",
|
|
17861
18754
|
schema: ProviderNotConfiguredErrorSchema
|
|
17862
18755
|
}
|
|
17863
18756
|
},
|
|
@@ -18660,7 +19553,7 @@ defineEndpoint({
|
|
|
18660
19553
|
streaming: false
|
|
18661
19554
|
}
|
|
18662
19555
|
});
|
|
18663
|
-
const EXAMPLE_REQUEST$
|
|
19556
|
+
const EXAMPLE_REQUEST$2 = {
|
|
18664
19557
|
model: "text-embedding-3-small",
|
|
18665
19558
|
input: ["The quick brown fox", "jumps over the lazy dog"],
|
|
18666
19559
|
dimensions: 1024
|
|
@@ -18675,7 +19568,7 @@ defineEndpoint({
|
|
|
18675
19568
|
auth: "apiKeyOrJwt",
|
|
18676
19569
|
scopes: ["ai:generate"],
|
|
18677
19570
|
request: EmbeddingsRequestSchema,
|
|
18678
|
-
requestExample: EXAMPLE_REQUEST$
|
|
19571
|
+
requestExample: EXAMPLE_REQUEST$2,
|
|
18679
19572
|
responses: {
|
|
18680
19573
|
200: {
|
|
18681
19574
|
description: "One embedding per input, in input order.",
|
|
@@ -18732,6 +19625,55 @@ defineEndpoint({
|
|
|
18732
19625
|
}
|
|
18733
19626
|
},
|
|
18734
19627
|
emitsRateLimitHeaders: true,
|
|
19628
|
+
codeSample: {
|
|
19629
|
+
authToken: "b4m_live_<key>",
|
|
19630
|
+
streaming: false,
|
|
19631
|
+
body: EXAMPLE_REQUEST$2
|
|
19632
|
+
}
|
|
19633
|
+
});
|
|
19634
|
+
const EXAMPLE_REQUEST$1 = {
|
|
19635
|
+
text: "a dog on a beach",
|
|
19636
|
+
context: "prompt for an image generator"
|
|
19637
|
+
};
|
|
19638
|
+
defineEndpoint({
|
|
19639
|
+
method: "post",
|
|
19640
|
+
path: "/api/v1/text-refinements",
|
|
19641
|
+
operationId: "createTextRefinement",
|
|
19642
|
+
summary: "Refine text",
|
|
19643
|
+
description: `Rewrites \`text\` to be more concise, clear and detailed while keeping its intent. \`context\` is optional background that steers the rewrite. \`text\` is at most ${MAX_REFINE_TEXT_CHARS} characters and \`context\` at most ${MAX_REFINE_CONTEXT_CHARS}. Output is capped at about 800 tokens, and identical requests are served from a cache for about five minutes. Not billed in credits. Authenticate with an API key (\`b4m_live_\`) carrying \`ai:generate\`, or a JWT.`,
|
|
19644
|
+
tags: ["AI"],
|
|
19645
|
+
auth: "apiKeyOrJwt",
|
|
19646
|
+
scopes: ["ai:generate"],
|
|
19647
|
+
request: TextRefinementRequestSchema,
|
|
19648
|
+
requestExample: EXAMPLE_REQUEST$1,
|
|
19649
|
+
responses: {
|
|
19650
|
+
200: {
|
|
19651
|
+
description: "The refined text.",
|
|
19652
|
+
schema: TextRefinementResponseSchema,
|
|
19653
|
+
example: { text: "A golden retriever running along a sunlit beach at sunset, waves breaking behind it." }
|
|
19654
|
+
},
|
|
19655
|
+
401: {
|
|
19656
|
+
description: "Missing/invalid credentials, or the text-refinement provider refused the configured key (`errorCode: \"provider_rejected\"`).",
|
|
19657
|
+
schema: TextRefinementErrorSchema
|
|
19658
|
+
},
|
|
19659
|
+
429: {
|
|
19660
|
+
description: "Per-key rate limit exceeded.",
|
|
19661
|
+
schema: ApiErrorSchema
|
|
19662
|
+
},
|
|
19663
|
+
500: {
|
|
19664
|
+
description: "Unexpected server error (for example the refinement cache is unavailable).",
|
|
19665
|
+
schema: ApiErrorSchema
|
|
19666
|
+
},
|
|
19667
|
+
502: {
|
|
19668
|
+
description: "The model call failed for a reason other than a rejected credential, or returned no refined text.",
|
|
19669
|
+
schema: ApiErrorSchema
|
|
19670
|
+
},
|
|
19671
|
+
503: {
|
|
19672
|
+
description: "This deployment has no operations model configured (`errorCode: \"provider_not_configured\"`).",
|
|
19673
|
+
schema: TextRefinementErrorSchema
|
|
19674
|
+
}
|
|
19675
|
+
},
|
|
19676
|
+
emitsRateLimitHeaders: true,
|
|
18735
19677
|
codeSample: {
|
|
18736
19678
|
authToken: "b4m_live_<key>",
|
|
18737
19679
|
streaming: false,
|
|
@@ -19385,7 +20327,7 @@ defineEndpoint({
|
|
|
19385
20327
|
path: "/api/v1/transcriptions",
|
|
19386
20328
|
operationId: "createTranscription",
|
|
19387
20329
|
summary: "Transcribe audio",
|
|
19388
|
-
description: "Transcribes an upload minted by `POST /api/v1/transcriptions/uploads` and returns the text. Call it within 5 minutes of minting the upload. Credits are charged by file size. The uploaded audio is deleted when the call returns, whether it succeeds or fails, so each upload can be transcribed once.\n\n**Limit:** this call is synchronous.
|
|
20330
|
+
description: "Transcribes an upload minted by `POST /api/v1/transcriptions/uploads` and returns the text. Call it within 5 minutes of minting the upload. Credits are charged by file size. The uploaded audio is deleted when the call returns, whether it succeeds or fails, so each upload can be transcribed once.\n\n**Limit:** this call is synchronous. Provider work stops being awaited after 45 seconds from request arrival, leaving time to return reserved credits and delete the upload before the hosted server stops at 60 seconds. A slow recording returns a gateway timeout (`504`) instead of text. AWS batch jobs cannot be cancelled remotely and may finish later; their output expires automatically. Do not retry with the same `file_key`: mint a new upload and send shorter audio. If cleanup fails, the upload may not be deleted right away (it expires on its own).",
|
|
19389
20331
|
tags: ["Transcriptions"],
|
|
19390
20332
|
auth: "apiKeyOrJwt",
|
|
19391
20333
|
scopes: ["ai:generate"],
|
|
@@ -19415,6 +20357,10 @@ defineEndpoint({
|
|
|
19415
20357
|
503: {
|
|
19416
20358
|
description: "This deployment has no speech model, or no credential for its provider, configured (`errorCode: \"provider_not_configured\"`).",
|
|
19417
20359
|
schema: ProviderNotConfiguredErrorSchema
|
|
20360
|
+
},
|
|
20361
|
+
504: {
|
|
20362
|
+
description: "The transcription exceeded the request deadline; reserved credits are returned.",
|
|
20363
|
+
schema: ApiErrorSchema
|
|
19418
20364
|
}
|
|
19419
20365
|
},
|
|
19420
20366
|
codeSample: {
|
|
@@ -19521,6 +20467,35 @@ defineEndpoint({
|
|
|
19521
20467
|
}
|
|
19522
20468
|
}
|
|
19523
20469
|
});
|
|
20470
|
+
defineEndpoint({
|
|
20471
|
+
method: "get",
|
|
20472
|
+
path: "/api/v1/whats-new/media/{id}/{asset}",
|
|
20473
|
+
operationId: "getWhatsNewMedia",
|
|
20474
|
+
summary: "Get release note media",
|
|
20475
|
+
description: "Redirects to one file of a published release note video: `landscape` and `portrait` are the 16:9 and 9:16 MP4s, the `-poster` assets their still images. The `video` URLs that listWhatsNew returns for uploaded files point here, so a browser can use them as `src` and `poster` as they are. Public: no credentials are needed, and the note must be one listWhatsNew would show. The redirect is cacheable for up to 10 minutes and its target is signed for 1 hour, longer than that, so follow it rather than storing the target. Rate limited per client IP.",
|
|
20476
|
+
tags: ["Release notes"],
|
|
20477
|
+
auth: "public",
|
|
20478
|
+
pathParams: ReleaseNoteMediaParamsSchema,
|
|
20479
|
+
responses: {
|
|
20480
|
+
303: {
|
|
20481
|
+
description: "`Location` is a time-limited signed GET for the file.",
|
|
20482
|
+
noBody: true,
|
|
20483
|
+
headers: { Location: "Signed URL of the file." }
|
|
20484
|
+
},
|
|
20485
|
+
404: {
|
|
20486
|
+
description: "No published note has this id, or the note has no such file, or the file is not an upload this deployment serves (a linked URL is listed as is, not through this route).",
|
|
20487
|
+
schema: ApiErrorSchema
|
|
20488
|
+
},
|
|
20489
|
+
429: {
|
|
20490
|
+
description: "Per-IP rate limit exceeded.",
|
|
20491
|
+
schema: ApiErrorSchema
|
|
20492
|
+
},
|
|
20493
|
+
500: {
|
|
20494
|
+
description: "Unexpected server error.",
|
|
20495
|
+
schema: ApiErrorSchema
|
|
20496
|
+
}
|
|
20497
|
+
}
|
|
20498
|
+
});
|
|
19524
20499
|
/**
|
|
19525
20500
|
* The read/write/query API-key scope sets the data-lake doors accept (OR semantics), shared by the
|
|
19526
20501
|
* SPA routes (`apps/client/server/dataLakes/dataLakeScopes.ts` re-exports these) and the public
|
|
@@ -19873,11 +20848,11 @@ defineEndpoint({
|
|
|
19873
20848
|
schema: ApiErrorSchema
|
|
19874
20849
|
},
|
|
19875
20850
|
404: {
|
|
19876
|
-
description: "`input_image_file_id` does not name an image you own (`errorCode: input_image_not_found`). A nonexistent `organization_id` is `404` only for an admin caller; for anyone else it is `403`.",
|
|
20851
|
+
description: "An `inputs` file (or `input_image_file_id`) does not name an image you own (`errorCode: input_image_not_found`). A nonexistent `organization_id` is `404` only for an admin caller; for anyone else it is `403`.",
|
|
19877
20852
|
schema: VideoGenerationErrorResponseSchema
|
|
19878
20853
|
},
|
|
19879
20854
|
422: {
|
|
19880
|
-
description: "The request cannot run: a body or capability violation (`errorCode` names it, e.g. `unsupported_duration`), an unknown or unavailable model (`model_unavailable`), a model your administrator disabled (`model_disabled`), too few credits (`insufficient_credits`), or an Idempotency-Key problem (`invalid_idempotency_key`, `idempotency_key_reused`).",
|
|
20855
|
+
description: "The request cannot run: a body or capability violation (`errorCode` names it, e.g. `unsupported_duration`, or `unsupported_input_role` for an input role the model does not take), an unknown or unavailable model (`model_unavailable`), a model your administrator disabled (`model_disabled`), too few credits (`insufficient_credits`), or an Idempotency-Key problem (`invalid_idempotency_key`, `idempotency_key_reused`).",
|
|
19881
20856
|
schema: VideoGenerationErrorResponseSchema
|
|
19882
20857
|
},
|
|
19883
20858
|
429: rateLimited$1
|
|
@@ -20720,6 +21695,94 @@ defineEndpoint({
|
|
|
20720
21695
|
streaming: false
|
|
20721
21696
|
}
|
|
20722
21697
|
});
|
|
21698
|
+
const AUTH_NOTE = "Authenticate with an API key (`b4m_live_`) carrying `skills:read`, sent as `Authorization: Bearer`. Claude Code sends that header when it is set as the marketplace source's `headers` in its settings, and forwards it to the same-origin plugin archives.";
|
|
21699
|
+
defineEndpoint({
|
|
21700
|
+
method: "get",
|
|
21701
|
+
path: "/api/v1/skills/market/claude-marketplace.json",
|
|
21702
|
+
operationId: "getClaudeMarketplace",
|
|
21703
|
+
summary: "Get an organization's Claude Code plugin marketplace",
|
|
21704
|
+
description: `Returns a Claude Code \`marketplace.json\` listing the organization's approved Organization-visibility Skill Market listings, one \`archive\` plugin each, pinned by \`sha256\`. Public and unlisted listings are not included. Responses are never cacheable. ${AUTH_NOTE}`,
|
|
21705
|
+
tags: ["Skills"],
|
|
21706
|
+
auth: "apiKeyOrJwt",
|
|
21707
|
+
scopes: ["skills:read"],
|
|
21708
|
+
queryParams: ClaudeMarketplaceQuerySchema,
|
|
21709
|
+
emitsRateLimitHeaders: true,
|
|
21710
|
+
responses: {
|
|
21711
|
+
200: {
|
|
21712
|
+
description: "The marketplace.",
|
|
21713
|
+
schema: ClaudeMarketplaceSchema,
|
|
21714
|
+
example: {
|
|
21715
|
+
name: `b4m-org-${EXAMPLE_RESOURCE_ID}`,
|
|
21716
|
+
owner: { name: "Acme" },
|
|
21717
|
+
forceRemoveDeletedPlugins: true,
|
|
21718
|
+
plugins: [{
|
|
21719
|
+
name: "review-pr",
|
|
21720
|
+
description: "Review a pull request against the team checklist.",
|
|
21721
|
+
version: "3",
|
|
21722
|
+
source: {
|
|
21723
|
+
source: "archive",
|
|
21724
|
+
url: `https://app.bike4mind.com/api/v1/skills/market/${EXAMPLE_RESOURCE_ID}/claude-plugin.zip?version=3`,
|
|
21725
|
+
sha256: "a3f1c0de9b8e7d6c5b4a39281706f5e4d3c2b1a09f8e7d6c5b4a392817060f5e"
|
|
21726
|
+
}
|
|
21727
|
+
}]
|
|
21728
|
+
}
|
|
21729
|
+
},
|
|
21730
|
+
403: {
|
|
21731
|
+
description: "The API key lacks `skills:read`, or the caller is not a member of the organization.",
|
|
21732
|
+
schema: ScopeForbiddenErrorSchema
|
|
21733
|
+
},
|
|
21734
|
+
429: {
|
|
21735
|
+
description: "Per-user rate limit exceeded.",
|
|
21736
|
+
schema: ApiErrorSchema
|
|
21737
|
+
}
|
|
21738
|
+
},
|
|
21739
|
+
codeSample: {
|
|
21740
|
+
authToken: "b4m_live_<key>",
|
|
21741
|
+
streaming: false,
|
|
21742
|
+
body: {}
|
|
21743
|
+
}
|
|
21744
|
+
});
|
|
21745
|
+
defineEndpoint({
|
|
21746
|
+
method: "get",
|
|
21747
|
+
path: "/api/v1/skills/market/{id}/claude-plugin.zip",
|
|
21748
|
+
operationId: "getClaudePluginZip",
|
|
21749
|
+
summary: "Download a Skill Market listing as a Claude Code plugin",
|
|
21750
|
+
description: `A zip holding an approved version as \`skills/<name>/SKILL.md\`. The optional \`version\` query pins the listing version advertised by the feed, so later approvals do not change its bytes or \`sha256\`. Without it, returns the current approved version. ${AUTH_NOTE}`,
|
|
21751
|
+
tags: ["Skills"],
|
|
21752
|
+
auth: "apiKeyOrJwt",
|
|
21753
|
+
scopes: ["skills:read"],
|
|
21754
|
+
pathParams: ClaudePluginZipParamSchema,
|
|
21755
|
+
queryParams: ClaudePluginZipQuerySchema,
|
|
21756
|
+
validationErrorStatus: 400,
|
|
21757
|
+
emitsRateLimitHeaders: true,
|
|
21758
|
+
responses: {
|
|
21759
|
+
200: {
|
|
21760
|
+
description: "The plugin archive.",
|
|
21761
|
+
contentType: "application/zip"
|
|
21762
|
+
},
|
|
21763
|
+
400: {
|
|
21764
|
+
description: "Invalid version query.",
|
|
21765
|
+
schema: ApiErrorSchema
|
|
21766
|
+
},
|
|
21767
|
+
403: {
|
|
21768
|
+
description: "The API key lacks `skills:read`.",
|
|
21769
|
+
schema: ScopeForbiddenErrorSchema
|
|
21770
|
+
},
|
|
21771
|
+
404: {
|
|
21772
|
+
description: "No Organization listing with that id is visible to the caller. A listing in an org you are not in, a public or unlisted listing, and a malformed id are all reported as 404.",
|
|
21773
|
+
schema: ApiErrorSchema
|
|
21774
|
+
},
|
|
21775
|
+
429: {
|
|
21776
|
+
description: "Per-user rate limit exceeded.",
|
|
21777
|
+
schema: ApiErrorSchema
|
|
21778
|
+
}
|
|
21779
|
+
},
|
|
21780
|
+
codeSample: {
|
|
21781
|
+
authToken: "b4m_live_<key>",
|
|
21782
|
+
streaming: false,
|
|
21783
|
+
body: {}
|
|
21784
|
+
}
|
|
21785
|
+
});
|
|
20723
21786
|
/**
|
|
20724
21787
|
* The fence language the model writes to place an inline map of search-result places in a reply.
|
|
20725
21788
|
*
|
|
@@ -23448,7 +24511,7 @@ async function sleep(ms, abortSignal) {
|
|
|
23448
24511
|
* Respects Retry-After headers when present (e.g., for 429 rate limiting).
|
|
23449
24512
|
*/
|
|
23450
24513
|
async function withRetry(fn, options = {}) {
|
|
23451
|
-
const { maxRetries = 3, initialDelayMs = 100, maxDelayMs = 5e3, jitterFactor = .1, isRetryable = isRetryableError, logger, abortSignal } = options;
|
|
24514
|
+
const { maxRetries = 3, initialDelayMs = 100, maxDelayMs = 5e3, jitterFactor = .1, isRetryable = isRetryableError, logger, abortSignal, onRetry } = options;
|
|
23452
24515
|
let attempts = 0;
|
|
23453
24516
|
let totalDelayMs = 0;
|
|
23454
24517
|
while (true) try {
|
|
@@ -23479,6 +24542,15 @@ async function withRetry(fn, options = {}) {
|
|
|
23479
24542
|
attempt: attempts,
|
|
23480
24543
|
delayMs
|
|
23481
24544
|
});
|
|
24545
|
+
try {
|
|
24546
|
+
onRetry?.({
|
|
24547
|
+
attempt: attempts,
|
|
24548
|
+
delayMs,
|
|
24549
|
+
error: err
|
|
24550
|
+
});
|
|
24551
|
+
} catch (callbackError) {
|
|
24552
|
+
logger?.warn("onRetry callback threw; continuing the retry", { error: String(callbackError) });
|
|
24553
|
+
}
|
|
23482
24554
|
try {
|
|
23483
24555
|
await sleep(delayMs, abortSignal);
|
|
23484
24556
|
} catch {
|
|
@@ -26015,4 +27087,4 @@ var ConfigStore = class {
|
|
|
26015
27087
|
}
|
|
26016
27088
|
};
|
|
26017
27089
|
//#endregion
|
|
26018
|
-
export {
|
|
27090
|
+
export { ModelBackend as $, selfClaimedActorKindSchema as $t, ARTIFACT_REMOVED_PLACEHOLDER as A, isUserInitiatedAbort as At, ChatModels as B, supportedVoiceGenerationVendor as Bt, htmlErrorTitle as C, getMcpProviderMetadata as Ct, AGENT_QUEST_MANIFEST as D, isEarlyStop as Dt, AGENT_QUEST_ID as E, hasDeliverablePinnedArtifact as Et, BRIEFCASE_CATALOG_QUERIES as F, secureParameters as Ft, DecisionTextPartSchema as G, visibleReplyText as Gt, CreateArtifactRequestSchema as H, ttsBase64ResponseSchema as Ht, BedrockEmbeddingModel as I, signImageUrl as It, ImageModels as J, DELEGATION_PAYLOAD_SCHEMA_NAME as Jt, DecisionsRequestSchema as K, withRetry as Kt, BriefcasePromptIdSchema as L, splitEquals as Lt, ApiKeyType as M, obfuscateApiKey as Mt, ArtifactTypeSchema as N, questReplyText as Nt, AGENT_QUEST_MCP_URI as O, isPlaceholderImageSigningSecret as Ot, AudioMimeType as P, replacePromptVariables as Pt, McpServerName as Q, delegationPayloadSchema as Qt, CONTEXT_WINDOW_SAFETY_BUFFER_TOKENS as R, stripDeliveredArtifactBlocks as Rt, isValidSessionId as S, generatedAudioResponseSchema as St, escapeArtifactBodyJson as T, googleMapsSearchUrl as Tt, DEFAULT_TTS_PROVIDER as U, ttsRequestSchema as Ut, CompletionReasoningEffortSchema as V, tokenEstimateMultiplier as Vt, DEGENERATE_FINISH_REASON as W, ttsResponseTooLargeSchema as Wt, LOCATION_MAP_LANGUAGE as X, actorKindMarker as Xt, ImagePromptResolutionSchema as Y, actorColorIndex as Yt, MODEL_INFO_FIELD_GROUP_OF as Z, actorKindSchema as Zt, LOCAL_DEV_URL as _, buildPromptContext as _t, commandTextOf as a, REVIEW_GATE_STATUS_VALUES as at, logger as b, escapeThinkMarkers as bt, toolCategory as c, SUBQUEST_STATUS_VALUES as ct, getCreditsUrl as d, TTS_MAX_INPUT_CHARS as dt, frontmatterHasSourceStamp as en, NotFoundError as et, getEnvironmentName as f, UnprocessableEntityError as ft, DeviceFlowClient as g, assertAuthOriginMatchesApiKey as gt, AuthenticatedApiClient as h, WORK_ITEM_STATUSES as ht, ToolCatalog as i, WEBSITE_URL as in, PermissionDeniedError as it, ApiKeyScope as j, joinReplySlots as jt, ARTIFACT_DELIVERED_PLACEHOLDER as k, isRetryableError as kt, writePathOf as l, SupportedFabFileMimeTypes as lt, resolveApiEndpoint as m, VoyageAIEmbeddingModel as mt, extractCompactInstructions as n, splitSkillMdFrontmatter as nn, OpenAIEmbeddingModel as nt, isReadOnlyTool as o, SEARCH_RESULT_CARDS_LANGUAGE as ot, requireApiUrl as p, VisibilitySchema as pt, GENERATED_IMAGE_EXTENSION_RE as q, ACTOR_COLOR_SLOTS as qt, loadContextFiles as r, APP_NAME as rn, PROMPT_TEXT_MAX as rt, sandboxedCommandArg as s, SLUG_OWNED_BY_OTHER as st, ConfigStore as t, readSkillMdSourceUrl as tn, OllamaEmbeddingModel as tt, ApiEndpointUnconfiguredError as u, TTS_DEFAULT_MODEL as ut, NotAuthenticatedError as v, completionsSupportsToolSearch as vt, htmlFirstH1 as w, getQuestErrorCode as wt, SESSION_ID_PATTERN as x, filterToolArtifactMarkup as xt, parseApiUrl as y, createThinkMarkerEscaper as yt, CREDIT_DEDUCT_TRANSACTION_TYPES as z, stripToolArtifactMarkup as zt };
|