@bike4mind/cli 3.0.0 → 3.2.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 +1 -1
- package/dist/{AgentHistoryStore-DVxv1kSO.mjs → AgentHistoryStore-BWko6txx.mjs} +5999 -5603
- package/dist/{ConfigStore-51UaP9pJ.mjs → ConfigStore-v0wgf0_j.mjs} +748 -317
- package/dist/{WorkItemsClient-BMY0Qq1s.mjs → WorkItemsClient-BZL44N12.mjs} +1 -1
- package/dist/{buildAgent-CrSRKYU_.mjs → buildAgent-BZnmDQIr.mjs} +14 -206
- package/dist/commands/acpCommand.mjs +13 -9
- 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 +16 -15
- package/dist/commands/mcpCommand.mjs +3 -3
- package/dist/commands/pluginCommand.mjs +1 -1
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/{dist-BsG2Hlp-.mjs → dist-5DDaX8tB.mjs} +2 -2
- package/dist/index.mjs +21 -15
- package/dist/{package-DEsNSP54.mjs → package-COr17yKT.mjs} +1 -1
- package/dist/{serve-BaHzVbcm.mjs → serve-D6Eu3oXv.mjs} +46 -2
- package/package.json +10 -10
|
@@ -250,6 +250,19 @@ const StorageLimitErrorInfoSchema = z$1.object({
|
|
|
250
250
|
requested_bytes: z$1.number().nonnegative().describe("Size of the refused upload, in bytes."),
|
|
251
251
|
owner: z$1.enum(["user", "org"]).describe("Whose limit was hit: `user` or `org`. Always `user` for `file_too_large`, a platform-wide cap.")
|
|
252
252
|
});
|
|
253
|
+
/**
|
|
254
|
+
* The refusal a caller gets when the limit belongs to someone else (an update-share editor growing
|
|
255
|
+
* another user's file): the code and whose limit, without that owner's byte counts.
|
|
256
|
+
*/
|
|
257
|
+
const RedactedStorageLimitErrorInfoSchema = StorageLimitErrorInfoSchema.pick({
|
|
258
|
+
errorCode: true,
|
|
259
|
+
owner: true
|
|
260
|
+
}).extend({
|
|
261
|
+
used_bytes: z$1.never().optional(),
|
|
262
|
+
limit_bytes: z$1.never().optional(),
|
|
263
|
+
requested_bytes: z$1.never().optional()
|
|
264
|
+
});
|
|
265
|
+
z$1.union([StorageLimitErrorInfoSchema, RedactedStorageLimitErrorInfoSchema]);
|
|
253
266
|
function isZodError(err) {
|
|
254
267
|
return Boolean(err && (err instanceof ZodError || err.name === "ZodError"));
|
|
255
268
|
}
|
|
@@ -269,6 +282,7 @@ var PermissionDeniedError = class extends Error {
|
|
|
269
282
|
};
|
|
270
283
|
const UNKNOWN_MODEL_ERROR_CODE = "unknown_model";
|
|
271
284
|
const BILLING_ORGANIZATION_MISMATCH_ERROR_CODE = "billing_organization_mismatch";
|
|
285
|
+
const REQUEST_TIMEOUT_ERROR_CODE = "request_timeout";
|
|
272
286
|
const GROUP_TYPE_CATALOG = Object.freeze([
|
|
273
287
|
{
|
|
274
288
|
key: "sales",
|
|
@@ -777,6 +791,20 @@ const shareableDocumentSchema = z$1.object({
|
|
|
777
791
|
users: z$1.array(userShareSchema),
|
|
778
792
|
groups: z$1.array(groupShareSchema)
|
|
779
793
|
});
|
|
794
|
+
/** Bedrock's `[<scope>.]anthropic.` id prefix (any region or `global`), as regex source. Shared with isClaudeModelId. */
|
|
795
|
+
const BEDROCK_ANTHROPIC_PREFIX = "(?:(?:[a-z-]+\\.)?anthropic\\.)?";
|
|
796
|
+
const CLAUDE_MODEL_ID = new RegExp(`^${BEDROCK_ANTHROPIC_PREFIX}claude-(opus|sonnet|haiku|fable|mythos)-(\\d+)(?:-(\\d{1,2}))?(?=$|[:@[]|-(?:\\d{8}(?!\\d)|[a-z]))`);
|
|
797
|
+
/** Family and version of a Claude id (native, Bedrock-scoped, dated or aliased); null for any other shape. */
|
|
798
|
+
function parseClaudeModelId(modelId) {
|
|
799
|
+
const match = CLAUDE_MODEL_ID.exec(modelId);
|
|
800
|
+
if (!match) return null;
|
|
801
|
+
const [, family, major, minor] = match;
|
|
802
|
+
return {
|
|
803
|
+
family,
|
|
804
|
+
major: Number(major),
|
|
805
|
+
minor: minor === void 0 ? null : Number(minor)
|
|
806
|
+
};
|
|
807
|
+
}
|
|
780
808
|
/**
|
|
781
809
|
* Model backends
|
|
782
810
|
*/
|
|
@@ -1032,6 +1060,7 @@ let ChatModels = /* @__PURE__ */ function(ChatModels) {
|
|
|
1032
1060
|
}({});
|
|
1033
1061
|
const CHAT_MODELS = Object.values(ChatModels);
|
|
1034
1062
|
const supportedChatModels = z$1.enum(ChatModels);
|
|
1063
|
+
new RegExp(`^${BEDROCK_ANTHROPIC_PREFIX}claude-`);
|
|
1035
1064
|
/**
|
|
1036
1065
|
* Models that support OpenAI's `reasoning_effort` request parameter.
|
|
1037
1066
|
* o1-preview and o1-mini do NOT support reasoning_effort.
|
|
@@ -3126,8 +3155,22 @@ z.object({
|
|
|
3126
3155
|
/** Set for job-backed generations; the save is idempotent per job. */
|
|
3127
3156
|
jobId: z.string().optional(),
|
|
3128
3157
|
prompt: z.string(),
|
|
3158
|
+
/**
|
|
3159
|
+
* Storing caps `prompt` at a prefix of what was generated (sourceMetadata rides every metadata-only
|
|
3160
|
+
* listing). Written on every save, true when it was cut. Absent only on files saved before it existed:
|
|
3161
|
+
* read it through isStoredPromptPossiblyTruncated, which covers those.
|
|
3162
|
+
*/
|
|
3163
|
+
promptTruncated: z.boolean().optional(),
|
|
3129
3164
|
lyrics: z.string().optional(),
|
|
3130
|
-
durationSeconds: z.number().positive().optional()
|
|
3165
|
+
durationSeconds: z.number().positive().optional(),
|
|
3166
|
+
/** Speech: the requested voice; absent when the provider default was used or another provider stood in. */
|
|
3167
|
+
voice: z.string().optional(),
|
|
3168
|
+
/** Speech: the output format. */
|
|
3169
|
+
format: z.string().optional(),
|
|
3170
|
+
/** Speech: the requested language; absent when the provider auto-detected it. */
|
|
3171
|
+
languageCode: z.string().optional(),
|
|
3172
|
+
/** Sound effects: how closely the provider followed the prompt, 0-1. */
|
|
3173
|
+
promptInfluence: z.number().min(0).max(1).optional()
|
|
3131
3174
|
});
|
|
3132
3175
|
/**
|
|
3133
3176
|
* Why a generated file was not kept in the user's files. Never fatal: the output was already produced and
|
|
@@ -3613,6 +3656,199 @@ z$1.enum([
|
|
|
3613
3656
|
"investigate_soon",
|
|
3614
3657
|
"immediate_action"
|
|
3615
3658
|
]);
|
|
3659
|
+
const CompletionReasoningEffortSchema = z$1.enum([
|
|
3660
|
+
"none",
|
|
3661
|
+
"minimal",
|
|
3662
|
+
"low",
|
|
3663
|
+
"medium",
|
|
3664
|
+
"high",
|
|
3665
|
+
"xhigh"
|
|
3666
|
+
]);
|
|
3667
|
+
/**
|
|
3668
|
+
* Tool schema matching ICompletionOptionTools.toolSchema. The Zod surface only
|
|
3669
|
+
* covers wire-format fields (toolFn is server-side). Replaces the historical
|
|
3670
|
+
* z.array(z.any()) so client-side bugs (typos in name, missing type) surface
|
|
3671
|
+
* at parse time instead of failing silently inside the backend.
|
|
3672
|
+
*/
|
|
3673
|
+
const CompletionCustomToolSchema = z$1.object({
|
|
3674
|
+
toolSchema: z$1.object({
|
|
3675
|
+
name: z$1.string(),
|
|
3676
|
+
description: z$1.string(),
|
|
3677
|
+
parameters: z$1.object({
|
|
3678
|
+
type: z$1.literal("object"),
|
|
3679
|
+
properties: z$1.record(z$1.string(), z$1.any()).optional(),
|
|
3680
|
+
additionalProperties: z$1.boolean().optional(),
|
|
3681
|
+
required: z$1.array(z$1.string()).optional()
|
|
3682
|
+
}).passthrough(),
|
|
3683
|
+
strict: z$1.boolean().optional(),
|
|
3684
|
+
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 served by the direct Anthropic API whose `supports_tool_search` is true; on every other model (including Bedrock-served Claude, for now) 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\"`)."),
|
|
3685
|
+
cache_control: z$1.unknown().optional().describe("Accepted for validation only and not forwarded. Rejected on a deferred tool (`errorCode: \"deferred_tool_cache_control\"`).")
|
|
3686
|
+
}),
|
|
3687
|
+
_isMcpTool: z$1.boolean().optional()
|
|
3688
|
+
});
|
|
3689
|
+
/** Anthropic's tool search server tools; `name` is fixed by `type`. */
|
|
3690
|
+
const ToolSearchServerToolSchema = z$1.discriminatedUnion("type", [z$1.object({
|
|
3691
|
+
type: z$1.literal("tool_search_tool_regex_20251119"),
|
|
3692
|
+
name: z$1.literal("tool_search_tool_regex")
|
|
3693
|
+
}), z$1.object({
|
|
3694
|
+
type: z$1.literal("tool_search_tool_bm25_20251119"),
|
|
3695
|
+
name: z$1.literal("tool_search_tool_bm25")
|
|
3696
|
+
})]);
|
|
3697
|
+
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 served by the direct Anthropic API whose `supports_tool_search` is true; any other model, Bedrock-served Claude included, is refused with `errorCode: \"tool_search_unsupported\"` rather than run without it.") });
|
|
3698
|
+
/** One `tools[]` entry: a caller-defined tool, or a provider-run server tool. */
|
|
3699
|
+
const CompletionToolSchema = z$1.union([CompletionCustomToolSchema, CompletionServerToolSchema]);
|
|
3700
|
+
/**
|
|
3701
|
+
* The `errorCode`s of the completions 400s for tool search requests (CONVENTIONS.md section 1).
|
|
3702
|
+
* Assigned in services/cliCompletionsToolSearch.ts.
|
|
3703
|
+
*/
|
|
3704
|
+
const COMPLETION_TOOL_ERROR_CODES = [
|
|
3705
|
+
"tool_search_unsupported",
|
|
3706
|
+
"all_tools_deferred",
|
|
3707
|
+
"deferred_tool_cache_control",
|
|
3708
|
+
"unknown_tool_reference"
|
|
3709
|
+
];
|
|
3710
|
+
/**
|
|
3711
|
+
* JSON Schema definition for structured output. The `schema` field is a full
|
|
3712
|
+
* JSON Schema document (we don't try to validate JSON Schema with Zod - that's
|
|
3713
|
+
* the caller's contract with the model). `strict: true` is the default, matching
|
|
3714
|
+
* OpenAI's strict-mode subset semantics.
|
|
3715
|
+
*/
|
|
3716
|
+
const ResponseFormatSchema = z$1.discriminatedUnion("type", [z$1.object({ type: z$1.literal("text") }), z$1.object({
|
|
3717
|
+
type: z$1.literal("json_schema"),
|
|
3718
|
+
json_schema: z$1.object({
|
|
3719
|
+
name: z$1.string(),
|
|
3720
|
+
description: z$1.string().optional(),
|
|
3721
|
+
schema: z$1.record(z$1.string(), z$1.any()),
|
|
3722
|
+
strict: z$1.boolean().optional().default(true)
|
|
3723
|
+
})
|
|
3724
|
+
})]);
|
|
3725
|
+
/**
|
|
3726
|
+
* Wire-format message for /api/ai/v1/completions. The optional `cache: true`
|
|
3727
|
+
* flag is honored by Anthropic (translated to `cache_control: { type: 'ephemeral' }`
|
|
3728
|
+
* with the appropriate beta header) and silently ignored by other providers.
|
|
3729
|
+
*/
|
|
3730
|
+
const CompletionMessageSchema = z$1.object({
|
|
3731
|
+
role: z$1.enum([
|
|
3732
|
+
"user",
|
|
3733
|
+
"assistant",
|
|
3734
|
+
"system"
|
|
3735
|
+
]),
|
|
3736
|
+
content: z$1.union([z$1.string(), z$1.array(z$1.any())]),
|
|
3737
|
+
cache: z$1.boolean().optional()
|
|
3738
|
+
});
|
|
3739
|
+
/**
|
|
3740
|
+
* Schema for CLI LLM completion requests
|
|
3741
|
+
* Shared between Next.js API route (dev) and Lambda function (production)
|
|
3742
|
+
*
|
|
3743
|
+
* `response_format`, `stream`, `tools`, `temperature`, and `max_tokens` are all
|
|
3744
|
+
* accepted at the top level (OpenAI-compatible, matching how every major LLM
|
|
3745
|
+
* SDK shapes a completion request) AND nested under `options` (legacy shape).
|
|
3746
|
+
* Use `normalizeCompletionRequest()` to collapse both surfaces into the
|
|
3747
|
+
* canonical `options.<field>` location before downstream consumption.
|
|
3748
|
+
*/
|
|
3749
|
+
const CompletionRequestSchema = z$1.object({
|
|
3750
|
+
model: z$1.string().max(256),
|
|
3751
|
+
messages: z$1.array(CompletionMessageSchema),
|
|
3752
|
+
response_format: ResponseFormatSchema.optional(),
|
|
3753
|
+
stream: z$1.boolean().optional(),
|
|
3754
|
+
tools: z$1.array(CompletionToolSchema).optional(),
|
|
3755
|
+
temperature: z$1.number().optional(),
|
|
3756
|
+
max_tokens: z$1.number().optional(),
|
|
3757
|
+
options: z$1.object({
|
|
3758
|
+
temperature: z$1.number().optional(),
|
|
3759
|
+
maxTokens: z$1.number().optional(),
|
|
3760
|
+
stream: z$1.boolean().optional(),
|
|
3761
|
+
tools: z$1.array(CompletionToolSchema).optional(),
|
|
3762
|
+
response_format: ResponseFormatSchema.optional(),
|
|
3763
|
+
reasoningEffort: CompletionReasoningEffortSchema.optional().describe("Reasoning effort hint. Honoured by the OpenAI (reasoning models only, and not alongside tools on some of them), Kimi (K3 only), DeepSeek and Anthropic Claude (direct and Bedrock) adapters; each maps it onto its own scale. On Claude, `none` turns thinking off where the model allows it (otherwise it runs at the lowest effort), so short `max_tokens` replies stream visible text from the start; `minimal` maps to `low`. When `thinking.enabled` is also set on a Claude model, thinking stays on and this sets its effort instead, with `none` and `minimal` mapping to `low`. Claude models that reason inside `max_tokens` never have that ceiling raised, and on older Claude models any level above `none` turns thinking on (it is off by default there), forces temperature to 1 and drops top_p, and a thinking budget that cannot fit under `max_tokens` is skipped. On the direct Anthropic API, a json_schema `response_format` with no tools is served by a forced tool on models that support forced tool use, and that tool cannot run alongside thinking, so there only `none` is honoured; models served by native structured outputs honour every level. Silently ignored by every other adapter (Gemini, xAI, Ollama) and by non-reasoning models, so sending it there is a no-op."),
|
|
3764
|
+
thinking: z$1.object({
|
|
3765
|
+
enabled: z$1.boolean(),
|
|
3766
|
+
budget_tokens: z$1.number().int().min(1024).optional()
|
|
3767
|
+
}).optional().describe("Ask a model that can think to think on this turn. On Claude, `reasoningEffort` then sets how much it thinks, and `budget_tokens` (default 16000, minimum 1024) sizes thinking on older Claude models. Ignored by models that cannot think, and on the direct Anthropic API when a json_schema `response_format` is served by a forced tool, which cannot run alongside thinking.")
|
|
3768
|
+
}).optional()
|
|
3769
|
+
});
|
|
3770
|
+
const CompletionUsageSchema = z$1.object({
|
|
3771
|
+
inputTokens: z$1.number().optional(),
|
|
3772
|
+
outputTokens: z$1.number().optional(),
|
|
3773
|
+
reasoningTokens: z$1.number().optional().describe("Reasoning/thinking tokens the provider reported. A subset of outputTokens, not additive and not billed on top. Absent when the provider or adapter reports no count."),
|
|
3774
|
+
cacheReadInputTokens: z$1.number().optional(),
|
|
3775
|
+
cacheCreationInputTokens: z$1.number().optional()
|
|
3776
|
+
});
|
|
3777
|
+
const CompletionMetaEventSchema = z$1.object({
|
|
3778
|
+
type: z$1.literal("meta"),
|
|
3779
|
+
requestId: z$1.string()
|
|
3780
|
+
});
|
|
3781
|
+
const CompletionContentEventSchema = z$1.object({
|
|
3782
|
+
type: z$1.enum(["content", "tool_use"]),
|
|
3783
|
+
text: z$1.string(),
|
|
3784
|
+
tools: z$1.array(z$1.object({
|
|
3785
|
+
name: z$1.string(),
|
|
3786
|
+
arguments: z$1.string().optional(),
|
|
3787
|
+
id: z$1.string().optional()
|
|
3788
|
+
})).optional(),
|
|
3789
|
+
usage: CompletionUsageSchema.optional(),
|
|
3790
|
+
credits: z$1.object({
|
|
3791
|
+
used: z$1.number().optional(),
|
|
3792
|
+
usdCost: z$1.number().optional()
|
|
3793
|
+
}).optional(),
|
|
3794
|
+
responseFormatMode: z$1.enum([
|
|
3795
|
+
"native",
|
|
3796
|
+
"tool_use",
|
|
3797
|
+
"best-effort"
|
|
3798
|
+
]).optional(),
|
|
3799
|
+
stopReason: z$1.string().optional(),
|
|
3800
|
+
thinking: z$1.array(z$1.any()).optional(),
|
|
3801
|
+
toolStarted: z$1.object({
|
|
3802
|
+
name: z$1.string(),
|
|
3803
|
+
id: z$1.string().optional()
|
|
3804
|
+
}).optional()
|
|
3805
|
+
});
|
|
3806
|
+
/**
|
|
3807
|
+
* Classifiers the completions `error` frame may carry: the persisted quest codes plus the two
|
|
3808
|
+
* provider codes. A separate tuple because QUEST_ERROR_CODES is stored on quests and must not widen.
|
|
3809
|
+
*/
|
|
3810
|
+
const COMPLETION_SSE_ERROR_CODES = [
|
|
3811
|
+
...QUEST_ERROR_CODES,
|
|
3812
|
+
"provider_error",
|
|
3813
|
+
"provider_rejected",
|
|
3814
|
+
"content_blocked"
|
|
3815
|
+
];
|
|
3816
|
+
/**
|
|
3817
|
+
* The in-band terminal failure frame, sent only once the stream has opened. Failures found before
|
|
3818
|
+
* the provider call (auth, scope, validation, rate limit, model, credits) are JSON errors with a
|
|
3819
|
+
* real status instead; see completions.contract.ts.
|
|
3820
|
+
*
|
|
3821
|
+
* `code` is the machine-readable classifier: a billing code when settlement runs out mid-generation,
|
|
3822
|
+
* `provider_rejected` / `provider_error` when the model provider fails, `content_blocked` when the
|
|
3823
|
+
* model's safety classifier declined the request. Optional; callers must never match on the prose
|
|
3824
|
+
* `message`.
|
|
3825
|
+
*
|
|
3826
|
+
* The field is `code` rather than the conventions' `errorCode` because this frame shipped that way
|
|
3827
|
+
* and is a published wire shape.
|
|
3828
|
+
*/
|
|
3829
|
+
const CompletionSseErrorEventSchema = z$1.object({
|
|
3830
|
+
type: z$1.literal("error"),
|
|
3831
|
+
message: z$1.string(),
|
|
3832
|
+
requestId: z$1.string().optional(),
|
|
3833
|
+
code: z$1.enum(COMPLETION_SSE_ERROR_CODES).optional()
|
|
3834
|
+
});
|
|
3835
|
+
/**
|
|
3836
|
+
* A provider content block the caller must echo back verbatim, in stream order, in the assistant
|
|
3837
|
+
* `messages` content of the next request: today the Anthropic tool search `server_tool_use` and
|
|
3838
|
+
* `tool_search_tool_result` blocks. Never executed by the caller and never answered with a tool_result.
|
|
3839
|
+
*/
|
|
3840
|
+
const CompletionProviderBlockEventSchema = z$1.object({
|
|
3841
|
+
type: z$1.literal("provider_block"),
|
|
3842
|
+
provider: z$1.literal("anthropic"),
|
|
3843
|
+
block: z$1.record(z$1.string(), z$1.unknown())
|
|
3844
|
+
});
|
|
3845
|
+
/** One `data:` event in the `text/event-stream` completions response. */
|
|
3846
|
+
const CompletionStreamEventSchema = z$1.union([
|
|
3847
|
+
CompletionMetaEventSchema,
|
|
3848
|
+
CompletionContentEventSchema,
|
|
3849
|
+
CompletionProviderBlockEventSchema,
|
|
3850
|
+
CompletionSseErrorEventSchema
|
|
3851
|
+
]);
|
|
3616
3852
|
/** Splits on the marker tokens, keeping them in the result so a scan can track nesting depth. */
|
|
3617
3853
|
const THINK_TAG_TOKENS = /(<think>|<\/think>)/g;
|
|
3618
3854
|
/**
|
|
@@ -3750,8 +3986,8 @@ const invalid = (reason) => ({
|
|
|
3750
3986
|
status: "invalid",
|
|
3751
3987
|
reason
|
|
3752
3988
|
});
|
|
3753
|
-
const FENCE_OPEN_LINE = /^[ \t]*(`{3,}|~{3,})(.*)$/;
|
|
3754
|
-
const FENCE_CLOSE_LINE = /^[ \t]*(`{3,}|~{3,})[ \t]*$/;
|
|
3989
|
+
const FENCE_OPEN_LINE$1 = /^[ \t]*(`{3,}|~{3,})(.*)$/;
|
|
3990
|
+
const FENCE_CLOSE_LINE$1 = /^[ \t]*(`{3,}|~{3,})[ \t]*$/;
|
|
3755
3991
|
/**
|
|
3756
3992
|
* Offset where a slot's visible answer starts: just past its last top-level `</think>`, 0 when it
|
|
3757
3993
|
* has none, or null while a `<think>` is still open. Depth-tracked to match visibleReplyText in
|
|
@@ -3781,7 +4017,7 @@ function findLastChoicesFence(text) {
|
|
|
3781
4017
|
const lineEnd = newline === -1 ? text.length : newline;
|
|
3782
4018
|
const line = text.slice(lineStart, lineEnd).replace(/\r$/, "");
|
|
3783
4019
|
if (!open) {
|
|
3784
|
-
const match = line.match(FENCE_OPEN_LINE);
|
|
4020
|
+
const match = line.match(FENCE_OPEN_LINE$1);
|
|
3785
4021
|
if (match && !(match[1][0] === "`" && match[2].includes("`"))) open = {
|
|
3786
4022
|
start: lineStart,
|
|
3787
4023
|
bodyStart: newline === -1 ? text.length : newline + 1,
|
|
@@ -3789,7 +4025,7 @@ function findLastChoicesFence(text) {
|
|
|
3789
4025
|
isChoices: match[1] === "```" && match[2].trim().toLowerCase() === "choices"
|
|
3790
4026
|
};
|
|
3791
4027
|
} else {
|
|
3792
|
-
const match = line.match(FENCE_CLOSE_LINE);
|
|
4028
|
+
const match = line.match(FENCE_CLOSE_LINE$1);
|
|
3793
4029
|
if (match && match[1][0] === open.marker[0] && match[1].length >= open.marker.length) {
|
|
3794
4030
|
if (open.isChoices) last = {
|
|
3795
4031
|
start: open.start,
|
|
@@ -4796,6 +5032,13 @@ z$1.object({
|
|
|
4796
5032
|
reason: z$1.enum(REPLY_CHOICES_INVALID_REASONS).optional()
|
|
4797
5033
|
}).optional(),
|
|
4798
5034
|
/**
|
|
5035
|
+
* Set when finalize stripped a tool call the model wrote into its reply as text instead of
|
|
5036
|
+
* calling it (see ../utils/narratedToolCalls.ts). The call never ran; `toolNames` are the
|
|
5037
|
+
* offered tools it named. Absent when nothing was stripped. Consumers read this rather than
|
|
5038
|
+
* matching the reply text, which no longer carries the call.
|
|
5039
|
+
*/
|
|
5040
|
+
narratedToolCall: z$1.object({ toolNames: z$1.array(z$1.string()) }).optional(),
|
|
5041
|
+
/**
|
|
4799
5042
|
* Set when an emitted artifact looks voluntarily abbreviated - placeholder comments in
|
|
4800
5043
|
* place of real code, or calls into functions that were never defined. The complement to
|
|
4801
5044
|
* `finishReason === 'max_tokens'`: truncation is a hard stop the provider reports, elision
|
|
@@ -5016,6 +5259,17 @@ const ApiErrorSchema = z$1.object({
|
|
|
5016
5259
|
*/
|
|
5017
5260
|
const InsufficientCreditsErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.enum(QUEST_ERROR_CODES).optional() });
|
|
5018
5261
|
/**
|
|
5262
|
+
* 504 for a `wait: true` turn that ran past the request deadline. The turn is already settled
|
|
5263
|
+
* (timed out, unused credits refunded) when this is sent; `quest_id` is the quest to poll and
|
|
5264
|
+
* `sessionId` is the notebook the turn was recorded in, so a caller that sent no `sessionId` can
|
|
5265
|
+
* continue the conversation it just started (same field name as the ACK and the `wait: true` body).
|
|
5266
|
+
*/
|
|
5267
|
+
const ChatWaitTimeoutErrorSchema = ApiErrorSchema.extend({
|
|
5268
|
+
errorCode: z$1.literal(REQUEST_TIMEOUT_ERROR_CODE),
|
|
5269
|
+
quest_id: z$1.string(),
|
|
5270
|
+
sessionId: z$1.string().optional()
|
|
5271
|
+
});
|
|
5272
|
+
/**
|
|
5019
5273
|
* 400 for an upload refused on size or quota. The typed members are optional because the same 400 also
|
|
5020
5274
|
* covers errors that carry none (an unsupported file type); when `errorCode` is present all five arrive
|
|
5021
5275
|
* together, which the endpoint's 400 description states for integrators.
|
|
@@ -5023,8 +5277,11 @@ const InsufficientCreditsErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.en
|
|
|
5023
5277
|
const StorageLimitErrorSchema = ApiErrorSchema.extend(StorageLimitErrorInfoSchema.partial().shape);
|
|
5024
5278
|
/** 503 when this deployment has no usable key for a provider the request needs (data-lake search, voice). */
|
|
5025
5279
|
const ProviderNotConfiguredErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.literal("provider_not_configured").optional() });
|
|
5026
|
-
/**
|
|
5027
|
-
|
|
5280
|
+
/**
|
|
5281
|
+
* 400 for a `model` the caller cannot use, or a refused tool search request; `errorCode` is absent on the
|
|
5282
|
+
* other 400s (e.g. malformed JSON).
|
|
5283
|
+
*/
|
|
5284
|
+
const CompletionsBadRequestErrorSchema = ApiErrorSchema.extend({ errorCode: z$1.enum([UNKNOWN_MODEL_ERROR_CODE, ...COMPLETION_TOOL_ERROR_CODES]).optional() });
|
|
5028
5285
|
/**
|
|
5029
5286
|
* Error envelope for the 403 apiKeyAuth (apps/client/server/middlewares/apiKeyAuth.ts)
|
|
5030
5287
|
* throws when an API key lacks a route's scopes. It names what the ROUTE requires,
|
|
@@ -5205,6 +5462,16 @@ const MUSIC_VALIDATION_ERROR_CODES = [
|
|
|
5205
5462
|
"lyrics_with_instrumental",
|
|
5206
5463
|
"lyrics_too_long"
|
|
5207
5464
|
];
|
|
5465
|
+
/**
|
|
5466
|
+
* Building blocks for entity response schemas held to an entity's key list (see
|
|
5467
|
+
* selfUserResponseSchema in ./user.ts for the full rationale). A passthrough value is
|
|
5468
|
+
* `z.unknown()`: the boundary enforces WHICH keys leave the server, not their types, so a
|
|
5469
|
+
* legacy value on a long-lived Mongo document can never 500 a read.
|
|
5470
|
+
*/
|
|
5471
|
+
const passthroughField = z$2.unknown().optional();
|
|
5472
|
+
function passthroughShape(fields) {
|
|
5473
|
+
return Object.fromEntries(Object.keys(fields).map((field) => [field, passthroughField]));
|
|
5474
|
+
}
|
|
5208
5475
|
z$2.enum([
|
|
5209
5476
|
"",
|
|
5210
5477
|
"TFG",
|
|
@@ -5352,10 +5619,6 @@ const SELF_VIEW_PASSTHROUGH_FIELDS = {
|
|
|
5352
5619
|
currentCredits: true,
|
|
5353
5620
|
lastCreditsPurchasedAt: true
|
|
5354
5621
|
};
|
|
5355
|
-
const passthroughField = z$2.unknown().optional();
|
|
5356
|
-
function passthroughShape(fields) {
|
|
5357
|
-
return Object.fromEntries(Object.keys(fields).map((field) => [field, passthroughField]));
|
|
5358
|
-
}
|
|
5359
5622
|
/** A redacted integration object: only the named non-secret subfields survive. */
|
|
5360
5623
|
function redactedSubdocument(fields) {
|
|
5361
5624
|
return z$2.object(passthroughShape(Object.fromEntries(fields.map((field) => [field, true])))).nullable().optional();
|
|
@@ -5942,34 +6205,95 @@ function parseCidr(raw) {
|
|
|
5942
6205
|
prefix: Number(value.slice(slash + 1))
|
|
5943
6206
|
};
|
|
5944
6207
|
}
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
6208
|
+
/**
|
|
6209
|
+
* Networks a private-network opt-in never reaches, whatever the operator lists, self-host included.
|
|
6210
|
+
* One list for both sides: the settings validator refuses any range that overlaps an entry, and the
|
|
6211
|
+
* fetch path (`buildNeverAdmitted` in fab-pipeline's pinnedFetch.ts) refuses these at connect time.
|
|
6212
|
+
* IPv4 entries also cover their IPv4-mapped IPv6 forms (`::ffff:0:0/96`) on both sides.
|
|
6213
|
+
*/
|
|
6214
|
+
const NEVER_ADMITTED_NETWORKS = [
|
|
6215
|
+
{
|
|
6216
|
+
cidr: "0.0.0.0/8",
|
|
6217
|
+
label: "this network"
|
|
6218
|
+
},
|
|
6219
|
+
{
|
|
6220
|
+
cidr: "127.0.0.0/8",
|
|
6221
|
+
label: "loopback"
|
|
6222
|
+
},
|
|
6223
|
+
{
|
|
6224
|
+
cidr: "169.254.0.0/16",
|
|
6225
|
+
label: "link-local, including cloud metadata"
|
|
6226
|
+
},
|
|
6227
|
+
{
|
|
6228
|
+
cidr: "100.100.100.200/32",
|
|
6229
|
+
label: "cloud metadata"
|
|
6230
|
+
},
|
|
6231
|
+
{
|
|
6232
|
+
cidr: "fd00:ec2::254/128",
|
|
6233
|
+
label: "cloud metadata"
|
|
6234
|
+
},
|
|
6235
|
+
{
|
|
6236
|
+
cidr: "64:ff9b::a9fe:a9fe/128",
|
|
6237
|
+
label: "cloud metadata"
|
|
6238
|
+
},
|
|
6239
|
+
{
|
|
6240
|
+
cidr: "::/128",
|
|
6241
|
+
label: "unspecified"
|
|
6242
|
+
},
|
|
6243
|
+
{
|
|
6244
|
+
cidr: "::1/128",
|
|
6245
|
+
label: "loopback"
|
|
6246
|
+
},
|
|
6247
|
+
{
|
|
6248
|
+
cidr: "fe80::/10",
|
|
6249
|
+
label: "link-local"
|
|
6250
|
+
}
|
|
6251
|
+
];
|
|
6252
|
+
const IPV4_MAPPED_PREFIX = [
|
|
6253
|
+
0,
|
|
6254
|
+
0,
|
|
6255
|
+
0,
|
|
6256
|
+
0,
|
|
6257
|
+
0,
|
|
6258
|
+
0,
|
|
6259
|
+
0,
|
|
6260
|
+
0,
|
|
6261
|
+
0,
|
|
6262
|
+
0,
|
|
6263
|
+
255,
|
|
6264
|
+
255
|
|
6265
|
+
];
|
|
6266
|
+
/** An IPv4 CIDR in its IPv4-mapped IPv6 form; other CIDRs unchanged. */
|
|
6267
|
+
function asIpv6(cidr) {
|
|
6268
|
+
if (cidr.version === 6) return cidr;
|
|
6269
|
+
return {
|
|
6270
|
+
version: 6,
|
|
6271
|
+
bytes: [...IPV4_MAPPED_PREFIX, ...cidr.bytes],
|
|
6272
|
+
prefix: cidr.prefix + 96
|
|
6273
|
+
};
|
|
6274
|
+
}
|
|
6275
|
+
function cidrsOverlap(a, b) {
|
|
6276
|
+
const [left, right] = a.version === b.version ? [a, b] : [asIpv6(a), asIpv6(b)];
|
|
6277
|
+
const prefix = Math.min(left.prefix, right.prefix);
|
|
6278
|
+
for (let bit = 0; bit < prefix; bit++) {
|
|
5949
6279
|
const byte = bit >> 3;
|
|
5950
6280
|
const mask = 128 >> (bit & 7);
|
|
5951
|
-
if (((
|
|
6281
|
+
if (((left.bytes[byte] ?? 0) & mask) !== ((right.bytes[byte] ?? 0) & mask)) return false;
|
|
5952
6282
|
}
|
|
5953
6283
|
return true;
|
|
5954
6284
|
}
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
const CLOUD_METADATA_ADDRESSES = [
|
|
5960
|
-
"169.254.169.254",
|
|
5961
|
-
"fd00:ec2::254",
|
|
5962
|
-
"::ffff:169.254.169.254",
|
|
5963
|
-
"64:ff9b::169.254.169.254"
|
|
5964
|
-
];
|
|
6285
|
+
const NEVER_ADMITTED_PARSED = NEVER_ADMITTED_NETWORKS.map((entry) => ({
|
|
6286
|
+
...entry,
|
|
6287
|
+
parsed: parseCidr(entry.cidr)
|
|
6288
|
+
}));
|
|
5965
6289
|
/** Why `raw` may not be allowed as a private network, or null when it may. */
|
|
5966
6290
|
function customMcpPrivateCidrProblem(raw) {
|
|
5967
6291
|
const cidr = parseCidr(raw);
|
|
5968
6292
|
if (!cidr) return "Must be a CIDR such as 10.0.0.0/8 or fd12:3456::/32";
|
|
5969
6293
|
const minPrefix = CUSTOM_MCP_MIN_CIDR_PREFIX[cidr.version];
|
|
5970
6294
|
if (cidr.prefix < minPrefix) return `IPv${cidr.version} ranges must be /${minPrefix} or narrower`;
|
|
5971
|
-
const
|
|
5972
|
-
if (
|
|
6295
|
+
const blocked = NEVER_ADMITTED_PARSED.find((entry) => cidrsOverlap(cidr, entry.parsed));
|
|
6296
|
+
if (blocked) return `Range overlaps ${blocked.cidr} (${blocked.label}), which is never reachable`;
|
|
5973
6297
|
return null;
|
|
5974
6298
|
}
|
|
5975
6299
|
const CustomMcpPrivateCidrSchema = z$1.string().trim().toLowerCase().superRefine((value, ctx) => {
|
|
@@ -6973,8 +7297,8 @@ const CustomMcpPolicySchema = z$1.object({
|
|
|
6973
7297
|
const CustomMcpBlockedHostsSchema = z$1.object({ hosts: McpHostPatternListSchema.default([]) });
|
|
6974
7298
|
/**
|
|
6975
7299
|
* Self-host only; hosted deployments never reach private networks regardless of this value. Each
|
|
6976
|
-
* CIDR is strictly parsed, at least /8 (IPv4) or /16 (IPv6), and never
|
|
6977
|
-
*
|
|
7300
|
+
* CIDR is strictly parsed, at least /8 (IPv4) or /16 (IPv6), and never overlaps a network the fetch
|
|
7301
|
+
* path refuses anyway (NEVER_ADMITTED_NETWORKS in customMcpHosts.ts).
|
|
6978
7302
|
*/
|
|
6979
7303
|
const CustomMcpAllowPrivateNetworksSchema = z$1.object({
|
|
6980
7304
|
cidrs: z$1.array(CustomMcpPrivateCidrSchema).max(100).default([]),
|
|
@@ -11686,16 +12010,8 @@ const CliCompletionRequestAction = z$1.object({
|
|
|
11686
12010
|
temperature: z$1.number().optional(),
|
|
11687
12011
|
maxTokens: z$1.number().optional(),
|
|
11688
12012
|
stream: z$1.boolean().optional(),
|
|
11689
|
-
tools: z$1.array(
|
|
11690
|
-
response_format:
|
|
11691
|
-
type: z$1.literal("json_schema"),
|
|
11692
|
-
json_schema: z$1.object({
|
|
11693
|
-
name: z$1.string(),
|
|
11694
|
-
description: z$1.string().optional(),
|
|
11695
|
-
schema: z$1.record(z$1.string(), z$1.any()),
|
|
11696
|
-
strict: z$1.boolean().optional().default(true)
|
|
11697
|
-
})
|
|
11698
|
-
})]).optional()
|
|
12013
|
+
tools: z$1.array(CompletionToolSchema).optional(),
|
|
12014
|
+
response_format: ResponseFormatSchema.optional()
|
|
11699
12015
|
}).optional()
|
|
11700
12016
|
});
|
|
11701
12017
|
/**
|
|
@@ -12184,7 +12500,7 @@ const VoiceCreditsExhaustedAction = z$1.object({
|
|
|
12184
12500
|
const CliCompletionChunkAction = z$1.object({
|
|
12185
12501
|
action: z$1.literal("cli_completion_chunk"),
|
|
12186
12502
|
requestId: z$1.string(),
|
|
12187
|
-
chunk: z$1.object({
|
|
12503
|
+
chunk: z$1.union([z$1.object({
|
|
12188
12504
|
type: z$1.enum(["content", "tool_use"]),
|
|
12189
12505
|
text: z$1.string(),
|
|
12190
12506
|
toolStarted: z$1.object({
|
|
@@ -12197,7 +12513,7 @@ const CliCompletionChunkAction = z$1.object({
|
|
|
12197
12513
|
outputTokens: z$1.number().optional()
|
|
12198
12514
|
}).optional(),
|
|
12199
12515
|
thinking: z$1.array(z$1.unknown()).optional()
|
|
12200
|
-
})
|
|
12516
|
+
}), CompletionProviderBlockEventSchema])
|
|
12201
12517
|
});
|
|
12202
12518
|
/**
|
|
12203
12519
|
* CLI Completion stream finished successfully
|
|
@@ -12214,7 +12530,9 @@ const CliCompletionErrorAction = z$1.object({
|
|
|
12214
12530
|
requestId: z$1.string(),
|
|
12215
12531
|
error: z$1.string(),
|
|
12216
12532
|
/** Seconds until the caller's rate-limit window reopens; present only on a rate-limit refusal. */
|
|
12217
|
-
retryAfter: z$1.number().optional()
|
|
12533
|
+
retryAfter: z$1.number().optional(),
|
|
12534
|
+
/** Machine-readable reason on a request the caller must fix (a 4xx), e.g. `tool_search_unsupported`. */
|
|
12535
|
+
errorCode: z$1.string().optional()
|
|
12218
12536
|
});
|
|
12219
12537
|
/**
|
|
12220
12538
|
* CLI Tool execution response over WebSocket
|
|
@@ -12860,7 +13178,17 @@ const AgentProgressAction = z$1.object({
|
|
|
12860
13178
|
executionId: z$1.string(),
|
|
12861
13179
|
status: z$1.string().optional(),
|
|
12862
13180
|
creditsUsed: z$1.number().optional(),
|
|
12863
|
-
iteration: z$1.number().optional()
|
|
13181
|
+
iteration: z$1.number().optional(),
|
|
13182
|
+
questId: z$1.string().optional(),
|
|
13183
|
+
generationJobs: z$1.array(z$1.object({
|
|
13184
|
+
id: z$1.string(),
|
|
13185
|
+
kind: z$1.enum(GENERATION_JOB_KINDS)
|
|
13186
|
+
})).optional(),
|
|
13187
|
+
pendingAction: z$1.object({
|
|
13188
|
+
tool: z$1.string(),
|
|
13189
|
+
params: z$1.record(z$1.string(), z$1.unknown()),
|
|
13190
|
+
ts: z$1.number()
|
|
13191
|
+
}).optional()
|
|
12864
13192
|
});
|
|
12865
13193
|
const AgentCompletedAction = z$1.object({
|
|
12866
13194
|
action: z$1.literal("completed"),
|
|
@@ -13324,165 +13652,6 @@ const AgentExecutionStatusResponseSchema = z$1.object({
|
|
|
13324
13652
|
});
|
|
13325
13653
|
/** Path parameter for `GET /api/v1/agent-executions/{id}`. */
|
|
13326
13654
|
const AgentExecutionIdParamSchema = z$1.object({ id: z$1.string().min(1) });
|
|
13327
|
-
const CompletionReasoningEffortSchema = z$1.enum([
|
|
13328
|
-
"none",
|
|
13329
|
-
"minimal",
|
|
13330
|
-
"low",
|
|
13331
|
-
"medium",
|
|
13332
|
-
"high",
|
|
13333
|
-
"xhigh"
|
|
13334
|
-
]);
|
|
13335
|
-
/**
|
|
13336
|
-
* Tool schema matching ICompletionOptionTools.toolSchema. The Zod surface only
|
|
13337
|
-
* covers wire-format fields (toolFn is server-side). Replaces the historical
|
|
13338
|
-
* z.array(z.any()) so client-side bugs (typos in name, missing type) surface
|
|
13339
|
-
* at parse time instead of failing silently inside the backend.
|
|
13340
|
-
*/
|
|
13341
|
-
const CompletionToolSchema = z$1.object({
|
|
13342
|
-
toolSchema: z$1.object({
|
|
13343
|
-
name: z$1.string(),
|
|
13344
|
-
description: z$1.string(),
|
|
13345
|
-
parameters: z$1.object({
|
|
13346
|
-
type: z$1.literal("object"),
|
|
13347
|
-
properties: z$1.record(z$1.string(), z$1.any()).optional(),
|
|
13348
|
-
additionalProperties: z$1.boolean().optional(),
|
|
13349
|
-
required: z$1.array(z$1.string()).optional()
|
|
13350
|
-
}).passthrough(),
|
|
13351
|
-
strict: z$1.boolean().optional()
|
|
13352
|
-
}),
|
|
13353
|
-
_isMcpTool: z$1.boolean().optional()
|
|
13354
|
-
});
|
|
13355
|
-
/**
|
|
13356
|
-
* JSON Schema definition for structured output. The `schema` field is a full
|
|
13357
|
-
* JSON Schema document (we don't try to validate JSON Schema with Zod - that's
|
|
13358
|
-
* the caller's contract with the model). `strict: true` is the default, matching
|
|
13359
|
-
* OpenAI's strict-mode subset semantics.
|
|
13360
|
-
*/
|
|
13361
|
-
const ResponseFormatSchema = z$1.discriminatedUnion("type", [z$1.object({ type: z$1.literal("text") }), z$1.object({
|
|
13362
|
-
type: z$1.literal("json_schema"),
|
|
13363
|
-
json_schema: z$1.object({
|
|
13364
|
-
name: z$1.string(),
|
|
13365
|
-
description: z$1.string().optional(),
|
|
13366
|
-
schema: z$1.record(z$1.string(), z$1.any()),
|
|
13367
|
-
strict: z$1.boolean().optional().default(true)
|
|
13368
|
-
})
|
|
13369
|
-
})]);
|
|
13370
|
-
/**
|
|
13371
|
-
* Wire-format message for /api/ai/v1/completions. The optional `cache: true`
|
|
13372
|
-
* flag is honored by Anthropic (translated to `cache_control: { type: 'ephemeral' }`
|
|
13373
|
-
* with the appropriate beta header) and silently ignored by other providers.
|
|
13374
|
-
*/
|
|
13375
|
-
const CompletionMessageSchema = z$1.object({
|
|
13376
|
-
role: z$1.enum([
|
|
13377
|
-
"user",
|
|
13378
|
-
"assistant",
|
|
13379
|
-
"system"
|
|
13380
|
-
]),
|
|
13381
|
-
content: z$1.union([z$1.string(), z$1.array(z$1.any())]),
|
|
13382
|
-
cache: z$1.boolean().optional()
|
|
13383
|
-
});
|
|
13384
|
-
/**
|
|
13385
|
-
* Schema for CLI LLM completion requests
|
|
13386
|
-
* Shared between Next.js API route (dev) and Lambda function (production)
|
|
13387
|
-
*
|
|
13388
|
-
* `response_format`, `stream`, `tools`, `temperature`, and `max_tokens` are all
|
|
13389
|
-
* accepted at the top level (OpenAI-compatible, matching how every major LLM
|
|
13390
|
-
* SDK shapes a completion request) AND nested under `options` (legacy shape).
|
|
13391
|
-
* Use `normalizeCompletionRequest()` to collapse both surfaces into the
|
|
13392
|
-
* canonical `options.<field>` location before downstream consumption.
|
|
13393
|
-
*/
|
|
13394
|
-
const CompletionRequestSchema = z$1.object({
|
|
13395
|
-
model: z$1.string().max(256),
|
|
13396
|
-
messages: z$1.array(CompletionMessageSchema),
|
|
13397
|
-
response_format: ResponseFormatSchema.optional(),
|
|
13398
|
-
stream: z$1.boolean().optional(),
|
|
13399
|
-
tools: z$1.array(CompletionToolSchema).optional(),
|
|
13400
|
-
temperature: z$1.number().optional(),
|
|
13401
|
-
max_tokens: z$1.number().optional(),
|
|
13402
|
-
options: z$1.object({
|
|
13403
|
-
temperature: z$1.number().optional(),
|
|
13404
|
-
maxTokens: z$1.number().optional(),
|
|
13405
|
-
stream: z$1.boolean().optional(),
|
|
13406
|
-
tools: z$1.array(CompletionToolSchema).optional(),
|
|
13407
|
-
response_format: ResponseFormatSchema.optional(),
|
|
13408
|
-
reasoningEffort: CompletionReasoningEffortSchema.optional().describe("Reasoning effort hint. Honoured by the OpenAI (reasoning models only, and not alongside tools on some of them), Kimi (K3 only), DeepSeek and Anthropic Claude (direct and Bedrock) adapters; each maps it onto its own scale. On Claude, `none` turns thinking off where the model allows it (otherwise it runs at the lowest effort), so short `max_tokens` replies stream visible text from the start; `minimal` maps to `low`. When `thinking.enabled` is also set on a Claude model, thinking stays on and this sets its effort instead, with `none` and `minimal` mapping to `low`. Claude models that reason inside `max_tokens` never have that ceiling raised, and on older Claude models any level above `none` turns thinking on (it is off by default there), forces temperature to 1 and drops top_p, and a thinking budget that cannot fit under `max_tokens` is skipped. On the direct Anthropic API, a json_schema `response_format` with no tools is served by a forced tool on models that support forced tool use, and that tool cannot run alongside thinking, so there only `none` is honoured; models served by native structured outputs honour every level. Silently ignored by every other adapter (Gemini, xAI, Ollama) and by non-reasoning models, so sending it there is a no-op."),
|
|
13409
|
-
thinking: z$1.object({
|
|
13410
|
-
enabled: z$1.boolean(),
|
|
13411
|
-
budget_tokens: z$1.number().int().min(1024).optional()
|
|
13412
|
-
}).optional().describe("Ask a model that can think to think on this turn. On Claude, `reasoningEffort` then sets how much it thinks, and `budget_tokens` (default 16000, minimum 1024) sizes thinking on older Claude models. Ignored by models that cannot think, and on the direct Anthropic API when a json_schema `response_format` is served by a forced tool, which cannot run alongside thinking.")
|
|
13413
|
-
}).optional()
|
|
13414
|
-
});
|
|
13415
|
-
const CompletionUsageSchema = z$1.object({
|
|
13416
|
-
inputTokens: z$1.number().optional(),
|
|
13417
|
-
outputTokens: z$1.number().optional(),
|
|
13418
|
-
reasoningTokens: z$1.number().optional().describe("Reasoning/thinking tokens the provider reported. A subset of outputTokens, not additive and not billed on top. Absent when the provider or adapter reports no count."),
|
|
13419
|
-
cacheReadInputTokens: z$1.number().optional(),
|
|
13420
|
-
cacheCreationInputTokens: z$1.number().optional()
|
|
13421
|
-
});
|
|
13422
|
-
const CompletionMetaEventSchema = z$1.object({
|
|
13423
|
-
type: z$1.literal("meta"),
|
|
13424
|
-
requestId: z$1.string()
|
|
13425
|
-
});
|
|
13426
|
-
const CompletionContentEventSchema = z$1.object({
|
|
13427
|
-
type: z$1.enum(["content", "tool_use"]),
|
|
13428
|
-
text: z$1.string(),
|
|
13429
|
-
tools: z$1.array(z$1.object({
|
|
13430
|
-
name: z$1.string(),
|
|
13431
|
-
arguments: z$1.string().optional(),
|
|
13432
|
-
id: z$1.string().optional()
|
|
13433
|
-
})).optional(),
|
|
13434
|
-
usage: CompletionUsageSchema.optional(),
|
|
13435
|
-
credits: z$1.object({
|
|
13436
|
-
used: z$1.number().optional(),
|
|
13437
|
-
usdCost: z$1.number().optional()
|
|
13438
|
-
}).optional(),
|
|
13439
|
-
responseFormatMode: z$1.enum([
|
|
13440
|
-
"native",
|
|
13441
|
-
"tool_use",
|
|
13442
|
-
"best-effort"
|
|
13443
|
-
]).optional(),
|
|
13444
|
-
stopReason: z$1.string().optional(),
|
|
13445
|
-
thinking: z$1.array(z$1.any()).optional(),
|
|
13446
|
-
toolStarted: z$1.object({
|
|
13447
|
-
name: z$1.string(),
|
|
13448
|
-
id: z$1.string().optional()
|
|
13449
|
-
}).optional()
|
|
13450
|
-
});
|
|
13451
|
-
/**
|
|
13452
|
-
* Classifiers the completions `error` frame may carry: the persisted quest codes plus the two
|
|
13453
|
-
* provider codes. A separate tuple because QUEST_ERROR_CODES is stored on quests and must not widen.
|
|
13454
|
-
*/
|
|
13455
|
-
const COMPLETION_SSE_ERROR_CODES = [
|
|
13456
|
-
...QUEST_ERROR_CODES,
|
|
13457
|
-
"provider_error",
|
|
13458
|
-
"provider_rejected",
|
|
13459
|
-
"content_blocked"
|
|
13460
|
-
];
|
|
13461
|
-
/**
|
|
13462
|
-
* The in-band terminal failure frame, sent only once the stream has opened. Failures found before
|
|
13463
|
-
* the provider call (auth, scope, validation, rate limit, model, credits) are JSON errors with a
|
|
13464
|
-
* real status instead; see completions.contract.ts.
|
|
13465
|
-
*
|
|
13466
|
-
* `code` is the machine-readable classifier: a billing code when settlement runs out mid-generation,
|
|
13467
|
-
* `provider_rejected` / `provider_error` when the model provider fails, `content_blocked` when the
|
|
13468
|
-
* model's safety classifier declined the request. Optional; callers must never match on the prose
|
|
13469
|
-
* `message`.
|
|
13470
|
-
*
|
|
13471
|
-
* The field is `code` rather than the conventions' `errorCode` because this frame shipped that way
|
|
13472
|
-
* and is a published wire shape.
|
|
13473
|
-
*/
|
|
13474
|
-
const CompletionSseErrorEventSchema = z$1.object({
|
|
13475
|
-
type: z$1.literal("error"),
|
|
13476
|
-
message: z$1.string(),
|
|
13477
|
-
requestId: z$1.string().optional(),
|
|
13478
|
-
code: z$1.enum(COMPLETION_SSE_ERROR_CODES).optional()
|
|
13479
|
-
});
|
|
13480
|
-
/** One `data:` event in the `text/event-stream` completions response. */
|
|
13481
|
-
const CompletionStreamEventSchema = z$1.union([
|
|
13482
|
-
CompletionMetaEventSchema,
|
|
13483
|
-
CompletionContentEventSchema,
|
|
13484
|
-
CompletionSseErrorEventSchema
|
|
13485
|
-
]);
|
|
13486
13655
|
/**
|
|
13487
13656
|
* Server-side tool execution schemas for POST /api/ai/v1/tools.
|
|
13488
13657
|
*
|
|
@@ -14808,6 +14977,93 @@ const CreateSessionRequestSchema = z$1.object({
|
|
|
14808
14977
|
tags: z$1.array(SessionTagSchema).optional(),
|
|
14809
14978
|
lastUsedModel: z$1.string().nullish()
|
|
14810
14979
|
});
|
|
14980
|
+
z$2.object(passthroughShape({
|
|
14981
|
+
id: true,
|
|
14982
|
+
createdAt: true,
|
|
14983
|
+
updatedAt: true,
|
|
14984
|
+
name: true,
|
|
14985
|
+
description: true,
|
|
14986
|
+
type: true,
|
|
14987
|
+
organizationId: true
|
|
14988
|
+
})).extend({
|
|
14989
|
+
memberIds: z$2.array(z$2.string()),
|
|
14990
|
+
memberCount: z$2.number()
|
|
14991
|
+
});
|
|
14992
|
+
z$2.object(passthroughShape({
|
|
14993
|
+
id: true,
|
|
14994
|
+
createdAt: true,
|
|
14995
|
+
updatedAt: true,
|
|
14996
|
+
deletedAt: true,
|
|
14997
|
+
sessionId: true,
|
|
14998
|
+
conversationItemId: true,
|
|
14999
|
+
openaiMessageId: true,
|
|
15000
|
+
claudeMessageId: true,
|
|
15001
|
+
type: true,
|
|
15002
|
+
timestamp: true,
|
|
15003
|
+
prompt: true,
|
|
15004
|
+
fabFileIds: true,
|
|
15005
|
+
agentIds: true,
|
|
15006
|
+
reply: true,
|
|
15007
|
+
replies: true,
|
|
15008
|
+
structuredReplies: true,
|
|
15009
|
+
toolResults: true,
|
|
15010
|
+
questMasterReply: true,
|
|
15011
|
+
images: true,
|
|
15012
|
+
videos: true,
|
|
15013
|
+
videoJobIds: true,
|
|
15014
|
+
generationJobs: true,
|
|
15015
|
+
agentVideoClipsClaimed: true,
|
|
15016
|
+
agentMusicTracksClaimed: true,
|
|
15017
|
+
oob: true,
|
|
15018
|
+
promptMeta: true,
|
|
15019
|
+
status: true,
|
|
15020
|
+
creditsUsed: true,
|
|
15021
|
+
errorCode: true,
|
|
15022
|
+
questMasterPlanId: true,
|
|
15023
|
+
agentExecutionId: true,
|
|
15024
|
+
correctsQuestId: true,
|
|
15025
|
+
clientFirstTokenTime: true,
|
|
15026
|
+
routingSource: true,
|
|
15027
|
+
pinned: true,
|
|
15028
|
+
researchModeResults: true,
|
|
15029
|
+
deepResearchState: true,
|
|
15030
|
+
fallbackInfo: true,
|
|
15031
|
+
promptEnhancement: true,
|
|
15032
|
+
pendingAction: true,
|
|
15033
|
+
attachmentNotices: true,
|
|
15034
|
+
attachmentDelivery: true,
|
|
15035
|
+
navigationIntents: true,
|
|
15036
|
+
suggestedChoices: true,
|
|
15037
|
+
attachmentList: true,
|
|
15038
|
+
uiSideEffects: true,
|
|
15039
|
+
jupyterNotebook: true
|
|
15040
|
+
}));
|
|
15041
|
+
const questMasterPlanResponseSchema = z$2.object(passthroughShape({
|
|
15042
|
+
id: true,
|
|
15043
|
+
createdAt: true,
|
|
15044
|
+
updatedAt: true,
|
|
15045
|
+
notebookId: true,
|
|
15046
|
+
goal: true,
|
|
15047
|
+
quests: true,
|
|
15048
|
+
userId: true,
|
|
15049
|
+
visibility: true,
|
|
15050
|
+
state: true,
|
|
15051
|
+
lastAccessedAt: true,
|
|
15052
|
+
sessionHistory: true,
|
|
15053
|
+
metrics: true,
|
|
15054
|
+
tags: true,
|
|
15055
|
+
priority: true,
|
|
15056
|
+
parentPlanId: true,
|
|
15057
|
+
sharedWith: true,
|
|
15058
|
+
handoff: true,
|
|
15059
|
+
blockers: true,
|
|
15060
|
+
decisions: true
|
|
15061
|
+
}));
|
|
15062
|
+
z$2.array(questMasterPlanResponseSchema);
|
|
15063
|
+
z$2.object({
|
|
15064
|
+
success: z$2.literal(true),
|
|
15065
|
+
plan: questMasterPlanResponseSchema
|
|
15066
|
+
}).extend({ metrics: passthroughField });
|
|
14811
15067
|
z$1.preprocess((val) => {
|
|
14812
15068
|
if (typeof val === "string") {
|
|
14813
15069
|
if (val.toLowerCase() === "true") return true;
|
|
@@ -16114,8 +16370,8 @@ const ListModelsResponseSchema = paginatedResponseSchema(z$1.object({
|
|
|
16114
16370
|
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."),
|
|
16115
16371
|
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."),
|
|
16116
16372
|
supports_tools: z$1.boolean(),
|
|
16117
|
-
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
|
|
16118
|
-
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 only: `/api/ai/v1/completions` does not accept these blocks yet
|
|
16373
|
+
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 only for models whose `backend` is `anthropic`. A `bedrock` model with this flag set is not served with tool search there yet: a `serverTool` entry is refused with `errorCode: \"tool_search_unsupported\"` and `defer_loading` is ignored."),
|
|
16374
|
+
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 only: `/api/ai/v1/completions` does not accept these blocks yet, and will accept them first for models whose `backend` is `anthropic`."),
|
|
16119
16375
|
supports_vision: z$1.boolean(),
|
|
16120
16376
|
deprecation_date: z$1.string().nullable().describe("`YYYY-MM-DD`; null when no retirement is scheduled."),
|
|
16121
16377
|
replaced_by: z$1.string().nullable().describe("The id of the recommended successor, when there is one."),
|
|
@@ -16509,7 +16765,12 @@ z$1.object({
|
|
|
16509
16765
|
* Session-creation input, not a completion parameter, so it is applied only when `sessionId`
|
|
16510
16766
|
* is absent; ignored when an existing session is resolved.
|
|
16511
16767
|
*/
|
|
16512
|
-
agentIds: z$1.array(z$1.string()).optional()
|
|
16768
|
+
agentIds: z$1.array(z$1.string()).optional(),
|
|
16769
|
+
/**
|
|
16770
|
+
* The subset of `messageFileIds` the user scoped to this message only. Every other notebook-scope
|
|
16771
|
+
* message attachment is pinned to the session so it stays in context on later turns.
|
|
16772
|
+
*/
|
|
16773
|
+
messageOnlyFileIds: z$1.array(z$1.string()).optional()
|
|
16513
16774
|
});
|
|
16514
16775
|
/**
|
|
16515
16776
|
* Response shapes for the public image endpoints (`generateImage` / `editImage`,
|
|
@@ -16832,7 +17093,7 @@ defineEndpoint({
|
|
|
16832
17093
|
path: "/api/chat",
|
|
16833
17094
|
operationId: "sendChatMessage",
|
|
16834
17095
|
summary: "Send a chat message",
|
|
16835
|
-
description: "Sends a message to the AI and creates a quest to process it. By default (async) the call returns immediately with a quest id; poll `GET /api/v1/quests/{id}` for the reply. Send `wait: true` to block until the reply is ready and receive it inline. A tool that produced machine-readable state reports it under `toolPayloads` - an array of `{ type, payload }` entries in emission order, alongside (never instead of) the prose reply - on the `wait: true` body and on the polled quest. A turn can FAIL after the ACK - reported on the polled quest as `type: \"error\"`, since the ACK was already sent. A terminal `status: \"stopped\"` (a missing session, a user-cancelled turn) is ALSO a failure even without `type: \"error\"` - it carries an explanatory string in `reply`/`replies` rather than an answer. `type` is the failure signal for the classified failure classes (an abort, a provider timeout, credit exhaustion); `errorCode` is an optional refinement present only when the failure is a classified billing reason. A recovered stuck quest is NOT in that list: one that still has renderable content resolves as a success by design. `QUEST_ERROR_CODES` has two members, but only `insufficient_credits` is raised as a quest errorCode by any current throw site on this endpoint - `spend_cap_exceeded` is thrown only by the embed chat route's pre-flight, which fires outside the process try/catch that would classify it onto a quest. A caller must treat `type: \"error\"` OR a terminal `status: \"stopped\"` as failure even when `errorCode` is absent, and must not read `reply` as an answer without checking those first. Authenticate with an API key (`b4m_live_`) or a JWT. Session resolution: pass `sessionId` to continue an existing notebook. An API-key caller that omits it gets a BRAND-NEW notebook rather than the notebook the human last had open, and `newConversation: true` forces a new notebook for any auth mode; both return the new id as `sessionId`, so the caller can continue the conversation by passing it back. A first-party JWT caller that omits `sessionId` keeps the last-opened-notebook fallback. Sending `sessionId` and `newConversation` together is a 422.",
|
|
17096
|
+
description: "Sends a message to the AI and creates a quest to process it. By default (async) the call returns immediately with a quest id; poll `GET /api/v1/quests/{id}` for the reply. Send `wait: true` to block until the reply is ready and receive it inline. A `wait: true` turn is bounded at about 45 seconds: one that runs longer is ended (unused credits refunded) and answered with a 504 naming the quest in `quest_id`. Send long or tool-heavy turns (large attachments, tool calls) in the default async mode and poll instead. A tool that produced machine-readable state reports it under `toolPayloads` - an array of `{ type, payload }` entries in emission order, alongside (never instead of) the prose reply - on the `wait: true` body and on the polled quest. A turn can FAIL after the ACK - reported on the polled quest as `type: \"error\"`, since the ACK was already sent. A terminal `status: \"stopped\"` (a missing session, a user-cancelled turn) is ALSO a failure even without `type: \"error\"` - it carries an explanatory string in `reply`/`replies` rather than an answer. `type` is the failure signal for the classified failure classes (an abort, a provider timeout, credit exhaustion); `errorCode` is an optional refinement present only when the failure is a classified billing reason. A recovered stuck quest is NOT in that list: one that still has renderable content resolves as a success by design. `QUEST_ERROR_CODES` has two members, but only `insufficient_credits` is raised as a quest errorCode by any current throw site on this endpoint - `spend_cap_exceeded` is thrown only by the embed chat route's pre-flight, which fires outside the process try/catch that would classify it onto a quest. A caller must treat `type: \"error\"` OR a terminal `status: \"stopped\"` as failure even when `errorCode` is absent, and must not read `reply` as an answer without checking those first. Authenticate with an API key (`b4m_live_`) or a JWT. Session resolution: pass `sessionId` to continue an existing notebook. An API-key caller that omits it gets a BRAND-NEW notebook rather than the notebook the human last had open, and `newConversation: true` forces a new notebook for any auth mode; both return the new id as `sessionId`, so the caller can continue the conversation by passing it back. A first-party JWT caller that omits `sessionId` keeps the last-opened-notebook fallback. Sending `sessionId` and `newConversation` together is a 422.",
|
|
16836
17097
|
tags: ["AI"],
|
|
16837
17098
|
auth: "apiKeyOrJwt",
|
|
16838
17099
|
scopes: ["ai:chat", "ai:generate"],
|
|
@@ -16873,6 +17134,10 @@ defineEndpoint({
|
|
|
16873
17134
|
429: {
|
|
16874
17135
|
description: "Per-user rate limit exceeded.",
|
|
16875
17136
|
schema: ApiErrorSchema
|
|
17137
|
+
},
|
|
17138
|
+
504: {
|
|
17139
|
+
description: "A `wait: true` turn ran past the request deadline. The turn is already ended: its quest (`quest_id`) is settled as timed out with any partial reply kept, and unused reserved credits are refunded. Retry in async mode for a long turn.",
|
|
17140
|
+
schema: ChatWaitTimeoutErrorSchema
|
|
16876
17141
|
}
|
|
16877
17142
|
},
|
|
16878
17143
|
codeSample: {
|
|
@@ -17172,7 +17437,7 @@ defineEndpoint({
|
|
|
17172
17437
|
path: "/api/ai/v1/completions",
|
|
17173
17438
|
operationId: "createCompletion",
|
|
17174
17439
|
summary: "Create a chat completion",
|
|
17175
|
-
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\nERRORS. Everything checked before the model provider is called fails with a JSON error body and a real HTTP status, before any stream opens: a malformed or otherwise invalid request or an unknown `model` `400` (`errorCode: \"unknown_model\"` for the latter), a bad credential `401`, a key without a required scope `403` (with `required_scopes`), a body over 25 MB `413`, a 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 `503` with `errorCode: \"provider_not_configured\"` (retryable). 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, `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.",
|
|
17440
|
+
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` and `backend: \"anthropic\"`, 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, Bedrock-served Claude included, `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: a malformed or otherwise invalid request or an unknown `model` `400` (`errorCode: \"unknown_model\"` for the latter), a bad credential `401`, a key without a required scope `403` (with `required_scopes`), a body over 25 MB `413`, a 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 `503` with `errorCode: \"provider_not_configured\"` (retryable). 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, `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.",
|
|
17176
17441
|
tags: ["AI"],
|
|
17177
17442
|
auth: "apiKeyOrJwt",
|
|
17178
17443
|
scopes: ["ai:chat", "ai:generate"],
|
|
@@ -17206,8 +17471,8 @@ defineEndpoint({
|
|
|
17206
17471
|
}
|
|
17207
17472
|
},
|
|
17208
17473
|
400: {
|
|
17209
|
-
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`.",
|
|
17210
|
-
schema:
|
|
17474
|
+
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`).",
|
|
17475
|
+
schema: CompletionsBadRequestErrorSchema
|
|
17211
17476
|
},
|
|
17212
17477
|
413: {
|
|
17213
17478
|
description: "Request body over 25 MB.",
|
|
@@ -21039,7 +21304,7 @@ function scanArtifactOpenTag(text, at, leading, memo) {
|
|
|
21039
21304
|
end: close + 1
|
|
21040
21305
|
};
|
|
21041
21306
|
}
|
|
21042
|
-
const OPENER = /<artifact(?=\s)/gi;
|
|
21307
|
+
const OPENER$1 = /<artifact(?=\s)/gi;
|
|
21043
21308
|
const LEADING_WS = /\s+/y;
|
|
21044
21309
|
const CLOSER = /<\/artifact>/gi;
|
|
21045
21310
|
const GT = />/g;
|
|
@@ -21054,9 +21319,9 @@ function scanArtifactTags(text, attrsMayCrossLines) {
|
|
|
21054
21319
|
const stop = attrsMayCrossLines ? GT : GT_OR_LINE_TERMINATOR;
|
|
21055
21320
|
const out = [];
|
|
21056
21321
|
let termAt = -1;
|
|
21057
|
-
OPENER.lastIndex = 0;
|
|
21322
|
+
OPENER$1.lastIndex = 0;
|
|
21058
21323
|
let opener;
|
|
21059
|
-
while ((opener = OPENER.exec(text)) !== null) {
|
|
21324
|
+
while ((opener = OPENER$1.exec(text)) !== null) {
|
|
21060
21325
|
LEADING_WS.lastIndex = opener.index + opener[0].length;
|
|
21061
21326
|
LEADING_WS.exec(text);
|
|
21062
21327
|
const attrsStart = LEADING_WS.lastIndex;
|
|
@@ -21076,7 +21341,7 @@ function scanArtifactTags(text, attrsMayCrossLines) {
|
|
|
21076
21341
|
attrs: text.slice(attrsStart, termAt),
|
|
21077
21342
|
body: text.slice(termAt + 1, closer.index)
|
|
21078
21343
|
});
|
|
21079
|
-
OPENER.lastIndex = end;
|
|
21344
|
+
OPENER$1.lastIndex = end;
|
|
21080
21345
|
}
|
|
21081
21346
|
return out;
|
|
21082
21347
|
}
|
|
@@ -21244,7 +21509,11 @@ function stripDeliveredArtifactBlocks(text, deliveredMarkup) {
|
|
|
21244
21509
|
*/
|
|
21245
21510
|
const CLAUDE_4_7_PLUS_MULTIPLIER = 1.5;
|
|
21246
21511
|
const CLAUDE_4_5_MULTIPLIER = 1.09;
|
|
21247
|
-
const
|
|
21512
|
+
const MEASURED_FAMILIES = /* @__PURE__ */ new Set([
|
|
21513
|
+
"opus",
|
|
21514
|
+
"sonnet",
|
|
21515
|
+
"haiku"
|
|
21516
|
+
]);
|
|
21248
21517
|
/**
|
|
21249
21518
|
* Factor to scale a cl100k_base token count by for `modelId`. 1 for anything unmeasured: non-Claude
|
|
21250
21519
|
* models, Claude before 4.5 (retired on Bedrock, could not be measured), and Fable (Bedrock rejects it
|
|
@@ -21252,10 +21521,10 @@ const CLAUDE_FAMILY_VERSION = /(?:^|\.)claude-(?:opus|sonnet|haiku)-(\d+)(?:-(\d
|
|
|
21252
21521
|
* assumption they keep its tokenizer; [BILLING_DRIFT] flags it if one does not.
|
|
21253
21522
|
*/
|
|
21254
21523
|
function tokenEstimateMultiplier(modelId) {
|
|
21255
|
-
const
|
|
21256
|
-
if (!
|
|
21257
|
-
const major =
|
|
21258
|
-
const minor =
|
|
21524
|
+
const parsed = modelId ? parseClaudeModelId(modelId) : null;
|
|
21525
|
+
if (!parsed || !MEASURED_FAMILIES.has(parsed.family)) return 1;
|
|
21526
|
+
const { major } = parsed;
|
|
21527
|
+
const minor = parsed.minor ?? 0;
|
|
21259
21528
|
if (major > 4 || major === 4 && minor >= 7) return CLAUDE_4_7_PLUS_MULTIPLIER;
|
|
21260
21529
|
if (major === 4 && minor >= 5) return CLAUDE_4_5_MULTIPLIER;
|
|
21261
21530
|
return 1;
|
|
@@ -23650,111 +23919,273 @@ function getEnvironmentName(configApiConfig) {
|
|
|
23650
23919
|
return "Self-Hosted";
|
|
23651
23920
|
}
|
|
23652
23921
|
//#endregion
|
|
23653
|
-
//#region src/
|
|
23922
|
+
//#region src/tools/gateway/coreToolDescriptors.ts
|
|
23923
|
+
const CORE = { kind: "core" };
|
|
23924
|
+
const CLI = { kind: "cli" };
|
|
23925
|
+
const pureCompute = () => ({
|
|
23926
|
+
source: CORE,
|
|
23927
|
+
effect: "none",
|
|
23928
|
+
approval: "auto_approve"
|
|
23929
|
+
});
|
|
23930
|
+
const sessionTool = () => ({
|
|
23931
|
+
source: CLI,
|
|
23932
|
+
effect: "session",
|
|
23933
|
+
approval: "auto_approve"
|
|
23934
|
+
});
|
|
23935
|
+
const reader = (source = CORE, extra = {}) => ({
|
|
23936
|
+
source,
|
|
23937
|
+
effect: "read",
|
|
23938
|
+
approval: "prompt_default",
|
|
23939
|
+
...extra
|
|
23940
|
+
});
|
|
23941
|
+
const fileWriter = () => ({
|
|
23942
|
+
source: CORE,
|
|
23943
|
+
effect: "write",
|
|
23944
|
+
approval: "prompt_always",
|
|
23945
|
+
writePathArg: "path"
|
|
23946
|
+
});
|
|
23947
|
+
const lattice = () => ({
|
|
23948
|
+
source: CORE,
|
|
23949
|
+
effect: "none",
|
|
23950
|
+
approval: "prompt_default"
|
|
23951
|
+
});
|
|
23952
|
+
/**
|
|
23953
|
+
* Descriptors for every tool the CLI builds itself or gets from @bike4mind/services:
|
|
23954
|
+
* generateCliTools, buildCliToolList and the subagent-injected tools. A tool missing here
|
|
23955
|
+
* resolves to the unknown fallback in toolCatalog.ts; coreToolCompleteness.test.ts
|
|
23956
|
+
* fails when a generated tool has no entry.
|
|
23957
|
+
*/
|
|
23958
|
+
const CORE_TOOL_DESCRIPTORS = new Map(Object.entries({
|
|
23959
|
+
math_evaluate: pureCompute(),
|
|
23960
|
+
current_datetime: pureCompute(),
|
|
23961
|
+
dice_roll: pureCompute(),
|
|
23962
|
+
prompt_enhancement: pureCompute(),
|
|
23963
|
+
find_definition: {
|
|
23964
|
+
source: CLI,
|
|
23965
|
+
effect: "read",
|
|
23966
|
+
approval: "auto_approve"
|
|
23967
|
+
},
|
|
23968
|
+
ask_user_question: {
|
|
23969
|
+
source: CORE,
|
|
23970
|
+
effect: "session",
|
|
23971
|
+
approval: "auto_approve"
|
|
23972
|
+
},
|
|
23973
|
+
agent_delegate: sessionTool(),
|
|
23974
|
+
check_agent_status: sessionTool(),
|
|
23975
|
+
list_background_agents: sessionTool(),
|
|
23976
|
+
cancel_background_agent: sessionTool(),
|
|
23977
|
+
resume_agent: sessionTool(),
|
|
23978
|
+
create_dynamic_agent: sessionTool(),
|
|
23979
|
+
coordinate_task: sessionTool(),
|
|
23980
|
+
decompose_task: sessionTool(),
|
|
23981
|
+
shared_context_read: sessionTool(),
|
|
23982
|
+
shared_context_write: sessionTool(),
|
|
23983
|
+
write_todos: sessionTool(),
|
|
23984
|
+
read_prior_todos: sessionTool(),
|
|
23985
|
+
log_decision: sessionTool(),
|
|
23986
|
+
track_blocker: sessionTool(),
|
|
23987
|
+
resolve_blocker: sessionTool(),
|
|
23988
|
+
request_review_gate: sessionTool(),
|
|
23989
|
+
work_item_create: sessionTool(),
|
|
23990
|
+
work_item_update: sessionTool(),
|
|
23991
|
+
work_item_close: sessionTool(),
|
|
23992
|
+
work_item_ready: sessionTool(),
|
|
23993
|
+
work_item_graph: sessionTool(),
|
|
23994
|
+
tool_search: sessionTool(),
|
|
23995
|
+
create_file: fileWriter(),
|
|
23996
|
+
edit_local_file: fileWriter(),
|
|
23997
|
+
delete_file: fileWriter(),
|
|
23998
|
+
edit_file: {
|
|
23999
|
+
source: CORE,
|
|
24000
|
+
effect: "write",
|
|
24001
|
+
approval: "prompt_always"
|
|
24002
|
+
},
|
|
24003
|
+
bash_execute: {
|
|
24004
|
+
source: CORE,
|
|
24005
|
+
effect: "execute",
|
|
24006
|
+
approval: "prompt_always",
|
|
24007
|
+
openWorld: true,
|
|
24008
|
+
commandArg: "command"
|
|
24009
|
+
},
|
|
24010
|
+
shell_execute: {
|
|
24011
|
+
source: CORE,
|
|
24012
|
+
effect: "execute",
|
|
24013
|
+
approval: "prompt_always",
|
|
24014
|
+
openWorld: true
|
|
24015
|
+
},
|
|
24016
|
+
write_shell_stdin: {
|
|
24017
|
+
source: CORE,
|
|
24018
|
+
effect: "execute",
|
|
24019
|
+
approval: "prompt_always",
|
|
24020
|
+
commandArg: "chars"
|
|
24021
|
+
},
|
|
24022
|
+
kill_background_shell: {
|
|
24023
|
+
source: CORE,
|
|
24024
|
+
effect: "execute",
|
|
24025
|
+
approval: "prompt_always"
|
|
24026
|
+
},
|
|
24027
|
+
git_commit: {
|
|
24028
|
+
source: CORE,
|
|
24029
|
+
effect: "write",
|
|
24030
|
+
approval: "prompt_always"
|
|
24031
|
+
},
|
|
24032
|
+
git_push: {
|
|
24033
|
+
source: CORE,
|
|
24034
|
+
effect: "write",
|
|
24035
|
+
approval: "prompt_always",
|
|
24036
|
+
openWorld: true
|
|
24037
|
+
},
|
|
24038
|
+
skill: {
|
|
24039
|
+
source: CLI,
|
|
24040
|
+
effect: "execute",
|
|
24041
|
+
approval: "prompt_always"
|
|
24042
|
+
},
|
|
24043
|
+
weather_info: reader(CORE, { openWorld: true }),
|
|
24044
|
+
web_search: reader(CORE, { openWorld: true }),
|
|
24045
|
+
web_fetch: reader(CORE, { openWorld: true }),
|
|
24046
|
+
deep_research: reader(CORE, { openWorld: true }),
|
|
24047
|
+
check_shell_output: reader(),
|
|
24048
|
+
list_background_shells: reader(),
|
|
24049
|
+
file_read: reader(),
|
|
24050
|
+
grep_search: reader(),
|
|
24051
|
+
glob_files: reader(),
|
|
24052
|
+
get_file_tree: reader(),
|
|
24053
|
+
get_file_structure: reader(CLI),
|
|
24054
|
+
recent_changes: reader(),
|
|
24055
|
+
git_status: reader(),
|
|
24056
|
+
git_diff: reader(),
|
|
24057
|
+
git_log: reader(),
|
|
24058
|
+
git_branch: reader(),
|
|
24059
|
+
lattice_create_model: lattice(),
|
|
24060
|
+
lattice_add_entity: lattice(),
|
|
24061
|
+
lattice_set_value: lattice(),
|
|
24062
|
+
lattice_create_rule: lattice(),
|
|
24063
|
+
lattice_query: lattice(),
|
|
24064
|
+
lattice_explain: lattice()
|
|
24065
|
+
}));
|
|
24066
|
+
//#endregion
|
|
24067
|
+
//#region src/tools/gateway/toolPolicy.ts
|
|
23654
24068
|
/**
|
|
23655
|
-
*
|
|
24069
|
+
* Every policy decision about a tool, derived from its descriptor. `undefined` is a tool the
|
|
24070
|
+
* catalog could not resolve; it keeps the pre-descriptor fallback (prompt_default, read-only)
|
|
24071
|
+
* because feature-module and plugin tools do not register descriptors yet.
|
|
23656
24072
|
*/
|
|
23657
|
-
const
|
|
23658
|
-
|
|
23659
|
-
"
|
|
23660
|
-
"
|
|
24073
|
+
const UNKNOWN_TOOL_CATEGORY = "prompt_default";
|
|
24074
|
+
const READ_ONLY_EFFECTS = /* @__PURE__ */ new Set([
|
|
24075
|
+
"none",
|
|
24076
|
+
"session",
|
|
24077
|
+
"read"
|
|
23661
24078
|
]);
|
|
23662
|
-
z$1.object({
|
|
23663
|
-
categories: z$1.record(z$1.string(), ToolCategorySchema),
|
|
23664
|
-
trustedTools: z$1.array(z$1.string())
|
|
23665
|
-
});
|
|
23666
|
-
/**
|
|
23667
|
-
* Default tool categories
|
|
23668
|
-
*
|
|
23669
|
-
* Categories:
|
|
23670
|
-
* - auto_approve: Safe tools that don't need permission (math, search, datetime)
|
|
23671
|
-
* - prompt_always: Dangerous tools that ALWAYS need permission, cannot be trusted (file edits, shell commands)
|
|
23672
|
-
* - prompt_default: Tools that prompt by default but users can trust them (file reads, searches)
|
|
23673
|
-
*/
|
|
23674
|
-
const DEFAULT_TOOL_CATEGORIES = {
|
|
23675
|
-
math_evaluate: "auto_approve",
|
|
23676
|
-
current_datetime: "auto_approve",
|
|
23677
|
-
dice_roll: "auto_approve",
|
|
23678
|
-
prompt_enhancement: "auto_approve",
|
|
23679
|
-
find_definition: "auto_approve",
|
|
23680
|
-
ask_user_question: "auto_approve",
|
|
23681
|
-
weather_info: "prompt_default",
|
|
23682
|
-
agent_delegate: "auto_approve",
|
|
23683
|
-
check_agent_status: "auto_approve",
|
|
23684
|
-
list_background_agents: "auto_approve",
|
|
23685
|
-
cancel_background_agent: "auto_approve",
|
|
23686
|
-
resume_agent: "auto_approve",
|
|
23687
|
-
create_dynamic_agent: "auto_approve",
|
|
23688
|
-
coordinate_task: "auto_approve",
|
|
23689
|
-
decompose_task: "auto_approve",
|
|
23690
|
-
shared_context_read: "auto_approve",
|
|
23691
|
-
shared_context_write: "auto_approve",
|
|
23692
|
-
write_todos: "auto_approve",
|
|
23693
|
-
read_prior_todos: "auto_approve",
|
|
23694
|
-
log_decision: "auto_approve",
|
|
23695
|
-
track_blocker: "auto_approve",
|
|
23696
|
-
resolve_blocker: "auto_approve",
|
|
23697
|
-
request_review_gate: "auto_approve",
|
|
23698
|
-
work_item_create: "auto_approve",
|
|
23699
|
-
work_item_update: "auto_approve",
|
|
23700
|
-
work_item_close: "auto_approve",
|
|
23701
|
-
work_item_ready: "auto_approve",
|
|
23702
|
-
work_item_graph: "auto_approve",
|
|
23703
|
-
tool_search: "auto_approve",
|
|
23704
|
-
edit_file: "prompt_always",
|
|
23705
|
-
edit_local_file: "prompt_always",
|
|
23706
|
-
create_file: "prompt_always",
|
|
23707
|
-
delete_file: "prompt_always",
|
|
23708
|
-
shell_execute: "prompt_always",
|
|
23709
|
-
bash_execute: "prompt_always",
|
|
23710
|
-
write_shell_stdin: "prompt_always",
|
|
23711
|
-
kill_background_shell: "prompt_always",
|
|
23712
|
-
git_commit: "prompt_always",
|
|
23713
|
-
git_push: "prompt_always",
|
|
23714
|
-
skill: "prompt_always",
|
|
23715
|
-
web_search: "prompt_default",
|
|
23716
|
-
check_shell_output: "prompt_default",
|
|
23717
|
-
list_background_shells: "prompt_default",
|
|
23718
|
-
web_fetch: "prompt_default",
|
|
23719
|
-
deep_research: "prompt_default",
|
|
23720
|
-
file_read: "prompt_default",
|
|
23721
|
-
grep_search: "prompt_default",
|
|
23722
|
-
glob_files: "prompt_default",
|
|
23723
|
-
get_file_tree: "prompt_default",
|
|
23724
|
-
get_file_structure: "prompt_default",
|
|
23725
|
-
git_status: "prompt_default",
|
|
23726
|
-
git_diff: "prompt_default",
|
|
23727
|
-
git_log: "prompt_default",
|
|
23728
|
-
git_branch: "prompt_default"
|
|
23729
|
-
};
|
|
23730
24079
|
/**
|
|
23731
|
-
*
|
|
23732
|
-
*
|
|
23733
|
-
|
|
23734
|
-
|
|
23735
|
-
|
|
23736
|
-
|
|
23737
|
-
|
|
23738
|
-
|
|
23739
|
-
|
|
24080
|
+
* How far a source's own declarations are believed. Core, cli and builtin-module tools ship in
|
|
24081
|
+
* this repo and are reviewed, so their descriptor is taken as written. A plugin is third-party
|
|
24082
|
+
* code the user installed and enabled: it can be trusted per tool after a prompt, but cannot
|
|
24083
|
+
* skip the first prompt or claim to be read-only. MCP tools and lifecycle hooks always prompt.
|
|
24084
|
+
*/
|
|
24085
|
+
function categoryCeiling(source) {
|
|
24086
|
+
switch (source.kind) {
|
|
24087
|
+
case "mcp":
|
|
24088
|
+
case "hook": return "prompt_always";
|
|
24089
|
+
case "plugin": return "prompt_default";
|
|
24090
|
+
default: return;
|
|
24091
|
+
}
|
|
24092
|
+
}
|
|
24093
|
+
function believesDeclaredEffect(source) {
|
|
24094
|
+
return categoryCeiling(source) === void 0;
|
|
24095
|
+
}
|
|
24096
|
+
function toolCategory(descriptor) {
|
|
24097
|
+
if (!descriptor) return UNKNOWN_TOOL_CATEGORY;
|
|
24098
|
+
const ceiling = categoryCeiling(descriptor.source);
|
|
24099
|
+
if (ceiling === "prompt_always") return ceiling;
|
|
24100
|
+
if (ceiling === "prompt_default" && descriptor.approval === "auto_approve") return ceiling;
|
|
24101
|
+
return descriptor.approval;
|
|
24102
|
+
}
|
|
24103
|
+
/** Whether a prompt_default trust decision can be persisted for the tool. */
|
|
24104
|
+
function canTrustTool(descriptor) {
|
|
24105
|
+
return toolCategory(descriptor) !== "prompt_always";
|
|
24106
|
+
}
|
|
24107
|
+
/** Read-only tools run in plan mode and in parallel batches; the rest are blocked / sequential. */
|
|
24108
|
+
function isReadOnlyTool(descriptor) {
|
|
24109
|
+
if (!descriptor) return true;
|
|
24110
|
+
if (!believesDeclaredEffect(descriptor.source)) return false;
|
|
24111
|
+
return READ_ONLY_EFFECTS.has(descriptor.effect);
|
|
24112
|
+
}
|
|
24113
|
+
/** The shell command text the risk gate classifies, when the tool has one in `args`. */
|
|
24114
|
+
function commandTextOf(descriptor, args) {
|
|
24115
|
+
return stringArg(args, descriptor?.commandArg);
|
|
24116
|
+
}
|
|
24117
|
+
/** The path a file-writing tool will write, when the tool declares one and `args` carries it. */
|
|
24118
|
+
function writePathOf(descriptor, args) {
|
|
24119
|
+
const writePath = stringArg(args, descriptor?.writePathArg);
|
|
24120
|
+
return writePath ? writePath : void 0;
|
|
24121
|
+
}
|
|
24122
|
+
function stringArg(args, field) {
|
|
24123
|
+
if (!field || args === null || typeof args !== "object") return void 0;
|
|
24124
|
+
const value = args[field];
|
|
24125
|
+
return typeof value === "string" ? value : void 0;
|
|
24126
|
+
}
|
|
24127
|
+
//#endregion
|
|
24128
|
+
//#region src/tools/gateway/toolCatalog.ts
|
|
24129
|
+
const MCP_PREFIX = "mcp__";
|
|
24130
|
+
const HOOK_PREFIXES = ["agent_hook:", "skill_hook:"];
|
|
24131
|
+
function isHookName(toolName) {
|
|
24132
|
+
return HOOK_PREFIXES.some((prefix) => toolName.startsWith(prefix));
|
|
23740
24133
|
}
|
|
23741
24134
|
/**
|
|
23742
|
-
*
|
|
23743
|
-
|
|
23744
|
-
|
|
23745
|
-
|
|
24135
|
+
* Resolve a tool name without a catalog instance: the core table, then the MCP namespace
|
|
24136
|
+
* (`mcp__<server>__<tool>`), then the lifecycle-hook namespaces. Undefined means unknown.
|
|
24137
|
+
* ToolCatalog.resolve falls back to this after its registered descriptors.
|
|
24138
|
+
*/
|
|
24139
|
+
function resolveStaticToolDescriptor(toolName) {
|
|
24140
|
+
const core = CORE_TOOL_DESCRIPTORS.get(toolName);
|
|
24141
|
+
if (core) return core;
|
|
24142
|
+
if (toolName.startsWith(MCP_PREFIX)) return {
|
|
24143
|
+
source: {
|
|
24144
|
+
kind: "mcp",
|
|
24145
|
+
server: toolName.slice(5).split("__")[0]
|
|
24146
|
+
},
|
|
24147
|
+
effect: "execute",
|
|
24148
|
+
approval: "prompt_always"
|
|
24149
|
+
};
|
|
24150
|
+
if (isHookName(toolName)) return {
|
|
24151
|
+
source: { kind: "hook" },
|
|
24152
|
+
effect: "execute",
|
|
24153
|
+
approval: "prompt_always"
|
|
24154
|
+
};
|
|
23746
24155
|
}
|
|
23747
24156
|
/**
|
|
23748
|
-
*
|
|
23749
|
-
*
|
|
23750
|
-
*
|
|
23751
|
-
* @param toolName - Name of the tool to check
|
|
23752
|
-
* @param customCategories - Optional custom category overrides
|
|
23753
|
-
* @returns true if the tool is read-only, false if it's a write tool
|
|
24157
|
+
* Name -> descriptor lookup for one CLI process or ACP stack. Entry points create one and hand
|
|
24158
|
+
* it to their PermissionManager, which the permission gateway and the agent's read-only
|
|
24159
|
+
* predicate read it through.
|
|
23754
24160
|
*/
|
|
23755
|
-
|
|
23756
|
-
|
|
23757
|
-
|
|
24161
|
+
var ToolCatalog = class {
|
|
24162
|
+
constructor() {
|
|
24163
|
+
this.registered = /* @__PURE__ */ new Map();
|
|
24164
|
+
}
|
|
24165
|
+
/**
|
|
24166
|
+
* Add a descriptor for a tool the core table does not know. Core names and the MCP and hook
|
|
24167
|
+
* namespaces are reserved: nothing can re-declare a core tool, or declare itself into a
|
|
24168
|
+
* namespace whose descriptor comes from the name alone, with a lower tier.
|
|
24169
|
+
*/
|
|
24170
|
+
register(toolName, descriptor) {
|
|
24171
|
+
if (toolName.startsWith(MCP_PREFIX) || isHookName(toolName)) throw new Error(`Tool name "${toolName}" is in a reserved namespace and cannot be registered`);
|
|
24172
|
+
if (CORE_TOOL_DESCRIPTORS.has(toolName)) throw new Error(`Tool "${toolName}" is a core tool and already has a descriptor`);
|
|
24173
|
+
if (this.registered.has(toolName)) throw new Error(`Tool "${toolName}" already has a registered descriptor`);
|
|
24174
|
+
this.registered.set(toolName, descriptor);
|
|
24175
|
+
}
|
|
24176
|
+
resolve(toolName) {
|
|
24177
|
+
return this.registered.get(toolName) ?? resolveStaticToolDescriptor(toolName);
|
|
24178
|
+
}
|
|
24179
|
+
category(toolName) {
|
|
24180
|
+
return toolCategory(this.resolve(toolName));
|
|
24181
|
+
}
|
|
24182
|
+
canTrust(toolName) {
|
|
24183
|
+
return canTrustTool(this.resolve(toolName));
|
|
24184
|
+
}
|
|
24185
|
+
isReadOnly(toolName) {
|
|
24186
|
+
return isReadOnlyTool(this.resolve(toolName));
|
|
24187
|
+
}
|
|
24188
|
+
};
|
|
23758
24189
|
const PROJECT_CONTEXT_FILES = [
|
|
23759
24190
|
"CLAUDE.local.md",
|
|
23760
24191
|
"CLAUDE.md",
|
|
@@ -24495,7 +24926,7 @@ function mergeConfigs(global, project, local) {
|
|
|
24495
24926
|
enabled: merged.tools.enabled.filter((t) => !disabledSet.has(t))
|
|
24496
24927
|
};
|
|
24497
24928
|
const globalTrusted = new Set(global.trustedTools || []);
|
|
24498
|
-
merged.trustedTools = (merged.trustedTools || []).filter((t) => globalTrusted.has(t) || canTrustTool(t) && !disabledSet.has(t));
|
|
24929
|
+
merged.trustedTools = (merged.trustedTools || []).filter((t) => globalTrusted.has(t) || canTrustTool(resolveStaticToolDescriptor(t)) && !disabledSet.has(t));
|
|
24499
24930
|
return merged;
|
|
24500
24931
|
}
|
|
24501
24932
|
/**
|
|
@@ -25172,4 +25603,4 @@ var ConfigStore = class {
|
|
|
25172
25603
|
}
|
|
25173
25604
|
};
|
|
25174
25605
|
//#endregion
|
|
25175
|
-
export {
|
|
25606
|
+
export { PermissionDeniedError as $, ApiKeyType as A, stripToolArtifactMarkup as At, DEFAULT_TTS_PROVIDER as B, actorKindMarker as Bt, htmlFirstH1 as C, obfuscateApiKey as Ct, AGENT_QUEST_MCP_URI as D, signImageUrl as Dt, AGENT_QUEST_MANIFEST as E, secureParameters as Et, CONTEXT_WINDOW_SAFETY_BUFFER_TOKENS as F, ttsResponseTooLargeSchema as Ft, LOCATION_MAP_LANGUAGE as G, WEBSITE_URL as Gt, GENERATED_IMAGE_EXTENSION_RE as H, delegationPayloadSchema as Ht, CREDIT_DEDUCT_TRANSACTION_TYPES as I, withRetry as It, ModelBackend as J, MODEL_INFO_FIELD_GROUP_OF as K, ChatModels as L, ACTOR_COLOR_SLOTS as Lt, BRIEFCASE_CATALOG_QUERIES as M, tokenEstimateMultiplier as Mt, BedrockEmbeddingModel as N, ttsBase64ResponseSchema as Nt, ARTIFACT_DELIVERED_PLACEHOLDER as O, splitEquals as Ot, BriefcasePromptIdSchema as P, ttsRequestSchema as Pt, PROMPT_TEXT_MAX as Q, CompletionReasoningEffortSchema as R, DELEGATION_PAYLOAD_SCHEMA_NAME as Rt, htmlErrorTitle as S, joinReplySlots as St, AGENT_QUEST_ID as T, replacePromptVariables as Tt, ImageModels as U, selfClaimedActorKindSchema as Ut, DEGENERATE_FINISH_REASON as V, actorKindSchema as Vt, ImagePromptResolutionSchema as W, APP_NAME as Wt, OllamaEmbeddingModel as X, NotFoundError as Y, OpenAIEmbeddingModel as Z, NotAuthenticatedError as _, hasDeliverablePinnedArtifact as _t, commandTextOf as a, VisibilitySchema as at, SESSION_ID_PATTERN as b, isRetryableError as bt, writePathOf as c, assertAuthOriginMatchesApiKey as ct, getEnvironmentName as d, escapeThinkMarkers as dt, REVIEW_GATE_STATUS_VALUES as et, requireApiUrl as f, filterToolArtifactMarkup as ft, LOCAL_DEV_URL as g, googleMapsSearchUrl as gt, DeviceFlowClient as h, getQuestErrorCode as ht, ToolCatalog as i, SupportedFabFileMimeTypes as it, ArtifactTypeSchema as j, supportedVoiceGenerationVendor as jt, ARTIFACT_REMOVED_PLACEHOLDER as k, stripDeliveredArtifactBlocks as kt, ApiEndpointUnconfiguredError as l, buildPromptContext as lt, AuthenticatedApiClient as m, getMcpProviderMetadata as mt, extractCompactInstructions as n, SLUG_OWNED_BY_OTHER as nt, isReadOnlyTool as o, VoyageAIEmbeddingModel as ot, resolveApiEndpoint as p, generatedAudioResponseSchema as pt, McpServerName as q, loadContextFiles as r, SUBQUEST_STATUS_VALUES as rt, toolCategory as s, WORK_ITEM_STATUSES as st, ConfigStore as t, SEARCH_RESULT_CARDS_LANGUAGE as tt, getCreditsUrl as u, createThinkMarkerEscaper as ut, parseApiUrl as v, isEarlyStop as vt, escapeArtifactBodyJson as w, questReplyText as wt, isValidSessionId as x, isUserInitiatedAbort as xt, logger as y, isPlaceholderImageSigningSecret as yt, CreateArtifactRequestSchema as z, actorColorIndex as zt };
|