@byfriends/sdk 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs
CHANGED
|
@@ -3,23 +3,23 @@ import { dirname as __cjsShimDirname } from 'node:path';
|
|
|
3
3
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
4
4
|
const __dirname = __cjsShimDirname(__filename);
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
-
import * as fs$8 from "node:fs";
|
|
7
|
-
import Vt, { appendFileSync, chmodSync, closeSync, constants, createReadStream, createWriteStream, existsSync, fsyncSync, mkdirSync, openSync, promises, readFileSync, renameSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
8
|
-
import jn, { access, appendFile, chmod, copyFile, cp, lstat, mkdir, mkdtemp, open, readFile, readdir, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
9
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
10
7
|
import * as path$8 from "node:path";
|
|
11
8
|
import path, { basename, dirname, isAbsolute, join, normalize, posix, relative, resolve, win32 } from "node:path";
|
|
12
|
-
import I, { createWriteStream
|
|
9
|
+
import I, { createWriteStream } from "fs";
|
|
13
10
|
import Kr, { EventEmitter } from "events";
|
|
14
11
|
import * as path$1$1 from "path";
|
|
15
12
|
import $s, { dirname as dirname$1, parse } from "path";
|
|
16
13
|
import { Buffer as Buffer$1 } from "buffer";
|
|
17
14
|
import * as fs$9 from "fs/promises";
|
|
18
|
-
import { writeFile
|
|
15
|
+
import { writeFile } from "fs/promises";
|
|
19
16
|
import Ns, { PassThrough, Readable } from "node:stream";
|
|
20
17
|
import { finished, pipeline as pipeline$1 } from "node:stream/promises";
|
|
21
18
|
import * as ks from "zlib";
|
|
22
19
|
import qr from "zlib";
|
|
20
|
+
import * as fs$8 from "node:fs";
|
|
21
|
+
import Vt, { appendFileSync, chmodSync, closeSync, constants, createReadStream, createWriteStream as createWriteStream$1, existsSync, fsyncSync, mkdirSync, openSync, promises, readFileSync, renameSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
22
|
+
import jn, { access, appendFile, chmod, cp, lstat, mkdir, mkdtemp, open, readFile, readdir, rename, rm, stat, unlink, writeFile as writeFile$1 } from "node:fs/promises";
|
|
23
23
|
import { z } from "zod";
|
|
24
24
|
import * as posixPath from "node:path/posix";
|
|
25
25
|
import * as win32Path from "node:path/win32";
|
|
@@ -10288,7 +10288,7 @@ var require_gaxios = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
10288
10288
|
}
|
|
10289
10289
|
static async #getFetch() {
|
|
10290
10290
|
const hasWindow = typeof window !== "undefined" && !!window;
|
|
10291
|
-
this.#fetch ||= hasWindow ? window.fetch : (await import("./src-
|
|
10291
|
+
this.#fetch ||= hasWindow ? window.fetch : (await import("./src-Dedv0Wfs.mjs")).default;
|
|
10292
10292
|
return this.#fetch;
|
|
10293
10293
|
}
|
|
10294
10294
|
/**
|
|
@@ -36078,11 +36078,11 @@ var NodeDownloader = class {
|
|
|
36078
36078
|
if (params.downloadPath) {
|
|
36079
36079
|
const response = await downloadFile(params, apiClient);
|
|
36080
36080
|
if (response instanceof HttpResponse) {
|
|
36081
|
-
const writer = createWriteStream
|
|
36081
|
+
const writer = createWriteStream(params.downloadPath);
|
|
36082
36082
|
Readable.fromWeb(response.responseInternal.body).pipe(writer);
|
|
36083
36083
|
await finished(writer);
|
|
36084
36084
|
} else try {
|
|
36085
|
-
await writeFile
|
|
36085
|
+
await writeFile(params.downloadPath, response, { encoding: "base64" });
|
|
36086
36086
|
} catch (error) {
|
|
36087
36087
|
throw new Error(`Failed to write file to ${params.downloadPath}: ${error}`);
|
|
36088
36088
|
}
|
|
@@ -38110,7 +38110,7 @@ function normalizeOpenAICompatToolSchema(schema) {
|
|
|
38110
38110
|
}
|
|
38111
38111
|
function ensureOpenAICompatPropertyTypes(schema) {
|
|
38112
38112
|
const normalized = cloneJsonValue(schema);
|
|
38113
|
-
if (!isRecord$
|
|
38113
|
+
if (!isRecord$5(normalized)) throw new Error("JSON Schema root must normalize to an object.");
|
|
38114
38114
|
recurseSchema(normalized);
|
|
38115
38115
|
return normalized;
|
|
38116
38116
|
}
|
|
@@ -38171,7 +38171,7 @@ function resolveLocalJsonPointer(root, ref) {
|
|
|
38171
38171
|
let current = root;
|
|
38172
38172
|
for (const rawPart of ref.slice(2).split("/")) {
|
|
38173
38173
|
const part = unescapeJsonPointerPart(rawPart);
|
|
38174
|
-
if (isRecord$
|
|
38174
|
+
if (isRecord$5(current)) {
|
|
38175
38175
|
if (!hasOwn$1(current, part)) return { found: false };
|
|
38176
38176
|
current = current[part];
|
|
38177
38177
|
} else if (Array.isArray(current)) {
|
|
@@ -38193,20 +38193,20 @@ function parseJsonPointerArrayIndex(part) {
|
|
|
38193
38193
|
return Number(part);
|
|
38194
38194
|
}
|
|
38195
38195
|
function recurseSchema(node) {
|
|
38196
|
-
if (!isRecord$
|
|
38196
|
+
if (!isRecord$5(node)) return;
|
|
38197
38197
|
visitChildSchemas(node, normalizeProperty);
|
|
38198
38198
|
}
|
|
38199
38199
|
function visitChildSchemas(node, visit) {
|
|
38200
38200
|
for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
|
|
38201
38201
|
const value = node[key];
|
|
38202
38202
|
if (kind === "single") {
|
|
38203
|
-
if (isRecord$
|
|
38203
|
+
if (isRecord$5(value)) visit(value);
|
|
38204
38204
|
} else if (kind === "array") {
|
|
38205
38205
|
if (Array.isArray(value)) for (const item of value) visit(item);
|
|
38206
38206
|
} else if (kind === "map") {
|
|
38207
|
-
if (isRecord$
|
|
38207
|
+
if (isRecord$5(value)) for (const item of Object.values(value)) visit(item);
|
|
38208
38208
|
} else if (kind === "schema-or-array") {
|
|
38209
|
-
if (isRecord$
|
|
38209
|
+
if (isRecord$5(value)) visit(value);
|
|
38210
38210
|
else if (Array.isArray(value)) for (const item of value) visit(item);
|
|
38211
38211
|
}
|
|
38212
38212
|
}
|
|
@@ -38218,7 +38218,7 @@ function childSchemaKeysForParentType(parentType) {
|
|
|
38218
38218
|
});
|
|
38219
38219
|
}
|
|
38220
38220
|
function normalizeProperty(node) {
|
|
38221
|
-
if (!isRecord$
|
|
38221
|
+
if (!isRecord$5(node)) return;
|
|
38222
38222
|
if (!hasOwn$1(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
|
|
38223
38223
|
const enumValues = node["enum"];
|
|
38224
38224
|
if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
|
|
@@ -38282,14 +38282,14 @@ function hasAnyKey(obj, keys) {
|
|
|
38282
38282
|
}
|
|
38283
38283
|
function cloneJsonValue(value) {
|
|
38284
38284
|
if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
|
|
38285
|
-
if (isRecord$
|
|
38285
|
+
if (isRecord$5(value)) {
|
|
38286
38286
|
const cloned = {};
|
|
38287
38287
|
for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
|
|
38288
38288
|
return cloned;
|
|
38289
38289
|
}
|
|
38290
38290
|
return value;
|
|
38291
38291
|
}
|
|
38292
|
-
function isRecord$
|
|
38292
|
+
function isRecord$5(value) {
|
|
38293
38293
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38294
38294
|
}
|
|
38295
38295
|
function hasOwn$1(obj, key) {
|
|
@@ -54783,7 +54783,7 @@ function isAbortError(err) {
|
|
|
54783
54783
|
if (err instanceof Error) return err.name === "AbortError";
|
|
54784
54784
|
return false;
|
|
54785
54785
|
}
|
|
54786
|
-
function errorMessage$
|
|
54786
|
+
function errorMessage$2(err) {
|
|
54787
54787
|
if (err instanceof Error) return err.message;
|
|
54788
54788
|
return String(err);
|
|
54789
54789
|
}
|
|
@@ -58027,7 +58027,7 @@ function parseSkillText(options) {
|
|
|
58027
58027
|
throw error;
|
|
58028
58028
|
}
|
|
58029
58029
|
const frontmatter = parsed.data ?? {};
|
|
58030
|
-
if (!isRecord$
|
|
58030
|
+
if (!isRecord$4(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
|
|
58031
58031
|
const metadata = normalizeMetadata(frontmatter);
|
|
58032
58032
|
if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
|
|
58033
58033
|
const name = nonEmptyString$3(metadata.name);
|
|
@@ -58140,7 +58140,7 @@ function tokenizeArgs(raw) {
|
|
|
58140
58140
|
function nonEmptyString$3(value) {
|
|
58141
58141
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
58142
58142
|
}
|
|
58143
|
-
function isRecord$
|
|
58143
|
+
function isRecord$4(value) {
|
|
58144
58144
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
58145
58145
|
}
|
|
58146
58146
|
//#endregion
|
|
@@ -58148,14 +58148,36 @@ function isRecord$5(value) {
|
|
|
58148
58148
|
var mcp_config_default = "---\nname: mcp-config\ndescription: Configure MCP servers and handle MCP OAuth login.\n---\n\n# Interactive MCP server configuration\n\nThe user invoked this skill through `/mcp-config` or `/skill:mcp-config`.\nEither they want to log into an MCP server that asked for OAuth, or they\nwant to edit the `mcp.json` that lists MCP servers. The work is small and\nlocal — handle it on this turn yourself, no agents or planning todos.\n\nPick the flow from the user's message and your tool list:\n\n- An `mcp__<server>__authenticate` tool is in your list, the user says\n \"log in\" / \"auth\" / \"sign in\", they invoke `/mcp-config login\n <server>`, or they quote a `needs-auth` status → **Login**.\n- Add / edit / remove / list of an `mcp.json` entry → **Config edit**.\n- Bare `/mcp-config` with no `authenticate` tool in your list →\n **Config edit**. If there were a pending login, the authenticate tool\n would be in your list.\n\n## Login\n\nEach MCP server in `needs-auth` exposes one `mcp__<server>__authenticate`\ntool. Call it for the server the user means — its own description owns\nthe OAuth UX (printing the URL, blocking on the callback, reconnecting on\nsuccess). Surface its output verbatim, including the authorization URL\nunchanged; the URL contains state and PKCE parameters that break if\nedited.\n\nIf the user named a server that has no authenticate tool, say so in one\nsentence and stop — do **not** fall into config edit. They're trying to\nlog in to a server that isn't currently waiting for login; quietly\nrewriting `mcp.json` would be the wrong fix. If multiple authenticate\ntools exist and the user didn't name one, ask which.\n\n## Config edit\n\nConfig lives in two files; on key collision the project file overrides\nthe user-global one:\n\n- User-global: `~/.byf/mcp.json` (or `$BYF_HOME/mcp.json` if\n set). Use for servers you want everywhere.\n- Project-local: `<cwd>/.byf/mcp.json`. Mention once that stdio\n entries spawn commands at session start, so this should only live in\n trusted repos.\n\nBoth files wrap their entries the same way:\n\n```json\n{ \"mcpServers\": { \"<name>\": { /* entry */ } } }\n```\n\nA minimal stdio entry needs `command` (+ optional `args`, `env`, `cwd`).\nA minimal http entry needs `url`; add `bearerTokenEnvVar: \"ENV_NAME\"` for\nservers that authenticate with a static bearer token from the\nenvironment. Servers that use OAuth take no token field — the login flow\nabove handles them. `transport` is inferred from `command` vs `url`, so\nomit it. For less common fields (`enabled`, `startupTimeoutMs`,\n`toolTimeoutMs`, `enabledTools`, `disabledTools`, `headers`) the source of\ntruth is `McpServerStdioConfigSchema` / `McpServerHttpConfigSchema` in\n`packages/agent-core/src/config/schema.ts`.\n\nIf the user only wants to **see** what's configured, read both files,\nshow a merged view, and stop — no scope prompt, no write.\n\nFor changes, the flow is:\n\n1. **Pick a scope.** Infer it from the user's words when you can\n (project / repo / this checkout / cwd → project; global / everywhere /\n all projects → user-global). When the request is genuinely scope-less,\n use one `AskUserQuestion` to ask user-global vs project-local, defaulting\n to user-global. Use plain text for every other question — `AskUserQuestion`\n is a poor fit for free-form input. If the user dismisses the scope\n question, stop; you can't safely guess where they wanted the change.\n2. **Read and announce.** Read the target file (a missing or empty file\n is fine; you'll create `{ \"mcpServers\": {} }`). If JSON parsing fails,\n surface the error verbatim and stop — silently overwriting a broken\n file could destroy work. Then show the user the target path, what's\n currently in it, and the entry you're about to write or delete. This\n is for transparency, not a confirmation gate — the Edit/Write\n permission prompt is the real gate, and your message is what gives\n the user context when that prompt appears. In yolo / afk modes there\n is no prompt, which is those modes' explicit contract.\n3. **Write and tell them how to reload MCP servers.** Preserve unrelated\n entries and the `mcpServers` wrapper. MCP servers load at session\n start, so tell the user to start a new session (for example `/new`) or\n restart BYF for the change to take effect.\n\n## Secrets\n\nDon't store secrets (tokens, keys, passwords) as literals in\n`mcp.json` — it's a plain config file on disk. http servers should use\n`bearerTokenEnvVar` to reference an env var instead; if a stdio entry\nmust inline one in `env`, warn the user before writing.\n";
|
|
58149
58149
|
//#endregion
|
|
58150
58150
|
//#region ../agent-core/src/skill/builtin/mcp-config.ts
|
|
58151
|
-
const PSEUDO_PATH = "builtin://mcp-config";
|
|
58152
|
-
const parsed = parseSkillText({
|
|
58151
|
+
const PSEUDO_PATH$1 = "builtin://mcp-config";
|
|
58152
|
+
const parsed$1 = parseSkillText({
|
|
58153
58153
|
skillMdPath: "/builtin/skills/mcp-config.md",
|
|
58154
58154
|
skillDirName: "mcp-config",
|
|
58155
58155
|
source: "builtin",
|
|
58156
58156
|
text: mcp_config_default
|
|
58157
58157
|
});
|
|
58158
58158
|
const MCP_CONFIG_SKILL = {
|
|
58159
|
+
...parsed$1,
|
|
58160
|
+
path: PSEUDO_PATH$1,
|
|
58161
|
+
dir: PSEUDO_PATH$1,
|
|
58162
|
+
metadata: {
|
|
58163
|
+
...parsed$1.metadata,
|
|
58164
|
+
type: parsed$1.metadata.type ?? "inline",
|
|
58165
|
+
disableModelInvocation: true
|
|
58166
|
+
}
|
|
58167
|
+
};
|
|
58168
|
+
//#endregion
|
|
58169
|
+
//#region ../agent-core/src/skill/builtin/update-config.md
|
|
58170
|
+
var update_config_default = "---\nname: update-config\ndescription: Audit and fix ~/.byf/config.toml — remove deprecated fields, migrate legacy settings, and flag semantic conflicts.\n---\n\n# Audit and fix config.toml\n\nThe user invoked this skill via `/update-config` or `/skill:update-config`.\nThe goal is to bring `~/.byf/config.toml` in line with the current BYF schema:\nremove deprecated fields, migrate legacy settings, and point out semantic\nconflicts that a deterministic linter cannot catch. The work is small and\nlocal — handle it on this turn yourself, no agents or planning todos.\n\n## Read the config\n\n1. **Resolve the path.** Default: `~/.byf/config.toml` (or\n `$BYF_HOME/config.toml` if that env var is set). If the user passed a path\n as an argument, use that instead.\n2. **Read the file.** If it does not exist, say so and stop — there is nothing\n to update. If the TOML fails to parse, surface the parse error verbatim and\n **stop** — do not overwrite a broken file, that could destroy the user's\n work.\n3. **Never echo secrets.** `config.toml` stores `api_key` secret values, and\n `oauth` references (a `{ storage, key }` handle that points at a\n file/keyring entry — not the token itself). When you describe what you\n found or plan to change, state only that a credential is present or\n absent — never quote the `api_key` value itself, not even partially.\n\n## What to check for\n\nField-level validity (which keys exist, what types and enums are allowed) is\n**not** something to reproduce here. The single source of truth is\n`ByfConfigSchema` in `packages/agent-core/src/config/schema.ts` — read it when\nyou need to confirm whether a field is recognized and what values it accepts.\n\nThe checks below fall into three groups. Report findings from all three before\nmaking any change.\n\n### 1. Deprecated, renamed, and migrated fields\n\nThese are historical fields that the schema no longer accepts or has replaced.\nDelete them, except where the table says to rename or migrate:\n\n| Field | Action |\n|---|---|\n| `default_yolo` / `defaultYolo` (top-level) | Remove. Use `yolo` instead. |\n| `services.byf_search` | Remove. (Legacy service, superseded by `[services.web_search]`.) |\n| `services.byf_fetch` | Remove. Use `[services.fetch_url]` instead. |\n| `loop_control.max_steps_per_run` | **Rename** to `max_steps_per_turn`, preserving the value. First check whether `max_steps_per_turn` is already present: if so, the old key is a stale duplicate — just delete it; if not, write `max_steps_per_turn` with the old value, then delete `max_steps_per_run`. (The runtime auto-copies the value on read, but this skill edits the file directly and skips that roundtrip — so you must perform the rename yourself to avoid losing the limit.) |\n| `default_thinking` (top-level boolean) | Migrate — see below. |\n\n**`default_thinking` migration** (matches the runtime precedence in\n`byf-tui.ts`: a `[thinking]` block wins over `default_thinking`):\n\n- If `[thinking]` already has `mode` or `effort` set, `default_thinking` was\n never effective — just remove it.\n- Otherwise migrate by value: `true` → write `[thinking]` with\n `mode = \"on\"` and `effort = \"high\"`; `false` → `[thinking]` with\n `mode = \"off\"`. Then remove `default_thinking`.\n\n> **Raw-passthrough blind spot.** Fields stripped by the schema (like\n> `byf_search`, `byf_fetch`) survive inside `config.raw` and get written back\n> on every read→write roundtrip, so they linger in the file even though they\n> have no effect. Deleting them here is the only way to clear them — that is\n> the core value of this skill.\n\n### 2. Semantic conflicts (the part a linter cannot enumerate)\n\nLook for cross-field problems that require understanding intent:\n\n- A provider with **both** `api_key` and `oauth` configured — these are\n mutually exclusive; ask which one the user meant.\n- `thinking.mode = \"off\"` **and** a non-empty `thinking.effort` — the effort\n is ignored; suggest removing it or flipping the mode.\n- `models.<alias>.capabilities` containing a value not in the valid set. The\n valid set is the single source of truth: read `CAPABILITY_DEFINITIONS` (or\n the derived `VALID_CAPABILITIES`) in\n `packages/agent-core/src/providers/runtime-provider.ts`. Comparison is\n case-insensitive at runtime, so flag only genuine mismatches.\n- A model alias, `default_provider`, or `default_model` that points at a\n provider or model that does not exist — a dangling reference. Report it; do\n **not** delete it, the user may be mid-edit.\n\n### 3. Housekeeping\n\n- Top-level keys that are not in `ByfConfigSchema` (and not a deprecated key\n above) — likely typos or leftovers from an old version. Report them; only\n remove with user confirmation. Note that legitimate unknown keys (e.g.\n `theme`, `notifications`) are preserved by design through `config.raw`, so\n do not touch keys the user clearly added on purpose.\n- **Nested keys inside containers** (`[providers.<name>]`, `[models.<alias>]`,\n `[services]`, `[background]`, `[loop_control]`, `[thinking]`,\n `[permission]`). A key that the corresponding section of `ByfConfigSchema`\n does not recognize is silently dropped by the parser and has no effect — a\n common cause is a typo (e.g. `max_context_tokns` instead of\n `max_context_size`). Cross-check each sub-key against the schema and flag\n any mismatch; fix only with user confirmation. Note that `[permission]`\n still accepts the legacy `deny`/`allow`/`ask` array shorthand, so do not\n report those as unknown.\n\n## Make changes\n\nFor each change, show the user **what is currently there → what you plan to\nwrite** before editing. Then apply edits with Write/Edit. The Edit/Write\npermission prompt is the real safety gate — your summary is what gives the\nuser context when that prompt appears. There is no automatic backup; if the\nuser wants one, suggest they copy the file first.\n\nAfter editing, tell the user to start a new session (e.g. `/new`) or restart\nBYF for the config change to take effect.\n";
|
|
58171
|
+
//#endregion
|
|
58172
|
+
//#region ../agent-core/src/skill/builtin/update-config.ts
|
|
58173
|
+
const PSEUDO_PATH = "builtin://update-config";
|
|
58174
|
+
const parsed = parseSkillText({
|
|
58175
|
+
skillMdPath: "/builtin/skills/update-config.md",
|
|
58176
|
+
skillDirName: "update-config",
|
|
58177
|
+
source: "builtin",
|
|
58178
|
+
text: update_config_default
|
|
58179
|
+
});
|
|
58180
|
+
const UPDATE_CONFIG_SKILL = {
|
|
58159
58181
|
...parsed,
|
|
58160
58182
|
path: PSEUDO_PATH,
|
|
58161
58183
|
dir: PSEUDO_PATH,
|
|
@@ -58169,6 +58191,7 @@ const MCP_CONFIG_SKILL = {
|
|
|
58169
58191
|
//#region ../agent-core/src/skill/builtin/index.ts
|
|
58170
58192
|
function registerBuiltinSkills(registry) {
|
|
58171
58193
|
registry.registerBuiltinSkill(MCP_CONFIG_SKILL);
|
|
58194
|
+
registry.registerBuiltinSkill(UPDATE_CONFIG_SKILL);
|
|
58172
58195
|
}
|
|
58173
58196
|
//#endregion
|
|
58174
58197
|
//#region ../agent-core/src/skill/scanner.ts
|
|
@@ -63468,7 +63491,7 @@ async function downloadAndInstallRg(shareDir) {
|
|
|
63468
63491
|
clearTimeout(timeoutHandle);
|
|
63469
63492
|
}
|
|
63470
63493
|
if (!resp.ok || resp.body === null) throw new Error(`Failed to download ripgrep: HTTP ${String(resp.status)} ${resp.statusText}`);
|
|
63471
|
-
const write = createWriteStream(archivePath);
|
|
63494
|
+
const write = createWriteStream$1(archivePath);
|
|
63472
63495
|
await pipeline$1(Readable.fromWeb(resp.body), write);
|
|
63473
63496
|
await verifyArchiveChecksum(archivePath, archiveName, expectedSha256);
|
|
63474
63497
|
if (isWindows) await extractRgFromZip(archivePath, destination);
|
|
@@ -63529,7 +63552,7 @@ async function extractRgFromZip(archivePath, destination) {
|
|
|
63529
63552
|
zipfile.close();
|
|
63530
63553
|
return;
|
|
63531
63554
|
}
|
|
63532
|
-
const out = createWriteStream(destination);
|
|
63555
|
+
const out = createWriteStream$1(destination);
|
|
63533
63556
|
(async () => {
|
|
63534
63557
|
try {
|
|
63535
63558
|
await pipeline$1(stream, out);
|
|
@@ -67347,7 +67370,7 @@ const OptionalStringSchema = z.preprocess((value) => {
|
|
|
67347
67370
|
if (typeof value === "string") return value;
|
|
67348
67371
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
67349
67372
|
}, z.string().optional());
|
|
67350
|
-
const HookSpecificOutputSchema = z.preprocess((value) => isRecord$
|
|
67373
|
+
const HookSpecificOutputSchema = z.preprocess((value) => isRecord$3(value) ? value : void 0, z.looseObject({
|
|
67351
67374
|
message: OptionalStringSchema,
|
|
67352
67375
|
permissionDecision: z.unknown().optional(),
|
|
67353
67376
|
permissionDecisionReason: OptionalStringSchema
|
|
@@ -67366,7 +67389,7 @@ async function runHook(command, input, options) {
|
|
|
67366
67389
|
detached: process.platform !== "win32"
|
|
67367
67390
|
});
|
|
67368
67391
|
} catch (error) {
|
|
67369
|
-
return allowResult({ stderr: errorMessage$
|
|
67392
|
+
return allowResult({ stderr: errorMessage$1(error) });
|
|
67370
67393
|
}
|
|
67371
67394
|
return new Promise((resolve) => {
|
|
67372
67395
|
let stdout = "";
|
|
@@ -67414,7 +67437,7 @@ async function runHook(command, input, options) {
|
|
|
67414
67437
|
child.on("error", (error) => {
|
|
67415
67438
|
settle(allowResult({
|
|
67416
67439
|
stdout,
|
|
67417
|
-
stderr: stderr + errorMessage$
|
|
67440
|
+
stderr: stderr + errorMessage$1(error)
|
|
67418
67441
|
}));
|
|
67419
67442
|
});
|
|
67420
67443
|
child.on("close", (code) => {
|
|
@@ -67507,10 +67530,10 @@ function tryKillProcess(child, signal) {
|
|
|
67507
67530
|
} catch {}
|
|
67508
67531
|
}
|
|
67509
67532
|
}
|
|
67510
|
-
function isRecord$
|
|
67533
|
+
function isRecord$3(value) {
|
|
67511
67534
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
67512
67535
|
}
|
|
67513
|
-
function errorMessage$
|
|
67536
|
+
function errorMessage$1(error) {
|
|
67514
67537
|
return error instanceof Error ? error.message : String(error);
|
|
67515
67538
|
}
|
|
67516
67539
|
//#endregion
|
|
@@ -70175,6 +70198,7 @@ const YoloOutsideWorkspacePermissionPolicy = {
|
|
|
70175
70198
|
evaluate({ agent, mode, toolCallContext }) {
|
|
70176
70199
|
if (mode !== "yolo") return void 0;
|
|
70177
70200
|
const toolName = toolCallContext.toolCall.name;
|
|
70201
|
+
if (isDefaultAutoAllowTool(toolName)) return void 0;
|
|
70178
70202
|
const toolAccess = FILE_ACCESS_TOOLS[toolName];
|
|
70179
70203
|
if (toolAccess === void 0) return void 0;
|
|
70180
70204
|
const [operation, displayOperation] = toolAccess;
|
|
@@ -70442,8 +70466,8 @@ function approvalTelemetryMode(mode) {
|
|
|
70442
70466
|
//#endregion
|
|
70443
70467
|
//#region ../agent-core/src/agent/records/migration/v1.1.ts
|
|
70444
70468
|
function isLegacyToolCall(v) {
|
|
70445
|
-
if (!isRecord$
|
|
70446
|
-
return v["type"] === "function" && typeof v["id"] === "string" && isRecord$
|
|
70469
|
+
if (!isRecord$2(v)) return false;
|
|
70470
|
+
return v["type"] === "function" && typeof v["id"] === "string" && isRecord$2(v["function"]);
|
|
70447
70471
|
}
|
|
70448
70472
|
function migrateToolCall(v) {
|
|
70449
70473
|
const { function: fn, ...rest } = v;
|
|
@@ -70453,7 +70477,7 @@ function migrateToolCall(v) {
|
|
|
70453
70477
|
arguments: fn.arguments
|
|
70454
70478
|
};
|
|
70455
70479
|
}
|
|
70456
|
-
function isRecord$
|
|
70480
|
+
function isRecord$2(value) {
|
|
70457
70481
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
70458
70482
|
}
|
|
70459
70483
|
const MIGRATIONS = [{
|
|
@@ -78265,7 +78289,7 @@ function parseToolCallArguments(raw) {
|
|
|
78265
78289
|
} catch (error) {
|
|
78266
78290
|
return {
|
|
78267
78291
|
success: false,
|
|
78268
|
-
error: errorMessage$
|
|
78292
|
+
error: errorMessage$2(error)
|
|
78269
78293
|
};
|
|
78270
78294
|
}
|
|
78271
78295
|
}
|
|
@@ -78317,7 +78341,7 @@ async function prepareToolCall(step, call) {
|
|
|
78317
78341
|
toolCallId: call.toolCall.id,
|
|
78318
78342
|
error
|
|
78319
78343
|
});
|
|
78320
|
-
const output = error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$
|
|
78344
|
+
const output = error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$2(error)}`;
|
|
78321
78345
|
await dispatchToolCall(step, call, effectiveArgs);
|
|
78322
78346
|
return { task: makeResolvedToolCallTask(makeErrorToolResult(call, effectiveArgs, output)) };
|
|
78323
78347
|
}
|
|
@@ -78377,7 +78401,7 @@ async function runPrepareToolExecutionHook(step, call) {
|
|
|
78377
78401
|
return {
|
|
78378
78402
|
kind: "hookFailed",
|
|
78379
78403
|
args,
|
|
78380
|
-
output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$
|
|
78404
|
+
output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$2(error)}`
|
|
78381
78405
|
};
|
|
78382
78406
|
}
|
|
78383
78407
|
const effectiveArgs = hookResult?.updatedArgs ?? args;
|
|
@@ -78421,7 +78445,7 @@ async function runRunnableToolCall(step, call, effectiveArgs, metadata, executio
|
|
|
78421
78445
|
toolCallId: toolCall.id,
|
|
78422
78446
|
error
|
|
78423
78447
|
});
|
|
78424
|
-
return makeErrorToolResult(call, effectiveArgs, aborted ? `Tool "${toolName}" was aborted` : `Tool "${toolName}" failed: ${errorMessage$
|
|
78448
|
+
return makeErrorToolResult(call, effectiveArgs, aborted ? `Tool "${toolName}" was aborted` : `Tool "${toolName}" failed: ${errorMessage$2(error)}`);
|
|
78425
78449
|
}
|
|
78426
78450
|
return makeToolResult(call, effectiveArgs, toolResult);
|
|
78427
78451
|
}
|
|
@@ -78453,7 +78477,7 @@ async function finalizePendingToolResult(step, pendingResult) {
|
|
|
78453
78477
|
toolCallId: pendingResult.toolCall.id,
|
|
78454
78478
|
error
|
|
78455
78479
|
});
|
|
78456
|
-
const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$
|
|
78480
|
+
const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$2(error)}`;
|
|
78457
78481
|
return {
|
|
78458
78482
|
...pendingResult,
|
|
78459
78483
|
stopTurn: pendingResult.stopTurn,
|
|
@@ -78815,7 +78839,7 @@ async function runTurn(input) {
|
|
|
78815
78839
|
usage
|
|
78816
78840
|
};
|
|
78817
78841
|
}
|
|
78818
|
-
dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$
|
|
78842
|
+
dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$2(error)));
|
|
78819
78843
|
throw error;
|
|
78820
78844
|
}
|
|
78821
78845
|
return {
|
|
@@ -85325,595 +85349,6 @@ function isFileExistsError(error) {
|
|
|
85325
85349
|
return typeof error === "object" && error !== null && error.code === "EEXIST";
|
|
85326
85350
|
}
|
|
85327
85351
|
//#endregion
|
|
85328
|
-
//#region ../agent-core/src/config/update-rules.ts
|
|
85329
|
-
const REMOVED_RULES = [
|
|
85330
|
-
{
|
|
85331
|
-
path: "default_yolo",
|
|
85332
|
-
pathParts: ["default_yolo"],
|
|
85333
|
-
kind: "removed",
|
|
85334
|
-
detail: "Top-level field default_yolo is removed. Use yolo instead.",
|
|
85335
|
-
deprecatedSince: "pre-0.1.0"
|
|
85336
|
-
},
|
|
85337
|
-
{
|
|
85338
|
-
path: "defaultYolo",
|
|
85339
|
-
pathParts: ["defaultYolo"],
|
|
85340
|
-
kind: "removed",
|
|
85341
|
-
detail: "Top-level field defaultYolo is removed. Use yolo instead.",
|
|
85342
|
-
deprecatedSince: "pre-0.1.0"
|
|
85343
|
-
},
|
|
85344
|
-
{
|
|
85345
|
-
path: "services.byf_search",
|
|
85346
|
-
pathParts: ["services", "byf_search"],
|
|
85347
|
-
kind: "removed",
|
|
85348
|
-
detail: "Deprecated service byf_search is removed.",
|
|
85349
|
-
deprecatedSince: "pre-0.1.0"
|
|
85350
|
-
},
|
|
85351
|
-
{
|
|
85352
|
-
path: "services.byf_fetch",
|
|
85353
|
-
pathParts: ["services", "byf_fetch"],
|
|
85354
|
-
kind: "removed",
|
|
85355
|
-
detail: "Deprecated service byf_fetch is removed. Use services.fetch_url instead.",
|
|
85356
|
-
deprecatedSince: "pre-0.1.0"
|
|
85357
|
-
}
|
|
85358
|
-
];
|
|
85359
|
-
const RENAMED_RULES = [{
|
|
85360
|
-
path: "loop_control.max_steps_per_run",
|
|
85361
|
-
pathParts: ["loop_control", "max_steps_per_run"],
|
|
85362
|
-
kind: "renamed",
|
|
85363
|
-
detail: "Renamed to max_steps_per_turn.",
|
|
85364
|
-
deprecatedSince: "pre-0.1.0"
|
|
85365
|
-
}];
|
|
85366
|
-
const MIGRATED_RULES = [{
|
|
85367
|
-
path: "default_thinking",
|
|
85368
|
-
pathParts: ["default_thinking"],
|
|
85369
|
-
kind: "migrated",
|
|
85370
|
-
detail: "Migrate default_thinking to [thinking] block.",
|
|
85371
|
-
deprecatedSince: "pre-0.1.0"
|
|
85372
|
-
}];
|
|
85373
|
-
/**
|
|
85374
|
-
* Combined list of all deprecated-field rules.
|
|
85375
|
-
*
|
|
85376
|
-
* Order within the list does not affect correctness (the CLI groups by kind
|
|
85377
|
-
* at display time), but a stable order helps test expectations.
|
|
85378
|
-
*/
|
|
85379
|
-
const DEPRECATED_FIELD_RULES = [
|
|
85380
|
-
...REMOVED_RULES,
|
|
85381
|
-
...RENAMED_RULES,
|
|
85382
|
-
...MIGRATED_RULES
|
|
85383
|
-
];
|
|
85384
|
-
//#endregion
|
|
85385
|
-
//#region ../agent-core/src/providers/runtime-provider.ts
|
|
85386
|
-
function resolveRuntimeProvider(input) {
|
|
85387
|
-
const modelName = input.model ?? input.config.defaultModel;
|
|
85388
|
-
if (modelName === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, "No model is selected. Set default_model in config.toml or pass a configured model alias.");
|
|
85389
|
-
const alias = input.config.models?.[modelName];
|
|
85390
|
-
if (alias === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Model "${modelName}" is not configured in config.toml. Add a [models."${modelName}"] entry with max_context_size.`);
|
|
85391
|
-
const resolvedModel = alias.model;
|
|
85392
|
-
const providerName = alias.provider ?? input.config.defaultProvider;
|
|
85393
|
-
const providerConfig = providerName === void 0 ? void 0 : input.config.providers[providerName];
|
|
85394
|
-
if (providerName === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Model "${modelName}" must define a provider in config.toml.`);
|
|
85395
|
-
if (providerConfig === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" for model "${modelName}" is not configured.`);
|
|
85396
|
-
if (!Number.isInteger(alias.maxContextSize) || alias.maxContextSize <= 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Model "${modelName}" must define a positive max_context_size in config.toml.`);
|
|
85397
|
-
if (input.validateCredentials !== false && providerConfig.type !== "vertexai" && providerConfig.oauth === void 0 && providerApiKey(providerConfig) === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" has no credentials configured. Set apiKey, oauth, or a provider env API key in config.toml.`);
|
|
85398
|
-
const provider = toKosongProviderConfig(providerConfig, resolvedModel, input.byfRequestHeaders, alias.maxOutputSize, alias.reasoningKey, input.promptCacheKey);
|
|
85399
|
-
return {
|
|
85400
|
-
modelName,
|
|
85401
|
-
providerName,
|
|
85402
|
-
modelCapabilities: resolveModelCapabilities(alias, provider),
|
|
85403
|
-
provider
|
|
85404
|
-
};
|
|
85405
|
-
}
|
|
85406
|
-
async function resolveRuntimeProviderWithOAuth(input) {
|
|
85407
|
-
const resolved = resolveRuntimeProvider(input);
|
|
85408
|
-
const resolveAuth = createRuntimeProviderAuthResolver(input, resolved);
|
|
85409
|
-
if (resolveAuth === void 0) return resolved;
|
|
85410
|
-
await resolveAuth();
|
|
85411
|
-
return {
|
|
85412
|
-
...resolved,
|
|
85413
|
-
resolveAuth
|
|
85414
|
-
};
|
|
85415
|
-
}
|
|
85416
|
-
function createRuntimeProviderAuthResolver(input, resolved = resolveRuntimeProvider(input)) {
|
|
85417
|
-
const providerName = resolved.providerName;
|
|
85418
|
-
if (providerName === void 0) return void 0;
|
|
85419
|
-
const providerConfig = input.config.providers[providerName];
|
|
85420
|
-
if (providerConfig?.oauth === void 0) return void 0;
|
|
85421
|
-
if (providerApiKey(providerConfig) !== void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" has both apiKey and oauth set in config.toml — they are mutually exclusive. Remove one.`);
|
|
85422
|
-
const tokenProvider = input.resolveOAuthTokenProvider?.(providerName, providerConfig.oauth);
|
|
85423
|
-
if (tokenProvider === void 0) return async () => {
|
|
85424
|
-
throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`);
|
|
85425
|
-
};
|
|
85426
|
-
return async (options) => {
|
|
85427
|
-
let apiKey;
|
|
85428
|
-
try {
|
|
85429
|
-
apiKey = await tokenProvider.getAccessToken(options?.forceRefresh === true ? { force: true } : void 0);
|
|
85430
|
-
} catch (error) {
|
|
85431
|
-
if (!isAuthLoginRequired(error)) (input.log ?? log).warn("oauth token fetch failed", {
|
|
85432
|
-
providerName,
|
|
85433
|
-
error
|
|
85434
|
-
});
|
|
85435
|
-
throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`, { cause: error });
|
|
85436
|
-
}
|
|
85437
|
-
if (apiKey.trim().length === 0) throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`);
|
|
85438
|
-
return { apiKey };
|
|
85439
|
-
};
|
|
85440
|
-
}
|
|
85441
|
-
function isAuthLoginRequired(error) {
|
|
85442
|
-
return isByfError(error) && error.code === ErrorCodes.AUTH_LOGIN_REQUIRED;
|
|
85443
|
-
}
|
|
85444
|
-
const CAPABILITY_DEFINITIONS = [
|
|
85445
|
-
{
|
|
85446
|
-
name: "image_in",
|
|
85447
|
-
returnKey: "image_in"
|
|
85448
|
-
},
|
|
85449
|
-
{
|
|
85450
|
-
name: "video_in",
|
|
85451
|
-
returnKey: "video_in"
|
|
85452
|
-
},
|
|
85453
|
-
{
|
|
85454
|
-
name: "audio_in",
|
|
85455
|
-
returnKey: "audio_in"
|
|
85456
|
-
},
|
|
85457
|
-
{
|
|
85458
|
-
name: "thinking",
|
|
85459
|
-
returnKey: "thinking"
|
|
85460
|
-
},
|
|
85461
|
-
{
|
|
85462
|
-
name: "always_thinking",
|
|
85463
|
-
returnKey: "thinking"
|
|
85464
|
-
},
|
|
85465
|
-
{
|
|
85466
|
-
name: "tool_use",
|
|
85467
|
-
returnKey: "tool_use"
|
|
85468
|
-
},
|
|
85469
|
-
{
|
|
85470
|
-
name: "thinking_effort",
|
|
85471
|
-
returnKey: "thinking_effort"
|
|
85472
|
-
},
|
|
85473
|
-
{
|
|
85474
|
-
name: "thinking_xhigh",
|
|
85475
|
-
returnKey: "thinking_xhigh"
|
|
85476
|
-
},
|
|
85477
|
-
{
|
|
85478
|
-
name: "thinking_max",
|
|
85479
|
-
returnKey: "thinking_max"
|
|
85480
|
-
}
|
|
85481
|
-
];
|
|
85482
|
-
/**
|
|
85483
|
-
* The list of every valid capability name that can appear in a model
|
|
85484
|
-
* alias's `capabilities` array.
|
|
85485
|
-
*
|
|
85486
|
-
* Derives directly from {@link CAPABILITY_DEFINITIONS} so that adding a
|
|
85487
|
-
* new capability in one place automatically keeps both the validation
|
|
85488
|
-
* gate (`update-config`) and the runtime resolver in sync.
|
|
85489
|
-
*/
|
|
85490
|
-
const VALID_CAPABILITIES = CAPABILITY_DEFINITIONS.map((d) => d.name);
|
|
85491
|
-
function resolveModelCapabilities(alias, provider) {
|
|
85492
|
-
const capabilities = new Set((alias.capabilities ?? []).map((capability) => capability.trim().toLowerCase()));
|
|
85493
|
-
const has = (capability) => capabilities.has(capability);
|
|
85494
|
-
const providerCapability = createProvider$1(providerForCapabilityProbe(provider)).getCapability?.(provider.model) ?? UNKNOWN_CAPABILITY;
|
|
85495
|
-
const returnKeyToNames = /* @__PURE__ */ new Map();
|
|
85496
|
-
for (const def of CAPABILITY_DEFINITIONS) {
|
|
85497
|
-
const names = returnKeyToNames.get(def.returnKey) ?? [];
|
|
85498
|
-
names.push(def.name);
|
|
85499
|
-
returnKeyToNames.set(def.returnKey, names);
|
|
85500
|
-
}
|
|
85501
|
-
const resolved = {};
|
|
85502
|
-
for (const [returnKey, names] of returnKeyToNames) resolved[returnKey] = names.some((n) => has(n)) || Boolean(providerCapability[returnKey]);
|
|
85503
|
-
return {
|
|
85504
|
-
...resolved,
|
|
85505
|
-
max_context_tokens: alias.maxContextSize
|
|
85506
|
-
};
|
|
85507
|
-
}
|
|
85508
|
-
function toKosongProviderConfig(provider, model, byfRequestHeaders, maxOutputSize, reasoningKey, promptCacheKey) {
|
|
85509
|
-
switch (provider.type) {
|
|
85510
|
-
case "anthropic": return {
|
|
85511
|
-
type: "anthropic",
|
|
85512
|
-
model,
|
|
85513
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "ANTHROPIC_BASE_URL"),
|
|
85514
|
-
apiKey: providerApiKey(provider),
|
|
85515
|
-
...maxOutputSize !== void 0 ? { defaultMaxTokens: maxOutputSize } : {},
|
|
85516
|
-
...defaultHeadersField(provider.customHeaders)
|
|
85517
|
-
};
|
|
85518
|
-
case "openai-completions": {
|
|
85519
|
-
const defaultHeaders = {
|
|
85520
|
-
...byfRequestHeaders,
|
|
85521
|
-
...provider.customHeaders
|
|
85522
|
-
};
|
|
85523
|
-
const generationKwargs = {
|
|
85524
|
-
prompt_cache_key: promptCacheKey,
|
|
85525
|
-
extra_body: provider.extraBody
|
|
85526
|
-
};
|
|
85527
|
-
if (Object.keys(defaultHeaders).length === 0) return {
|
|
85528
|
-
type: "openai-completions",
|
|
85529
|
-
model,
|
|
85530
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "BYF_BASE_URL"),
|
|
85531
|
-
reasoningKey,
|
|
85532
|
-
thinkingEffortKey: provider.thinkingEffortKey,
|
|
85533
|
-
generationKwargs,
|
|
85534
|
-
apiKey: providerApiKey(provider)
|
|
85535
|
-
};
|
|
85536
|
-
return {
|
|
85537
|
-
type: "openai-completions",
|
|
85538
|
-
model,
|
|
85539
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "BYF_BASE_URL"),
|
|
85540
|
-
reasoningKey,
|
|
85541
|
-
thinkingEffortKey: provider.thinkingEffortKey,
|
|
85542
|
-
generationKwargs,
|
|
85543
|
-
defaultHeaders,
|
|
85544
|
-
apiKey: providerApiKey(provider)
|
|
85545
|
-
};
|
|
85546
|
-
}
|
|
85547
|
-
case "google-genai": return {
|
|
85548
|
-
type: "google-genai",
|
|
85549
|
-
model,
|
|
85550
|
-
apiKey: providerApiKey(provider)
|
|
85551
|
-
};
|
|
85552
|
-
case "openai_responses": return {
|
|
85553
|
-
type: "openai_responses",
|
|
85554
|
-
model,
|
|
85555
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "OPENAI_BASE_URL"),
|
|
85556
|
-
apiKey: providerApiKey(provider),
|
|
85557
|
-
...defaultHeadersField(provider.customHeaders)
|
|
85558
|
-
};
|
|
85559
|
-
case "vertexai": return {
|
|
85560
|
-
type: "vertexai",
|
|
85561
|
-
model,
|
|
85562
|
-
vertexai: hasVertexAIServiceEnv(provider),
|
|
85563
|
-
apiKey: hasVertexAIServiceEnv(provider) ? void 0 : providerApiKey(provider),
|
|
85564
|
-
project: vertexAIProject(provider),
|
|
85565
|
-
location: vertexAILocation(provider)
|
|
85566
|
-
};
|
|
85567
|
-
default: {
|
|
85568
|
-
const exhaustive = provider.type;
|
|
85569
|
-
throw new ByfError(ErrorCodes.MODEL_CONFIG_INVALID, `Unsupported provider type: ${String(exhaustive)}`);
|
|
85570
|
-
}
|
|
85571
|
-
}
|
|
85572
|
-
}
|
|
85573
|
-
function defaultHeadersField(headers) {
|
|
85574
|
-
if (headers === void 0 || Object.keys(headers).length === 0) return {};
|
|
85575
|
-
return { defaultHeaders: { ...headers } };
|
|
85576
|
-
}
|
|
85577
|
-
function providerForCapabilityProbe(provider) {
|
|
85578
|
-
if (provider.type === "vertexai") return {
|
|
85579
|
-
...provider,
|
|
85580
|
-
vertexai: false,
|
|
85581
|
-
project: void 0,
|
|
85582
|
-
location: void 0,
|
|
85583
|
-
apiKey: provider.apiKey === void 0 || provider.apiKey.length === 0 ? "capability-probe" : provider.apiKey
|
|
85584
|
-
};
|
|
85585
|
-
if (provider.apiKey !== void 0 && provider.apiKey.length > 0) return provider;
|
|
85586
|
-
return {
|
|
85587
|
-
...provider,
|
|
85588
|
-
apiKey: "capability-probe"
|
|
85589
|
-
};
|
|
85590
|
-
}
|
|
85591
|
-
function providerApiKey(provider) {
|
|
85592
|
-
switch (provider.type) {
|
|
85593
|
-
case "anthropic": return providerValue(provider.apiKey, provider.env, "ANTHROPIC_API_KEY");
|
|
85594
|
-
case "openai_responses": return providerValue(provider.apiKey, provider.env, "OPENAI_API_KEY");
|
|
85595
|
-
case "openai-completions": return providerValue(provider.apiKey, provider.env, "BYF_API_KEY");
|
|
85596
|
-
case "google-genai": return providerValue(provider.apiKey, provider.env, "GOOGLE_API_KEY");
|
|
85597
|
-
case "vertexai": return nonEmptyString$2(provider.apiKey) ?? envValue(provider.env, "VERTEXAI_API_KEY") ?? envValue(provider.env, "GOOGLE_API_KEY");
|
|
85598
|
-
default: {
|
|
85599
|
-
const exhaustive = provider.type;
|
|
85600
|
-
throw new ByfError(ErrorCodes.MODEL_CONFIG_INVALID, `Unsupported provider type: ${String(exhaustive)}`);
|
|
85601
|
-
}
|
|
85602
|
-
}
|
|
85603
|
-
}
|
|
85604
|
-
function hasVertexAIServiceEnv(provider) {
|
|
85605
|
-
return vertexAIProject(provider) !== void 0 && vertexAILocation(provider) !== void 0;
|
|
85606
|
-
}
|
|
85607
|
-
function vertexAIProject(provider) {
|
|
85608
|
-
return envValue(provider.env, "GOOGLE_CLOUD_PROJECT");
|
|
85609
|
-
}
|
|
85610
|
-
function vertexAILocation(provider) {
|
|
85611
|
-
return envValue(provider.env, "GOOGLE_CLOUD_LOCATION") ?? locationFromVertexAIBaseUrl(provider.baseUrl);
|
|
85612
|
-
}
|
|
85613
|
-
function providerValue(configured, env, envKey) {
|
|
85614
|
-
return nonEmptyString$2(configured) ?? envValue(env, envKey);
|
|
85615
|
-
}
|
|
85616
|
-
function envValue(env, key) {
|
|
85617
|
-
return nonEmptyString$2(env?.[key]);
|
|
85618
|
-
}
|
|
85619
|
-
function nonEmptyString$2(value) {
|
|
85620
|
-
const trimmed = value?.trim();
|
|
85621
|
-
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
85622
|
-
}
|
|
85623
|
-
function locationFromVertexAIBaseUrl(baseUrl) {
|
|
85624
|
-
const url = nonEmptyString$2(baseUrl);
|
|
85625
|
-
if (url === void 0) return void 0;
|
|
85626
|
-
try {
|
|
85627
|
-
const host = new URL(url).hostname;
|
|
85628
|
-
return host.endsWith("-aiplatform.googleapis.com") ? nonEmptyString$2(host.slice(0, -26)) : void 0;
|
|
85629
|
-
} catch {
|
|
85630
|
-
return;
|
|
85631
|
-
}
|
|
85632
|
-
}
|
|
85633
|
-
//#endregion
|
|
85634
|
-
//#region ../agent-core/src/config/update.ts
|
|
85635
|
-
/**
|
|
85636
|
-
* Scan a parsed config (including `config.raw`) and return all Findings
|
|
85637
|
-
* for deprecated / renamed / migrated / dangling / unknown / invalid-value
|
|
85638
|
-
* fields.
|
|
85639
|
-
*
|
|
85640
|
-
* This is a **pure** function — no file I/O, no side effects.
|
|
85641
|
-
*
|
|
85642
|
-
* Detection is based on `config.raw` (the clone of the original TOML data),
|
|
85643
|
-
* not on the parsed camelCase schema. This matches the PRD's observation
|
|
85644
|
-
* that `raw` is both the protection layer (preserving unknown fields) and
|
|
85645
|
-
* the blind spot (retaining stale keys through read→write cycles).
|
|
85646
|
-
*/
|
|
85647
|
-
function analyzeConfig(config) {
|
|
85648
|
-
const raw = config.raw;
|
|
85649
|
-
const findings = [];
|
|
85650
|
-
if (isRecord$2(raw)) {
|
|
85651
|
-
for (const rule of DEPRECATED_FIELD_RULES) if (pathExistsInRaw(raw, rule.pathParts)) findings.push({
|
|
85652
|
-
kind: rule.kind,
|
|
85653
|
-
path: rule.path,
|
|
85654
|
-
detail: rule.detail,
|
|
85655
|
-
deprecatedSince: rule.deprecatedSince
|
|
85656
|
-
});
|
|
85657
|
-
const defaultThinkingFinding = findings.find((f) => f.path === "default_thinking");
|
|
85658
|
-
if (defaultThinkingFinding) {
|
|
85659
|
-
const thinking = config.thinking;
|
|
85660
|
-
if (thinking && (thinking.mode !== void 0 || thinking.effort !== void 0)) {
|
|
85661
|
-
defaultThinkingFinding.kind = "removed";
|
|
85662
|
-
defaultThinkingFinding.detail = "Already superseded by [thinking] block.";
|
|
85663
|
-
}
|
|
85664
|
-
}
|
|
85665
|
-
const UNKNOWN_SKIP_PATHS = new Set(DEPRECATED_FIELD_RULES.map((r) => r.pathParts.join(".")));
|
|
85666
|
-
const byfShapeKeys = /* @__PURE__ */ new Set();
|
|
85667
|
-
for (const key of Object.keys(ByfConfigSchema.shape)) {
|
|
85668
|
-
byfShapeKeys.add(key);
|
|
85669
|
-
byfShapeKeys.add(camelToSnakeStatic(key));
|
|
85670
|
-
}
|
|
85671
|
-
for (const rawKey of Object.keys(raw)) {
|
|
85672
|
-
if (rawKey === "raw") continue;
|
|
85673
|
-
if (UNKNOWN_SKIP_PATHS.has(rawKey)) continue;
|
|
85674
|
-
const camelKey = snakeToCamelStatic(rawKey);
|
|
85675
|
-
if (!byfShapeKeys.has(camelKey) && !byfShapeKeys.has(rawKey)) findings.push({
|
|
85676
|
-
kind: "unknown",
|
|
85677
|
-
path: rawKey,
|
|
85678
|
-
detail: `Field "${rawKey}" is not recognized by the current schema. Its value has been ignored. This may be a typo or a field from a previous version.`
|
|
85679
|
-
});
|
|
85680
|
-
}
|
|
85681
|
-
const nestedFindings = scanNestedUnknowns(raw, UNKNOWN_SKIP_PATHS);
|
|
85682
|
-
findings.push(...nestedFindings);
|
|
85683
|
-
}
|
|
85684
|
-
if (config.models) {
|
|
85685
|
-
const validCapsLower = new Set(VALID_CAPABILITIES.map((c) => c.toLowerCase()));
|
|
85686
|
-
for (const [alias, modelConfig] of Object.entries(config.models)) if (modelConfig.capabilities) for (let i = 0; i < modelConfig.capabilities.length; i++) {
|
|
85687
|
-
const cap = modelConfig.capabilities[i];
|
|
85688
|
-
if (cap === void 0) continue;
|
|
85689
|
-
if (!validCapsLower.has(cap.toLowerCase())) findings.push({
|
|
85690
|
-
kind: "invalid-value",
|
|
85691
|
-
path: `models.${alias}.capabilities[${i}]`,
|
|
85692
|
-
detail: `"${cap}" is not a valid capability. Valid values: ${VALID_CAPABILITIES.join(", ")}.`
|
|
85693
|
-
});
|
|
85694
|
-
}
|
|
85695
|
-
}
|
|
85696
|
-
const providerKeys = Object.keys(config.providers ?? {});
|
|
85697
|
-
if (config.models) {
|
|
85698
|
-
for (const [alias, modelConfig] of Object.entries(config.models)) if (!providerKeys.includes(modelConfig.provider)) findings.push({
|
|
85699
|
-
kind: "dangling",
|
|
85700
|
-
path: `models.${alias}.provider`,
|
|
85701
|
-
detail: `Model alias "${alias}" references provider "${modelConfig.provider}", which does not exist in [providers].`
|
|
85702
|
-
});
|
|
85703
|
-
}
|
|
85704
|
-
if (config.defaultProvider !== void 0 && !providerKeys.includes(config.defaultProvider)) findings.push({
|
|
85705
|
-
kind: "dangling",
|
|
85706
|
-
path: "default_provider",
|
|
85707
|
-
detail: `Default provider "${config.defaultProvider}" does not exist in [providers].`
|
|
85708
|
-
});
|
|
85709
|
-
const modelKeys = Object.keys(config.models ?? {});
|
|
85710
|
-
if (config.defaultModel !== void 0 && !modelKeys.includes(config.defaultModel)) findings.push({
|
|
85711
|
-
kind: "dangling",
|
|
85712
|
-
path: "default_model",
|
|
85713
|
-
detail: `Default model "${config.defaultModel}" does not exist in [models].`
|
|
85714
|
-
});
|
|
85715
|
-
return findings;
|
|
85716
|
-
}
|
|
85717
|
-
/**
|
|
85718
|
-
* Apply automatic fixes to a `ByfConfig` by deleting every path registered in
|
|
85719
|
-
* `DEPRECATED_FIELD_RULES` from `config.raw`.
|
|
85720
|
-
*
|
|
85721
|
-
* The `_findings` parameter is intentionally **not consulted** — deletion is
|
|
85722
|
-
* driven exclusively by the whitelist in `DEPRECATED_FIELD_RULES`. This ensures
|
|
85723
|
-
* that a call to `applyFixes` always produces a clean config regardless of
|
|
85724
|
-
* what analysis step previously ran.
|
|
85725
|
-
*
|
|
85726
|
-
* This is a **pure** function — it returns a new config object without
|
|
85727
|
-
* mutating the input.
|
|
85728
|
-
*/
|
|
85729
|
-
function applyFixes(config, findings) {
|
|
85730
|
-
const newRaw = rawShallowClone(config.raw);
|
|
85731
|
-
for (const rule of DEPRECATED_FIELD_RULES) deletePath(newRaw, rule.pathParts);
|
|
85732
|
-
let newConfig = {
|
|
85733
|
-
...config,
|
|
85734
|
-
raw: newRaw
|
|
85735
|
-
};
|
|
85736
|
-
if (findings.find((f) => f.kind === "migrated" && f.path === "default_thinking")) {
|
|
85737
|
-
const rawValue = config.raw?.["default_thinking"];
|
|
85738
|
-
const isTruthy = rawValue === true || rawValue === "true" || rawValue === 1;
|
|
85739
|
-
newConfig = {
|
|
85740
|
-
...newConfig,
|
|
85741
|
-
thinking: isTruthy ? {
|
|
85742
|
-
mode: "on",
|
|
85743
|
-
effort: "high"
|
|
85744
|
-
} : { mode: "off" }
|
|
85745
|
-
};
|
|
85746
|
-
}
|
|
85747
|
-
return newConfig;
|
|
85748
|
-
}
|
|
85749
|
-
/** Convert snake_case to camelCase (static helper for unknown detection). */
|
|
85750
|
-
function snakeToCamelStatic(str) {
|
|
85751
|
-
return str.replaceAll(/_([a-z])/g, (_, ch) => ch.toUpperCase());
|
|
85752
|
-
}
|
|
85753
|
-
/** Convert camelCase to snake_case (static helper for unknown detection). */
|
|
85754
|
-
function camelToSnakeStatic(str) {
|
|
85755
|
-
return str.replaceAll(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
85756
|
-
}
|
|
85757
|
-
/** True when `value` is a non-null, non-array object. */
|
|
85758
|
-
function isRecord$2(value) {
|
|
85759
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
85760
|
-
}
|
|
85761
|
-
/**
|
|
85762
|
-
* Walk `root` along `pathParts` checking that **every** segment exists.
|
|
85763
|
-
*
|
|
85764
|
-
* Returns `true` iff all parts exist as own keys (or inherited keys — TOML
|
|
85765
|
-
* parse results are plain objects so the distinction doesn't matter here).
|
|
85766
|
-
*/
|
|
85767
|
-
function pathExistsInRaw(root, pathParts) {
|
|
85768
|
-
let current = root;
|
|
85769
|
-
for (const part of pathParts) {
|
|
85770
|
-
if (!isRecord$2(current) || !(part in current)) return false;
|
|
85771
|
-
current = current[part];
|
|
85772
|
-
}
|
|
85773
|
-
return true;
|
|
85774
|
-
}
|
|
85775
|
-
/**
|
|
85776
|
-
* Delete a leaf (or entire sub-tree) from `root` following `pathParts`.
|
|
85777
|
-
*
|
|
85778
|
-
* If the parent after deletion becomes empty it is cleaned up as well
|
|
85779
|
-
* (recursive upward), so that a service table cleared of all deprecated
|
|
85780
|
-
* keys does not leave behind an empty `{}`.
|
|
85781
|
-
*/
|
|
85782
|
-
function deletePath(root, pathParts) {
|
|
85783
|
-
if (pathParts.length === 0) return;
|
|
85784
|
-
const parentParts = pathParts.slice(0, -1);
|
|
85785
|
-
const leafKey = pathParts.at(-1);
|
|
85786
|
-
let current;
|
|
85787
|
-
if (parentParts.length === 0) current = root;
|
|
85788
|
-
else current = traverseTo(root, parentParts);
|
|
85789
|
-
if (current === void 0) return;
|
|
85790
|
-
const keyExisted = leafKey in current;
|
|
85791
|
-
delete current[leafKey];
|
|
85792
|
-
if (keyExisted && parentParts.length > 0 && Object.keys(current).length === 0) deletePath(root, parentParts);
|
|
85793
|
-
}
|
|
85794
|
-
/**
|
|
85795
|
-
* Walk `root` along `pathParts` returning the penultimate record, or
|
|
85796
|
-
* `undefined` if any segment is missing.
|
|
85797
|
-
*/
|
|
85798
|
-
function traverseTo(root, pathParts) {
|
|
85799
|
-
let current = root;
|
|
85800
|
-
for (const part of pathParts) {
|
|
85801
|
-
if (!isRecord$2(current) || !(part in current)) return void 0;
|
|
85802
|
-
current = current[part];
|
|
85803
|
-
}
|
|
85804
|
-
return isRecord$2(current) ? current : void 0;
|
|
85805
|
-
}
|
|
85806
|
-
/**
|
|
85807
|
-
* Shallow-clone `raw`: each nested record is also shallow-cloned so that
|
|
85808
|
-
* mutations in `applyFixes` do not affect the original object.
|
|
85809
|
-
*/
|
|
85810
|
-
function rawShallowClone(raw) {
|
|
85811
|
-
if (!isRecord$2(raw)) return {};
|
|
85812
|
-
const clone = {};
|
|
85813
|
-
for (const [key, value] of Object.entries(raw)) clone[key] = isRecord$2(value) ? { ...value } : value;
|
|
85814
|
-
return clone;
|
|
85815
|
-
}
|
|
85816
|
-
/**
|
|
85817
|
-
* Build a set of all valid keys (camelCase + snake_case) from a zod
|
|
85818
|
-
* object schema's `.shape`.
|
|
85819
|
-
*/
|
|
85820
|
-
function getShapeKeySet(schema) {
|
|
85821
|
-
const keys = /* @__PURE__ */ new Set();
|
|
85822
|
-
for (const key of Object.keys(schema.shape)) {
|
|
85823
|
-
keys.add(key);
|
|
85824
|
-
keys.add(camelToSnakeStatic(key));
|
|
85825
|
-
}
|
|
85826
|
-
return keys;
|
|
85827
|
-
}
|
|
85828
|
-
/**
|
|
85829
|
-
* Scan known container keys in `raw` for sub-keys that don't match the
|
|
85830
|
-
* corresponding schema shape. Unknown paths that overlap with
|
|
85831
|
-
* `skipPaths` (e.g. already reported deprecated fields) are skipped.
|
|
85832
|
-
*
|
|
85833
|
-
* Detects e.g. `models.gpt4.max_context_tokns` (typo) or
|
|
85834
|
-
* `providers.anthropic.api_kei` (typo).
|
|
85835
|
-
*/
|
|
85836
|
-
function scanNestedUnknowns(raw, skipPaths) {
|
|
85837
|
-
const findings = [];
|
|
85838
|
-
const containers = [
|
|
85839
|
-
{
|
|
85840
|
-
rawKey: "models",
|
|
85841
|
-
isRecord: true,
|
|
85842
|
-
schema: ModelAliasSchema
|
|
85843
|
-
},
|
|
85844
|
-
{
|
|
85845
|
-
rawKey: "providers",
|
|
85846
|
-
isRecord: true,
|
|
85847
|
-
schema: ProviderConfigSchema
|
|
85848
|
-
},
|
|
85849
|
-
{
|
|
85850
|
-
rawKey: "services",
|
|
85851
|
-
isRecord: false,
|
|
85852
|
-
schema: ServicesConfigSchema
|
|
85853
|
-
},
|
|
85854
|
-
{
|
|
85855
|
-
rawKey: "background",
|
|
85856
|
-
isRecord: false,
|
|
85857
|
-
schema: BackgroundConfigSchema
|
|
85858
|
-
},
|
|
85859
|
-
{
|
|
85860
|
-
rawKey: "loop_control",
|
|
85861
|
-
isRecord: false,
|
|
85862
|
-
schema: LoopControlSchema
|
|
85863
|
-
},
|
|
85864
|
-
{
|
|
85865
|
-
rawKey: "thinking",
|
|
85866
|
-
isRecord: false,
|
|
85867
|
-
schema: ThinkingConfigSchema
|
|
85868
|
-
},
|
|
85869
|
-
{
|
|
85870
|
-
rawKey: "permission",
|
|
85871
|
-
isRecord: false,
|
|
85872
|
-
schema: PermissionConfigSchema,
|
|
85873
|
-
legacyKeys: [
|
|
85874
|
-
"deny",
|
|
85875
|
-
"allow",
|
|
85876
|
-
"ask"
|
|
85877
|
-
]
|
|
85878
|
-
}
|
|
85879
|
-
];
|
|
85880
|
-
const schemaKeySets = /* @__PURE__ */ new Map();
|
|
85881
|
-
containers.forEach((entry, index) => {
|
|
85882
|
-
const base = getShapeKeySet(entry.schema);
|
|
85883
|
-
if (entry.legacyKeys) for (const k of entry.legacyKeys) base.add(k);
|
|
85884
|
-
schemaKeySets.set(index, base);
|
|
85885
|
-
});
|
|
85886
|
-
for (const [entryIndex, entry] of containers.entries()) {
|
|
85887
|
-
if (!(entry.rawKey in raw)) continue;
|
|
85888
|
-
const rawValue = raw[entry.rawKey];
|
|
85889
|
-
if (!isRecord$2(rawValue)) continue;
|
|
85890
|
-
if (entry.isRecord) for (const [itemKey, itemValue] of Object.entries(rawValue)) {
|
|
85891
|
-
if (!isRecord$2(itemValue)) continue;
|
|
85892
|
-
const validKeys = schemaKeySets.get(entryIndex);
|
|
85893
|
-
for (const subKey of Object.keys(itemValue)) if (!validKeys.has(subKey)) {
|
|
85894
|
-
const path = `${entry.rawKey}.${itemKey}.${subKey}`;
|
|
85895
|
-
if (!skipPaths.has(path)) findings.push({
|
|
85896
|
-
kind: "unknown",
|
|
85897
|
-
path,
|
|
85898
|
-
detail: `Field "${subKey}" is not recognized in ${entry.rawKey}.${itemKey}. This may be a typo or a field from a previous version.`
|
|
85899
|
-
});
|
|
85900
|
-
}
|
|
85901
|
-
}
|
|
85902
|
-
else {
|
|
85903
|
-
const validKeys = schemaKeySets.get(entryIndex);
|
|
85904
|
-
for (const subKey of Object.keys(rawValue)) if (!validKeys.has(subKey)) {
|
|
85905
|
-
const path = `${entry.rawKey}.${subKey}`;
|
|
85906
|
-
if (!skipPaths.has(path)) findings.push({
|
|
85907
|
-
kind: "unknown",
|
|
85908
|
-
path,
|
|
85909
|
-
detail: `Field "${subKey}" is not recognized in [${entry.rawKey}]. This may be a typo or a field from a previous version.`
|
|
85910
|
-
});
|
|
85911
|
-
}
|
|
85912
|
-
}
|
|
85913
|
-
}
|
|
85914
|
-
return findings;
|
|
85915
|
-
}
|
|
85916
|
-
//#endregion
|
|
85917
85352
|
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
85918
85353
|
function isZ4Schema(s) {
|
|
85919
85354
|
return !!s._zod;
|
|
@@ -90650,14 +90085,14 @@ var LocalKaos = class {
|
|
|
90650
90085
|
}
|
|
90651
90086
|
}
|
|
90652
90087
|
async writeBytes(path, data) {
|
|
90653
|
-
await writeFile(this._resolvePath(path), data);
|
|
90088
|
+
await writeFile$1(this._resolvePath(path), data);
|
|
90654
90089
|
return data.length;
|
|
90655
90090
|
}
|
|
90656
90091
|
async writeText(path, data, options) {
|
|
90657
90092
|
const resolved = this._resolvePath(path);
|
|
90658
90093
|
const encoding = options?.encoding ?? "utf-8";
|
|
90659
90094
|
if ((options?.mode ?? "w") === "a") await appendFile(resolved, data, encoding);
|
|
90660
|
-
else await writeFile(resolved, data, encoding);
|
|
90095
|
+
else await writeFile$1(resolved, data, encoding);
|
|
90661
90096
|
return data.length;
|
|
90662
90097
|
}
|
|
90663
90098
|
async mkdir(path, options) {
|
|
@@ -126724,7 +126159,7 @@ async function writeExportZip(args) {
|
|
|
126724
126159
|
entries.push(extra.target);
|
|
126725
126160
|
} catch {}
|
|
126726
126161
|
zip.end();
|
|
126727
|
-
await pipeline$1(zip.outputStream, createWriteStream(args.outputPath));
|
|
126162
|
+
await pipeline$1(zip.outputStream, createWriteStream$1(args.outputPath));
|
|
126728
126163
|
return entries;
|
|
126729
126164
|
}
|
|
126730
126165
|
//#endregion
|
|
@@ -126783,6 +126218,247 @@ async function readOptionalFile(path) {
|
|
|
126783
126218
|
}
|
|
126784
126219
|
}
|
|
126785
126220
|
//#endregion
|
|
126221
|
+
//#region ../agent-core/src/providers/runtime-provider.ts
|
|
126222
|
+
function resolveRuntimeProvider(input) {
|
|
126223
|
+
const modelName = input.model ?? input.config.defaultModel;
|
|
126224
|
+
if (modelName === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, "No model is selected. Set default_model in config.toml or pass a configured model alias.");
|
|
126225
|
+
const alias = input.config.models?.[modelName];
|
|
126226
|
+
if (alias === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Model "${modelName}" is not configured in config.toml. Add a [models."${modelName}"] entry with max_context_size.`);
|
|
126227
|
+
const resolvedModel = alias.model;
|
|
126228
|
+
const providerName = alias.provider ?? input.config.defaultProvider;
|
|
126229
|
+
const providerConfig = providerName === void 0 ? void 0 : input.config.providers[providerName];
|
|
126230
|
+
if (providerName === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Model "${modelName}" must define a provider in config.toml.`);
|
|
126231
|
+
if (providerConfig === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" for model "${modelName}" is not configured.`);
|
|
126232
|
+
if (!Number.isInteger(alias.maxContextSize) || alias.maxContextSize <= 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Model "${modelName}" must define a positive max_context_size in config.toml.`);
|
|
126233
|
+
if (input.validateCredentials !== false && providerConfig.type !== "vertexai" && providerConfig.oauth === void 0 && providerApiKey(providerConfig) === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" has no credentials configured. Set apiKey, oauth, or a provider env API key in config.toml.`);
|
|
126234
|
+
const provider = toKosongProviderConfig(providerConfig, resolvedModel, input.byfRequestHeaders, alias.maxOutputSize, alias.reasoningKey, input.promptCacheKey);
|
|
126235
|
+
return {
|
|
126236
|
+
modelName,
|
|
126237
|
+
providerName,
|
|
126238
|
+
modelCapabilities: resolveModelCapabilities(alias, provider),
|
|
126239
|
+
provider
|
|
126240
|
+
};
|
|
126241
|
+
}
|
|
126242
|
+
async function resolveRuntimeProviderWithOAuth(input) {
|
|
126243
|
+
const resolved = resolveRuntimeProvider(input);
|
|
126244
|
+
const resolveAuth = createRuntimeProviderAuthResolver(input, resolved);
|
|
126245
|
+
if (resolveAuth === void 0) return resolved;
|
|
126246
|
+
await resolveAuth();
|
|
126247
|
+
return {
|
|
126248
|
+
...resolved,
|
|
126249
|
+
resolveAuth
|
|
126250
|
+
};
|
|
126251
|
+
}
|
|
126252
|
+
function createRuntimeProviderAuthResolver(input, resolved = resolveRuntimeProvider(input)) {
|
|
126253
|
+
const providerName = resolved.providerName;
|
|
126254
|
+
if (providerName === void 0) return void 0;
|
|
126255
|
+
const providerConfig = input.config.providers[providerName];
|
|
126256
|
+
if (providerConfig?.oauth === void 0) return void 0;
|
|
126257
|
+
if (providerApiKey(providerConfig) !== void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" has both apiKey and oauth set in config.toml — they are mutually exclusive. Remove one.`);
|
|
126258
|
+
const tokenProvider = input.resolveOAuthTokenProvider?.(providerName, providerConfig.oauth);
|
|
126259
|
+
if (tokenProvider === void 0) return async () => {
|
|
126260
|
+
throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`);
|
|
126261
|
+
};
|
|
126262
|
+
return async (options) => {
|
|
126263
|
+
let apiKey;
|
|
126264
|
+
try {
|
|
126265
|
+
apiKey = await tokenProvider.getAccessToken(options?.forceRefresh === true ? { force: true } : void 0);
|
|
126266
|
+
} catch (error) {
|
|
126267
|
+
if (!isAuthLoginRequired(error)) (input.log ?? log).warn("oauth token fetch failed", {
|
|
126268
|
+
providerName,
|
|
126269
|
+
error
|
|
126270
|
+
});
|
|
126271
|
+
throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`, { cause: error });
|
|
126272
|
+
}
|
|
126273
|
+
if (apiKey.trim().length === 0) throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`);
|
|
126274
|
+
return { apiKey };
|
|
126275
|
+
};
|
|
126276
|
+
}
|
|
126277
|
+
function isAuthLoginRequired(error) {
|
|
126278
|
+
return isByfError(error) && error.code === ErrorCodes.AUTH_LOGIN_REQUIRED;
|
|
126279
|
+
}
|
|
126280
|
+
const CAPABILITY_DEFINITIONS = [
|
|
126281
|
+
{
|
|
126282
|
+
name: "image_in",
|
|
126283
|
+
returnKey: "image_in"
|
|
126284
|
+
},
|
|
126285
|
+
{
|
|
126286
|
+
name: "video_in",
|
|
126287
|
+
returnKey: "video_in"
|
|
126288
|
+
},
|
|
126289
|
+
{
|
|
126290
|
+
name: "audio_in",
|
|
126291
|
+
returnKey: "audio_in"
|
|
126292
|
+
},
|
|
126293
|
+
{
|
|
126294
|
+
name: "thinking",
|
|
126295
|
+
returnKey: "thinking"
|
|
126296
|
+
},
|
|
126297
|
+
{
|
|
126298
|
+
name: "always_thinking",
|
|
126299
|
+
returnKey: "thinking"
|
|
126300
|
+
},
|
|
126301
|
+
{
|
|
126302
|
+
name: "tool_use",
|
|
126303
|
+
returnKey: "tool_use"
|
|
126304
|
+
},
|
|
126305
|
+
{
|
|
126306
|
+
name: "thinking_effort",
|
|
126307
|
+
returnKey: "thinking_effort"
|
|
126308
|
+
},
|
|
126309
|
+
{
|
|
126310
|
+
name: "thinking_xhigh",
|
|
126311
|
+
returnKey: "thinking_xhigh"
|
|
126312
|
+
},
|
|
126313
|
+
{
|
|
126314
|
+
name: "thinking_max",
|
|
126315
|
+
returnKey: "thinking_max"
|
|
126316
|
+
}
|
|
126317
|
+
];
|
|
126318
|
+
CAPABILITY_DEFINITIONS.map((d) => d.name);
|
|
126319
|
+
function resolveModelCapabilities(alias, provider) {
|
|
126320
|
+
const capabilities = new Set((alias.capabilities ?? []).map((capability) => capability.trim().toLowerCase()));
|
|
126321
|
+
const has = (capability) => capabilities.has(capability);
|
|
126322
|
+
const providerCapability = createProvider$1(providerForCapabilityProbe(provider)).getCapability?.(provider.model) ?? UNKNOWN_CAPABILITY;
|
|
126323
|
+
const returnKeyToNames = /* @__PURE__ */ new Map();
|
|
126324
|
+
for (const def of CAPABILITY_DEFINITIONS) {
|
|
126325
|
+
const names = returnKeyToNames.get(def.returnKey) ?? [];
|
|
126326
|
+
names.push(def.name);
|
|
126327
|
+
returnKeyToNames.set(def.returnKey, names);
|
|
126328
|
+
}
|
|
126329
|
+
const resolved = {};
|
|
126330
|
+
for (const [returnKey, names] of returnKeyToNames) resolved[returnKey] = names.some((n) => has(n)) || Boolean(providerCapability[returnKey]);
|
|
126331
|
+
return {
|
|
126332
|
+
...resolved,
|
|
126333
|
+
max_context_tokens: alias.maxContextSize
|
|
126334
|
+
};
|
|
126335
|
+
}
|
|
126336
|
+
function toKosongProviderConfig(provider, model, byfRequestHeaders, maxOutputSize, reasoningKey, promptCacheKey) {
|
|
126337
|
+
switch (provider.type) {
|
|
126338
|
+
case "anthropic": return {
|
|
126339
|
+
type: "anthropic",
|
|
126340
|
+
model,
|
|
126341
|
+
baseUrl: providerValue(provider.baseUrl, provider.env, "ANTHROPIC_BASE_URL"),
|
|
126342
|
+
apiKey: providerApiKey(provider),
|
|
126343
|
+
...maxOutputSize !== void 0 ? { defaultMaxTokens: maxOutputSize } : {},
|
|
126344
|
+
...defaultHeadersField(provider.customHeaders)
|
|
126345
|
+
};
|
|
126346
|
+
case "openai-completions": {
|
|
126347
|
+
const defaultHeaders = {
|
|
126348
|
+
...byfRequestHeaders,
|
|
126349
|
+
...provider.customHeaders
|
|
126350
|
+
};
|
|
126351
|
+
const generationKwargs = {
|
|
126352
|
+
prompt_cache_key: promptCacheKey,
|
|
126353
|
+
extra_body: provider.extraBody
|
|
126354
|
+
};
|
|
126355
|
+
if (Object.keys(defaultHeaders).length === 0) return {
|
|
126356
|
+
type: "openai-completions",
|
|
126357
|
+
model,
|
|
126358
|
+
baseUrl: providerValue(provider.baseUrl, provider.env, "BYF_BASE_URL"),
|
|
126359
|
+
reasoningKey,
|
|
126360
|
+
thinkingEffortKey: provider.thinkingEffortKey,
|
|
126361
|
+
generationKwargs,
|
|
126362
|
+
apiKey: providerApiKey(provider)
|
|
126363
|
+
};
|
|
126364
|
+
return {
|
|
126365
|
+
type: "openai-completions",
|
|
126366
|
+
model,
|
|
126367
|
+
baseUrl: providerValue(provider.baseUrl, provider.env, "BYF_BASE_URL"),
|
|
126368
|
+
reasoningKey,
|
|
126369
|
+
thinkingEffortKey: provider.thinkingEffortKey,
|
|
126370
|
+
generationKwargs,
|
|
126371
|
+
defaultHeaders,
|
|
126372
|
+
apiKey: providerApiKey(provider)
|
|
126373
|
+
};
|
|
126374
|
+
}
|
|
126375
|
+
case "google-genai": return {
|
|
126376
|
+
type: "google-genai",
|
|
126377
|
+
model,
|
|
126378
|
+
apiKey: providerApiKey(provider)
|
|
126379
|
+
};
|
|
126380
|
+
case "openai_responses": return {
|
|
126381
|
+
type: "openai_responses",
|
|
126382
|
+
model,
|
|
126383
|
+
baseUrl: providerValue(provider.baseUrl, provider.env, "OPENAI_BASE_URL"),
|
|
126384
|
+
apiKey: providerApiKey(provider),
|
|
126385
|
+
...defaultHeadersField(provider.customHeaders)
|
|
126386
|
+
};
|
|
126387
|
+
case "vertexai": return {
|
|
126388
|
+
type: "vertexai",
|
|
126389
|
+
model,
|
|
126390
|
+
vertexai: hasVertexAIServiceEnv(provider),
|
|
126391
|
+
apiKey: hasVertexAIServiceEnv(provider) ? void 0 : providerApiKey(provider),
|
|
126392
|
+
project: vertexAIProject(provider),
|
|
126393
|
+
location: vertexAILocation(provider)
|
|
126394
|
+
};
|
|
126395
|
+
default: {
|
|
126396
|
+
const exhaustive = provider.type;
|
|
126397
|
+
throw new ByfError(ErrorCodes.MODEL_CONFIG_INVALID, `Unsupported provider type: ${String(exhaustive)}`);
|
|
126398
|
+
}
|
|
126399
|
+
}
|
|
126400
|
+
}
|
|
126401
|
+
function defaultHeadersField(headers) {
|
|
126402
|
+
if (headers === void 0 || Object.keys(headers).length === 0) return {};
|
|
126403
|
+
return { defaultHeaders: { ...headers } };
|
|
126404
|
+
}
|
|
126405
|
+
function providerForCapabilityProbe(provider) {
|
|
126406
|
+
if (provider.type === "vertexai") return {
|
|
126407
|
+
...provider,
|
|
126408
|
+
vertexai: false,
|
|
126409
|
+
project: void 0,
|
|
126410
|
+
location: void 0,
|
|
126411
|
+
apiKey: provider.apiKey === void 0 || provider.apiKey.length === 0 ? "capability-probe" : provider.apiKey
|
|
126412
|
+
};
|
|
126413
|
+
if (provider.apiKey !== void 0 && provider.apiKey.length > 0) return provider;
|
|
126414
|
+
return {
|
|
126415
|
+
...provider,
|
|
126416
|
+
apiKey: "capability-probe"
|
|
126417
|
+
};
|
|
126418
|
+
}
|
|
126419
|
+
function providerApiKey(provider) {
|
|
126420
|
+
switch (provider.type) {
|
|
126421
|
+
case "anthropic": return providerValue(provider.apiKey, provider.env, "ANTHROPIC_API_KEY");
|
|
126422
|
+
case "openai_responses": return providerValue(provider.apiKey, provider.env, "OPENAI_API_KEY");
|
|
126423
|
+
case "openai-completions": return providerValue(provider.apiKey, provider.env, "BYF_API_KEY");
|
|
126424
|
+
case "google-genai": return providerValue(provider.apiKey, provider.env, "GOOGLE_API_KEY");
|
|
126425
|
+
case "vertexai": return nonEmptyString$2(provider.apiKey) ?? envValue(provider.env, "VERTEXAI_API_KEY") ?? envValue(provider.env, "GOOGLE_API_KEY");
|
|
126426
|
+
default: {
|
|
126427
|
+
const exhaustive = provider.type;
|
|
126428
|
+
throw new ByfError(ErrorCodes.MODEL_CONFIG_INVALID, `Unsupported provider type: ${String(exhaustive)}`);
|
|
126429
|
+
}
|
|
126430
|
+
}
|
|
126431
|
+
}
|
|
126432
|
+
function hasVertexAIServiceEnv(provider) {
|
|
126433
|
+
return vertexAIProject(provider) !== void 0 && vertexAILocation(provider) !== void 0;
|
|
126434
|
+
}
|
|
126435
|
+
function vertexAIProject(provider) {
|
|
126436
|
+
return envValue(provider.env, "GOOGLE_CLOUD_PROJECT");
|
|
126437
|
+
}
|
|
126438
|
+
function vertexAILocation(provider) {
|
|
126439
|
+
return envValue(provider.env, "GOOGLE_CLOUD_LOCATION") ?? locationFromVertexAIBaseUrl(provider.baseUrl);
|
|
126440
|
+
}
|
|
126441
|
+
function providerValue(configured, env, envKey) {
|
|
126442
|
+
return nonEmptyString$2(configured) ?? envValue(env, envKey);
|
|
126443
|
+
}
|
|
126444
|
+
function envValue(env, key) {
|
|
126445
|
+
return nonEmptyString$2(env?.[key]);
|
|
126446
|
+
}
|
|
126447
|
+
function nonEmptyString$2(value) {
|
|
126448
|
+
const trimmed = value?.trim();
|
|
126449
|
+
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
126450
|
+
}
|
|
126451
|
+
function locationFromVertexAIBaseUrl(baseUrl) {
|
|
126452
|
+
const url = nonEmptyString$2(baseUrl);
|
|
126453
|
+
if (url === void 0) return void 0;
|
|
126454
|
+
try {
|
|
126455
|
+
const host = new URL(url).hostname;
|
|
126456
|
+
return host.endsWith("-aiplatform.googleapis.com") ? nonEmptyString$2(host.slice(0, -26)) : void 0;
|
|
126457
|
+
} catch {
|
|
126458
|
+
return;
|
|
126459
|
+
}
|
|
126460
|
+
}
|
|
126461
|
+
//#endregion
|
|
126786
126462
|
//#region ../agent-core/src/providers/provider-manager.ts
|
|
126787
126463
|
var ProviderManager = class ProviderManager {
|
|
126788
126464
|
options;
|
|
@@ -127043,7 +126719,7 @@ var SessionStore = class {
|
|
|
127043
126719
|
title: normalized,
|
|
127044
126720
|
isCustomTitle: true
|
|
127045
126721
|
};
|
|
127046
|
-
await writeFile(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
126722
|
+
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
127047
126723
|
}
|
|
127048
126724
|
async list(options) {
|
|
127049
126725
|
const workDir = normalizeWorkDir(options.workDir);
|
|
@@ -127098,7 +126774,7 @@ var SessionStore = class {
|
|
|
127098
126774
|
agents: rewriteAgentHomedirs(parsed["agents"], sourceDir, targetDir),
|
|
127099
126775
|
custom: Object.assign({}, isRecord$1(parsed["custom"]) ? parsed["custom"] : {}, input.metadata)
|
|
127100
126776
|
};
|
|
127101
|
-
await writeFile(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
126777
|
+
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
127102
126778
|
}
|
|
127103
126779
|
async summaryFromDir(id, sessionDir, workDir) {
|
|
127104
126780
|
const dirStat = await stat(sessionDir);
|
|
@@ -127995,7 +127671,7 @@ var SDKRpcClient = class {
|
|
|
127995
127671
|
type: "error",
|
|
127996
127672
|
sessionId: request.sessionId,
|
|
127997
127673
|
agentId: request.agentId,
|
|
127998
|
-
...makeErrorPayload(ErrorCodes.SESSION_APPROVAL_HANDLER_ERROR, errorMessage
|
|
127674
|
+
...makeErrorPayload(ErrorCodes.SESSION_APPROVAL_HANDLER_ERROR, errorMessage(error))
|
|
127999
127675
|
});
|
|
128000
127676
|
return {
|
|
128001
127677
|
decision: "cancelled",
|
|
@@ -128013,7 +127689,7 @@ var SDKRpcClient = class {
|
|
|
128013
127689
|
type: "error",
|
|
128014
127690
|
sessionId: request.sessionId,
|
|
128015
127691
|
agentId: request.agentId,
|
|
128016
|
-
...makeErrorPayload(ErrorCodes.SESSION_QUESTION_HANDLER_ERROR, errorMessage
|
|
127692
|
+
...makeErrorPayload(ErrorCodes.SESSION_QUESTION_HANDLER_ERROR, errorMessage(error))
|
|
128017
127693
|
});
|
|
128018
127694
|
return null;
|
|
128019
127695
|
}
|
|
@@ -128048,7 +127724,7 @@ var ClientAPI = class {
|
|
|
128048
127724
|
return this.client.toolCall(request);
|
|
128049
127725
|
}
|
|
128050
127726
|
};
|
|
128051
|
-
function errorMessage
|
|
127727
|
+
function errorMessage(error) {
|
|
128052
127728
|
return error instanceof Error ? error.message : String(error);
|
|
128053
127729
|
}
|
|
128054
127730
|
//#endregion
|
|
@@ -128448,38 +128124,6 @@ var ByfHarness = class {
|
|
|
128448
128124
|
async removeProvider(providerId) {
|
|
128449
128125
|
return this.rpc.removeProvider(providerId);
|
|
128450
128126
|
}
|
|
128451
|
-
async updateConfig(input = {}) {
|
|
128452
|
-
const configPath = input.configPath ?? this.configPath;
|
|
128453
|
-
if (!existsSync(configPath)) return {
|
|
128454
|
-
findings: [],
|
|
128455
|
-
fixed: false
|
|
128456
|
-
};
|
|
128457
|
-
const config = readConfigFile(configPath);
|
|
128458
|
-
const findings = analyzeConfig(config);
|
|
128459
|
-
if (!input.fix || findings.length === 0) return {
|
|
128460
|
-
findings,
|
|
128461
|
-
fixed: false
|
|
128462
|
-
};
|
|
128463
|
-
const backupPath = `${configPath}.bak.${(/* @__PURE__ */ new Date()).toISOString().replaceAll(/[:.]/g, "-")}`;
|
|
128464
|
-
await copyFile(configPath, backupPath);
|
|
128465
|
-
await chmod(backupPath, 384);
|
|
128466
|
-
try {
|
|
128467
|
-
await writeConfigFile(configPath, applyFixes(config, findings));
|
|
128468
|
-
readConfigFile(configPath);
|
|
128469
|
-
return {
|
|
128470
|
-
findings,
|
|
128471
|
-
fixed: true,
|
|
128472
|
-
backupPath
|
|
128473
|
-
};
|
|
128474
|
-
} catch (error) {
|
|
128475
|
-
try {
|
|
128476
|
-
await copyFile(backupPath, configPath);
|
|
128477
|
-
} catch (rollbackError) {
|
|
128478
|
-
throw new Error(`[update-config] Rollback failed: could not restore backup at ${backupPath}. Original error: ${errorMessage(error)}. Rollback error: ${errorMessage(rollbackError)}.`, { cause: rollbackError });
|
|
128479
|
-
}
|
|
128480
|
-
throw error;
|
|
128481
|
-
}
|
|
128482
|
-
}
|
|
128483
128127
|
async shellExec(command, options = {}) {
|
|
128484
128128
|
const normalizedCommand = command.trim();
|
|
128485
128129
|
if (normalizedCommand.length === 0) throw new ByfError(ErrorCodes.REQUEST_INVALID, "Shell command cannot be empty.");
|
|
@@ -128510,9 +128154,6 @@ function normalizeSessionId(value) {
|
|
|
128510
128154
|
if (normalized.length === 0) throw new ByfError(ErrorCodes.SESSION_ID_EMPTY, "Session id cannot be empty.");
|
|
128511
128155
|
return normalized;
|
|
128512
128156
|
}
|
|
128513
|
-
function errorMessage(error) {
|
|
128514
|
-
return error instanceof Error ? error.message : String(error);
|
|
128515
|
-
}
|
|
128516
128157
|
//#endregion
|
|
128517
128158
|
//#region src/catalog.ts
|
|
128518
128159
|
const DEFAULT_CATALOG_URL = "https://models.dev/api.json";
|