@byfriends/sdk 0.2.5 → 0.3.1
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";
|
|
6
9
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
10
|
import * as path$8 from "node:path";
|
|
8
11
|
import path, { basename, dirname, isAbsolute, join, normalize, posix, relative, resolve, win32 } from "node:path";
|
|
9
|
-
import I, { createWriteStream } from "fs";
|
|
12
|
+
import I, { createWriteStream as createWriteStream$1 } from "fs";
|
|
10
13
|
import Kr, { EventEmitter } from "events";
|
|
11
14
|
import * as path$1$1 from "path";
|
|
12
15
|
import $s, { dirname as dirname$1, parse } from "path";
|
|
13
16
|
import { Buffer as Buffer$1 } from "buffer";
|
|
14
17
|
import * as fs$9 from "fs/promises";
|
|
15
|
-
import { writeFile } from "fs/promises";
|
|
18
|
+
import { writeFile as writeFile$1 } from "fs/promises";
|
|
16
19
|
import Ns, { PassThrough, Readable } from "node:stream";
|
|
17
20
|
import { finished, pipeline as pipeline$1 } from "node:stream/promises";
|
|
18
21
|
import * as ks from "zlib";
|
|
19
22
|
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";
|
|
@@ -8375,47 +8375,202 @@ function resolveAuthBackedClient(state, auth, build) {
|
|
|
8375
8375
|
return build(auth);
|
|
8376
8376
|
}
|
|
8377
8377
|
//#endregion
|
|
8378
|
-
//#region ../kosong/src/providers/
|
|
8378
|
+
//#region ../kosong/src/providers/base-chat-provider.ts
|
|
8379
8379
|
/**
|
|
8380
|
-
*
|
|
8381
|
-
* {@link FinishReason} enum.
|
|
8380
|
+
* Abstract base implementing the SDK-agnostic ChatProvider boilerplate.
|
|
8382
8381
|
*
|
|
8383
|
-
*
|
|
8384
|
-
*
|
|
8382
|
+
* Subclasses must implement:
|
|
8383
|
+
* - `generate(...)` — the streaming/dispatch loop (protocol-specific)
|
|
8384
|
+
* - `createRawClient(auth, defaultHeaders)` — `new OpenAI(...)` / `new Anthropic(...)` / etc.
|
|
8385
|
+
* - `thinkingEffort` getter — per-provider effort mapping
|
|
8386
|
+
* - `getCapability(model?)` — per-provider capability registry lookup
|
|
8387
|
+
* - `withThinking(effort)` — per-provider thinking configuration
|
|
8388
|
+
*
|
|
8389
|
+
* Subclasses inherit: `_clone`, `withGenerationKwargs`, `modelName`,
|
|
8390
|
+
* `modelParameters`, and the `_createClient` shell.
|
|
8385
8391
|
*/
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8392
|
+
var BaseChatProvider = class {
|
|
8393
|
+
_model;
|
|
8394
|
+
_generationKwargs;
|
|
8395
|
+
_apiKey;
|
|
8396
|
+
_baseUrl;
|
|
8397
|
+
_defaultHeaders;
|
|
8398
|
+
_client;
|
|
8399
|
+
_clientFactory;
|
|
8400
|
+
constructor(_model, _generationKwargs, _apiKey = void 0, _baseUrl = "", _defaultHeaders = void 0, _client = void 0, _clientFactory = void 0) {
|
|
8401
|
+
this._model = _model;
|
|
8402
|
+
this._generationKwargs = _generationKwargs;
|
|
8403
|
+
this._apiKey = _apiKey;
|
|
8404
|
+
this._baseUrl = _baseUrl;
|
|
8405
|
+
this._defaultHeaders = _defaultHeaders;
|
|
8406
|
+
this._client = _client;
|
|
8407
|
+
this._clientFactory = _clientFactory;
|
|
8408
|
+
}
|
|
8409
|
+
get modelName() {
|
|
8410
|
+
return this._model;
|
|
8411
|
+
}
|
|
8412
|
+
get modelParameters() {
|
|
8413
|
+
return {
|
|
8414
|
+
model: this._model,
|
|
8415
|
+
...this._generationKwargs
|
|
8404
8416
|
};
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
|
|
8417
|
+
}
|
|
8418
|
+
/**
|
|
8419
|
+
* Return a shallow copy of this provider with `kwargs` merged into the
|
|
8420
|
+
* generation-keyword bag. The clone shares transport state (client) with
|
|
8421
|
+
* the original; only `_generationKwargs` is deep-copied.
|
|
8422
|
+
*/
|
|
8423
|
+
withGenerationKwargs(kwargs) {
|
|
8424
|
+
const clone = this._clone();
|
|
8425
|
+
clone._generationKwargs = {
|
|
8426
|
+
...clone._generationKwargs,
|
|
8427
|
+
...kwargs
|
|
8408
8428
|
};
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8429
|
+
return clone;
|
|
8430
|
+
}
|
|
8431
|
+
/**
|
|
8432
|
+
* Shallow clone preserving prototype and instance state, with a fresh
|
|
8433
|
+
* `_generationKwargs` copy. Subclasses with extra clone-time cleanup
|
|
8434
|
+
* (e.g. resetting a lazy `_files` cache) override and call `super._clone()`
|
|
8435
|
+
* then apply their cleanup.
|
|
8436
|
+
*/
|
|
8437
|
+
_clone() {
|
|
8438
|
+
const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
|
|
8439
|
+
clone._generationKwargs = { ...this._generationKwargs };
|
|
8440
|
+
return clone;
|
|
8441
|
+
}
|
|
8442
|
+
/**
|
|
8443
|
+
* Resolve the SDK client for the current request, using cached/client-factory
|
|
8444
|
+
* auth resolution. Delegates the actual SDK construction to
|
|
8445
|
+
* {@link createRawClient}. The provider name passed to `requireProviderApiKey`
|
|
8446
|
+
* is the subclass's `name`.
|
|
8447
|
+
*/
|
|
8448
|
+
_createClient(auth) {
|
|
8449
|
+
return resolveAuthBackedClient({
|
|
8450
|
+
cachedClient: this._client,
|
|
8451
|
+
clientFactory: this._clientFactory
|
|
8452
|
+
}, auth, (a) => {
|
|
8453
|
+
const defaultHeaders = mergeRequestHeaders(this._defaultHeaders, a?.headers);
|
|
8454
|
+
return this.createRawClient({
|
|
8455
|
+
apiKey: requireProviderApiKey(this.name, a, this._apiKey),
|
|
8456
|
+
headers: defaultHeaders
|
|
8457
|
+
}, defaultHeaders);
|
|
8458
|
+
});
|
|
8459
|
+
}
|
|
8460
|
+
};
|
|
8461
|
+
//#endregion
|
|
8462
|
+
//#region ../kosong/src/providers/base-streamed-message.ts
|
|
8463
|
+
var BaseStreamedMessage = class {
|
|
8464
|
+
_id = null;
|
|
8465
|
+
_usage = null;
|
|
8466
|
+
_finishReason = null;
|
|
8467
|
+
_rawFinishReason = null;
|
|
8468
|
+
_iter;
|
|
8469
|
+
get id() {
|
|
8470
|
+
return this._id;
|
|
8471
|
+
}
|
|
8472
|
+
get usage() {
|
|
8473
|
+
return this._usage;
|
|
8474
|
+
}
|
|
8475
|
+
get finishReason() {
|
|
8476
|
+
return this._finishReason;
|
|
8477
|
+
}
|
|
8478
|
+
get rawFinishReason() {
|
|
8479
|
+
return this._rawFinishReason;
|
|
8480
|
+
}
|
|
8481
|
+
async *[Symbol.asyncIterator]() {
|
|
8482
|
+
this._iter ??= this._buildIter();
|
|
8483
|
+
yield* this._iter;
|
|
8484
|
+
}
|
|
8485
|
+
};
|
|
8486
|
+
//#endregion
|
|
8487
|
+
//#region ../kosong/src/providers/provider-common.ts
|
|
8488
|
+
/**
|
|
8489
|
+
* Build a finish-reason normalizer from a per-provider raw-string → FinishReason table.
|
|
8490
|
+
*
|
|
8491
|
+
* Mirrors the shape of the per-adapter `normalizeXxxFinishReason` functions:
|
|
8492
|
+
* - `null` / `undefined` raw → `{ finishReason: null, rawFinishReason: null }`
|
|
8493
|
+
* - raw present and in the table → mapped FinishReason, raw echoed back
|
|
8494
|
+
* - raw present but not in the table → `'other'`, raw echoed back
|
|
8495
|
+
*
|
|
8496
|
+
* The returned function is stateless and safe to call repeatedly.
|
|
8497
|
+
*/
|
|
8498
|
+
function makeFinishReasonNormalizer(mapping) {
|
|
8499
|
+
return (raw) => {
|
|
8500
|
+
if (raw === null || raw === void 0) return {
|
|
8501
|
+
finishReason: null,
|
|
8502
|
+
rawFinishReason: null
|
|
8412
8503
|
};
|
|
8413
|
-
|
|
8414
|
-
finishReason: "other",
|
|
8504
|
+
return {
|
|
8505
|
+
finishReason: mapping[raw] ?? "other",
|
|
8415
8506
|
rawFinishReason: raw
|
|
8416
8507
|
};
|
|
8417
|
-
}
|
|
8508
|
+
};
|
|
8509
|
+
}
|
|
8510
|
+
/**
|
|
8511
|
+
* Build the four-field `TokenUsage` from already-parsed per-provider numbers,
|
|
8512
|
+
* applying the `inputOther = total - cached` formula shared by OpenAI-style and
|
|
8513
|
+
* Google providers (which expose only a total prompt count and a cached subset).
|
|
8514
|
+
*
|
|
8515
|
+
* `inputOther` is clamped to ≥ 0 when `cached` exceeds `total` (defensive — a
|
|
8516
|
+
* provider should never report more cached than total, but we never emit a
|
|
8517
|
+
* negative usage field). Anthropic is excluded: it reports a real
|
|
8518
|
+
* `inputCacheCreation` field that does not fit this formula.
|
|
8519
|
+
*/
|
|
8520
|
+
function extractCacheUsage(total, cached, output) {
|
|
8521
|
+
return {
|
|
8522
|
+
inputOther: Math.max(0, total - cached),
|
|
8523
|
+
output,
|
|
8524
|
+
inputCacheRead: cached,
|
|
8525
|
+
inputCacheCreation: 0
|
|
8526
|
+
};
|
|
8418
8527
|
}
|
|
8528
|
+
const NETWORK_RE$1 = /network|connection|connect|disconnect/i;
|
|
8529
|
+
const TIMEOUT_RE$1 = /timed?\s*out|timeout|deadline/i;
|
|
8530
|
+
/**
|
|
8531
|
+
* Convert a raw thrown value into a kosong `ChatProviderError` using the
|
|
8532
|
+
* shared message-based classification ladder:
|
|
8533
|
+
*
|
|
8534
|
+
* 1. already a `ChatProviderError` → returned as-is (identity)
|
|
8535
|
+
* 2. `status` provided → `normalizeAPIStatusError` (status + message + requestId)
|
|
8536
|
+
* 3. message matches `TIMEOUT_RE` → `APITimeoutError`
|
|
8537
|
+
* 4. message matches `NETWORK_RE` or any `extraNetworkMatchers`, or the value
|
|
8538
|
+
* is a `TypeError` matching `extraTypeErrorMatch` → `APIConnectionError`
|
|
8539
|
+
* 5. otherwise → `ChatProviderError` wrapping the message
|
|
8540
|
+
*
|
|
8541
|
+
* Provider adapters that recognize SDK-specific error classes (e.g. OpenAI's
|
|
8542
|
+
* `APIConnectionTimeoutError`, Google's `GoogleApiError`) should unwrap them
|
|
8543
|
+
* into `(message, status?, requestId?)` before calling this function. The
|
|
8544
|
+
* SDK-class detection itself is provider-specific and stays in the adapter.
|
|
8545
|
+
*/
|
|
8546
|
+
function convertProviderError(error, opts = {}) {
|
|
8547
|
+
if (error instanceof ChatProviderError) return error;
|
|
8548
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8549
|
+
if (typeof opts.status === "number") return normalizeAPIStatusError(opts.status, message, opts.requestId);
|
|
8550
|
+
if (TIMEOUT_RE$1.test(message)) return new APITimeoutError(message);
|
|
8551
|
+
if (NETWORK_RE$1.test(message)) return new APIConnectionError$3(message);
|
|
8552
|
+
if (opts.extraNetworkMatchers?.some((re) => re.test(message))) return new APIConnectionError$3(message);
|
|
8553
|
+
if (opts.extraTypeErrorMatch !== void 0 && error instanceof TypeError && message.includes(opts.extraTypeErrorMatch)) return new APIConnectionError$3(message);
|
|
8554
|
+
if (error instanceof Error) return new ChatProviderError(`Error: ${message}`);
|
|
8555
|
+
return new ChatProviderError(`Error: ${String(error)}`);
|
|
8556
|
+
}
|
|
8557
|
+
//#endregion
|
|
8558
|
+
//#region ../kosong/src/providers/anthropic.ts
|
|
8559
|
+
/**
|
|
8560
|
+
* Normalize an Anthropic `stop_reason` string to the unified
|
|
8561
|
+
* {@link FinishReason} enum.
|
|
8562
|
+
*
|
|
8563
|
+
* Source: `message.stop_reason` (non-stream) or the last `message_delta`
|
|
8564
|
+
* event's `delta.stop_reason` (stream).
|
|
8565
|
+
*/
|
|
8566
|
+
const normalizeAnthropicStopReason = makeFinishReasonNormalizer({
|
|
8567
|
+
end_turn: "completed",
|
|
8568
|
+
stop_sequence: "completed",
|
|
8569
|
+
max_tokens: "truncated",
|
|
8570
|
+
tool_use: "tool_calls",
|
|
8571
|
+
pause_turn: "paused",
|
|
8572
|
+
refusal: "filtered"
|
|
8573
|
+
});
|
|
8419
8574
|
const INTERLEAVED_THINKING_BETA = "interleaved-thinking-2025-05-14";
|
|
8420
8575
|
const FAMILY_VERSION_RE = /(?:opus|sonnet|haiku)[.-](\d+)[.-](\d{1,2})(?!\d)/;
|
|
8421
8576
|
const OPUS_VERSION_RE = /opus[.-](\d+)[.-](\d{1,2})(?!\d)/;
|
|
@@ -8729,35 +8884,23 @@ function convertAnthropicError(error) {
|
|
|
8729
8884
|
if (error instanceof Error) return new ChatProviderError(`Error: ${error.message}`);
|
|
8730
8885
|
return new ChatProviderError(`Error: ${String(error)}`);
|
|
8731
8886
|
}
|
|
8732
|
-
var AnthropicStreamedMessage = class {
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
inputOther: 0,
|
|
8736
|
-
output: 0,
|
|
8737
|
-
inputCacheRead: 0,
|
|
8738
|
-
inputCacheCreation: 0
|
|
8739
|
-
};
|
|
8740
|
-
_finishReason = null;
|
|
8741
|
-
_rawFinishReason = null;
|
|
8742
|
-
_iter;
|
|
8887
|
+
var AnthropicStreamedMessage = class extends BaseStreamedMessage {
|
|
8888
|
+
_response;
|
|
8889
|
+
_isStream;
|
|
8743
8890
|
constructor(response, isStream) {
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
get finishReason() {
|
|
8754
|
-
return this._finishReason;
|
|
8755
|
-
}
|
|
8756
|
-
get rawFinishReason() {
|
|
8757
|
-
return this._rawFinishReason;
|
|
8891
|
+
super();
|
|
8892
|
+
this._response = response;
|
|
8893
|
+
this._isStream = isStream;
|
|
8894
|
+
this._usage = {
|
|
8895
|
+
inputOther: 0,
|
|
8896
|
+
output: 0,
|
|
8897
|
+
inputCacheRead: 0,
|
|
8898
|
+
inputCacheCreation: 0
|
|
8899
|
+
};
|
|
8758
8900
|
}
|
|
8759
|
-
|
|
8760
|
-
|
|
8901
|
+
_buildIter() {
|
|
8902
|
+
if (this._isStream) return this._convertStreamResponse(this._response);
|
|
8903
|
+
return this._convertNonStreamResponse(this._response);
|
|
8761
8904
|
}
|
|
8762
8905
|
_captureStopReason(raw) {
|
|
8763
8906
|
const normalized = normalizeAnthropicStopReason(raw);
|
|
@@ -8765,11 +8908,14 @@ var AnthropicStreamedMessage = class {
|
|
|
8765
8908
|
this._rawFinishReason = normalized.rawFinishReason;
|
|
8766
8909
|
}
|
|
8767
8910
|
_extractUsage(usage) {
|
|
8911
|
+
const inputTokens = usage.input_tokens ?? 0;
|
|
8912
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
8913
|
+
const cacheCreation = usage.cache_creation_input_tokens ?? 0;
|
|
8768
8914
|
this._usage = {
|
|
8769
|
-
inputOther:
|
|
8915
|
+
inputOther: Math.max(0, inputTokens - cacheRead - cacheCreation),
|
|
8770
8916
|
output: usage.output_tokens ?? 0,
|
|
8771
|
-
inputCacheRead:
|
|
8772
|
-
inputCacheCreation:
|
|
8917
|
+
inputCacheRead: cacheRead,
|
|
8918
|
+
inputCacheCreation: cacheCreation
|
|
8773
8919
|
};
|
|
8774
8920
|
}
|
|
8775
8921
|
async *_convertNonStreamResponse(response) {
|
|
@@ -8894,9 +9040,16 @@ var AnthropicStreamedMessage = class {
|
|
|
8894
9040
|
const deltaUsage = evt.usage;
|
|
8895
9041
|
if (deltaUsage !== void 0) {
|
|
8896
9042
|
if (typeof deltaUsage["output_tokens"] === "number") this._usage.output = deltaUsage["output_tokens"];
|
|
9043
|
+
const prevInputOther = this._usage.inputOther;
|
|
9044
|
+
const prevCacheRead = this._usage.inputCacheRead;
|
|
9045
|
+
const prevCacheCreation = this._usage.inputCacheCreation;
|
|
8897
9046
|
if (typeof deltaUsage["cache_read_input_tokens"] === "number") this._usage.inputCacheRead = deltaUsage["cache_read_input_tokens"];
|
|
8898
9047
|
if (typeof deltaUsage["cache_creation_input_tokens"] === "number") this._usage.inputCacheCreation = deltaUsage["cache_creation_input_tokens"];
|
|
8899
|
-
if (typeof deltaUsage["input_tokens"] === "number") this._usage.inputOther = deltaUsage["input_tokens"];
|
|
9048
|
+
if (typeof deltaUsage["input_tokens"] === "number") this._usage.inputOther = Math.max(0, deltaUsage["input_tokens"] - this._usage.inputCacheRead - this._usage.inputCacheCreation);
|
|
9049
|
+
else {
|
|
9050
|
+
const totalInput = prevInputOther + prevCacheRead + prevCacheCreation;
|
|
9051
|
+
this._usage.inputOther = Math.max(0, totalInput - this._usage.inputCacheRead - this._usage.inputCacheCreation);
|
|
9052
|
+
}
|
|
8900
9053
|
}
|
|
8901
9054
|
const messageDeltaPayload = evt.delta;
|
|
8902
9055
|
if (messageDeltaPayload !== void 0 && "stop_reason" in messageDeltaPayload) this._captureStopReason(messageDeltaPayload["stop_reason"]);
|
|
@@ -8907,31 +9060,22 @@ var AnthropicStreamedMessage = class {
|
|
|
8907
9060
|
}
|
|
8908
9061
|
}
|
|
8909
9062
|
};
|
|
8910
|
-
var AnthropicChatProvider = class {
|
|
9063
|
+
var AnthropicChatProvider = class AnthropicChatProvider extends BaseChatProvider {
|
|
8911
9064
|
name = "anthropic";
|
|
8912
|
-
_model;
|
|
8913
9065
|
_stream;
|
|
8914
|
-
_client;
|
|
8915
|
-
_generationKwargs;
|
|
8916
9066
|
_metadata;
|
|
8917
|
-
_apiKey;
|
|
8918
|
-
_baseUrl;
|
|
8919
|
-
_defaultHeaders;
|
|
8920
|
-
_clientFactory;
|
|
8921
9067
|
constructor(options) {
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
const
|
|
8926
|
-
|
|
8927
|
-
this._baseUrl = options.baseUrl;
|
|
8928
|
-
this._defaultHeaders = options.defaultHeaders;
|
|
8929
|
-
this._clientFactory = options.clientFactory;
|
|
8930
|
-
this._client = this._apiKey === void 0 ? void 0 : this._buildClient(this._apiKey);
|
|
8931
|
-
this._generationKwargs = {
|
|
9068
|
+
const apiKey = options.apiKey === void 0 || options.apiKey.length === 0 ? process.env["ANTHROPIC_API_KEY"] ?? void 0 : options.apiKey;
|
|
9069
|
+
const apiKeyResolved = apiKey === void 0 || apiKey.length === 0 ? void 0 : apiKey;
|
|
9070
|
+
const baseUrl = options.baseUrl;
|
|
9071
|
+
const client = apiKeyResolved === void 0 ? void 0 : AnthropicChatProvider.buildClient(apiKeyResolved, baseUrl, options.defaultHeaders);
|
|
9072
|
+
const generationKwargs = {
|
|
8932
9073
|
max_tokens: resolveDefaultMaxTokens(options.model, options.defaultMaxTokens),
|
|
8933
9074
|
betaFeatures: options.betaFeatures ?? [INTERLEAVED_THINKING_BETA]
|
|
8934
9075
|
};
|
|
9076
|
+
super(options.model, generationKwargs, apiKeyResolved, baseUrl ?? "", options.defaultHeaders, client, options.clientFactory);
|
|
9077
|
+
this._stream = options.stream ?? true;
|
|
9078
|
+
this._metadata = options.metadata;
|
|
8935
9079
|
}
|
|
8936
9080
|
get modelName() {
|
|
8937
9081
|
return this._model;
|
|
@@ -9024,24 +9168,25 @@ var AnthropicChatProvider = class {
|
|
|
9024
9168
|
throw convertAnthropicError(error);
|
|
9025
9169
|
}
|
|
9026
9170
|
}
|
|
9027
|
-
|
|
9028
|
-
return resolveAuthBackedClient({
|
|
9029
|
-
cachedClient: this._client,
|
|
9030
|
-
clientFactory: this._clientFactory
|
|
9031
|
-
}, auth, (a) => this._buildClient(requireProviderApiKey("AnthropicChatProvider", a, this._apiKey)));
|
|
9032
|
-
}
|
|
9033
|
-
_buildClient(apiKey) {
|
|
9171
|
+
static buildClient(apiKey, baseUrl, defaultHeaders) {
|
|
9034
9172
|
return new Anthropic({
|
|
9035
9173
|
apiKey,
|
|
9174
|
+
baseURL: baseUrl,
|
|
9175
|
+
defaultHeaders
|
|
9176
|
+
});
|
|
9177
|
+
}
|
|
9178
|
+
createRawClient(auth, defaultHeaders) {
|
|
9179
|
+
return new Anthropic({
|
|
9180
|
+
apiKey: auth.apiKey,
|
|
9036
9181
|
baseURL: this._baseUrl,
|
|
9037
|
-
defaultHeaders
|
|
9182
|
+
defaultHeaders
|
|
9038
9183
|
});
|
|
9039
9184
|
}
|
|
9040
9185
|
withThinking(effort) {
|
|
9041
9186
|
if (effort === "off") {
|
|
9042
9187
|
let newBetas = [...this._generationKwargs.betaFeatures ?? []];
|
|
9043
9188
|
newBetas = newBetas.filter((b) => b !== INTERLEAVED_THINKING_BETA);
|
|
9044
|
-
const clone = this.
|
|
9189
|
+
const clone = this.withGenerationKwargs({
|
|
9045
9190
|
thinking: { type: "disabled" },
|
|
9046
9191
|
betaFeatures: newBetas
|
|
9047
9192
|
});
|
|
@@ -9052,7 +9197,7 @@ var AnthropicChatProvider = class {
|
|
|
9052
9197
|
if (effectiveEffort === "off") throw new Error("Non-off thinking effort unexpectedly clamped to off.");
|
|
9053
9198
|
let newBetas = [...this._generationKwargs.betaFeatures ?? []];
|
|
9054
9199
|
newBetas = newBetas.filter((b) => b !== INTERLEAVED_THINKING_BETA);
|
|
9055
|
-
return this.
|
|
9200
|
+
return this.withGenerationKwargs({
|
|
9056
9201
|
thinking: {
|
|
9057
9202
|
type: "adaptive",
|
|
9058
9203
|
display: "summarized"
|
|
@@ -9061,22 +9206,6 @@ var AnthropicChatProvider = class {
|
|
|
9061
9206
|
betaFeatures: newBetas
|
|
9062
9207
|
});
|
|
9063
9208
|
}
|
|
9064
|
-
withGenerationKwargs(kwargs) {
|
|
9065
|
-
return this._withGenerationKwargs(kwargs);
|
|
9066
|
-
}
|
|
9067
|
-
_withGenerationKwargs(kwargs) {
|
|
9068
|
-
const clone = this._clone();
|
|
9069
|
-
clone._generationKwargs = {
|
|
9070
|
-
...clone._generationKwargs,
|
|
9071
|
-
...kwargs
|
|
9072
|
-
};
|
|
9073
|
-
return clone;
|
|
9074
|
-
}
|
|
9075
|
-
_clone() {
|
|
9076
|
-
const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
|
|
9077
|
-
clone._generationKwargs = { ...this._generationKwargs };
|
|
9078
|
-
return clone;
|
|
9079
|
-
}
|
|
9080
9209
|
};
|
|
9081
9210
|
//#endregion
|
|
9082
9211
|
//#region ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry_operation.js
|
|
@@ -10159,7 +10288,7 @@ var require_gaxios = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
10159
10288
|
}
|
|
10160
10289
|
static async #getFetch() {
|
|
10161
10290
|
const hasWindow = typeof window !== "undefined" && !!window;
|
|
10162
|
-
this.#fetch ||= hasWindow ? window.fetch : (await import("./src-
|
|
10291
|
+
this.#fetch ||= hasWindow ? window.fetch : (await import("./src-u7agTn5O.mjs")).default;
|
|
10163
10292
|
return this.#fetch;
|
|
10164
10293
|
}
|
|
10165
10294
|
/**
|
|
@@ -35949,11 +36078,11 @@ var NodeDownloader = class {
|
|
|
35949
36078
|
if (params.downloadPath) {
|
|
35950
36079
|
const response = await downloadFile(params, apiClient);
|
|
35951
36080
|
if (response instanceof HttpResponse) {
|
|
35952
|
-
const writer = createWriteStream(params.downloadPath);
|
|
36081
|
+
const writer = createWriteStream$1(params.downloadPath);
|
|
35953
36082
|
Readable.fromWeb(response.responseInternal.body).pipe(writer);
|
|
35954
36083
|
await finished(writer);
|
|
35955
36084
|
} else try {
|
|
35956
|
-
await writeFile(params.downloadPath, response, { encoding: "base64" });
|
|
36085
|
+
await writeFile$1(params.downloadPath, response, { encoding: "base64" });
|
|
35957
36086
|
} catch (error) {
|
|
35958
36087
|
throw new Error(`Failed to write file to ${params.downloadPath}: ${error}`);
|
|
35959
36088
|
}
|
|
@@ -37547,30 +37676,19 @@ function messagesToGoogleGenAIContents(messages) {
|
|
|
37547
37676
|
}
|
|
37548
37677
|
return contents;
|
|
37549
37678
|
}
|
|
37550
|
-
var GoogleGenAIStreamedMessage = class {
|
|
37551
|
-
|
|
37552
|
-
|
|
37553
|
-
|
|
37554
|
-
_rawFinishReason = null;
|
|
37555
|
-
_iter;
|
|
37679
|
+
var GoogleGenAIStreamedMessage = class extends BaseStreamedMessage {
|
|
37680
|
+
_response;
|
|
37681
|
+
_isStream;
|
|
37682
|
+
_signal;
|
|
37556
37683
|
constructor(response, isStream, signal) {
|
|
37557
|
-
|
|
37558
|
-
|
|
37559
|
-
|
|
37560
|
-
|
|
37561
|
-
return this._id;
|
|
37562
|
-
}
|
|
37563
|
-
get usage() {
|
|
37564
|
-
return this._usage;
|
|
37565
|
-
}
|
|
37566
|
-
get finishReason() {
|
|
37567
|
-
return this._finishReason;
|
|
37568
|
-
}
|
|
37569
|
-
get rawFinishReason() {
|
|
37570
|
-
return this._rawFinishReason;
|
|
37684
|
+
super();
|
|
37685
|
+
this._response = response;
|
|
37686
|
+
this._isStream = isStream;
|
|
37687
|
+
this._signal = signal;
|
|
37571
37688
|
}
|
|
37572
|
-
|
|
37573
|
-
|
|
37689
|
+
_buildIter() {
|
|
37690
|
+
if (this._isStream) return this._convertStreamResponse(this._response, this._signal);
|
|
37691
|
+
return this._convertNonStreamResponse(this._response, this._signal);
|
|
37574
37692
|
}
|
|
37575
37693
|
_captureFinishReason(response) {
|
|
37576
37694
|
const candidates = response["candidates"];
|
|
@@ -37626,12 +37744,8 @@ var GoogleGenAIStreamedMessage = class {
|
|
|
37626
37744
|
if (usageMetadata) {
|
|
37627
37745
|
const promptTokenCount = typeof usageMetadata["promptTokenCount"] === "number" ? usageMetadata["promptTokenCount"] : 0;
|
|
37628
37746
|
const cachedContentTokenCount = typeof usageMetadata["cachedContentTokenCount"] === "number" ? usageMetadata["cachedContentTokenCount"] : 0;
|
|
37629
|
-
|
|
37630
|
-
|
|
37631
|
-
output: usageMetadata["candidatesTokenCount"] ?? 0,
|
|
37632
|
-
inputCacheRead: cachedContentTokenCount,
|
|
37633
|
-
inputCacheCreation: 0
|
|
37634
|
-
};
|
|
37747
|
+
const output = usageMetadata["candidatesTokenCount"] ?? 0;
|
|
37748
|
+
this._usage = extractCacheUsage(promptTokenCount, cachedContentTokenCount, output);
|
|
37635
37749
|
}
|
|
37636
37750
|
}
|
|
37637
37751
|
/** Extract response ID from a response chunk. */
|
|
@@ -37669,59 +37783,44 @@ var GoogleGenAIStreamedMessage = class {
|
|
|
37669
37783
|
}
|
|
37670
37784
|
}
|
|
37671
37785
|
};
|
|
37672
|
-
const NETWORK_RE$1 = /network|connection|connect|disconnect|fetch failed/i;
|
|
37673
|
-
const TIMEOUT_RE$1 = /timed?\s*out|timeout|deadline/i;
|
|
37674
37786
|
/**
|
|
37675
37787
|
* Convert a Google GenAI SDK error (or raw Error) to a kosong `ChatProviderError`.
|
|
37676
37788
|
*/
|
|
37677
37789
|
function convertGoogleGenAIError(error) {
|
|
37678
37790
|
if (error instanceof ApiError) return normalizeAPIStatusError(error.status, error.message);
|
|
37679
|
-
|
|
37680
|
-
|
|
37681
|
-
|
|
37682
|
-
|
|
37683
|
-
|
|
37684
|
-
|
|
37685
|
-
return new ChatProviderError(`GoogleGenAI error: ${msg}`);
|
|
37686
|
-
}
|
|
37687
|
-
return new ChatProviderError(`GoogleGenAI error: ${String(error)}`);
|
|
37791
|
+
const statusCode = error.code;
|
|
37792
|
+
if (error instanceof Error && typeof statusCode === "number") return normalizeAPIStatusError(statusCode, error.message);
|
|
37793
|
+
return convertProviderError(error, {
|
|
37794
|
+
extraNetworkMatchers: [/^fetch failed$/i],
|
|
37795
|
+
extraTypeErrorMatch: "fetch"
|
|
37796
|
+
});
|
|
37688
37797
|
}
|
|
37689
|
-
var GoogleGenAIChatProvider = class {
|
|
37798
|
+
var GoogleGenAIChatProvider = class GoogleGenAIChatProvider extends BaseChatProvider {
|
|
37690
37799
|
name = "google_genai";
|
|
37691
|
-
_model;
|
|
37692
|
-
_client;
|
|
37693
|
-
_generationKwargs;
|
|
37694
|
-
_vertexai;
|
|
37695
37800
|
_stream;
|
|
37696
|
-
|
|
37801
|
+
_vertexai;
|
|
37697
37802
|
_project;
|
|
37698
37803
|
_location;
|
|
37699
|
-
_clientFactory;
|
|
37700
37804
|
constructor(options) {
|
|
37701
|
-
this._model = options.model;
|
|
37702
|
-
this._vertexai = options.vertexai ?? false;
|
|
37703
|
-
this._stream = options.stream ?? true;
|
|
37704
|
-
this._generationKwargs = {};
|
|
37705
37805
|
const apiKey = options.apiKey ?? process.env["GOOGLE_API_KEY"];
|
|
37706
|
-
|
|
37806
|
+
const apiKeyResolved = apiKey === void 0 || apiKey.length === 0 ? void 0 : apiKey;
|
|
37807
|
+
const client = (options.vertexai ?? false) || apiKeyResolved !== void 0 ? GoogleGenAIChatProvider.buildClient(apiKeyResolved, options.vertexai ?? false, options.project, options.location) : void 0;
|
|
37808
|
+
super(options.model, {}, apiKeyResolved, "", void 0, client, options.clientFactory);
|
|
37809
|
+
this._stream = options.stream ?? true;
|
|
37810
|
+
this._vertexai = options.vertexai ?? false;
|
|
37707
37811
|
this._project = options.project;
|
|
37708
37812
|
this._location = options.location;
|
|
37709
|
-
this._clientFactory = options.clientFactory;
|
|
37710
|
-
this._client = this._vertexai || this._apiKey !== void 0 ? this._buildClient(this._apiKey) : void 0;
|
|
37711
37813
|
}
|
|
37712
|
-
|
|
37814
|
+
static buildClient(apiKey, vertexai, project, location) {
|
|
37713
37815
|
return new GoogleGenAI({
|
|
37714
37816
|
apiKey,
|
|
37715
|
-
...
|
|
37817
|
+
...vertexai ? {
|
|
37716
37818
|
vertexai: true,
|
|
37717
|
-
project
|
|
37718
|
-
location
|
|
37819
|
+
project,
|
|
37820
|
+
location
|
|
37719
37821
|
} : {}
|
|
37720
37822
|
});
|
|
37721
37823
|
}
|
|
37722
|
-
get modelName() {
|
|
37723
|
-
return this._model;
|
|
37724
|
-
}
|
|
37725
37824
|
get thinkingEffort() {
|
|
37726
37825
|
const thinkingConfig = this._generationKwargs.thinking_config;
|
|
37727
37826
|
if (thinkingConfig === void 0) return null;
|
|
@@ -37771,15 +37870,26 @@ var GoogleGenAIChatProvider = class {
|
|
|
37771
37870
|
throw convertGoogleGenAIError(error);
|
|
37772
37871
|
}
|
|
37773
37872
|
}
|
|
37873
|
+
/**
|
|
37874
|
+
* Override the base auth-resolution path to preserve the Vertex AI
|
|
37875
|
+
* short-circuit: Vertex uses service credentials, not request-scoped keys
|
|
37876
|
+
* or headers, so `requireProviderApiKey` must not be enforced there.
|
|
37877
|
+
*/
|
|
37774
37878
|
_createClient(auth) {
|
|
37775
37879
|
return resolveAuthBackedClient({
|
|
37776
37880
|
cachedClient: this._client,
|
|
37777
37881
|
clientFactory: this._clientFactory
|
|
37778
37882
|
}, auth, (a) => {
|
|
37779
|
-
if (this._vertexai) return
|
|
37780
|
-
return this.
|
|
37883
|
+
if (this._vertexai) return GoogleGenAIChatProvider.buildClient(this._apiKey, this._vertexai, this._project, this._location);
|
|
37884
|
+
return this.createRawClient({
|
|
37885
|
+
apiKey: requireProviderApiKey("GoogleGenAIChatProvider", a, this._apiKey),
|
|
37886
|
+
headers: void 0
|
|
37887
|
+
}, void 0);
|
|
37781
37888
|
});
|
|
37782
37889
|
}
|
|
37890
|
+
createRawClient(auth, _defaultHeaders) {
|
|
37891
|
+
return GoogleGenAIChatProvider.buildClient(auth.apiKey, this._vertexai, this._project, this._location);
|
|
37892
|
+
}
|
|
37783
37893
|
withThinking(effort) {
|
|
37784
37894
|
const thinkingConfig = { include_thoughts: true };
|
|
37785
37895
|
if (this._model.includes("gemini-3")) switch (effort) {
|
|
@@ -37821,19 +37931,6 @@ var GoogleGenAIChatProvider = class {
|
|
|
37821
37931
|
}
|
|
37822
37932
|
return this.withGenerationKwargs({ thinking_config: thinkingConfig });
|
|
37823
37933
|
}
|
|
37824
|
-
withGenerationKwargs(kwargs) {
|
|
37825
|
-
const clone = this._clone();
|
|
37826
|
-
clone._generationKwargs = {
|
|
37827
|
-
...clone._generationKwargs,
|
|
37828
|
-
...kwargs
|
|
37829
|
-
};
|
|
37830
|
-
return clone;
|
|
37831
|
-
}
|
|
37832
|
-
_clone() {
|
|
37833
|
-
const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
|
|
37834
|
-
clone._generationKwargs = { ...this._generationKwargs };
|
|
37835
|
-
return clone;
|
|
37836
|
-
}
|
|
37837
37934
|
};
|
|
37838
37935
|
//#endregion
|
|
37839
37936
|
//#region ../kosong/src/providers/openai-compat-schema.ts
|
|
@@ -38013,7 +38110,7 @@ function normalizeOpenAICompatToolSchema(schema) {
|
|
|
38013
38110
|
}
|
|
38014
38111
|
function ensureOpenAICompatPropertyTypes(schema) {
|
|
38015
38112
|
const normalized = cloneJsonValue(schema);
|
|
38016
|
-
if (!isRecord$
|
|
38113
|
+
if (!isRecord$6(normalized)) throw new Error("JSON Schema root must normalize to an object.");
|
|
38017
38114
|
recurseSchema(normalized);
|
|
38018
38115
|
return normalized;
|
|
38019
38116
|
}
|
|
@@ -38074,7 +38171,7 @@ function resolveLocalJsonPointer(root, ref) {
|
|
|
38074
38171
|
let current = root;
|
|
38075
38172
|
for (const rawPart of ref.slice(2).split("/")) {
|
|
38076
38173
|
const part = unescapeJsonPointerPart(rawPart);
|
|
38077
|
-
if (isRecord$
|
|
38174
|
+
if (isRecord$6(current)) {
|
|
38078
38175
|
if (!hasOwn$1(current, part)) return { found: false };
|
|
38079
38176
|
current = current[part];
|
|
38080
38177
|
} else if (Array.isArray(current)) {
|
|
@@ -38096,20 +38193,20 @@ function parseJsonPointerArrayIndex(part) {
|
|
|
38096
38193
|
return Number(part);
|
|
38097
38194
|
}
|
|
38098
38195
|
function recurseSchema(node) {
|
|
38099
|
-
if (!isRecord$
|
|
38196
|
+
if (!isRecord$6(node)) return;
|
|
38100
38197
|
visitChildSchemas(node, normalizeProperty);
|
|
38101
38198
|
}
|
|
38102
38199
|
function visitChildSchemas(node, visit) {
|
|
38103
38200
|
for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
|
|
38104
38201
|
const value = node[key];
|
|
38105
38202
|
if (kind === "single") {
|
|
38106
|
-
if (isRecord$
|
|
38203
|
+
if (isRecord$6(value)) visit(value);
|
|
38107
38204
|
} else if (kind === "array") {
|
|
38108
38205
|
if (Array.isArray(value)) for (const item of value) visit(item);
|
|
38109
38206
|
} else if (kind === "map") {
|
|
38110
|
-
if (isRecord$
|
|
38207
|
+
if (isRecord$6(value)) for (const item of Object.values(value)) visit(item);
|
|
38111
38208
|
} else if (kind === "schema-or-array") {
|
|
38112
|
-
if (isRecord$
|
|
38209
|
+
if (isRecord$6(value)) visit(value);
|
|
38113
38210
|
else if (Array.isArray(value)) for (const item of value) visit(item);
|
|
38114
38211
|
}
|
|
38115
38212
|
}
|
|
@@ -38121,7 +38218,7 @@ function childSchemaKeysForParentType(parentType) {
|
|
|
38121
38218
|
});
|
|
38122
38219
|
}
|
|
38123
38220
|
function normalizeProperty(node) {
|
|
38124
|
-
if (!isRecord$
|
|
38221
|
+
if (!isRecord$6(node)) return;
|
|
38125
38222
|
if (!hasOwn$1(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
|
|
38126
38223
|
const enumValues = node["enum"];
|
|
38127
38224
|
if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
|
|
@@ -38185,14 +38282,14 @@ function hasAnyKey(obj, keys) {
|
|
|
38185
38282
|
}
|
|
38186
38283
|
function cloneJsonValue(value) {
|
|
38187
38284
|
if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
|
|
38188
|
-
if (isRecord$
|
|
38285
|
+
if (isRecord$6(value)) {
|
|
38189
38286
|
const cloned = {};
|
|
38190
38287
|
for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
|
|
38191
38288
|
return cloned;
|
|
38192
38289
|
}
|
|
38193
38290
|
return value;
|
|
38194
38291
|
}
|
|
38195
|
-
function isRecord$
|
|
38292
|
+
function isRecord$6(value) {
|
|
38196
38293
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38197
38294
|
}
|
|
38198
38295
|
function hasOwn$1(obj, key) {
|
|
@@ -45165,35 +45262,13 @@ function extractUsage(usage) {
|
|
|
45165
45262
|
* - `'content_filter'` → `'filtered'`
|
|
45166
45263
|
* - any other non-null string → `'other'`
|
|
45167
45264
|
*/
|
|
45168
|
-
|
|
45169
|
-
|
|
45170
|
-
|
|
45171
|
-
|
|
45172
|
-
|
|
45173
|
-
|
|
45174
|
-
|
|
45175
|
-
finishReason: "completed",
|
|
45176
|
-
rawFinishReason: raw
|
|
45177
|
-
};
|
|
45178
|
-
case "tool_calls":
|
|
45179
|
-
case "function_call": return {
|
|
45180
|
-
finishReason: "tool_calls",
|
|
45181
|
-
rawFinishReason: raw
|
|
45182
|
-
};
|
|
45183
|
-
case "length": return {
|
|
45184
|
-
finishReason: "truncated",
|
|
45185
|
-
rawFinishReason: raw
|
|
45186
|
-
};
|
|
45187
|
-
case "content_filter": return {
|
|
45188
|
-
finishReason: "filtered",
|
|
45189
|
-
rawFinishReason: raw
|
|
45190
|
-
};
|
|
45191
|
-
default: return {
|
|
45192
|
-
finishReason: "other",
|
|
45193
|
-
rawFinishReason: raw
|
|
45194
|
-
};
|
|
45195
|
-
}
|
|
45196
|
-
}
|
|
45265
|
+
const normalizeOpenAIFinishReason = makeFinishReasonNormalizer({
|
|
45266
|
+
stop: "completed",
|
|
45267
|
+
tool_calls: "tool_calls",
|
|
45268
|
+
function_call: "tool_calls",
|
|
45269
|
+
length: "truncated",
|
|
45270
|
+
content_filter: "filtered"
|
|
45271
|
+
});
|
|
45197
45272
|
/**
|
|
45198
45273
|
* Convert tool-role message content according to the chosen strategy.
|
|
45199
45274
|
*/
|
|
@@ -45481,30 +45556,19 @@ function extractUsageFromChunk(chunk) {
|
|
|
45481
45556
|
if (choiceUsage !== null && choiceUsage !== void 0 && typeof choiceUsage === "object") return choiceUsage;
|
|
45482
45557
|
return null;
|
|
45483
45558
|
}
|
|
45484
|
-
var OpenAICompletionsStreamedMessage = class {
|
|
45485
|
-
|
|
45486
|
-
|
|
45487
|
-
|
|
45488
|
-
_rawFinishReason = null;
|
|
45489
|
-
_iter;
|
|
45559
|
+
var OpenAICompletionsStreamedMessage = class extends BaseStreamedMessage {
|
|
45560
|
+
_response;
|
|
45561
|
+
_isStream;
|
|
45562
|
+
_reasoningKey;
|
|
45490
45563
|
constructor(response, isStream, reasoningKey) {
|
|
45491
|
-
|
|
45492
|
-
|
|
45493
|
-
|
|
45494
|
-
|
|
45495
|
-
return this._id;
|
|
45496
|
-
}
|
|
45497
|
-
get usage() {
|
|
45498
|
-
return this._usage;
|
|
45499
|
-
}
|
|
45500
|
-
get finishReason() {
|
|
45501
|
-
return this._finishReason;
|
|
45502
|
-
}
|
|
45503
|
-
get rawFinishReason() {
|
|
45504
|
-
return this._rawFinishReason;
|
|
45564
|
+
super();
|
|
45565
|
+
this._response = response;
|
|
45566
|
+
this._isStream = isStream;
|
|
45567
|
+
this._reasoningKey = reasoningKey;
|
|
45505
45568
|
}
|
|
45506
|
-
|
|
45507
|
-
|
|
45569
|
+
_buildIter() {
|
|
45570
|
+
if (this._isStream) return this._convertStreamResponse(this._response, this._reasoningKey);
|
|
45571
|
+
return this._convertNonStreamResponse(this._response, this._reasoningKey);
|
|
45508
45572
|
}
|
|
45509
45573
|
_captureFinishReason(raw) {
|
|
45510
45574
|
const normalized = normalizeOpenAIFinishReason(raw);
|
|
@@ -45564,42 +45628,29 @@ var OpenAICompletionsStreamedMessage = class {
|
|
|
45564
45628
|
}
|
|
45565
45629
|
}
|
|
45566
45630
|
};
|
|
45567
|
-
var OpenAICompletionsChatProvider = class {
|
|
45631
|
+
var OpenAICompletionsChatProvider = class extends BaseChatProvider {
|
|
45568
45632
|
name = "openai-completions";
|
|
45569
|
-
_model;
|
|
45570
45633
|
_stream;
|
|
45571
|
-
_apiKey;
|
|
45572
|
-
_baseUrl;
|
|
45573
|
-
_defaultHeaders;
|
|
45574
|
-
_generationKwargs;
|
|
45575
45634
|
_thinkingEffortKey;
|
|
45576
45635
|
_reasoningKey;
|
|
45577
45636
|
_toolMessageConversion;
|
|
45578
|
-
_client;
|
|
45579
|
-
_clientFactory;
|
|
45580
45637
|
_files;
|
|
45581
45638
|
constructor(options) {
|
|
45582
|
-
const apiKey = options.apiKey;
|
|
45583
|
-
|
|
45584
|
-
|
|
45585
|
-
|
|
45586
|
-
|
|
45587
|
-
|
|
45639
|
+
const apiKey = options.apiKey === void 0 || options.apiKey.length === 0 ? void 0 : options.apiKey;
|
|
45640
|
+
const baseUrl = options.baseUrl ?? "";
|
|
45641
|
+
const generationKwargs = { ...options.generationKwargs };
|
|
45642
|
+
const client = apiKey === void 0 ? void 0 : new OpenAI({
|
|
45643
|
+
apiKey,
|
|
45644
|
+
baseURL: baseUrl,
|
|
45645
|
+
defaultHeaders: options.defaultHeaders
|
|
45646
|
+
});
|
|
45647
|
+
super(options.model, generationKwargs, apiKey, baseUrl, options.defaultHeaders, client, options.clientFactory);
|
|
45588
45648
|
this._stream = options.stream ?? true;
|
|
45589
45649
|
const normalizedThinkingEffortKey = options.thinkingEffortKey?.trim();
|
|
45590
45650
|
this._thinkingEffortKey = normalizedThinkingEffortKey !== void 0 && normalizedThinkingEffortKey.length > 0 ? normalizedThinkingEffortKey : "reasoning_effort";
|
|
45591
45651
|
const normalizedReasoningKey = options.reasoningKey?.trim();
|
|
45592
45652
|
this._reasoningKey = normalizedReasoningKey !== void 0 && normalizedReasoningKey.length > 0 ? normalizedReasoningKey : void 0;
|
|
45593
|
-
this._generationKwargs = { ...options.generationKwargs };
|
|
45594
45653
|
this._toolMessageConversion = options.toolMessageConversion ?? null;
|
|
45595
|
-
this._client = this._apiKey === void 0 ? void 0 : new OpenAI({
|
|
45596
|
-
apiKey: this._apiKey,
|
|
45597
|
-
baseURL: this._baseUrl,
|
|
45598
|
-
defaultHeaders: this._defaultHeaders
|
|
45599
|
-
});
|
|
45600
|
-
}
|
|
45601
|
-
get modelName() {
|
|
45602
|
-
return this._model;
|
|
45603
45654
|
}
|
|
45604
45655
|
get thinkingEffort() {
|
|
45605
45656
|
const customValue = this._generationKwargs[this._thinkingEffortKey];
|
|
@@ -45685,9 +45736,6 @@ var OpenAICompletionsChatProvider = class {
|
|
|
45685
45736
|
const nextEffort = { [this._thinkingEffortKey]: reasoningEffort };
|
|
45686
45737
|
return this._withGenerationKwargs(nextEffort).withExtraBody({ thinking });
|
|
45687
45738
|
}
|
|
45688
|
-
withGenerationKwargs(kwargs) {
|
|
45689
|
-
return this._withGenerationKwargs(kwargs);
|
|
45690
|
-
}
|
|
45691
45739
|
withMaxCompletionTokens(maxCompletionTokens) {
|
|
45692
45740
|
return this._withGenerationKwargs({ max_completion_tokens: maxCompletionTokens });
|
|
45693
45741
|
}
|
|
@@ -45705,33 +45753,21 @@ var OpenAICompletionsChatProvider = class {
|
|
|
45705
45753
|
};
|
|
45706
45754
|
return this._withGenerationKwargs({ extra_body: merged });
|
|
45707
45755
|
}
|
|
45708
|
-
_createClient(auth) {
|
|
45709
|
-
return resolveAuthBackedClient({
|
|
45710
|
-
cachedClient: this._client,
|
|
45711
|
-
clientFactory: this._clientFactory
|
|
45712
|
-
}, auth, (a) => {
|
|
45713
|
-
const defaultHeaders = mergeRequestHeaders(this._defaultHeaders, a?.headers);
|
|
45714
|
-
return new OpenAI({
|
|
45715
|
-
apiKey: requireProviderApiKey("OpenAICompletionsChatProvider", a, this._apiKey),
|
|
45716
|
-
baseURL: this._baseUrl,
|
|
45717
|
-
defaultHeaders
|
|
45718
|
-
});
|
|
45719
|
-
});
|
|
45720
|
-
}
|
|
45721
45756
|
_withGenerationKwargs(kwargs) {
|
|
45722
|
-
|
|
45723
|
-
clone._generationKwargs = {
|
|
45724
|
-
...clone._generationKwargs,
|
|
45725
|
-
...kwargs
|
|
45726
|
-
};
|
|
45727
|
-
return clone;
|
|
45757
|
+
return this.withGenerationKwargs(kwargs);
|
|
45728
45758
|
}
|
|
45729
45759
|
_clone() {
|
|
45730
|
-
const clone =
|
|
45731
|
-
clone._generationKwargs = { ...this._generationKwargs };
|
|
45760
|
+
const clone = super._clone();
|
|
45732
45761
|
clone._files = void 0;
|
|
45733
45762
|
return clone;
|
|
45734
45763
|
}
|
|
45764
|
+
createRawClient(auth, defaultHeaders) {
|
|
45765
|
+
return new OpenAI({
|
|
45766
|
+
apiKey: auth.apiKey,
|
|
45767
|
+
baseURL: this._baseUrl,
|
|
45768
|
+
defaultHeaders
|
|
45769
|
+
});
|
|
45770
|
+
}
|
|
45735
45771
|
};
|
|
45736
45772
|
//#endregion
|
|
45737
45773
|
//#region ../kosong/src/providers/openai-responses.ts
|
|
@@ -46039,30 +46075,17 @@ function convertTool(tool) {
|
|
|
46039
46075
|
strict: false
|
|
46040
46076
|
};
|
|
46041
46077
|
}
|
|
46042
|
-
var OpenAIResponsesStreamedMessage = class {
|
|
46043
|
-
|
|
46044
|
-
|
|
46045
|
-
_finishReason = null;
|
|
46046
|
-
_rawFinishReason = null;
|
|
46047
|
-
_iter;
|
|
46078
|
+
var OpenAIResponsesStreamedMessage = class extends BaseStreamedMessage {
|
|
46079
|
+
_response;
|
|
46080
|
+
_isStream;
|
|
46048
46081
|
constructor(response, isStream) {
|
|
46049
|
-
|
|
46050
|
-
|
|
46051
|
-
|
|
46052
|
-
get id() {
|
|
46053
|
-
return this._id;
|
|
46054
|
-
}
|
|
46055
|
-
get usage() {
|
|
46056
|
-
return this._usage;
|
|
46057
|
-
}
|
|
46058
|
-
get finishReason() {
|
|
46059
|
-
return this._finishReason;
|
|
46082
|
+
super();
|
|
46083
|
+
this._response = response;
|
|
46084
|
+
this._isStream = isStream;
|
|
46060
46085
|
}
|
|
46061
|
-
|
|
46062
|
-
return this.
|
|
46063
|
-
|
|
46064
|
-
async *[Symbol.asyncIterator]() {
|
|
46065
|
-
yield* this._iter;
|
|
46086
|
+
_buildIter() {
|
|
46087
|
+
if (this._isStream) return this._convertStreamResponse(this._response);
|
|
46088
|
+
return this._convertNonStreamResponse(this._response);
|
|
46066
46089
|
}
|
|
46067
46090
|
_captureFinishReasonFromResponse(response) {
|
|
46068
46091
|
const status = readNullableStringField(response, "status");
|
|
@@ -46076,12 +46099,7 @@ var OpenAIResponsesStreamedMessage = class {
|
|
|
46076
46099
|
const outputTokens = readNumberField(usage, "output_tokens") ?? 0;
|
|
46077
46100
|
const details = readObjectField(usage, "input_tokens_details");
|
|
46078
46101
|
const cached = details ? readNumberField(details, "cached_tokens") ?? 0 : 0;
|
|
46079
|
-
this._usage =
|
|
46080
|
-
inputOther: inputTokens - cached,
|
|
46081
|
-
output: outputTokens,
|
|
46082
|
-
inputCacheRead: cached,
|
|
46083
|
-
inputCacheCreation: 0
|
|
46084
|
-
};
|
|
46102
|
+
this._usage = extractCacheUsage(inputTokens, cached, outputTokens);
|
|
46085
46103
|
}
|
|
46086
46104
|
async *_convertNonStreamResponse(response) {
|
|
46087
46105
|
this._id = readStringField$2(response, "id") ?? null;
|
|
@@ -46244,34 +46262,22 @@ var OpenAIResponsesStreamedMessage = class {
|
|
|
46244
46262
|
}
|
|
46245
46263
|
}
|
|
46246
46264
|
};
|
|
46247
|
-
var OpenAIResponsesChatProvider = class {
|
|
46265
|
+
var OpenAIResponsesChatProvider = class OpenAIResponsesChatProvider extends BaseChatProvider {
|
|
46248
46266
|
name = "openai-responses";
|
|
46249
|
-
_model;
|
|
46250
46267
|
_stream;
|
|
46251
|
-
_apiKey;
|
|
46252
|
-
_baseUrl;
|
|
46253
|
-
_defaultHeaders;
|
|
46254
|
-
_generationKwargs;
|
|
46255
46268
|
_toolMessageConversion;
|
|
46256
|
-
_client;
|
|
46257
46269
|
_httpClient;
|
|
46258
|
-
_clientFactory;
|
|
46259
46270
|
constructor(options) {
|
|
46260
46271
|
const apiKey = options.apiKey ?? process.env["OPENAI_API_KEY"];
|
|
46261
|
-
|
|
46262
|
-
|
|
46263
|
-
|
|
46264
|
-
|
|
46272
|
+
const apiKeyResolved = apiKey === void 0 || apiKey.length === 0 ? void 0 : apiKey;
|
|
46273
|
+
const baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
|
|
46274
|
+
const generationKwargs = {};
|
|
46275
|
+
if (options.maxOutputTokens !== void 0) generationKwargs.max_output_tokens = options.maxOutputTokens;
|
|
46276
|
+
const client = apiKeyResolved === void 0 ? void 0 : OpenAIResponsesChatProvider.buildClient(apiKeyResolved, baseUrl, options.defaultHeaders, options.httpClient);
|
|
46277
|
+
super(options.model, generationKwargs, apiKeyResolved, baseUrl, options.defaultHeaders, client, options.clientFactory);
|
|
46265
46278
|
this._stream = true;
|
|
46266
|
-
this._generationKwargs = {};
|
|
46267
46279
|
this._toolMessageConversion = options.toolMessageConversion ?? null;
|
|
46268
46280
|
this._httpClient = options.httpClient;
|
|
46269
|
-
this._clientFactory = options.clientFactory;
|
|
46270
|
-
if (options.maxOutputTokens !== void 0) this._generationKwargs.max_output_tokens = options.maxOutputTokens;
|
|
46271
|
-
this._client = this._apiKey === void 0 ? void 0 : this._buildClient(this._apiKey);
|
|
46272
|
-
}
|
|
46273
|
-
get modelName() {
|
|
46274
|
-
return this._model;
|
|
46275
46281
|
}
|
|
46276
46282
|
get thinkingEffort() {
|
|
46277
46283
|
return reasoningEffortToThinkingEffort(this._generationKwargs.reasoning_effort);
|
|
@@ -46330,46 +46336,23 @@ var OpenAIResponsesChatProvider = class {
|
|
|
46330
46336
|
}
|
|
46331
46337
|
withThinking(effort) {
|
|
46332
46338
|
const reasoningEffort = thinkingEffortToReasoningEffort(effort, this._model);
|
|
46333
|
-
|
|
46334
|
-
clone._generationKwargs = {
|
|
46335
|
-
...clone._generationKwargs,
|
|
46336
|
-
reasoning_effort: reasoningEffort
|
|
46337
|
-
};
|
|
46338
|
-
return clone;
|
|
46339
|
-
}
|
|
46340
|
-
withGenerationKwargs(kwargs) {
|
|
46341
|
-
const clone = this._clone();
|
|
46342
|
-
clone._generationKwargs = {
|
|
46343
|
-
...clone._generationKwargs,
|
|
46344
|
-
...kwargs
|
|
46345
|
-
};
|
|
46346
|
-
return clone;
|
|
46347
|
-
}
|
|
46348
|
-
_clone() {
|
|
46349
|
-
const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
|
|
46350
|
-
clone._generationKwargs = { ...this._generationKwargs };
|
|
46351
|
-
return clone;
|
|
46339
|
+
return this.withGenerationKwargs({ reasoning_effort: reasoningEffort });
|
|
46352
46340
|
}
|
|
46353
|
-
|
|
46354
|
-
return
|
|
46355
|
-
cachedClient: this._client,
|
|
46356
|
-
clientFactory: this._clientFactory
|
|
46357
|
-
}, auth, (a) => this._buildClient(requireProviderApiKey("OpenAIResponsesChatProvider", a, this._apiKey), a));
|
|
46341
|
+
createRawClient(auth, defaultHeaders) {
|
|
46342
|
+
return OpenAIResponsesChatProvider.buildClient(auth.apiKey, this._baseUrl, defaultHeaders, this._httpClient);
|
|
46358
46343
|
}
|
|
46359
|
-
|
|
46360
|
-
|
|
46344
|
+
static buildClient(apiKey, baseURL, defaultHeaders, httpClient) {
|
|
46345
|
+
return new OpenAI({
|
|
46361
46346
|
apiKey,
|
|
46362
|
-
baseURL
|
|
46363
|
-
|
|
46364
|
-
|
|
46365
|
-
|
|
46366
|
-
if (this._httpClient !== void 0) clientOpts["httpClient"] = this._httpClient;
|
|
46367
|
-
return new OpenAI(clientOpts);
|
|
46347
|
+
baseURL,
|
|
46348
|
+
...defaultHeaders !== void 0 ? { defaultHeaders } : {},
|
|
46349
|
+
...httpClient !== void 0 ? { httpClient } : {}
|
|
46350
|
+
});
|
|
46368
46351
|
}
|
|
46369
46352
|
};
|
|
46370
46353
|
//#endregion
|
|
46371
46354
|
//#region ../kosong/src/providers/index.ts
|
|
46372
|
-
function createProvider(config) {
|
|
46355
|
+
function createProvider$1(config) {
|
|
46373
46356
|
switch (config.type) {
|
|
46374
46357
|
case "anthropic": return new AnthropicChatProvider(config);
|
|
46375
46358
|
case "openai-completions": return new OpenAICompletionsChatProvider(config);
|
|
@@ -47542,17 +47525,17 @@ async function loadAgentsMd(kaos, workDir) {
|
|
|
47542
47525
|
return true;
|
|
47543
47526
|
};
|
|
47544
47527
|
const home = kaos.gethome();
|
|
47545
|
-
await collect(joinPath$
|
|
47546
|
-
const genericFiles = [joinPath$
|
|
47528
|
+
await collect(joinPath$1(kaos, home, ".byf", "AGENTS.md"));
|
|
47529
|
+
const genericFiles = [joinPath$1(kaos, home, ".agents")].flatMap((dir) => ["AGENTS.md", "agents.md"].map((name) => joinPath$1(kaos, dir, name)));
|
|
47547
47530
|
for (const file of genericFiles) if (await collect(file)) break;
|
|
47548
47531
|
for (const dir of dirs) {
|
|
47549
|
-
await collect(joinPath$
|
|
47550
|
-
for (const fileName of ["AGENTS.md", "agents.md"]) if (await collect(joinPath$
|
|
47532
|
+
await collect(joinPath$1(kaos, dir, ".byf", "AGENTS.md"));
|
|
47533
|
+
for (const fileName of ["AGENTS.md", "agents.md"]) if (await collect(joinPath$1(kaos, dir, fileName))) break;
|
|
47551
47534
|
}
|
|
47552
47535
|
return renderAgentFiles(discovered);
|
|
47553
47536
|
}
|
|
47554
47537
|
async function findProjectRoot$1(kaos, workDir) {
|
|
47555
|
-
const path = pathMod$
|
|
47538
|
+
const path = pathMod$5(kaos);
|
|
47556
47539
|
const initial = kaos.normpath(workDir);
|
|
47557
47540
|
let current = initial;
|
|
47558
47541
|
while (true) {
|
|
@@ -47563,7 +47546,7 @@ async function findProjectRoot$1(kaos, workDir) {
|
|
|
47563
47546
|
}
|
|
47564
47547
|
}
|
|
47565
47548
|
function dirsRootToLeaf(kaos, workDir, projectRoot) {
|
|
47566
|
-
const path = pathMod$
|
|
47549
|
+
const path = pathMod$5(kaos);
|
|
47567
47550
|
const dirs = [];
|
|
47568
47551
|
let current = kaos.normpath(workDir);
|
|
47569
47552
|
while (true) {
|
|
@@ -47638,10 +47621,10 @@ function byteLength(text) {
|
|
|
47638
47621
|
function annotationFor(path) {
|
|
47639
47622
|
return `<!-- From: ${path} -->\n`;
|
|
47640
47623
|
}
|
|
47641
|
-
function joinPath$
|
|
47642
|
-
return pathMod$
|
|
47624
|
+
function joinPath$1(kaos, ...parts) {
|
|
47625
|
+
return pathMod$5(kaos).join(...parts);
|
|
47643
47626
|
}
|
|
47644
|
-
function pathMod$
|
|
47627
|
+
function pathMod$5(kaos) {
|
|
47645
47628
|
return kaos.pathClass() === "win32" ? win32Path : posixPath;
|
|
47646
47629
|
}
|
|
47647
47630
|
//#endregion
|
|
@@ -54749,7 +54732,7 @@ const PROFILE_SOURCES = {
|
|
|
54749
54732
|
"profile/default/agent.yaml": agent_default$1,
|
|
54750
54733
|
"profile/default/coder.yaml": coder_default,
|
|
54751
54734
|
"profile/default/explore.yaml": explore_default,
|
|
54752
|
-
"profile/default/system.md": "You are BYF, an AI agent running on the user's computer. Your job is to help\nusers accomplish tasks by taking action — read, write, search, and execute to\nmake real changes on the user's system. Answer questions when asked; otherwise,\nact.\n\nWhen responding, use the same language as the user unless explicitly instructed\notherwise.\n\n{{ ROLE_ADDITIONAL }}\n\n# First Principles\n\nThink from first principles. Strip away assumptions and conventions; every\naction must be traceable to a verifiable fact — the actual file contents,\ncommand output, data, or the user's explicit words. When in doubt, read\nbefore guessing, ask before assuming, verify before claiming.\n\n# Tool Use\n\nUse tools only when the task requires them. If the request can be answered\nwithout reading files, running commands, or searching the web, reply in text\ndirectly. When a request is ambiguous, prefer action — the user can see your\noutput and correct course.\n\nCode that only appears in your text response is NOT saved to the file system\nand will not take effect. To create or modify files, use `Write` or `Edit`.\nTo run commands, use `Bash`.\n\n# Protocol\n\n<system> tags in user or tool messages provide supplementary context. Treat\nthem as background information.\n\n<system-reminder> tags are authoritative directives that override default\nbehavior. They are unrelated to the messages they appear in. Always comply.\n\n# Safety\n\nThe environment is not a sandbox — your actions immediately affect the user's\nsystem.\n\n- Stay within the working directory unless explicitly instructed otherwise.\n- Git operations are destructive and may affect remote repositories. Never\n execute git mutations unless explicitly asked; confirm each time.\n- Avoid installing or deleting anything outside the working directory. If\n necessary, ask for confirmation first.\n\n# Working Environment\n\n## Operating System\n\nYou are running on **{{ BYF_OS }}**. The Bash tool executes commands using **{{ BYF_SHELL }}**.\n{% if BYF_OS == \"Windows\" %}\n\nIMPORTANT: You are on Windows. The Bash tool runs through Git Bash, so use Unix shell syntax inside Bash commands — `/dev/null` not `NUL`, and forward slashes in paths. For file operations, always prefer the built-in tools (Read, Write, Edit, Glob, Grep) over Bash commands — they work reliably across all platforms.\n{% endif %}\n\n## Working Directory\n\nThe current working directory is `{{ BYF_WORK_DIR }}`. This should be considered as the project root if you are instructed to perform tasks on the project. Every file system operation will be relative to the working directory if you do not explicitly specify the absolute path. Tools may require absolute paths for some parameters, IF SO, YOU MUST use absolute paths for these parameters.\n{% if BYF_ADDITIONAL_DIRS_INFO %}\n\n## Additional Directories\n\nThe following directories have been added to the workspace. You can read, write, search, and glob files in these directories as part of your workspace scope.\n\n{{ BYF_ADDITIONAL_DIRS_INFO }}\n{% endif %}\n\n#
|
|
54735
|
+
"profile/default/system.md": "You are BYF, an AI agent running on the user's computer. Your job is to help\nusers accomplish tasks by taking action — read, write, search, and execute to\nmake real changes on the user's system. Answer questions when asked; otherwise,\nact.\n\nWhen responding, use the same language as the user unless explicitly instructed\notherwise.\n\n{{ ROLE_ADDITIONAL }}\n\n# First Principles\n\nThink from first principles. Strip away assumptions and conventions; every\naction must be traceable to a verifiable fact — the actual file contents,\ncommand output, data, or the user's explicit words. When in doubt, read\nbefore guessing, ask before assuming, verify before claiming.\n\n# Tool Use\n\nUse tools only when the task requires them. If the request can be answered\nwithout reading files, running commands, or searching the web, reply in text\ndirectly. When a request is ambiguous, prefer action — the user can see your\noutput and correct course.\n\nCode that only appears in your text response is NOT saved to the file system\nand will not take effect. To create or modify files, use `Write` or `Edit`.\nTo run commands, use `Bash`.\n\n# Protocol\n\n<system> tags in user or tool messages provide supplementary context. Treat\nthem as background information.\n\n<system-reminder> tags are authoritative directives that override default\nbehavior. They are unrelated to the messages they appear in. Always comply.\n\n# Safety\n\nThe environment is not a sandbox — your actions immediately affect the user's\nsystem.\n\n- Stay within the working directory unless explicitly instructed otherwise.\n- Git operations are destructive and may affect remote repositories. Never\n execute git mutations unless explicitly asked; confirm each time.\n- Avoid installing or deleting anything outside the working directory. If\n necessary, ask for confirmation first.\n\n# Project Information\n\n`AGENTS.md` files contain project-specific context, styles, and conventions for agents. They may exist at different locations in the project — each file governs its directory and all subdirectories beneath it. Deeper files take precedence over parent files.\n\nIf instructions conflict:\n- `<system-reminder>` directives override all other instructions, including user messages.\n- Safety rules are hard constraints and must never be violated, even if a user message or AGENTS.md says otherwise.\n- Beyond those two, user messages > AGENTS.md > default system instructions.\n\n{% if BYF_AGENTS_MD_TOO_LONG %}\n> ⚠️ The merged AGENTS.md content exceeds 4,000 tokens. Consider compressing project instructions to reduce context usage.\n{% endif %}\n\nThe `AGENTS.md` instructions (merged from all applicable directories):\n\n`````````\n{{ BYF_AGENTS_MD }}\n`````````\n\nIf you modified anything mentioned in `AGENTS.md` files, update the corresponding files to keep them up-to-date.\n\n# Working Environment\n\n## Operating System\n\nYou are running on **{{ BYF_OS }}**. The Bash tool executes commands using **{{ BYF_SHELL }}**.\n{% if BYF_OS == \"Windows\" %}\n\nIMPORTANT: You are on Windows. The Bash tool runs through Git Bash, so use Unix shell syntax inside Bash commands — `/dev/null` not `NUL`, and forward slashes in paths. For file operations, always prefer the built-in tools (Read, Write, Edit, Glob, Grep) over Bash commands — they work reliably across all platforms.\n{% endif %}\n\n## Working Directory\n\nThe current working directory is `{{ BYF_WORK_DIR }}`. This should be considered as the project root if you are instructed to perform tasks on the project. Every file system operation will be relative to the working directory if you do not explicitly specify the absolute path. Tools may require absolute paths for some parameters, IF SO, YOU MUST use absolute paths for these parameters.\n{% if BYF_ADDITIONAL_DIRS_INFO %}\n\n## Additional Directories\n\nThe following directories have been added to the workspace. You can read, write, search, and glob files in these directories as part of your workspace scope.\n\n{{ BYF_ADDITIONAL_DIRS_INFO }}\n{% endif %}\n\n# Skills\n\nSkills are reusable capabilities. When a skill from the listing matches the user's request, you MUST call the `Skill` tool (not free-form text).\n\n{{ BYF_SKILLS }}\n"
|
|
54753
54736
|
};
|
|
54754
54737
|
const DEFAULT_INIT_PROMPT = init_default;
|
|
54755
54738
|
const DEFAULT_AGENT_PROFILES = loadAgentProfilesFromSources([
|
|
@@ -54800,7 +54783,7 @@ function isAbortError(err) {
|
|
|
54800
54783
|
if (err instanceof Error) return err.name === "AbortError";
|
|
54801
54784
|
return false;
|
|
54802
54785
|
}
|
|
54803
|
-
function errorMessage$
|
|
54786
|
+
function errorMessage$3(err) {
|
|
54804
54787
|
if (err instanceof Error) return err.message;
|
|
54805
54788
|
return String(err);
|
|
54806
54789
|
}
|
|
@@ -55175,6 +55158,7 @@ var BackgroundProcessManager = class {
|
|
|
55175
55158
|
const kind = opts?.kind;
|
|
55176
55159
|
const taskId = generateTaskId(kind ?? "bash");
|
|
55177
55160
|
const entry = {
|
|
55161
|
+
kind: "process",
|
|
55178
55162
|
taskId,
|
|
55179
55163
|
command,
|
|
55180
55164
|
description,
|
|
@@ -55374,9 +55358,10 @@ var BackgroundProcessManager = class {
|
|
|
55374
55358
|
entry.approvalReason = void 0;
|
|
55375
55359
|
entry.stopRequested = true;
|
|
55376
55360
|
entry.stopReason = stopReason;
|
|
55377
|
-
try {
|
|
55361
|
+
if (entry.kind === "process") try {
|
|
55378
55362
|
await entry.proc.kill("SIGTERM");
|
|
55379
55363
|
} catch {}
|
|
55364
|
+
else entry.abort();
|
|
55380
55365
|
let graceTimer;
|
|
55381
55366
|
const graceful = await Promise.race([entry.lifecyclePromise.then(() => true, () => true), new Promise((resolve) => {
|
|
55382
55367
|
graceTimer = setTimeout(() => {
|
|
@@ -55388,9 +55373,11 @@ var BackgroundProcessManager = class {
|
|
|
55388
55373
|
await entry.persistWriteQueue;
|
|
55389
55374
|
return this.toInfo(entry);
|
|
55390
55375
|
}
|
|
55391
|
-
if (!graceful
|
|
55392
|
-
|
|
55393
|
-
|
|
55376
|
+
if (!graceful) if (entry.kind === "process") {
|
|
55377
|
+
if (entry.proc.exitCode === null) try {
|
|
55378
|
+
await entry.proc.kill("SIGKILL");
|
|
55379
|
+
} catch {}
|
|
55380
|
+
} else entry.abort();
|
|
55394
55381
|
if (TERMINAL_STATUSES.has(entry.status)) {
|
|
55395
55382
|
await entry.persistWriteQueue;
|
|
55396
55383
|
return this.toInfo(entry);
|
|
@@ -55448,32 +55435,15 @@ var BackgroundProcessManager = class {
|
|
|
55448
55435
|
else this.assertCanRegister();
|
|
55449
55436
|
const taskId = generateTaskId("agent");
|
|
55450
55437
|
const entry = {
|
|
55438
|
+
kind: "promise",
|
|
55451
55439
|
taskId,
|
|
55452
55440
|
command: `[agent] ${description}`,
|
|
55453
55441
|
description,
|
|
55454
55442
|
timeoutMs: opts.timeoutMs,
|
|
55443
|
+
completion,
|
|
55444
|
+
abort: () => opts.abort?.(),
|
|
55455
55445
|
agentId: opts.agentId ?? taskId,
|
|
55456
55446
|
subagentType: opts.subagentType ?? "agent",
|
|
55457
|
-
proc: {
|
|
55458
|
-
stdin: {
|
|
55459
|
-
write: () => false,
|
|
55460
|
-
end: () => {}
|
|
55461
|
-
},
|
|
55462
|
-
stdout: {
|
|
55463
|
-
setEncoding: () => {},
|
|
55464
|
-
on: () => {}
|
|
55465
|
-
},
|
|
55466
|
-
stderr: {
|
|
55467
|
-
setEncoding: () => {},
|
|
55468
|
-
on: () => {}
|
|
55469
|
-
},
|
|
55470
|
-
pid: 0,
|
|
55471
|
-
exitCode: null,
|
|
55472
|
-
wait: () => completion.then(() => 0),
|
|
55473
|
-
kill: async () => {
|
|
55474
|
-
opts.abort?.();
|
|
55475
|
-
}
|
|
55476
|
-
},
|
|
55477
55447
|
outputChunks: [],
|
|
55478
55448
|
outputSizeBytes: 0,
|
|
55479
55449
|
status: "running",
|
|
@@ -55649,7 +55619,7 @@ var BackgroundProcessManager = class {
|
|
|
55649
55619
|
if (this.sessionDir !== void 0) await removeTask(this.sessionDir, taskId);
|
|
55650
55620
|
}
|
|
55651
55621
|
/**
|
|
55652
|
-
* Persist the current state of a live
|
|
55622
|
+
* Persist the current state of a live TaskEntry. Called from
|
|
55653
55623
|
* `register()` and the lifecycle finally block. No-op unless attached.
|
|
55654
55624
|
*/
|
|
55655
55625
|
persistLive(entry) {
|
|
@@ -55659,7 +55629,7 @@ var BackgroundProcessManager = class {
|
|
|
55659
55629
|
task_id: entry.taskId,
|
|
55660
55630
|
command: entry.command,
|
|
55661
55631
|
description: entry.description,
|
|
55662
|
-
pid: entry.proc.pid,
|
|
55632
|
+
pid: entry.kind === "process" ? entry.proc.pid : 0,
|
|
55663
55633
|
started_at: entry.startedAt,
|
|
55664
55634
|
ended_at: entry.endedAt,
|
|
55665
55635
|
exit_code: entry.exitCode,
|
|
@@ -55705,7 +55675,7 @@ var BackgroundProcessManager = class {
|
|
|
55705
55675
|
}
|
|
55706
55676
|
observedExitCompletions() {
|
|
55707
55677
|
const completions = [];
|
|
55708
|
-
for (const entry of this.processes.values()) if (!TERMINAL_STATUSES.has(entry.status) && entry.proc.exitCode !== null) completions.push(entry.lifecyclePromise);
|
|
55678
|
+
for (const entry of this.processes.values()) if (entry.kind === "process" && !TERMINAL_STATUSES.has(entry.status) && entry.proc.exitCode !== null) completions.push(entry.lifecyclePromise);
|
|
55709
55679
|
return completions;
|
|
55710
55680
|
}
|
|
55711
55681
|
toInfo(entry) {
|
|
@@ -55714,7 +55684,7 @@ var BackgroundProcessManager = class {
|
|
|
55714
55684
|
command: entry.command,
|
|
55715
55685
|
description: entry.description,
|
|
55716
55686
|
status: entry.status,
|
|
55717
|
-
pid: entry.proc.pid,
|
|
55687
|
+
pid: entry.kind === "process" ? entry.proc.pid : null,
|
|
55718
55688
|
exitCode: entry.exitCode,
|
|
55719
55689
|
startedAt: entry.startedAt,
|
|
55720
55690
|
endedAt: entry.endedAt,
|
|
@@ -55762,7 +55732,7 @@ function infoToPersisted(info) {
|
|
|
55762
55732
|
task_id: info.taskId,
|
|
55763
55733
|
command: info.command,
|
|
55764
55734
|
description: info.description,
|
|
55765
|
-
pid: info.pid,
|
|
55735
|
+
pid: info.pid ?? 0,
|
|
55766
55736
|
started_at: info.startedAt,
|
|
55767
55737
|
ended_at: info.endedAt,
|
|
55768
55738
|
exit_code: info.exitCode,
|
|
@@ -58057,7 +58027,7 @@ function parseSkillText(options) {
|
|
|
58057
58027
|
throw error;
|
|
58058
58028
|
}
|
|
58059
58029
|
const frontmatter = parsed.data ?? {};
|
|
58060
|
-
if (!isRecord$
|
|
58030
|
+
if (!isRecord$5(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
|
|
58061
58031
|
const metadata = normalizeMetadata(frontmatter);
|
|
58062
58032
|
if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
|
|
58063
58033
|
const name = nonEmptyString$3(metadata.name);
|
|
@@ -58170,7 +58140,7 @@ function tokenizeArgs(raw) {
|
|
|
58170
58140
|
function nonEmptyString$3(value) {
|
|
58171
58141
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
58172
58142
|
}
|
|
58173
|
-
function isRecord$
|
|
58143
|
+
function isRecord$5(value) {
|
|
58174
58144
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
58175
58145
|
}
|
|
58176
58146
|
//#endregion
|
|
@@ -58617,14 +58587,14 @@ const SENSITIVE_DOT_VARIANT_SUFFIXES = [
|
|
|
58617
58587
|
];
|
|
58618
58588
|
const SENSITIVE_DOT_VARIANT_SUFFIX_SET = new Set(SENSITIVE_DOT_VARIANT_SUFFIXES);
|
|
58619
58589
|
const DEFAULT_PATH_CLASS$1 = path$8.sep === "\\" ? "win32" : "posix";
|
|
58620
|
-
function pathMod$
|
|
58590
|
+
function pathMod$4(pathClass) {
|
|
58621
58591
|
return pathClass === "win32" ? win32Path : posixPath;
|
|
58622
58592
|
}
|
|
58623
58593
|
function comparable(path, pathClass) {
|
|
58624
58594
|
return pathClass === "win32" ? path.toLowerCase() : path;
|
|
58625
58595
|
}
|
|
58626
58596
|
function isSensitiveFile(path, pathClass = DEFAULT_PATH_CLASS$1) {
|
|
58627
|
-
const mod = pathMod$
|
|
58597
|
+
const mod = pathMod$4(pathClass);
|
|
58628
58598
|
const comparableName = comparable(mod.basename(path), pathClass);
|
|
58629
58599
|
const comparablePath = comparable(path, pathClass);
|
|
58630
58600
|
if (ENV_EXEMPTIONS.has(comparableName)) return false;
|
|
@@ -58678,7 +58648,7 @@ var PathSecurityError = class extends Error {
|
|
|
58678
58648
|
}
|
|
58679
58649
|
};
|
|
58680
58650
|
const DEFAULT_PATH_CLASS = path$8.sep === "\\" ? "win32" : "posix";
|
|
58681
|
-
function pathMod$
|
|
58651
|
+
function pathMod$3(pathClass) {
|
|
58682
58652
|
return pathClass === "win32" ? win32Path : posixPath;
|
|
58683
58653
|
}
|
|
58684
58654
|
function comparablePath(path, pathClass) {
|
|
@@ -58708,7 +58678,7 @@ function normalizeUserPath(path, pathClass = DEFAULT_PATH_CLASS) {
|
|
|
58708
58678
|
function expandUserPath$1(path, homeDir, pathClass) {
|
|
58709
58679
|
if (homeDir === void 0) return path;
|
|
58710
58680
|
if (path === "~") return homeDir;
|
|
58711
|
-
if (path.startsWith("~/") || pathClass === "win32" && path.startsWith("~\\")) return pathMod$
|
|
58681
|
+
if (path.startsWith("~/") || pathClass === "win32" && path.startsWith("~\\")) return pathMod$3(pathClass).join(homeDir, path.slice(2));
|
|
58712
58682
|
return path;
|
|
58713
58683
|
}
|
|
58714
58684
|
/**
|
|
@@ -58717,7 +58687,7 @@ function expandUserPath$1(path, homeDir, pathClass) {
|
|
|
58717
58687
|
*/
|
|
58718
58688
|
function canonicalizePath(path, cwd, pathClass = DEFAULT_PATH_CLASS) {
|
|
58719
58689
|
if (path === "") throw new PathSecurityError("PATH_INVALID", path, path, "Path cannot be empty");
|
|
58720
|
-
const mod = pathMod$
|
|
58690
|
+
const mod = pathMod$3(pathClass);
|
|
58721
58691
|
const normalizedPath = normalizeUserPath(path, pathClass);
|
|
58722
58692
|
if (pathClass === "win32" && isWin32DriveRelative(normalizedPath)) throw new PathSecurityError("PATH_INVALID", path, normalizedPath, `"${path}" is a drive-relative Windows path. Use an absolute path like C:\\path or a path relative to the working directory.`);
|
|
58723
58693
|
if (!mod.isAbsolute(normalizedPath) && !mod.isAbsolute(cwd)) throw new PathSecurityError("PATH_INVALID", path, normalizedPath, `Cannot resolve "${path}" against non-absolute cwd "${cwd}".`);
|
|
@@ -58729,7 +58699,7 @@ function canonicalizePath(path, cwd, pathClass = DEFAULT_PATH_CLASS) {
|
|
|
58729
58699
|
* on path-component boundaries. Both arguments must already be canonical.
|
|
58730
58700
|
*/
|
|
58731
58701
|
function isWithinDirectory(candidate, base, pathClass = DEFAULT_PATH_CLASS) {
|
|
58732
|
-
const mod = pathMod$
|
|
58702
|
+
const mod = pathMod$3(pathClass);
|
|
58733
58703
|
const comparableCandidate = comparablePath(candidate, pathClass);
|
|
58734
58704
|
const comparableBase = comparablePath(base, pathClass);
|
|
58735
58705
|
if (comparableCandidate === comparableBase) return true;
|
|
@@ -58755,7 +58725,7 @@ function relativeOutsideMessage(path, operation) {
|
|
|
58755
58725
|
}
|
|
58756
58726
|
function resolvePathAccess(path, cwd, config, options) {
|
|
58757
58727
|
const pathClass = options.pathClass ?? DEFAULT_PATH_CLASS;
|
|
58758
|
-
const mod = pathMod$
|
|
58728
|
+
const mod = pathMod$3(pathClass);
|
|
58759
58729
|
const expandedPath = expandUserPath$1(normalizeUserPath(path, pathClass), options.homeDir, pathClass);
|
|
58760
58730
|
const rawIsAbsolute = mod.isAbsolute(expandedPath);
|
|
58761
58731
|
const canonical = canonicalizePath(expandedPath, cwd, pathClass);
|
|
@@ -58910,11 +58880,11 @@ var EditTool = class {
|
|
|
58910
58880
|
}
|
|
58911
58881
|
}
|
|
58912
58882
|
};
|
|
58913
|
-
async function collectEntries
|
|
58883
|
+
async function collectEntries(kaos, dirPath, maxWidth, pathClass) {
|
|
58914
58884
|
const all = [];
|
|
58915
58885
|
try {
|
|
58916
58886
|
for await (const fullPath of kaos.iterdir(dirPath)) {
|
|
58917
|
-
const name = basename$
|
|
58887
|
+
const name = basename$1(fullPath, pathClass);
|
|
58918
58888
|
let isDir = false;
|
|
58919
58889
|
try {
|
|
58920
58890
|
isDir = ((await kaos.stat(fullPath)).stMode & 61440) === 16384;
|
|
@@ -58941,11 +58911,11 @@ async function collectEntries$1(kaos, dirPath, maxWidth, pathClass) {
|
|
|
58941
58911
|
readable: true
|
|
58942
58912
|
};
|
|
58943
58913
|
}
|
|
58944
|
-
function pathMod$
|
|
58914
|
+
function pathMod$2(pathClass) {
|
|
58945
58915
|
return pathClass === "win32" ? win32Path : posixPath;
|
|
58946
58916
|
}
|
|
58947
|
-
function basename$
|
|
58948
|
-
return pathMod$
|
|
58917
|
+
function basename$1(p, pathClass) {
|
|
58918
|
+
return pathMod$2(pathClass).basename(p);
|
|
58949
58919
|
}
|
|
58950
58920
|
/**
|
|
58951
58921
|
* Return a 2-level tree listing of `workDir` suitable for inclusion in a
|
|
@@ -58955,7 +58925,7 @@ function basename$2(p, pathClass) {
|
|
|
58955
58925
|
async function listDirectory(kaos, workDir) {
|
|
58956
58926
|
const lines = [];
|
|
58957
58927
|
const pathClass = kaos.pathClass();
|
|
58958
|
-
const { entries, total, readable } = await collectEntries
|
|
58928
|
+
const { entries, total, readable } = await collectEntries(kaos, workDir, 30, pathClass);
|
|
58959
58929
|
if (!readable) return "[not readable]";
|
|
58960
58930
|
const remaining = total - entries.length;
|
|
58961
58931
|
for (let i = 0; i < entries.length; i++) {
|
|
@@ -58967,7 +58937,7 @@ async function listDirectory(kaos, workDir) {
|
|
|
58967
58937
|
if (isDir) {
|
|
58968
58938
|
lines.push(`${connector}${name}/`);
|
|
58969
58939
|
const childPrefix = isLast ? " " : "│ ";
|
|
58970
|
-
const child = await collectEntries
|
|
58940
|
+
const child = await collectEntries(kaos, joinPath(workDir, name, pathClass), 10, pathClass);
|
|
58971
58941
|
if (!child.readable) {
|
|
58972
58942
|
lines.push(`${childPrefix}└── [not readable]`);
|
|
58973
58943
|
continue;
|
|
@@ -58986,17 +58956,17 @@ async function listDirectory(kaos, workDir) {
|
|
|
58986
58956
|
if (remaining > 0) lines.push(`└── ... and ${String(remaining)} more entries`);
|
|
58987
58957
|
return lines.length > 0 ? lines.join("\n") : "(empty directory)";
|
|
58988
58958
|
}
|
|
58989
|
-
function joinPath
|
|
58990
|
-
return pathMod$
|
|
58959
|
+
function joinPath(parent, child, pathClass) {
|
|
58960
|
+
return pathMod$2(pathClass).join(parent, child);
|
|
58991
58961
|
}
|
|
58992
58962
|
//#endregion
|
|
58993
58963
|
//#region ../agent-core/src/tools/builtin/file/glob.md
|
|
58994
|
-
var glob_default = "Find files (and optionally directories) by glob pattern, sorted by modification time (most recent first).\n\
|
|
58964
|
+
var glob_default = "Find files (and optionally directories) by glob pattern, sorted by modification time (most recent first).\n\nREJECTED patterns (no literal anchor — will be rejected):\n- **Pure wildcards**: `**`, `**/*`, `*/*` — no literal anchor bounds the result. Add an extension or subdirectory to give the walk a concrete target.\n- **`**/` prefix**: Anything starting with `**/` (e.g. `**/*.py`, `**/main/*.ts`). The leading `**/` has no literal anchor in front of it. Anchor it with a top-level subdirectory like `src/**/*.ts`.\n- **Brace expansion**: `*.{ts,tsx}` is not supported. Split it into separate calls: `*.ts` and `*.tsx`.\n\nGood patterns:\n- `*.ts` — files in the current directory matching an extension\n- `src/**/*.ts` — recursive with a subdirectory anchor and extension\n- `test_*.py` — files whose name starts with a literal prefix\n\nLarge-directory warning — avoid recursing into dependency/build output even with an anchor:\n- `node_modules/**/*.js`, `.venv/**/*.py`, `__pycache__/**`, `target/**` match technically but typically produce thousands of results that truncate at the match cap. Prefer specific subpaths like `node_modules/react/src/**/*.js`.\n\nWhen you need to search the entire project, first use Glob to explore the top-level directory structure, then use an anchored pattern like `src/**/*.ts` or `packages/**/*.ts` to narrow the search.\n";
|
|
58995
58965
|
//#endregion
|
|
58996
58966
|
//#region ../agent-core/src/tools/builtin/file/glob.ts
|
|
58997
58967
|
const GlobInputSchema = z.object({
|
|
58998
|
-
pattern: z.string().describe("Glob pattern to match files/directories."),
|
|
58999
|
-
path: z.string().optional().describe("Absolute path to the directory to search in. Defaults to the current working directory."),
|
|
58968
|
+
pattern: z.string().describe("Glob pattern to match files/directories. IMPORTANT: pattern MUST contain a literal anchor like a file extension (.ts) or a subdirectory name (src/). Patterns starting with **/ (e.g. **/*.py, **/main/*.ts), pure wildcards (**, **/*, */*, *), and brace expansion (*.{ts,tsx}) are REJECTED. Example: src/**/*.ts searches all .ts files under src/."),
|
|
58969
|
+
path: z.string().optional().describe("Absolute path to the directory to search in. Defaults to the current working directory. Explicit absolute paths outside the workspace are allowed (e.g. to search a dependency installed elsewhere); relative paths are resolved against the working directory and rejected if they escape it."),
|
|
59000
58970
|
include_dirs: z.boolean().default(true).optional().describe("Whether to include directories in results. Defaults to true. Set false to return only files.")
|
|
59001
58971
|
});
|
|
59002
58972
|
const MAX_MATCHES = 1e3;
|
|
@@ -59038,7 +59008,7 @@ var GlobTool = class {
|
|
|
59038
59008
|
workspace: this.workspace,
|
|
59039
59009
|
operation: "search",
|
|
59040
59010
|
policy: {
|
|
59041
|
-
guardMode: "
|
|
59011
|
+
guardMode: "absolute-outside-allowed",
|
|
59042
59012
|
checkSensitive: false
|
|
59043
59013
|
}
|
|
59044
59014
|
});
|
|
@@ -59072,7 +59042,7 @@ var GlobTool = class {
|
|
|
59072
59042
|
}
|
|
59073
59043
|
return {
|
|
59074
59044
|
isError: true,
|
|
59075
|
-
output: `Pattern "${args.pattern}" is a pure wildcard (only \`*\`, \`?\`, \`**\`, \`/\`) and would enumerate every file under the search root — with no literal anchor to bound the result set, this typically exhausts your context on large trees. Add an extension ("${args.pattern === "**" || args.pattern === "**/*" ? "**/*.ts" : "**/*.md"}") or a subdirectory ("src/**/*.ts") to constrain the walk.\n\
|
|
59045
|
+
output: `Pattern "${args.pattern}" is a pure wildcard (only \`*\`, \`?\`, \`**\`, \`/\`) and would enumerate every file under the search root — with no literal anchor to bound the result set, this typically exhausts your context on large trees. Add an extension ("${args.pattern === "**" || args.pattern === "**/*" ? "**/*.ts" : "**/*.md"}") or a subdirectory ("src/**/*.ts") to constrain the walk.\n\nWorkspace roots:\n${rootList}\n\nTop of ${this.workspace.workspaceDir}:\n${tree}`
|
|
59076
59046
|
};
|
|
59077
59047
|
}
|
|
59078
59048
|
if (containsBraceExpansion(args.pattern)) return {
|
|
@@ -59100,6 +59070,8 @@ var GlobTool = class {
|
|
|
59100
59070
|
try {
|
|
59101
59071
|
const seen = /* @__PURE__ */ new Set();
|
|
59102
59072
|
const entries = [];
|
|
59073
|
+
const pathClass = this.kaos.pathClass();
|
|
59074
|
+
const filteredSensitive = [];
|
|
59103
59075
|
const YIELD_SAFETY_CAP = MAX_MATCHES * 2;
|
|
59104
59076
|
let yielded = 0;
|
|
59105
59077
|
let truncated = false;
|
|
@@ -59115,6 +59087,10 @@ var GlobTool = class {
|
|
|
59115
59087
|
break outer;
|
|
59116
59088
|
}
|
|
59117
59089
|
seen.add(filePath);
|
|
59090
|
+
if (isSensitiveFile(filePath, pathClass)) {
|
|
59091
|
+
filteredSensitive.push(filePath);
|
|
59092
|
+
continue;
|
|
59093
|
+
}
|
|
59118
59094
|
let mtime = 0;
|
|
59119
59095
|
let isDir = false;
|
|
59120
59096
|
try {
|
|
@@ -59130,10 +59106,10 @@ var GlobTool = class {
|
|
|
59130
59106
|
}
|
|
59131
59107
|
entries.sort((a, b) => b.mtime - a.mtime);
|
|
59132
59108
|
const paths = entries.map((e) => e.path);
|
|
59133
|
-
const pathClass = this.kaos.pathClass();
|
|
59134
59109
|
const relBase = searchRoots[0] ?? this.workspace.workspaceDir;
|
|
59135
59110
|
const displayLines = paths.map((p) => relativizeIfUnder$1(p, relBase, pathClass));
|
|
59136
|
-
|
|
59111
|
+
const filteredSome = filteredSensitive.length > 0;
|
|
59112
|
+
if (entries.length === 0 && !truncated) return { output: filteredSome ? `No non-sensitive matches found (filtered ${String(filteredSensitive.length)} sensitive file(s))` : "No matches found" };
|
|
59137
59113
|
const lines = [];
|
|
59138
59114
|
if (truncated) {
|
|
59139
59115
|
lines.push(`[Truncated at ${String(MAX_MATCHES)} matches — use a more specific pattern]`);
|
|
@@ -59141,6 +59117,10 @@ var GlobTool = class {
|
|
|
59141
59117
|
}
|
|
59142
59118
|
lines.push(...displayLines);
|
|
59143
59119
|
if (!truncated && entries.length === 1e3) lines.push(`Found ${String(entries.length)} matches`);
|
|
59120
|
+
if (filteredSome) {
|
|
59121
|
+
const displayedFiltered = filteredSensitive.map((p) => relativizeIfUnder$1(p, relBase, pathClass));
|
|
59122
|
+
lines.push(`Filtered ${String(filteredSensitive.length)} sensitive file(s): ${displayedFiltered.join(", ")}`);
|
|
59123
|
+
}
|
|
59144
59124
|
return { output: lines.join("\n") };
|
|
59145
59125
|
} catch (error) {
|
|
59146
59126
|
if (error !== null && typeof error === "object" && "code" in error) {
|
|
@@ -63488,7 +63468,7 @@ async function downloadAndInstallRg(shareDir) {
|
|
|
63488
63468
|
clearTimeout(timeoutHandle);
|
|
63489
63469
|
}
|
|
63490
63470
|
if (!resp.ok || resp.body === null) throw new Error(`Failed to download ripgrep: HTTP ${String(resp.status)} ${resp.statusText}`);
|
|
63491
|
-
const write = createWriteStream
|
|
63471
|
+
const write = createWriteStream(archivePath);
|
|
63492
63472
|
await pipeline$1(Readable.fromWeb(resp.body), write);
|
|
63493
63473
|
await verifyArchiveChecksum(archivePath, archiveName, expectedSha256);
|
|
63494
63474
|
if (isWindows) await extractRgFromZip(archivePath, destination);
|
|
@@ -63549,7 +63529,7 @@ async function extractRgFromZip(archivePath, destination) {
|
|
|
63549
63529
|
zipfile.close();
|
|
63550
63530
|
return;
|
|
63551
63531
|
}
|
|
63552
|
-
const out = createWriteStream
|
|
63532
|
+
const out = createWriteStream(destination);
|
|
63553
63533
|
(async () => {
|
|
63554
63534
|
try {
|
|
63555
63535
|
await pipeline$1(stream, out);
|
|
@@ -65095,7 +65075,7 @@ var write_default = "Overwrite or append to a file with content exactly as provi
|
|
|
65095
65075
|
const S_IFMT$2 = 61440;
|
|
65096
65076
|
/** File-type bits of a directory. */
|
|
65097
65077
|
const S_IFDIR$1 = 16384;
|
|
65098
|
-
function pathMod$
|
|
65078
|
+
function pathMod$1(pathClass) {
|
|
65099
65079
|
return pathClass === "win32" ? win32Path : posixPath;
|
|
65100
65080
|
}
|
|
65101
65081
|
const WriteInputSchema = z.object({
|
|
@@ -65162,7 +65142,7 @@ var WriteTool = class {
|
|
|
65162
65142
|
* skipped and the write proceeds, surfacing the real I/O error if any.
|
|
65163
65143
|
*/
|
|
65164
65144
|
async checkParentDirectory(safePath) {
|
|
65165
|
-
const parent = pathMod$
|
|
65145
|
+
const parent = pathMod$1(this.kaos.pathClass()).dirname(safePath);
|
|
65166
65146
|
let stat;
|
|
65167
65147
|
try {
|
|
65168
65148
|
stat = await this.kaos.stat(parent);
|
|
@@ -65465,7 +65445,7 @@ function rewriteWindowsNullRedirect$1(command) {
|
|
|
65465
65445
|
}
|
|
65466
65446
|
//#endregion
|
|
65467
65447
|
//#region ../agent-core/src/tools/builtin/state/todo-list.md
|
|
65468
|
-
var todo_list_default = "Use this tool to maintain a structured TODO list as you work through a multi-step task.\n\nUse for multi-step tasks, tracking investigation progress, or planning a sequence of edits. Do not use for single-shot answers or trivial requests.\n\n**
|
|
65448
|
+
var todo_list_default = "Use this tool to maintain a structured TODO list as you work through a multi-step task.\n\nUse for multi-step tasks, tracking investigation progress, or planning a sequence of edits. Do not use for single-shot answers or trivial requests.\n\n**Update discipline:**\n- Update status immediately when you start or complete a subtask: mark it `in_progress` when you begin working on it, and `done` when finished.\n- Do not skip the `in_progress` state — the user should always see what you are currently working on.\n- Avoid redundant calls: do not re-call this tool when nothing meaningful has changed since the last call.\n- When unsure of the current state, call query mode first (omit `todos`) to check the list before deciding what to update.\n- If no available tool can move any task forward, tell the user where you are stuck instead of repeatedly re-ordering the same todos.\n\n**How to use:**\n- Call with `todos: [...]` to replace the full list. Statuses: pending / in_progress / done.\n- Call with no arguments to query the current list.\n- Call with `todos: []` to clear the list.\n- Keep titles short and actionable.\n- Update statuses as you make progress — mark one item in_progress at a time.\n";
|
|
65469
65449
|
//#endregion
|
|
65470
65450
|
//#region ../agent-core/src/tools/builtin/state/todo-list.ts
|
|
65471
65451
|
/**
|
|
@@ -66078,8 +66058,14 @@ function project(history, ephemeralInjections) {
|
|
|
66078
66058
|
if (isBlockedUserPrompt(message)) return false;
|
|
66079
66059
|
return !isTranscriptOnlyHookResult(message) && message.partial !== true && !(message.role === "assistant" && message.content.length === 0 && message.toolCalls.length === 0);
|
|
66080
66060
|
}));
|
|
66081
|
-
|
|
66082
|
-
|
|
66061
|
+
if (!ephemeralInjections?.length) return merged;
|
|
66062
|
+
const afterSystemMsgs = ephemeralInjections.filter((injection) => !injection.position || injection.position === "after_system").map((injection) => renderInjection(injection));
|
|
66063
|
+
const beforeUserMsgs = ephemeralInjections.filter((injection) => injection.position === "before_user").map((injection) => renderInjection(injection));
|
|
66064
|
+
return [
|
|
66065
|
+
...afterSystemMsgs,
|
|
66066
|
+
...merged,
|
|
66067
|
+
...beforeUserMsgs
|
|
66068
|
+
];
|
|
66083
66069
|
}
|
|
66084
66070
|
function isTranscriptOnlyHookResult(message) {
|
|
66085
66071
|
return message.origin?.kind === "hook_result" && TRANSCRIPT_ONLY_HOOK_RESULT_EVENTS.has(message.origin.event ?? "");
|
|
@@ -66834,7 +66820,7 @@ var ConfigState = class {
|
|
|
66834
66820
|
return provider;
|
|
66835
66821
|
}
|
|
66836
66822
|
get provider() {
|
|
66837
|
-
return createProvider(this.providerConfig);
|
|
66823
|
+
return createProvider$1(this.providerConfig);
|
|
66838
66824
|
}
|
|
66839
66825
|
get model() {
|
|
66840
66826
|
if (this._modelAlias === void 0) throw new Error("Model not set");
|
|
@@ -67069,7 +67055,15 @@ var ContextMemory = class {
|
|
|
67069
67055
|
return this._history;
|
|
67070
67056
|
}
|
|
67071
67057
|
get messages() {
|
|
67072
|
-
return
|
|
67058
|
+
return this.getMessages();
|
|
67059
|
+
}
|
|
67060
|
+
/**
|
|
67061
|
+
* Project history into provider-ready messages, optionally with
|
|
67062
|
+
* ephemeral injections (e.g. timestamp, permission mode) appended
|
|
67063
|
+
* at the `'before_user'` position.
|
|
67064
|
+
*/
|
|
67065
|
+
getMessages(ephemeral) {
|
|
67066
|
+
return project(this.history, ephemeral);
|
|
67073
67067
|
}
|
|
67074
67068
|
applyObservationMasking(config) {
|
|
67075
67069
|
const effectiveConfig = config ?? DEFAULT_MASKING_CONFIG;
|
|
@@ -67353,7 +67347,7 @@ const OptionalStringSchema = z.preprocess((value) => {
|
|
|
67353
67347
|
if (typeof value === "string") return value;
|
|
67354
67348
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
67355
67349
|
}, z.string().optional());
|
|
67356
|
-
const HookSpecificOutputSchema = z.preprocess((value) => isRecord$
|
|
67350
|
+
const HookSpecificOutputSchema = z.preprocess((value) => isRecord$4(value) ? value : void 0, z.looseObject({
|
|
67357
67351
|
message: OptionalStringSchema,
|
|
67358
67352
|
permissionDecision: z.unknown().optional(),
|
|
67359
67353
|
permissionDecisionReason: OptionalStringSchema
|
|
@@ -67372,7 +67366,7 @@ async function runHook(command, input, options) {
|
|
|
67372
67366
|
detached: process.platform !== "win32"
|
|
67373
67367
|
});
|
|
67374
67368
|
} catch (error) {
|
|
67375
|
-
return allowResult({ stderr: errorMessage$
|
|
67369
|
+
return allowResult({ stderr: errorMessage$2(error) });
|
|
67376
67370
|
}
|
|
67377
67371
|
return new Promise((resolve) => {
|
|
67378
67372
|
let stdout = "";
|
|
@@ -67420,7 +67414,7 @@ async function runHook(command, input, options) {
|
|
|
67420
67414
|
child.on("error", (error) => {
|
|
67421
67415
|
settle(allowResult({
|
|
67422
67416
|
stdout,
|
|
67423
|
-
stderr: stderr + errorMessage$
|
|
67417
|
+
stderr: stderr + errorMessage$2(error)
|
|
67424
67418
|
}));
|
|
67425
67419
|
});
|
|
67426
67420
|
child.on("close", (code) => {
|
|
@@ -67513,10 +67507,10 @@ function tryKillProcess(child, signal) {
|
|
|
67513
67507
|
} catch {}
|
|
67514
67508
|
}
|
|
67515
67509
|
}
|
|
67516
|
-
function isRecord$
|
|
67510
|
+
function isRecord$4(value) {
|
|
67517
67511
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
67518
67512
|
}
|
|
67519
|
-
function errorMessage$
|
|
67513
|
+
function errorMessage$2(error) {
|
|
67520
67514
|
return error instanceof Error ? error.message : String(error);
|
|
67521
67515
|
}
|
|
67522
67516
|
//#endregion
|
|
@@ -67730,146 +67724,55 @@ var DynamicInjector = class {
|
|
|
67730
67724
|
}
|
|
67731
67725
|
};
|
|
67732
67726
|
//#endregion
|
|
67733
|
-
//#region ../agent-core/src/agent/injection/directory-tree.ts
|
|
67734
|
-
const EXCLUDED_DIRS = new Set([
|
|
67735
|
-
"node_modules",
|
|
67736
|
-
".git",
|
|
67737
|
-
"dist",
|
|
67738
|
-
"build",
|
|
67739
|
-
".next",
|
|
67740
|
-
".nuxt",
|
|
67741
|
-
".vite",
|
|
67742
|
-
"target",
|
|
67743
|
-
".turbo",
|
|
67744
|
-
"coverage",
|
|
67745
|
-
".cache",
|
|
67746
|
-
".DS_Store",
|
|
67747
|
-
".idea",
|
|
67748
|
-
".vscode",
|
|
67749
|
-
"venv",
|
|
67750
|
-
".venv"
|
|
67751
|
-
]);
|
|
67752
|
-
const HIDDEN_DIR_WHITELIST = new Set([
|
|
67753
|
-
".github",
|
|
67754
|
-
".byf",
|
|
67755
|
-
".agents",
|
|
67756
|
-
".changeset",
|
|
67757
|
-
".husky"
|
|
67758
|
-
]);
|
|
67759
|
-
var DirectoryTreeInjector = class extends DynamicInjector {
|
|
67760
|
-
injectionVariant = "directory_tree";
|
|
67761
|
-
lastTree;
|
|
67762
|
-
hasInjected = false;
|
|
67763
|
-
capturedTimestamp;
|
|
67764
|
-
async getInjection() {
|
|
67765
|
-
const kaos = this.agent.runtime.kaos;
|
|
67766
|
-
const workDir = this.agent.config.cwd || kaos.getcwd();
|
|
67767
|
-
const tree = await buildTree(kaos, workDir);
|
|
67768
|
-
if (this.hasInjected && tree === this.lastTree) return;
|
|
67769
|
-
this.lastTree = tree;
|
|
67770
|
-
this.hasInjected = true;
|
|
67771
|
-
if (this.capturedTimestamp === void 0) this.capturedTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
67772
|
-
return `Current working directory structure (${workDir}):\n${tree}\n\nThe current date and time in ISO format is \`${this.capturedTimestamp}\`. This is only a reference for you when searching the web or checking file modification time, etc. If you need the exact time, use Bash tool with proper command.`;
|
|
67773
|
-
}
|
|
67774
|
-
};
|
|
67775
|
-
async function buildTree(kaos, workDir) {
|
|
67776
|
-
const lines = [];
|
|
67777
|
-
const pathClass = kaos.pathClass();
|
|
67778
|
-
const { entries, total, readable } = await collectEntries(kaos, workDir, 30, pathClass);
|
|
67779
|
-
if (!readable) return "[not readable]";
|
|
67780
|
-
const remaining = total - entries.length;
|
|
67781
|
-
for (let i = 0; i < entries.length; i++) {
|
|
67782
|
-
const entry = entries[i];
|
|
67783
|
-
if (entry === void 0) continue;
|
|
67784
|
-
const { name, isDir } = entry;
|
|
67785
|
-
const isLast = i === entries.length - 1 && remaining === 0;
|
|
67786
|
-
const connector = isLast ? "└── " : "├── ";
|
|
67787
|
-
if (isDir) {
|
|
67788
|
-
lines.push(`${connector}${name}/`);
|
|
67789
|
-
const childPrefix = isLast ? " " : "│ ";
|
|
67790
|
-
const child = await collectEntries(kaos, joinPath(workDir, name, pathClass), 10, pathClass);
|
|
67791
|
-
if (!child.readable) {
|
|
67792
|
-
lines.push(`${childPrefix}└── [not readable]`);
|
|
67793
|
-
continue;
|
|
67794
|
-
}
|
|
67795
|
-
const childRemaining = child.total - child.entries.length;
|
|
67796
|
-
for (let j = 0; j < child.entries.length; j++) {
|
|
67797
|
-
const ce = child.entries[j];
|
|
67798
|
-
if (ce === void 0) continue;
|
|
67799
|
-
const cConnector = j === child.entries.length - 1 && childRemaining === 0 ? "└── " : "├── ";
|
|
67800
|
-
const suffix = ce.isDir ? "/" : "";
|
|
67801
|
-
lines.push(`${childPrefix}${cConnector}${ce.name}${suffix}`);
|
|
67802
|
-
}
|
|
67803
|
-
if (childRemaining > 0) lines.push(`${childPrefix}└── ... and ${String(childRemaining)} more`);
|
|
67804
|
-
} else lines.push(`${connector}${name}`);
|
|
67805
|
-
}
|
|
67806
|
-
if (remaining > 0) lines.push(`└── ... and ${String(remaining)} more entries`);
|
|
67807
|
-
return lines.length > 0 ? lines.join("\n") : "(empty directory)";
|
|
67808
|
-
}
|
|
67809
|
-
async function collectEntries(kaos, dirPath, maxWidth, pathClass) {
|
|
67810
|
-
const all = [];
|
|
67811
|
-
try {
|
|
67812
|
-
for await (const fullPath of kaos.iterdir(dirPath)) {
|
|
67813
|
-
const name = basename$1(fullPath, pathClass);
|
|
67814
|
-
if (shouldExclude(name)) continue;
|
|
67815
|
-
let isDir = false;
|
|
67816
|
-
try {
|
|
67817
|
-
isDir = ((await kaos.stat(fullPath)).stMode & 61440) === 16384;
|
|
67818
|
-
} catch {}
|
|
67819
|
-
all.push({
|
|
67820
|
-
name,
|
|
67821
|
-
isDir
|
|
67822
|
-
});
|
|
67823
|
-
}
|
|
67824
|
-
} catch {
|
|
67825
|
-
return {
|
|
67826
|
-
entries: [],
|
|
67827
|
-
total: 0,
|
|
67828
|
-
readable: false
|
|
67829
|
-
};
|
|
67830
|
-
}
|
|
67831
|
-
all.sort((a, b) => {
|
|
67832
|
-
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
67833
|
-
return a.name.localeCompare(b.name);
|
|
67834
|
-
});
|
|
67835
|
-
return {
|
|
67836
|
-
entries: all.slice(0, maxWidth),
|
|
67837
|
-
total: all.length,
|
|
67838
|
-
readable: true
|
|
67839
|
-
};
|
|
67840
|
-
}
|
|
67841
|
-
function shouldExclude(name) {
|
|
67842
|
-
if (EXCLUDED_DIRS.has(name)) return true;
|
|
67843
|
-
if (name.startsWith(".") && !HIDDEN_DIR_WHITELIST.has(name)) return true;
|
|
67844
|
-
return false;
|
|
67845
|
-
}
|
|
67846
|
-
function pathMod$1(pathClass) {
|
|
67847
|
-
return pathClass === "win32" ? win32Path : posixPath;
|
|
67848
|
-
}
|
|
67849
|
-
function basename$1(p, pathClass) {
|
|
67850
|
-
return pathMod$1(pathClass).basename(p);
|
|
67851
|
-
}
|
|
67852
|
-
function joinPath(parent, child, pathClass) {
|
|
67853
|
-
return pathMod$1(pathClass).join(parent, child);
|
|
67854
|
-
}
|
|
67855
|
-
//#endregion
|
|
67856
67727
|
//#region ../agent-core/src/agent/injection/permission-mode.ts
|
|
67857
|
-
const
|
|
67728
|
+
const AUTO_MODE_REMINDER = [
|
|
67858
67729
|
"Auto permission mode is active. Tool approvals will be handled automatically while this mode remains enabled.",
|
|
67859
67730
|
" - Continue normally without pausing for approval prompts.",
|
|
67860
67731
|
" - Do NOT call AskUserQuestion while auto mode is active. Make a reasonable decision and continue without asking the user."
|
|
67861
67732
|
].join("\n");
|
|
67862
|
-
|
|
67733
|
+
/**
|
|
67734
|
+
* Ephemeral injector for permission mode state.
|
|
67735
|
+
*
|
|
67736
|
+
* Emits the current permission mode as an ephemeral injection placed at
|
|
67737
|
+
* the `'before_user'` position. Unlike the previous persistent approach
|
|
67738
|
+
* (which recorded transition events into history), the ephemeral approach
|
|
67739
|
+
* always reflects the current state — surviving compaction and avoiding
|
|
67740
|
+
* history pollution.
|
|
67741
|
+
*
|
|
67742
|
+
* Only auto mode produces an injection; in all other modes the absence
|
|
67743
|
+
* of a reminder signals that normal approval prompts apply.
|
|
67744
|
+
*/
|
|
67863
67745
|
var PermissionModeInjector = class extends DynamicInjector {
|
|
67864
67746
|
injectionVariant = "permission_mode";
|
|
67865
|
-
|
|
67866
|
-
|
|
67867
|
-
|
|
67868
|
-
|
|
67869
|
-
|
|
67870
|
-
|
|
67871
|
-
|
|
67872
|
-
|
|
67747
|
+
getInjection() {}
|
|
67748
|
+
getEphemeral() {
|
|
67749
|
+
if (this.agent.permission.mode !== "auto") return [];
|
|
67750
|
+
return [{
|
|
67751
|
+
kind: "system_reminder",
|
|
67752
|
+
content: AUTO_MODE_REMINDER,
|
|
67753
|
+
position: "before_user"
|
|
67754
|
+
}];
|
|
67755
|
+
}
|
|
67756
|
+
};
|
|
67757
|
+
//#endregion
|
|
67758
|
+
//#region ../agent-core/src/agent/injection/timestamp.ts
|
|
67759
|
+
/**
|
|
67760
|
+
* Ephemeral injector that provides the current timestamp at request time.
|
|
67761
|
+
*
|
|
67762
|
+
* The timestamp is rendered fresh on every step (not frozen) and placed
|
|
67763
|
+
* at the `'before_user'` position so it never breaks the cached prefix.
|
|
67764
|
+
* This aligns with the prompt-cache best practice of keeping per-request
|
|
67765
|
+
* dynamic content out of the cacheable system-prompt blocks.
|
|
67766
|
+
*/
|
|
67767
|
+
var TimestampInjector = class extends DynamicInjector {
|
|
67768
|
+
injectionVariant = "timestamp";
|
|
67769
|
+
getInjection() {}
|
|
67770
|
+
getEphemeral() {
|
|
67771
|
+
return [{
|
|
67772
|
+
kind: "system_reminder",
|
|
67773
|
+
content: `The current date and time in ISO format is \`${(/* @__PURE__ */ new Date()).toISOString()}\`. This is only a reference for you when searching the web or checking file modification time, etc. If you need the exact time, use Bash tool with proper command.`,
|
|
67774
|
+
position: "before_user"
|
|
67775
|
+
}];
|
|
67873
67776
|
}
|
|
67874
67777
|
};
|
|
67875
67778
|
//#endregion
|
|
@@ -67879,11 +67782,20 @@ var InjectionManager = class {
|
|
|
67879
67782
|
injectors;
|
|
67880
67783
|
constructor(agent) {
|
|
67881
67784
|
this.agent = agent;
|
|
67882
|
-
this.injectors = [new PermissionModeInjector(agent), new
|
|
67785
|
+
this.injectors = [new PermissionModeInjector(agent), new TimestampInjector(agent)];
|
|
67883
67786
|
}
|
|
67884
67787
|
async inject() {
|
|
67885
67788
|
for (const injector of this.injectors) await injector.inject();
|
|
67886
67789
|
}
|
|
67790
|
+
getEphemeralInjections() {
|
|
67791
|
+
return this.injectors.flatMap((injector) => {
|
|
67792
|
+
try {
|
|
67793
|
+
return injector.getEphemeral?.() ?? [];
|
|
67794
|
+
} catch {
|
|
67795
|
+
return [];
|
|
67796
|
+
}
|
|
67797
|
+
});
|
|
67798
|
+
}
|
|
67887
67799
|
onContextClear() {
|
|
67888
67800
|
for (const injector of this.injectors) injector.onContextClear();
|
|
67889
67801
|
}
|
|
@@ -70530,8 +70442,8 @@ function approvalTelemetryMode(mode) {
|
|
|
70530
70442
|
//#endregion
|
|
70531
70443
|
//#region ../agent-core/src/agent/records/migration/v1.1.ts
|
|
70532
70444
|
function isLegacyToolCall(v) {
|
|
70533
|
-
if (!isRecord$
|
|
70534
|
-
return v["type"] === "function" && typeof v["id"] === "string" && isRecord$
|
|
70445
|
+
if (!isRecord$3(v)) return false;
|
|
70446
|
+
return v["type"] === "function" && typeof v["id"] === "string" && isRecord$3(v["function"]);
|
|
70535
70447
|
}
|
|
70536
70448
|
function migrateToolCall(v) {
|
|
70537
70449
|
const { function: fn, ...rest } = v;
|
|
@@ -70541,7 +70453,7 @@ function migrateToolCall(v) {
|
|
|
70541
70453
|
arguments: fn.arguments
|
|
70542
70454
|
};
|
|
70543
70455
|
}
|
|
70544
|
-
function isRecord$
|
|
70456
|
+
function isRecord$3(value) {
|
|
70545
70457
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
70546
70458
|
}
|
|
70547
70459
|
const MIGRATIONS = [{
|
|
@@ -70770,8 +70682,7 @@ var AgentRecords = class {
|
|
|
70770
70682
|
tools: "tools",
|
|
70771
70683
|
usage: "usage",
|
|
70772
70684
|
background: "background",
|
|
70773
|
-
full_compaction: "fullCompaction"
|
|
70774
|
-
plan_mode: "planMode"
|
|
70685
|
+
full_compaction: "fullCompaction"
|
|
70775
70686
|
}[recordType.split(".")[0]] ?? null;
|
|
70776
70687
|
}
|
|
70777
70688
|
async replay() {
|
|
@@ -78354,7 +78265,7 @@ function parseToolCallArguments(raw) {
|
|
|
78354
78265
|
} catch (error) {
|
|
78355
78266
|
return {
|
|
78356
78267
|
success: false,
|
|
78357
|
-
error: errorMessage$
|
|
78268
|
+
error: errorMessage$3(error)
|
|
78358
78269
|
};
|
|
78359
78270
|
}
|
|
78360
78271
|
}
|
|
@@ -78406,7 +78317,7 @@ async function prepareToolCall(step, call) {
|
|
|
78406
78317
|
toolCallId: call.toolCall.id,
|
|
78407
78318
|
error
|
|
78408
78319
|
});
|
|
78409
|
-
const output = error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$
|
|
78320
|
+
const output = error instanceof PathSecurityError ? error.message : `Tool "${call.toolName}" failed to resolve execution: ${errorMessage$3(error)}`;
|
|
78410
78321
|
await dispatchToolCall(step, call, effectiveArgs);
|
|
78411
78322
|
return { task: makeResolvedToolCallTask(makeErrorToolResult(call, effectiveArgs, output)) };
|
|
78412
78323
|
}
|
|
@@ -78466,7 +78377,7 @@ async function runPrepareToolExecutionHook(step, call) {
|
|
|
78466
78377
|
return {
|
|
78467
78378
|
kind: "hookFailed",
|
|
78468
78379
|
args,
|
|
78469
|
-
output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$
|
|
78380
|
+
output: `prepareToolExecution hook failed for "${call.toolName}": ${errorMessage$3(error)}`
|
|
78470
78381
|
};
|
|
78471
78382
|
}
|
|
78472
78383
|
const effectiveArgs = hookResult?.updatedArgs ?? args;
|
|
@@ -78510,7 +78421,7 @@ async function runRunnableToolCall(step, call, effectiveArgs, metadata, executio
|
|
|
78510
78421
|
toolCallId: toolCall.id,
|
|
78511
78422
|
error
|
|
78512
78423
|
});
|
|
78513
|
-
return makeErrorToolResult(call, effectiveArgs, aborted ? `Tool "${toolName}" was aborted` : `Tool "${toolName}" failed: ${errorMessage$
|
|
78424
|
+
return makeErrorToolResult(call, effectiveArgs, aborted ? `Tool "${toolName}" was aborted` : `Tool "${toolName}" failed: ${errorMessage$3(error)}`);
|
|
78514
78425
|
}
|
|
78515
78426
|
return makeToolResult(call, effectiveArgs, toolResult);
|
|
78516
78427
|
}
|
|
@@ -78542,7 +78453,7 @@ async function finalizePendingToolResult(step, pendingResult) {
|
|
|
78542
78453
|
toolCallId: pendingResult.toolCall.id,
|
|
78543
78454
|
error
|
|
78544
78455
|
});
|
|
78545
|
-
const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$
|
|
78456
|
+
const output = aborted ? `Tool "${pendingResult.toolName}" aborted during finalizeToolResult hook.` : `finalizeToolResult hook failed for "${pendingResult.toolName}": ${errorMessage$3(error)}`;
|
|
78546
78457
|
return {
|
|
78547
78458
|
...pendingResult,
|
|
78548
78459
|
stopTurn: pendingResult.stopTurn,
|
|
@@ -78904,7 +78815,7 @@ async function runTurn(input) {
|
|
|
78904
78815
|
usage
|
|
78905
78816
|
};
|
|
78906
78817
|
}
|
|
78907
|
-
dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$
|
|
78818
|
+
dispatchEvent(makeInterruptedEvent(isMaxStepsExceededError(error) ? "max_steps" : "error", steps, activeStep, errorMessage$3(error)));
|
|
78908
78819
|
throw error;
|
|
78909
78820
|
}
|
|
78910
78821
|
return {
|
|
@@ -83037,8 +82948,8 @@ var ToolManager = class {
|
|
|
83037
82948
|
return (input) => withProviderRequestAuth(resolveAuth, (auth) => uploadVideo(input, { auth }));
|
|
83038
82949
|
}
|
|
83039
82950
|
get loopTools() {
|
|
83040
|
-
const builtinNames = [...this.builtinTools.keys()].filter((name) => this.enabledTools.has(name)).
|
|
83041
|
-
const userNames = [...this.userTools.keys()].filter((name) => this.enabledTools.has(name)).
|
|
82951
|
+
const builtinNames = [...this.builtinTools.keys()].filter((name) => this.enabledTools.has(name)).toSorted();
|
|
82952
|
+
const userNames = [...this.userTools.keys()].filter((name) => this.enabledTools.has(name)).toSorted();
|
|
83042
82953
|
const mcpNames = [...this.mcpTools.keys()].filter((name) => this.isMcpToolEnabled(name));
|
|
83043
82954
|
return [
|
|
83044
82955
|
...builtinNames.map((name) => this.builtinTools.get(name)),
|
|
@@ -83152,20 +83063,25 @@ const CACHE_BOUNDARY_MARKER = "__CACHE_BOUNDARY__";
|
|
|
83152
83063
|
*
|
|
83153
83064
|
* These headers mark natural breaks in the system prompt where cache boundaries should be placed:
|
|
83154
83065
|
* - "# Project Information" marks the start of project-specific content
|
|
83066
|
+
* - "# Working Environment" marks the start of session-specific environment (OS, working directory)
|
|
83155
83067
|
* - "# Skills" marks the start of session-specific skills listing
|
|
83156
83068
|
*/
|
|
83157
|
-
const IMPLICIT_BOUNDARY_HEADERS = [
|
|
83069
|
+
const IMPLICIT_BOUNDARY_HEADERS = [
|
|
83070
|
+
"# Project Information",
|
|
83071
|
+
"# Working Environment",
|
|
83072
|
+
"# Skills"
|
|
83073
|
+
];
|
|
83158
83074
|
/**
|
|
83159
83075
|
* Block names by position.
|
|
83160
83076
|
*
|
|
83161
83077
|
* - First block (before first marker): 'base'
|
|
83162
83078
|
* - Last block (after last marker): 'sessionContext'
|
|
83163
|
-
* - Intermediate blocks: Sequential names from 'projectInstructions', '
|
|
83079
|
+
* - Intermediate blocks: Sequential names from 'projectInstructions', 'workingEnvironment', etc.
|
|
83164
83080
|
*/
|
|
83165
83081
|
const BLOCK_NAMES = [
|
|
83166
83082
|
"base",
|
|
83167
83083
|
"projectInstructions",
|
|
83168
|
-
"
|
|
83084
|
+
"workingEnvironment",
|
|
83169
83085
|
"sessionContext"
|
|
83170
83086
|
];
|
|
83171
83087
|
/**
|
|
@@ -83209,7 +83125,7 @@ function findImplicitBoundaries(prompt) {
|
|
|
83209
83125
|
const index = prompt.indexOf(header);
|
|
83210
83126
|
if (index !== -1) boundaries.push(index);
|
|
83211
83127
|
}
|
|
83212
|
-
return boundaries.
|
|
83128
|
+
return boundaries.toSorted((a, b) => a - b);
|
|
83213
83129
|
}
|
|
83214
83130
|
/**
|
|
83215
83131
|
* Split prompt by implicit boundaries into blocks.
|
|
@@ -83989,8 +83905,8 @@ var TurnFlow = class {
|
|
|
83989
83905
|
completionBudgetConfig
|
|
83990
83906
|
}),
|
|
83991
83907
|
buildMessages: () => {
|
|
83992
|
-
const
|
|
83993
|
-
return applyCacheStaking(
|
|
83908
|
+
const ephemeral = this.agent.injection.getEphemeralInjections();
|
|
83909
|
+
return applyCacheStaking(this.agent.context.getMessages(ephemeral), { previousTurnMessageCount: this._previousTurnMessageCount });
|
|
83994
83910
|
},
|
|
83995
83911
|
dispatchEvent: this.buildDispatchEvent(turnId),
|
|
83996
83912
|
tools: this.agent.tools.loopTools,
|
|
@@ -84634,15 +84550,6 @@ var Agent = class {
|
|
|
84634
84550
|
getModel: () => {
|
|
84635
84551
|
return this.config.modelAlias ?? "";
|
|
84636
84552
|
},
|
|
84637
|
-
enterPlan: async () => {
|
|
84638
|
-
throw new ByfError(ErrorCodes.NOT_IMPLEMENTED, "Plan mode has been removed");
|
|
84639
|
-
},
|
|
84640
|
-
cancelPlan: async () => {
|
|
84641
|
-
throw new ByfError(ErrorCodes.NOT_IMPLEMENTED, "Plan mode has been removed");
|
|
84642
|
-
},
|
|
84643
|
-
clearPlan: async () => {
|
|
84644
|
-
throw new ByfError(ErrorCodes.NOT_IMPLEMENTED, "Plan mode has been removed");
|
|
84645
|
-
},
|
|
84646
84553
|
beginCompaction: (payload) => {
|
|
84647
84554
|
this.fullCompaction.begin({
|
|
84648
84555
|
source: "manual",
|
|
@@ -84677,7 +84584,6 @@ var Agent = class {
|
|
|
84677
84584
|
getContext: () => this.context.data(),
|
|
84678
84585
|
getConfig: () => this.config.data(),
|
|
84679
84586
|
getPermission: () => this.permission.data(),
|
|
84680
|
-
getPlan: async () => null,
|
|
84681
84587
|
getUsage: () => this.usage.data(),
|
|
84682
84588
|
getTools: () => this.tools.data(),
|
|
84683
84589
|
getBackground: (payload) => this.background.list(payload.activeOnly ?? false, payload.limit)
|
|
@@ -84810,6 +84716,21 @@ function proxyWithExtraPayload(methods, extraPayload) {
|
|
|
84810
84716
|
}, ...args);
|
|
84811
84717
|
} });
|
|
84812
84718
|
}
|
|
84719
|
+
/** The Zod `z.enum` literal inferred from registry keys. */
|
|
84720
|
+
const PROVIDER_TYPE_VALUES = Object.keys({
|
|
84721
|
+
exa: { defaultBaseUrl: "https://api.exa.ai/search" },
|
|
84722
|
+
brave: { defaultBaseUrl: "https://api.search.brave.com/res/v1/web/search" },
|
|
84723
|
+
firecrawl: { defaultBaseUrl: "https://api.firecrawl.dev/v2/search" }
|
|
84724
|
+
});
|
|
84725
|
+
const providerClassMap = /* @__PURE__ */ new Map();
|
|
84726
|
+
function registerProvider(type, cls) {
|
|
84727
|
+
providerClassMap.set(type, cls);
|
|
84728
|
+
}
|
|
84729
|
+
function createProvider(type, options) {
|
|
84730
|
+
const cls = providerClassMap.get(type);
|
|
84731
|
+
if (cls === void 0) throw new Error(`WebSearch provider type "${type}" is not registered. Did you import the provider module?`);
|
|
84732
|
+
return new cls(options);
|
|
84733
|
+
}
|
|
84813
84734
|
//#endregion
|
|
84814
84735
|
//#region ../agent-core/src/config/schema.ts
|
|
84815
84736
|
const ProviderTypeSchema = z.enum([
|
|
@@ -84909,9 +84830,18 @@ const ByfServiceConfigSchema = z.object({
|
|
|
84909
84830
|
oauth: OAuthRefSchema.optional(),
|
|
84910
84831
|
customHeaders: StringRecordSchema.optional()
|
|
84911
84832
|
});
|
|
84833
|
+
/** Provider type enum derived from webSearchProviderRegistry keys. */
|
|
84834
|
+
const WebSearchProviderTypeSchema = z.enum(PROVIDER_TYPE_VALUES);
|
|
84835
|
+
const WebSearchProviderConfigSchema = z.object({
|
|
84836
|
+
type: WebSearchProviderTypeSchema,
|
|
84837
|
+
apiKeys: z.array(z.string().min(1)).nonempty(),
|
|
84838
|
+
baseUrl: z.string().optional(),
|
|
84839
|
+
priority: z.number().int().positive()
|
|
84840
|
+
});
|
|
84841
|
+
const WebSearchConfigSchema = z.object({ providers: z.array(WebSearchProviderConfigSchema).nonempty() });
|
|
84912
84842
|
const ServicesConfigSchema = z.object({
|
|
84913
|
-
|
|
84914
|
-
|
|
84843
|
+
webSearch: WebSearchConfigSchema.optional(),
|
|
84844
|
+
fetchUrl: ByfServiceConfigSchema.optional()
|
|
84915
84845
|
});
|
|
84916
84846
|
const McpServerCommonFields = {
|
|
84917
84847
|
enabled: z.boolean().optional(),
|
|
@@ -84977,8 +84907,8 @@ const LoopControlPatchSchema = LoopControlSchema.partial();
|
|
|
84977
84907
|
const BackgroundConfigPatchSchema = BackgroundConfigSchema.partial();
|
|
84978
84908
|
const ByfServiceConfigPatchSchema = ByfServiceConfigSchema.partial();
|
|
84979
84909
|
const ServicesConfigPatchSchema = z.object({
|
|
84980
|
-
|
|
84981
|
-
|
|
84910
|
+
webSearch: WebSearchConfigSchema.optional(),
|
|
84911
|
+
fetchUrl: ByfServiceConfigPatchSchema.optional()
|
|
84982
84912
|
});
|
|
84983
84913
|
const ByfConfigPatchSchema = z.object({
|
|
84984
84914
|
providers: z.record(z.string(), ProviderConfigPatchSchema).optional(),
|
|
@@ -85226,10 +85156,15 @@ function transformServiceData(data) {
|
|
|
85226
85156
|
const targetKey = snakeToCamel(key);
|
|
85227
85157
|
if (targetKey === "oauth") out[targetKey] = isPlainObject$1(value) ? transformPlainObject(value) : value;
|
|
85228
85158
|
else if (targetKey === "customHeaders") out[targetKey] = cloneObjectValue(value);
|
|
85159
|
+
else if (Array.isArray(value)) out[targetKey] = value.map((item) => isPlainObject$1(item) ? transformRecord(item, identity, snakeToCamel) : item);
|
|
85160
|
+
else if (isPlainObject$1(value)) out[targetKey] = transformPlainObject(value);
|
|
85229
85161
|
else out[targetKey] = value;
|
|
85230
85162
|
}
|
|
85231
85163
|
return out;
|
|
85232
85164
|
}
|
|
85165
|
+
function identity(v) {
|
|
85166
|
+
return v;
|
|
85167
|
+
}
|
|
85233
85168
|
function transformLoopControlData(data) {
|
|
85234
85169
|
const out = transformPlainObject(data);
|
|
85235
85170
|
if (out["maxStepsPerTurn"] === void 0 && out["maxStepsPerRun"] !== void 0) out["maxStepsPerTurn"] = out["maxStepsPerRun"];
|
|
@@ -85249,11 +85184,11 @@ function configToTomlData(config) {
|
|
|
85249
85184
|
delete out["default_yolo"];
|
|
85250
85185
|
delete out["defaultYolo"];
|
|
85251
85186
|
delete out["defaultPermissionMode"];
|
|
85187
|
+
delete out["default_thinking"];
|
|
85252
85188
|
for (const key of [
|
|
85253
85189
|
"defaultProvider",
|
|
85254
85190
|
"defaultModel",
|
|
85255
85191
|
"yolo",
|
|
85256
|
-
"defaultThinking",
|
|
85257
85192
|
"defaultPermissionMode",
|
|
85258
85193
|
"mergeAllAvailableSkills",
|
|
85259
85194
|
"extraSkillDirs"
|
|
@@ -85322,10 +85257,17 @@ function permissionRuleToToml(rule) {
|
|
|
85322
85257
|
}
|
|
85323
85258
|
function servicesToToml(services, rawServices) {
|
|
85324
85259
|
const out = cloneRecord(rawServices);
|
|
85325
|
-
if (services.
|
|
85326
|
-
|
|
85327
|
-
|
|
85328
|
-
|
|
85260
|
+
if (services.webSearch !== void 0 && services.webSearch.providers.length > 0) {
|
|
85261
|
+
const providersToml = services.webSearch.providers.map((p) => {
|
|
85262
|
+
const providerOut = {};
|
|
85263
|
+
for (const [key, value] of Object.entries(p)) setDefined(providerOut, camelToSnake(key), value);
|
|
85264
|
+
return providerOut;
|
|
85265
|
+
});
|
|
85266
|
+
out["web_search"] = out["web_search"] ?? {};
|
|
85267
|
+
out["web_search"]["providers"] = providersToml;
|
|
85268
|
+
} else delete out["web_search"];
|
|
85269
|
+
if (services.fetchUrl !== void 0) out["fetch_url"] = serviceToToml(services.fetchUrl);
|
|
85270
|
+
else delete out["fetch_url"];
|
|
85329
85271
|
return out;
|
|
85330
85272
|
}
|
|
85331
85273
|
function serviceToToml(service) {
|
|
@@ -85383,6 +85325,595 @@ function isFileExistsError(error) {
|
|
|
85383
85325
|
return typeof error === "object" && error !== null && error.code === "EEXIST";
|
|
85384
85326
|
}
|
|
85385
85327
|
//#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
|
|
85386
85917
|
//#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
85387
85918
|
function isZ4Schema(s) {
|
|
85388
85919
|
return !!s._zod;
|
|
@@ -89065,7 +89596,7 @@ var SessionSubagentHost = class {
|
|
|
89065
89596
|
const { id, agent } = await this.session.createAgent({
|
|
89066
89597
|
type: "sub",
|
|
89067
89598
|
generate: parent.rawGenerate
|
|
89068
|
-
}, void 0, this.ownerAgentId);
|
|
89599
|
+
}, void 0, this.ownerAgentId, options.parentToolCallId);
|
|
89069
89600
|
const controller = new AbortController();
|
|
89070
89601
|
const unlinkAbortSignal = linkAbortSignal(options.signal, controller);
|
|
89071
89602
|
this.activeChildren.set(id, {
|
|
@@ -89364,7 +89895,7 @@ var Session$1 = class {
|
|
|
89364
89895
|
})) return;
|
|
89365
89896
|
await Promise.all(Array.from(this.agents.values(), (agent) => agent.background.stopAll("Session closed")));
|
|
89366
89897
|
}
|
|
89367
|
-
async createAgent(config, profile, parentAgentId) {
|
|
89898
|
+
async createAgent(config, profile, parentAgentId, parentToolCallId) {
|
|
89368
89899
|
await this.skillsReady;
|
|
89369
89900
|
const type = config.type ?? "main";
|
|
89370
89901
|
const id = type === "main" ? "main" : this.nextGeneratedAgentId();
|
|
@@ -89376,7 +89907,8 @@ var Session$1 = class {
|
|
|
89376
89907
|
this.metadata.agents[id] = {
|
|
89377
89908
|
homedir,
|
|
89378
89909
|
type,
|
|
89379
|
-
parentAgentId: parentAgentId ?? null
|
|
89910
|
+
parentAgentId: parentAgentId ?? null,
|
|
89911
|
+
parentToolCallId
|
|
89380
89912
|
};
|
|
89381
89913
|
this.writeMetadata();
|
|
89382
89914
|
return {
|
|
@@ -90118,14 +90650,14 @@ var LocalKaos = class {
|
|
|
90118
90650
|
}
|
|
90119
90651
|
}
|
|
90120
90652
|
async writeBytes(path, data) {
|
|
90121
|
-
await writeFile
|
|
90653
|
+
await writeFile(this._resolvePath(path), data);
|
|
90122
90654
|
return data.length;
|
|
90123
90655
|
}
|
|
90124
90656
|
async writeText(path, data, options) {
|
|
90125
90657
|
const resolved = this._resolvePath(path);
|
|
90126
90658
|
const encoding = options?.encoding ?? "utf-8";
|
|
90127
90659
|
if ((options?.mode ?? "w") === "a") await appendFile(resolved, data, encoding);
|
|
90128
|
-
else await writeFile
|
|
90660
|
+
else await writeFile(resolved, data, encoding);
|
|
90129
90661
|
return data.length;
|
|
90130
90662
|
}
|
|
90131
90663
|
async mkdir(path, options) {
|
|
@@ -125304,11 +125836,15 @@ function createProxiedFetch(deps) {
|
|
|
125304
125836
|
const proxyUrl = getProxyForUrl(url, envLookup, sysProxy);
|
|
125305
125837
|
const noProxyMatch = noProxy !== void 0 && isNoProxyHost(hostname, noProxy);
|
|
125306
125838
|
const controller = new AbortController();
|
|
125307
|
-
const timeoutId = setTimeout(() =>
|
|
125839
|
+
const timeoutId = setTimeout(() => {
|
|
125840
|
+
controller.abort();
|
|
125841
|
+
}, REQUEST_TIMEOUT_MS);
|
|
125308
125842
|
if (init?.signal) if (init.signal.aborted) {
|
|
125309
125843
|
clearTimeout(timeoutId);
|
|
125310
125844
|
controller.abort();
|
|
125311
|
-
} else init.signal.addEventListener("abort", () =>
|
|
125845
|
+
} else init.signal.addEventListener("abort", () => {
|
|
125846
|
+
controller.abort();
|
|
125847
|
+
}, { once: true });
|
|
125312
125848
|
const mergedInit = {
|
|
125313
125849
|
...init,
|
|
125314
125850
|
signal: controller.signal
|
|
@@ -125320,7 +125856,7 @@ function createProxiedFetch(deps) {
|
|
|
125320
125856
|
return response;
|
|
125321
125857
|
} catch (error) {
|
|
125322
125858
|
clearTimeout(timeoutId);
|
|
125323
|
-
if (isRetryableError(error) && proxyUrl && !noProxyMatch) return
|
|
125859
|
+
if (isRetryableError(error) && proxyUrl && !noProxyMatch) return retryViaProxy(input, init, proxyUrl, innerFetch);
|
|
125324
125860
|
throw error;
|
|
125325
125861
|
}
|
|
125326
125862
|
};
|
|
@@ -125328,11 +125864,15 @@ function createProxiedFetch(deps) {
|
|
|
125328
125864
|
}
|
|
125329
125865
|
async function retryViaProxy(input, init, proxyUrl, innerFetch) {
|
|
125330
125866
|
const controller = new AbortController();
|
|
125331
|
-
const timeoutId = setTimeout(() =>
|
|
125867
|
+
const timeoutId = setTimeout(() => {
|
|
125868
|
+
controller.abort();
|
|
125869
|
+
}, REQUEST_TIMEOUT_MS);
|
|
125332
125870
|
if (init?.signal) if (init.signal.aborted) {
|
|
125333
125871
|
clearTimeout(timeoutId);
|
|
125334
125872
|
controller.abort();
|
|
125335
|
-
} else init.signal.addEventListener("abort", () =>
|
|
125873
|
+
} else init.signal.addEventListener("abort", () => {
|
|
125874
|
+
controller.abort();
|
|
125875
|
+
}, { once: true });
|
|
125336
125876
|
const dispatcher = new import_undici.ProxyAgent(proxyUrl);
|
|
125337
125877
|
const retryInit = {
|
|
125338
125878
|
...init,
|
|
@@ -125482,82 +126022,188 @@ var RemoteFetchURLProvider = class {
|
|
|
125482
126022
|
}
|
|
125483
126023
|
};
|
|
125484
126024
|
//#endregion
|
|
125485
|
-
//#region ../agent-core/src/tools/providers/
|
|
125486
|
-
var
|
|
125487
|
-
|
|
125488
|
-
|
|
126025
|
+
//#region ../agent-core/src/tools/providers/router.ts
|
|
126026
|
+
var AllProvidersFailedError = class extends Error {
|
|
126027
|
+
lastError;
|
|
126028
|
+
constructor(lastError) {
|
|
126029
|
+
super(`All search providers failed. Last error: ${lastError ?? "unknown"}`);
|
|
126030
|
+
this.lastError = lastError;
|
|
126031
|
+
this.name = "AllProvidersFailedError";
|
|
126032
|
+
}
|
|
126033
|
+
};
|
|
126034
|
+
var PriorityRouter = class {
|
|
126035
|
+
providers;
|
|
126036
|
+
constructor(providers) {
|
|
126037
|
+
this.providers = providers;
|
|
126038
|
+
}
|
|
126039
|
+
async search(query, options) {
|
|
126040
|
+
let lastError;
|
|
126041
|
+
for (const provider of this.providers) try {
|
|
126042
|
+
return await provider.search(query, options);
|
|
126043
|
+
} catch (error) {
|
|
126044
|
+
lastError = error instanceof Error ? error.message : String(error);
|
|
126045
|
+
}
|
|
126046
|
+
throw new AllProvidersFailedError(lastError);
|
|
126047
|
+
}
|
|
126048
|
+
};
|
|
126049
|
+
//#endregion
|
|
126050
|
+
//#region ../agent-core/src/tools/providers/exa.ts
|
|
126051
|
+
var ExaWebSearchProvider = class {
|
|
126052
|
+
apiKeys;
|
|
125489
126053
|
baseUrl;
|
|
125490
|
-
defaultHeaders;
|
|
125491
|
-
customHeaders;
|
|
125492
126054
|
fetchImpl;
|
|
125493
126055
|
constructor(options) {
|
|
125494
|
-
this.
|
|
125495
|
-
this.
|
|
125496
|
-
this.baseUrl = options.baseUrl;
|
|
125497
|
-
this.defaultHeaders = options.defaultHeaders ?? {};
|
|
125498
|
-
this.customHeaders = options.customHeaders ?? {};
|
|
126056
|
+
this.apiKeys = options.apiKeys;
|
|
126057
|
+
this.baseUrl = options.baseUrl ?? "https://api.exa.ai/search";
|
|
125499
126058
|
this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
125500
126059
|
}
|
|
125501
126060
|
async search(query, options) {
|
|
125502
|
-
const
|
|
125503
|
-
|
|
125504
|
-
|
|
125505
|
-
|
|
125506
|
-
|
|
126061
|
+
const limit = options?.limit ?? 5;
|
|
126062
|
+
const includeContent = options?.includeContent ?? false;
|
|
126063
|
+
const contents = {};
|
|
126064
|
+
if (includeContent) contents.text = { maxCharacters: 1e4 };
|
|
126065
|
+
else contents.highlights = {
|
|
126066
|
+
query,
|
|
126067
|
+
maxCharacters: 300
|
|
125507
126068
|
};
|
|
125508
|
-
const
|
|
125509
|
-
|
|
125510
|
-
|
|
125511
|
-
|
|
125512
|
-
throw new Error(`Remote search request failed: HTTP 401 (auth/unauthorized). ${detail}`.trim());
|
|
125513
|
-
}
|
|
125514
|
-
if (response.status !== 200) {
|
|
125515
|
-
const detail = await safeReadText(response);
|
|
125516
|
-
throw new Error(`Remote search request failed: HTTP ${String(response.status)}. ${detail}`.trim());
|
|
125517
|
-
}
|
|
125518
|
-
const json = await response.json();
|
|
125519
|
-
return (Array.isArray(json.search_results) ? json.search_results : []).map((r) => {
|
|
125520
|
-
const out = {
|
|
125521
|
-
title: r.title ?? "",
|
|
125522
|
-
url: r.url ?? "",
|
|
125523
|
-
snippet: r.snippet ?? ""
|
|
125524
|
-
};
|
|
125525
|
-
if (typeof r.date === "string" && r.date.length > 0) out.date = r.date;
|
|
125526
|
-
if (typeof r.content === "string" && r.content.length > 0) out.content = r.content;
|
|
125527
|
-
return out;
|
|
126069
|
+
const body = JSON.stringify({
|
|
126070
|
+
query,
|
|
126071
|
+
numResults: limit,
|
|
126072
|
+
contents
|
|
125528
126073
|
});
|
|
126074
|
+
let lastError;
|
|
126075
|
+
for (const apiKey of this.apiKeys) try {
|
|
126076
|
+
const response = await this.fetchImpl(this.baseUrl, {
|
|
126077
|
+
method: "POST",
|
|
126078
|
+
headers: {
|
|
126079
|
+
Authorization: `Bearer ${apiKey}`,
|
|
126080
|
+
"Content-Type": "application/json"
|
|
126081
|
+
},
|
|
126082
|
+
body
|
|
126083
|
+
});
|
|
126084
|
+
if (!response.ok) {
|
|
126085
|
+
const detail = (await response.text().catch(() => "")).slice(0, 200);
|
|
126086
|
+
throw new Error(`Exa search failed: HTTP ${response.status}${detail ? `: ${detail}` : ""}`);
|
|
126087
|
+
}
|
|
126088
|
+
const json = await response.json();
|
|
126089
|
+
return (Array.isArray(json.results) ? json.results : []).map((r) => {
|
|
126090
|
+
const out = {
|
|
126091
|
+
title: r.title ?? "",
|
|
126092
|
+
url: r.url ?? "",
|
|
126093
|
+
snippet: ""
|
|
126094
|
+
};
|
|
126095
|
+
if (includeContent && typeof r.text === "string") {
|
|
126096
|
+
out.snippet = r.text.slice(0, 300);
|
|
126097
|
+
if (r.text.length > 0) out.content = r.text;
|
|
126098
|
+
} else if (Array.isArray(r.highlights) && r.highlights.length > 0) out.snippet = r.highlights[0].slice(0, 300);
|
|
126099
|
+
if (typeof r.publishedDate === "string" && r.publishedDate.length > 0) out.date = r.publishedDate;
|
|
126100
|
+
return out;
|
|
126101
|
+
});
|
|
126102
|
+
} catch (error) {
|
|
126103
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
126104
|
+
}
|
|
126105
|
+
throw lastError ?? /* @__PURE__ */ new Error("Exa search failed: no API keys configured");
|
|
125529
126106
|
}
|
|
125530
|
-
|
|
125531
|
-
|
|
125532
|
-
|
|
125533
|
-
|
|
125534
|
-
|
|
125535
|
-
|
|
125536
|
-
|
|
125537
|
-
|
|
125538
|
-
|
|
125539
|
-
|
|
125540
|
-
|
|
125541
|
-
|
|
126107
|
+
};
|
|
126108
|
+
registerProvider("exa", ExaWebSearchProvider);
|
|
126109
|
+
//#endregion
|
|
126110
|
+
//#region ../agent-core/src/tools/providers/brave.ts
|
|
126111
|
+
var BraveWebSearchProvider = class {
|
|
126112
|
+
apiKeys;
|
|
126113
|
+
baseUrl;
|
|
126114
|
+
fetchImpl;
|
|
126115
|
+
constructor(options) {
|
|
126116
|
+
this.apiKeys = options.apiKeys;
|
|
126117
|
+
this.baseUrl = options.baseUrl ?? "https://api.search.brave.com/res/v1/web/search";
|
|
126118
|
+
this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
125542
126119
|
}
|
|
125543
|
-
async
|
|
125544
|
-
|
|
125545
|
-
|
|
126120
|
+
async search(query, options) {
|
|
126121
|
+
const limit = options?.limit ?? 5;
|
|
126122
|
+
const url = new URL(this.baseUrl);
|
|
126123
|
+
url.searchParams.set("q", query);
|
|
126124
|
+
url.searchParams.set("count", String(limit));
|
|
126125
|
+
let lastError;
|
|
126126
|
+
for (const apiKey of this.apiKeys) try {
|
|
126127
|
+
const response = await this.fetchImpl(url.toString(), {
|
|
126128
|
+
method: "GET",
|
|
126129
|
+
headers: {
|
|
126130
|
+
"Accept": "application/json",
|
|
126131
|
+
"Accept-Encoding": "gzip",
|
|
126132
|
+
"X-Subscription-Token": apiKey
|
|
126133
|
+
}
|
|
126134
|
+
});
|
|
126135
|
+
if (!response.ok) {
|
|
126136
|
+
const detail = (await response.text().catch(() => "")).slice(0, 200);
|
|
126137
|
+
throw new Error(`Brave search failed: HTTP ${response.status}${detail ? `: ${detail}` : ""}`);
|
|
126138
|
+
}
|
|
126139
|
+
const json = await response.json();
|
|
126140
|
+
return (Array.isArray(json.web?.results) ? json.web.results : []).map((r) => {
|
|
126141
|
+
const out = {
|
|
126142
|
+
title: r.title ?? "",
|
|
126143
|
+
url: r.url ?? "",
|
|
126144
|
+
snippet: r.description ?? ""
|
|
126145
|
+
};
|
|
126146
|
+
if (typeof r.age === "string" && r.age.length > 0) out.date = r.age;
|
|
126147
|
+
return out;
|
|
126148
|
+
});
|
|
125546
126149
|
} catch (error) {
|
|
125547
|
-
|
|
125548
|
-
throw error;
|
|
126150
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
125549
126151
|
}
|
|
125550
|
-
|
|
125551
|
-
throw new Error("Remote search service is not configured: missing API key or token provider.");
|
|
126152
|
+
throw lastError ?? /* @__PURE__ */ new Error("Brave search failed: no API keys configured");
|
|
125552
126153
|
}
|
|
125553
126154
|
};
|
|
125554
|
-
|
|
125555
|
-
|
|
125556
|
-
|
|
125557
|
-
|
|
125558
|
-
|
|
126155
|
+
registerProvider("brave", BraveWebSearchProvider);
|
|
126156
|
+
//#endregion
|
|
126157
|
+
//#region ../agent-core/src/tools/providers/firecrawl.ts
|
|
126158
|
+
var FirecrawlWebSearchProvider = class {
|
|
126159
|
+
apiKeys;
|
|
126160
|
+
baseUrl;
|
|
126161
|
+
fetchImpl;
|
|
126162
|
+
constructor(options) {
|
|
126163
|
+
this.apiKeys = options.apiKeys;
|
|
126164
|
+
this.baseUrl = options.baseUrl ?? "https://api.firecrawl.dev/v2/search";
|
|
126165
|
+
this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
125559
126166
|
}
|
|
125560
|
-
|
|
126167
|
+
async search(query, options) {
|
|
126168
|
+
const limit = options?.limit ?? 5;
|
|
126169
|
+
const includeContent = options?.includeContent ?? false;
|
|
126170
|
+
const requestBody = {
|
|
126171
|
+
query,
|
|
126172
|
+
limit
|
|
126173
|
+
};
|
|
126174
|
+
if (includeContent) requestBody.scrapeOptions = { formats: ["markdown"] };
|
|
126175
|
+
const body = JSON.stringify(requestBody);
|
|
126176
|
+
let lastError;
|
|
126177
|
+
for (const apiKey of this.apiKeys) try {
|
|
126178
|
+
const response = await this.fetchImpl(this.baseUrl, {
|
|
126179
|
+
method: "POST",
|
|
126180
|
+
headers: {
|
|
126181
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
126182
|
+
"Content-Type": "application/json"
|
|
126183
|
+
},
|
|
126184
|
+
body
|
|
126185
|
+
});
|
|
126186
|
+
if (!response.ok) {
|
|
126187
|
+
const detail = (await response.text().catch(() => "")).slice(0, 200);
|
|
126188
|
+
throw new Error(`Firecrawl search failed: HTTP ${response.status}${detail ? `: ${detail}` : ""}`);
|
|
126189
|
+
}
|
|
126190
|
+
const json = await response.json();
|
|
126191
|
+
return (Array.isArray(json.data?.web) ? json.data.web : []).map((r) => {
|
|
126192
|
+
const out = {
|
|
126193
|
+
title: r.title ?? "",
|
|
126194
|
+
url: r.url ?? "",
|
|
126195
|
+
snippet: r.description ?? ""
|
|
126196
|
+
};
|
|
126197
|
+
if (includeContent && typeof r.markdown === "string" && r.markdown.length > 0) out.content = r.markdown;
|
|
126198
|
+
return out;
|
|
126199
|
+
});
|
|
126200
|
+
} catch (error) {
|
|
126201
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
126202
|
+
}
|
|
126203
|
+
throw lastError ?? /* @__PURE__ */ new Error("Firecrawl search failed: no API keys configured");
|
|
126204
|
+
}
|
|
126205
|
+
};
|
|
126206
|
+
registerProvider("firecrawl", FirecrawlWebSearchProvider);
|
|
125561
126207
|
//#endregion
|
|
125562
126208
|
//#region ../agent-core/src/utils/environment.ts
|
|
125563
126209
|
/**
|
|
@@ -125819,15 +126465,6 @@ var SessionAPIImpl = class {
|
|
|
125819
126465
|
getModel({ agentId, ...payload }) {
|
|
125820
126466
|
return this.getAgent(agentId).getModel(payload);
|
|
125821
126467
|
}
|
|
125822
|
-
enterPlan({ agentId, ...payload }) {
|
|
125823
|
-
return this.getAgent(agentId).enterPlan(payload);
|
|
125824
|
-
}
|
|
125825
|
-
cancelPlan({ agentId, ...payload }) {
|
|
125826
|
-
return this.getAgent(agentId).cancelPlan(payload);
|
|
125827
|
-
}
|
|
125828
|
-
clearPlan({ agentId, ...payload }) {
|
|
125829
|
-
return this.getAgent(agentId).clearPlan(payload);
|
|
125830
|
-
}
|
|
125831
126468
|
beginCompaction({ agentId, ...payload }) {
|
|
125832
126469
|
return this.getAgent(agentId).beginCompaction(payload);
|
|
125833
126470
|
}
|
|
@@ -125868,9 +126505,6 @@ var SessionAPIImpl = class {
|
|
|
125868
126505
|
getPermission({ agentId, ...payload }) {
|
|
125869
126506
|
return this.getAgent(agentId).getPermission(payload);
|
|
125870
126507
|
}
|
|
125871
|
-
getPlan({ agentId, ...payload }) {
|
|
125872
|
-
return this.getAgent(agentId).getPlan(payload);
|
|
125873
|
-
}
|
|
125874
126508
|
getUsage({ agentId, ...payload }) {
|
|
125875
126509
|
return this.getAgent(agentId).getUsage(payload);
|
|
125876
126510
|
}
|
|
@@ -126090,7 +126724,7 @@ async function writeExportZip(args) {
|
|
|
126090
126724
|
entries.push(extra.target);
|
|
126091
126725
|
} catch {}
|
|
126092
126726
|
zip.end();
|
|
126093
|
-
await pipeline$1(zip.outputStream, createWriteStream
|
|
126727
|
+
await pipeline$1(zip.outputStream, createWriteStream(args.outputPath));
|
|
126094
126728
|
return entries;
|
|
126095
126729
|
}
|
|
126096
126730
|
//#endregion
|
|
@@ -126149,207 +126783,6 @@ async function readOptionalFile(path) {
|
|
|
126149
126783
|
}
|
|
126150
126784
|
}
|
|
126151
126785
|
//#endregion
|
|
126152
|
-
//#region ../agent-core/src/providers/runtime-provider.ts
|
|
126153
|
-
function resolveRuntimeProvider(input) {
|
|
126154
|
-
const modelName = input.model ?? input.config.defaultModel;
|
|
126155
|
-
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.");
|
|
126156
|
-
const alias = input.config.models?.[modelName];
|
|
126157
|
-
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.`);
|
|
126158
|
-
const resolvedModel = alias.model;
|
|
126159
|
-
const providerName = alias.provider ?? input.config.defaultProvider;
|
|
126160
|
-
const providerConfig = providerName === void 0 ? void 0 : input.config.providers[providerName];
|
|
126161
|
-
if (providerName === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Model "${modelName}" must define a provider in config.toml.`);
|
|
126162
|
-
if (providerConfig === void 0) throw new ByfError(ErrorCodes.CONFIG_INVALID, `Provider "${providerName}" for model "${modelName}" is not configured.`);
|
|
126163
|
-
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.`);
|
|
126164
|
-
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.`);
|
|
126165
|
-
const provider = toKosongProviderConfig(providerConfig, resolvedModel, input.byfRequestHeaders, alias.maxOutputSize, alias.reasoningKey, input.promptCacheKey);
|
|
126166
|
-
return {
|
|
126167
|
-
modelName,
|
|
126168
|
-
providerName,
|
|
126169
|
-
modelCapabilities: resolveModelCapabilities(alias, provider),
|
|
126170
|
-
provider
|
|
126171
|
-
};
|
|
126172
|
-
}
|
|
126173
|
-
async function resolveRuntimeProviderWithOAuth(input) {
|
|
126174
|
-
const resolved = resolveRuntimeProvider(input);
|
|
126175
|
-
const resolveAuth = createRuntimeProviderAuthResolver(input, resolved);
|
|
126176
|
-
if (resolveAuth === void 0) return resolved;
|
|
126177
|
-
await resolveAuth();
|
|
126178
|
-
return {
|
|
126179
|
-
...resolved,
|
|
126180
|
-
resolveAuth
|
|
126181
|
-
};
|
|
126182
|
-
}
|
|
126183
|
-
function createRuntimeProviderAuthResolver(input, resolved = resolveRuntimeProvider(input)) {
|
|
126184
|
-
const providerName = resolved.providerName;
|
|
126185
|
-
if (providerName === void 0) return void 0;
|
|
126186
|
-
const providerConfig = input.config.providers[providerName];
|
|
126187
|
-
if (providerConfig?.oauth === void 0) return void 0;
|
|
126188
|
-
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.`);
|
|
126189
|
-
const tokenProvider = input.resolveOAuthTokenProvider?.(providerName, providerConfig.oauth);
|
|
126190
|
-
if (tokenProvider === void 0) return async () => {
|
|
126191
|
-
throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`);
|
|
126192
|
-
};
|
|
126193
|
-
return async (options) => {
|
|
126194
|
-
let apiKey;
|
|
126195
|
-
try {
|
|
126196
|
-
apiKey = await tokenProvider.getAccessToken(options?.forceRefresh === true ? { force: true } : void 0);
|
|
126197
|
-
} catch (error) {
|
|
126198
|
-
if (!isAuthLoginRequired(error)) (input.log ?? log).warn("oauth token fetch failed", {
|
|
126199
|
-
providerName,
|
|
126200
|
-
error
|
|
126201
|
-
});
|
|
126202
|
-
throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`, { cause: error });
|
|
126203
|
-
}
|
|
126204
|
-
if (apiKey.trim().length === 0) throw new ByfError(ErrorCodes.AUTH_LOGIN_REQUIRED, `OAuth provider "${providerName}" requires login before it can be used.`);
|
|
126205
|
-
return { apiKey };
|
|
126206
|
-
};
|
|
126207
|
-
}
|
|
126208
|
-
function isAuthLoginRequired(error) {
|
|
126209
|
-
return isByfError(error) && error.code === ErrorCodes.AUTH_LOGIN_REQUIRED;
|
|
126210
|
-
}
|
|
126211
|
-
function resolveModelCapabilities(alias, provider) {
|
|
126212
|
-
const capabilities = new Set((alias.capabilities ?? []).map((capability) => capability.trim().toLowerCase()));
|
|
126213
|
-
const has = (capability) => capabilities.has(capability);
|
|
126214
|
-
const providerCapability = createProvider(providerForCapabilityProbe(provider)).getCapability?.(provider.model) ?? UNKNOWN_CAPABILITY;
|
|
126215
|
-
return {
|
|
126216
|
-
image_in: has("image_in") || providerCapability.image_in,
|
|
126217
|
-
video_in: has("video_in") || providerCapability.video_in,
|
|
126218
|
-
audio_in: has("audio_in") || providerCapability.audio_in,
|
|
126219
|
-
thinking: has("thinking") || has("always_thinking") || providerCapability.thinking,
|
|
126220
|
-
tool_use: has("tool_use") || providerCapability.tool_use,
|
|
126221
|
-
thinking_effort: has("thinking_effort") || providerCapability.thinking_effort,
|
|
126222
|
-
thinking_xhigh: has("thinking_xhigh") || providerCapability.thinking_xhigh,
|
|
126223
|
-
thinking_max: has("thinking_max") || providerCapability.thinking_max,
|
|
126224
|
-
max_context_tokens: alias.maxContextSize
|
|
126225
|
-
};
|
|
126226
|
-
}
|
|
126227
|
-
function toKosongProviderConfig(provider, model, byfRequestHeaders, maxOutputSize, reasoningKey, promptCacheKey) {
|
|
126228
|
-
switch (provider.type) {
|
|
126229
|
-
case "anthropic": return {
|
|
126230
|
-
type: "anthropic",
|
|
126231
|
-
model,
|
|
126232
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "ANTHROPIC_BASE_URL"),
|
|
126233
|
-
apiKey: providerApiKey(provider),
|
|
126234
|
-
...maxOutputSize !== void 0 ? { defaultMaxTokens: maxOutputSize } : {},
|
|
126235
|
-
...defaultHeadersField(provider.customHeaders)
|
|
126236
|
-
};
|
|
126237
|
-
case "openai-completions": {
|
|
126238
|
-
const defaultHeaders = {
|
|
126239
|
-
...byfRequestHeaders,
|
|
126240
|
-
...provider.customHeaders
|
|
126241
|
-
};
|
|
126242
|
-
const generationKwargs = {
|
|
126243
|
-
prompt_cache_key: promptCacheKey,
|
|
126244
|
-
extra_body: provider.extraBody
|
|
126245
|
-
};
|
|
126246
|
-
if (Object.keys(defaultHeaders).length === 0) return {
|
|
126247
|
-
type: "openai-completions",
|
|
126248
|
-
model,
|
|
126249
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "BYF_BASE_URL"),
|
|
126250
|
-
reasoningKey,
|
|
126251
|
-
thinkingEffortKey: provider.thinkingEffortKey,
|
|
126252
|
-
generationKwargs,
|
|
126253
|
-
apiKey: providerApiKey(provider)
|
|
126254
|
-
};
|
|
126255
|
-
return {
|
|
126256
|
-
type: "openai-completions",
|
|
126257
|
-
model,
|
|
126258
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "BYF_BASE_URL"),
|
|
126259
|
-
reasoningKey,
|
|
126260
|
-
thinkingEffortKey: provider.thinkingEffortKey,
|
|
126261
|
-
generationKwargs,
|
|
126262
|
-
defaultHeaders,
|
|
126263
|
-
apiKey: providerApiKey(provider)
|
|
126264
|
-
};
|
|
126265
|
-
}
|
|
126266
|
-
case "google-genai": return {
|
|
126267
|
-
type: "google-genai",
|
|
126268
|
-
model,
|
|
126269
|
-
apiKey: providerApiKey(provider)
|
|
126270
|
-
};
|
|
126271
|
-
case "openai_responses": return {
|
|
126272
|
-
type: "openai_responses",
|
|
126273
|
-
model,
|
|
126274
|
-
baseUrl: providerValue(provider.baseUrl, provider.env, "OPENAI_BASE_URL"),
|
|
126275
|
-
apiKey: providerApiKey(provider),
|
|
126276
|
-
...defaultHeadersField(provider.customHeaders)
|
|
126277
|
-
};
|
|
126278
|
-
case "vertexai": return {
|
|
126279
|
-
type: "vertexai",
|
|
126280
|
-
model,
|
|
126281
|
-
vertexai: hasVertexAIServiceEnv(provider),
|
|
126282
|
-
apiKey: hasVertexAIServiceEnv(provider) ? void 0 : providerApiKey(provider),
|
|
126283
|
-
project: vertexAIProject(provider),
|
|
126284
|
-
location: vertexAILocation(provider)
|
|
126285
|
-
};
|
|
126286
|
-
default: {
|
|
126287
|
-
const exhaustive = provider.type;
|
|
126288
|
-
throw new ByfError(ErrorCodes.MODEL_CONFIG_INVALID, `Unsupported provider type: ${String(exhaustive)}`);
|
|
126289
|
-
}
|
|
126290
|
-
}
|
|
126291
|
-
}
|
|
126292
|
-
function defaultHeadersField(headers) {
|
|
126293
|
-
if (headers === void 0 || Object.keys(headers).length === 0) return {};
|
|
126294
|
-
return { defaultHeaders: { ...headers } };
|
|
126295
|
-
}
|
|
126296
|
-
function providerForCapabilityProbe(provider) {
|
|
126297
|
-
if (provider.type === "vertexai") return {
|
|
126298
|
-
...provider,
|
|
126299
|
-
vertexai: false,
|
|
126300
|
-
project: void 0,
|
|
126301
|
-
location: void 0,
|
|
126302
|
-
apiKey: provider.apiKey === void 0 || provider.apiKey.length === 0 ? "capability-probe" : provider.apiKey
|
|
126303
|
-
};
|
|
126304
|
-
if (provider.apiKey !== void 0 && provider.apiKey.length > 0) return provider;
|
|
126305
|
-
return {
|
|
126306
|
-
...provider,
|
|
126307
|
-
apiKey: "capability-probe"
|
|
126308
|
-
};
|
|
126309
|
-
}
|
|
126310
|
-
function providerApiKey(provider) {
|
|
126311
|
-
switch (provider.type) {
|
|
126312
|
-
case "anthropic": return providerValue(provider.apiKey, provider.env, "ANTHROPIC_API_KEY");
|
|
126313
|
-
case "openai_responses": return providerValue(provider.apiKey, provider.env, "OPENAI_API_KEY");
|
|
126314
|
-
case "openai-completions": return providerValue(provider.apiKey, provider.env, "BYF_API_KEY");
|
|
126315
|
-
case "google-genai": return providerValue(provider.apiKey, provider.env, "GOOGLE_API_KEY");
|
|
126316
|
-
case "vertexai": return nonEmptyString$2(provider.apiKey) ?? envValue(provider.env, "VERTEXAI_API_KEY") ?? envValue(provider.env, "GOOGLE_API_KEY");
|
|
126317
|
-
default: {
|
|
126318
|
-
const exhaustive = provider.type;
|
|
126319
|
-
throw new ByfError(ErrorCodes.MODEL_CONFIG_INVALID, `Unsupported provider type: ${String(exhaustive)}`);
|
|
126320
|
-
}
|
|
126321
|
-
}
|
|
126322
|
-
}
|
|
126323
|
-
function hasVertexAIServiceEnv(provider) {
|
|
126324
|
-
return vertexAIProject(provider) !== void 0 && vertexAILocation(provider) !== void 0;
|
|
126325
|
-
}
|
|
126326
|
-
function vertexAIProject(provider) {
|
|
126327
|
-
return envValue(provider.env, "GOOGLE_CLOUD_PROJECT");
|
|
126328
|
-
}
|
|
126329
|
-
function vertexAILocation(provider) {
|
|
126330
|
-
return envValue(provider.env, "GOOGLE_CLOUD_LOCATION") ?? locationFromVertexAIBaseUrl(provider.baseUrl);
|
|
126331
|
-
}
|
|
126332
|
-
function providerValue(configured, env, envKey) {
|
|
126333
|
-
return nonEmptyString$2(configured) ?? envValue(env, envKey);
|
|
126334
|
-
}
|
|
126335
|
-
function envValue(env, key) {
|
|
126336
|
-
return nonEmptyString$2(env?.[key]);
|
|
126337
|
-
}
|
|
126338
|
-
function nonEmptyString$2(value) {
|
|
126339
|
-
const trimmed = value?.trim();
|
|
126340
|
-
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
126341
|
-
}
|
|
126342
|
-
function locationFromVertexAIBaseUrl(baseUrl) {
|
|
126343
|
-
const url = nonEmptyString$2(baseUrl);
|
|
126344
|
-
if (url === void 0) return void 0;
|
|
126345
|
-
try {
|
|
126346
|
-
const host = new URL(url).hostname;
|
|
126347
|
-
return host.endsWith("-aiplatform.googleapis.com") ? nonEmptyString$2(host.slice(0, -26)) : void 0;
|
|
126348
|
-
} catch {
|
|
126349
|
-
return;
|
|
126350
|
-
}
|
|
126351
|
-
}
|
|
126352
|
-
//#endregion
|
|
126353
126786
|
//#region ../agent-core/src/providers/provider-manager.ts
|
|
126354
126787
|
var ProviderManager = class ProviderManager {
|
|
126355
126788
|
options;
|
|
@@ -126610,7 +127043,7 @@ var SessionStore = class {
|
|
|
126610
127043
|
title: normalized,
|
|
126611
127044
|
isCustomTitle: true
|
|
126612
127045
|
};
|
|
126613
|
-
await writeFile
|
|
127046
|
+
await writeFile(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
126614
127047
|
}
|
|
126615
127048
|
async list(options) {
|
|
126616
127049
|
const workDir = normalizeWorkDir(options.workDir);
|
|
@@ -126665,7 +127098,7 @@ var SessionStore = class {
|
|
|
126665
127098
|
agents: rewriteAgentHomedirs(parsed["agents"], sourceDir, targetDir),
|
|
126666
127099
|
custom: Object.assign({}, isRecord$1(parsed["custom"]) ? parsed["custom"] : {}, input.metadata)
|
|
126667
127100
|
};
|
|
126668
|
-
await writeFile
|
|
127101
|
+
await writeFile(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
126669
127102
|
}
|
|
126670
127103
|
async summaryFromDir(id, sessionDir, workDir) {
|
|
126671
127104
|
const dirStat = await stat(sessionDir);
|
|
@@ -127028,15 +127461,6 @@ var ByfCore = class {
|
|
|
127028
127461
|
getModel({ sessionId, ...payload }) {
|
|
127029
127462
|
return this.sessionApi(sessionId).getModel(payload);
|
|
127030
127463
|
}
|
|
127031
|
-
enterPlan({ sessionId, ...payload }) {
|
|
127032
|
-
return this.sessionApi(sessionId).enterPlan(payload);
|
|
127033
|
-
}
|
|
127034
|
-
cancelPlan({ sessionId, ...payload }) {
|
|
127035
|
-
return this.sessionApi(sessionId).cancelPlan(payload);
|
|
127036
|
-
}
|
|
127037
|
-
clearPlan({ sessionId, ...payload }) {
|
|
127038
|
-
return this.sessionApi(sessionId).clearPlan(payload);
|
|
127039
|
-
}
|
|
127040
127464
|
beginCompaction({ sessionId, ...payload }) {
|
|
127041
127465
|
return this.sessionApi(sessionId).beginCompaction(payload);
|
|
127042
127466
|
}
|
|
@@ -127076,9 +127500,6 @@ var ByfCore = class {
|
|
|
127076
127500
|
getPermission({ sessionId, ...payload }) {
|
|
127077
127501
|
return this.sessionApi(sessionId).getPermission(payload);
|
|
127078
127502
|
}
|
|
127079
|
-
getPlan({ sessionId, ...payload }) {
|
|
127080
|
-
return this.sessionApi(sessionId).getPlan(payload);
|
|
127081
|
-
}
|
|
127082
127503
|
getUsage({ sessionId, ...payload }) {
|
|
127083
127504
|
return this.sessionApi(sessionId).getUsage(payload);
|
|
127084
127505
|
}
|
|
@@ -127166,8 +127587,8 @@ async function createRuntimeConfig(input) {
|
|
|
127166
127587
|
systemProxy: () => detectSystemProxy()
|
|
127167
127588
|
});
|
|
127168
127589
|
const localFetcher = new LocalFetchURLProvider({ fetchImpl: proxiedFetch });
|
|
127169
|
-
const
|
|
127170
|
-
const
|
|
127590
|
+
const fetchService = input.config.services?.fetchUrl;
|
|
127591
|
+
const webSearchConfig = input.config.services?.webSearch;
|
|
127171
127592
|
return {
|
|
127172
127593
|
kaos: localKaos,
|
|
127173
127594
|
osEnv: await detectEnvironmentFromNode(),
|
|
@@ -127179,12 +127600,11 @@ async function createRuntimeConfig(input) {
|
|
|
127179
127600
|
fetchImpl: proxiedFetch,
|
|
127180
127601
|
...serviceCredentials(fetchService, input.resolveOAuthTokenProvider)
|
|
127181
127602
|
}),
|
|
127182
|
-
webSearcher:
|
|
127183
|
-
|
|
127184
|
-
|
|
127185
|
-
fetchImpl: proxiedFetch
|
|
127186
|
-
|
|
127187
|
-
})
|
|
127603
|
+
webSearcher: webSearchConfig === void 0 ? void 0 : new PriorityRouter([...webSearchConfig.providers].toSorted((a, b) => a.priority - b.priority).map((p) => createProvider(p.type, {
|
|
127604
|
+
apiKeys: p.apiKeys,
|
|
127605
|
+
baseUrl: p.baseUrl,
|
|
127606
|
+
fetchImpl: proxiedFetch
|
|
127607
|
+
})))
|
|
127188
127608
|
};
|
|
127189
127609
|
}
|
|
127190
127610
|
function serviceCredentials(service, resolveOAuthTokenProvider) {
|
|
@@ -127219,11 +127639,11 @@ async function resumeSessionResult(summary, session, warning) {
|
|
|
127219
127639
|
context,
|
|
127220
127640
|
replay: agent.replayBuilder.buildResult(),
|
|
127221
127641
|
permission,
|
|
127222
|
-
plan: null,
|
|
127223
127642
|
usage,
|
|
127224
127643
|
tools: await api.getTools({ agentId }),
|
|
127225
127644
|
toolStore: agent.tools.storeData(),
|
|
127226
|
-
background: agent.background.list(false)
|
|
127645
|
+
background: agent.background.list(false),
|
|
127646
|
+
parentToolCallId: session.metadata.agents[agentId]?.parentToolCallId
|
|
127227
127647
|
};
|
|
127228
127648
|
}
|
|
127229
127649
|
return {
|
|
@@ -127319,7 +127739,8 @@ var SDKRpcClient = class {
|
|
|
127319
127739
|
this.core = new ByfCore(coreRpc, {
|
|
127320
127740
|
homeDir: options.homeDir,
|
|
127321
127741
|
configPath: options.configPath,
|
|
127322
|
-
skillDirs: options.skillDirs
|
|
127742
|
+
skillDirs: options.skillDirs,
|
|
127743
|
+
runtime: options.runtime
|
|
127323
127744
|
});
|
|
127324
127745
|
this.ready = sdkRpc(new ClientAPI(this)).then((rpc) => {
|
|
127325
127746
|
this.rpc = rpc;
|
|
@@ -127418,18 +127839,6 @@ var SDKRpcClient = class {
|
|
|
127418
127839
|
mode: input.mode
|
|
127419
127840
|
});
|
|
127420
127841
|
}
|
|
127421
|
-
async getPlan(input) {
|
|
127422
|
-
return (await this.getRpc()).getPlan({
|
|
127423
|
-
sessionId: input.sessionId,
|
|
127424
|
-
agentId: this.interactiveAgentId
|
|
127425
|
-
});
|
|
127426
|
-
}
|
|
127427
|
-
async clearPlan(input) {
|
|
127428
|
-
await (await this.getRpc()).clearPlan({
|
|
127429
|
-
sessionId: input.sessionId,
|
|
127430
|
-
agentId: this.interactiveAgentId
|
|
127431
|
-
});
|
|
127432
|
-
}
|
|
127433
127842
|
async compact(input) {
|
|
127434
127843
|
return (await this.getRpc()).beginCompaction({
|
|
127435
127844
|
sessionId: input.sessionId,
|
|
@@ -127586,7 +127995,7 @@ var SDKRpcClient = class {
|
|
|
127586
127995
|
type: "error",
|
|
127587
127996
|
sessionId: request.sessionId,
|
|
127588
127997
|
agentId: request.agentId,
|
|
127589
|
-
...makeErrorPayload(ErrorCodes.SESSION_APPROVAL_HANDLER_ERROR, errorMessage(error))
|
|
127998
|
+
...makeErrorPayload(ErrorCodes.SESSION_APPROVAL_HANDLER_ERROR, errorMessage$1(error))
|
|
127590
127999
|
});
|
|
127591
128000
|
return {
|
|
127592
128001
|
decision: "cancelled",
|
|
@@ -127604,7 +128013,7 @@ var SDKRpcClient = class {
|
|
|
127604
128013
|
type: "error",
|
|
127605
128014
|
sessionId: request.sessionId,
|
|
127606
128015
|
agentId: request.agentId,
|
|
127607
|
-
...makeErrorPayload(ErrorCodes.SESSION_QUESTION_HANDLER_ERROR, errorMessage(error))
|
|
128016
|
+
...makeErrorPayload(ErrorCodes.SESSION_QUESTION_HANDLER_ERROR, errorMessage$1(error))
|
|
127608
128017
|
});
|
|
127609
128018
|
return null;
|
|
127610
128019
|
}
|
|
@@ -127639,7 +128048,7 @@ var ClientAPI = class {
|
|
|
127639
128048
|
return this.client.toolCall(request);
|
|
127640
128049
|
}
|
|
127641
128050
|
};
|
|
127642
|
-
function errorMessage(error) {
|
|
128051
|
+
function errorMessage$1(error) {
|
|
127643
128052
|
return error instanceof Error ? error.message : String(error);
|
|
127644
128053
|
}
|
|
127645
128054
|
//#endregion
|
|
@@ -127735,13 +128144,6 @@ var Session = class {
|
|
|
127735
128144
|
mode
|
|
127736
128145
|
});
|
|
127737
128146
|
}
|
|
127738
|
-
async getPlan() {
|
|
127739
|
-
this.ensureOpen();
|
|
127740
|
-
return null;
|
|
127741
|
-
}
|
|
127742
|
-
async clearPlan() {
|
|
127743
|
-
this.ensureOpen();
|
|
127744
|
-
}
|
|
127745
128147
|
async compact(options = {}) {
|
|
127746
128148
|
this.ensureOpen();
|
|
127747
128149
|
const instruction = normalizeOptionalString(options.instruction);
|
|
@@ -127948,7 +128350,8 @@ var ByfHarness = class {
|
|
|
127948
128350
|
this.rpc = new SDKRpcClient({
|
|
127949
128351
|
homeDir: options.homeDir,
|
|
127950
128352
|
configPath: this.configPath,
|
|
127951
|
-
skillDirs: options.skillDirs
|
|
128353
|
+
skillDirs: options.skillDirs,
|
|
128354
|
+
runtime: options.runtime
|
|
127952
128355
|
});
|
|
127953
128356
|
}
|
|
127954
128357
|
configureLogging() {
|
|
@@ -127963,7 +128366,7 @@ var ByfHarness = class {
|
|
|
127963
128366
|
set interactiveAgentId(agentId) {
|
|
127964
128367
|
this.rpc.interactiveAgentId = agentId;
|
|
127965
128368
|
}
|
|
127966
|
-
track(
|
|
128369
|
+
track(_event, _properties) {}
|
|
127967
128370
|
async createSession(options) {
|
|
127968
128371
|
const summary = await this.rpc.createSession(options);
|
|
127969
128372
|
const session = new Session({
|
|
@@ -128045,6 +128448,38 @@ var ByfHarness = class {
|
|
|
128045
128448
|
async removeProvider(providerId) {
|
|
128046
128449
|
return this.rpc.removeProvider(providerId);
|
|
128047
128450
|
}
|
|
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
|
+
}
|
|
128048
128483
|
async shellExec(command, options = {}) {
|
|
128049
128484
|
const normalizedCommand = command.trim();
|
|
128050
128485
|
if (normalizedCommand.length === 0) throw new ByfError(ErrorCodes.REQUEST_INVALID, "Shell command cannot be empty.");
|
|
@@ -128075,6 +128510,9 @@ function normalizeSessionId(value) {
|
|
|
128075
128510
|
if (normalized.length === 0) throw new ByfError(ErrorCodes.SESSION_ID_EMPTY, "Session id cannot be empty.");
|
|
128076
128511
|
return normalized;
|
|
128077
128512
|
}
|
|
128513
|
+
function errorMessage(error) {
|
|
128514
|
+
return error instanceof Error ? error.message : String(error);
|
|
128515
|
+
}
|
|
128078
128516
|
//#endregion
|
|
128079
128517
|
//#region src/catalog.ts
|
|
128080
128518
|
const DEFAULT_CATALOG_URL = "https://models.dev/api.json";
|
|
@@ -128300,6 +128738,9 @@ function firstNonEmptyString(source, keys) {
|
|
|
128300
128738
|
}
|
|
128301
128739
|
}
|
|
128302
128740
|
async function fetchModels(baseUrl, apiKey, fetchImpl = fetch, signal) {
|
|
128741
|
+
return fetchOpenAICompatModels(baseUrl, apiKey, fetchImpl, signal);
|
|
128742
|
+
}
|
|
128743
|
+
async function fetchOpenAICompatModels(baseUrl, apiKey, fetchImpl = fetch, signal) {
|
|
128303
128744
|
const res = await fetchImpl(`${baseUrl.replace(/\/+$/, "")}/models`, {
|
|
128304
128745
|
headers: {
|
|
128305
128746
|
Authorization: `Bearer ${apiKey}`,
|
|
@@ -128312,6 +128753,70 @@ async function fetchModels(baseUrl, apiKey, fetchImpl = fetch, signal) {
|
|
|
128312
128753
|
if (!isRecord(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
|
|
128313
128754
|
return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
|
|
128314
128755
|
}
|
|
128756
|
+
/**
|
|
128757
|
+
* Lists models from a provider using its native wire-type endpoint. Dispatches
|
|
128758
|
+
* per `type` so each protocol gets its correct auth header and response shape.
|
|
128759
|
+
* `openai-completions` and `openai_responses` share the OpenAI-compatible
|
|
128760
|
+
* `/models` endpoint; `anthropic` uses its native `x-api-key` endpoint with
|
|
128761
|
+
* pagination. Other types have dedicated native fetchers (added in
|
|
128762
|
+
* later slices).
|
|
128763
|
+
*/
|
|
128764
|
+
async function fetchModelsByType(type, baseUrl, apiKey, fetchImpl = fetch, signal) {
|
|
128765
|
+
switch (type) {
|
|
128766
|
+
case "openai-completions":
|
|
128767
|
+
case "openai_responses": return fetchOpenAICompatModels(baseUrl, apiKey, fetchImpl, signal);
|
|
128768
|
+
case "anthropic": return fetchAnthropicModels(baseUrl, apiKey, fetchImpl, signal);
|
|
128769
|
+
default: throw new Error(`fetchModelsByType: unsupported provider type "${type}".`);
|
|
128770
|
+
}
|
|
128771
|
+
}
|
|
128772
|
+
/**
|
|
128773
|
+
* Anthropic native `/v1/models` listing. Uses `x-api-key` + `anthropic-version`
|
|
128774
|
+
* headers (not Bearer). Response is paginated via `has_more` + `last_id`;
|
|
128775
|
+
* follow pages by passing `?after_id=<last_id>`. Defensive guards: a page that
|
|
128776
|
+
* claims `has_more` but omits `last_id` stops pagination (returns what we have)
|
|
128777
|
+
* rather than looping forever; a hard cap (10 pages) also bounds the loop.
|
|
128778
|
+
*/
|
|
128779
|
+
async function fetchAnthropicModels(baseUrl, apiKey, fetchImpl = fetch, signal) {
|
|
128780
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
128781
|
+
const ANTHROPIC_VERSION = "2023-06-01";
|
|
128782
|
+
const MAX_PAGES = 10;
|
|
128783
|
+
const collected = [];
|
|
128784
|
+
let afterId;
|
|
128785
|
+
for (let page = 0; page < MAX_PAGES; page += 1) {
|
|
128786
|
+
const res = await fetchImpl(afterId === void 0 ? `${base}/models` : `${base}/models?after_id=${encodeURIComponent(afterId)}`, {
|
|
128787
|
+
headers: {
|
|
128788
|
+
"x-api-key": apiKey,
|
|
128789
|
+
"anthropic-version": ANTHROPIC_VERSION,
|
|
128790
|
+
Accept: "application/json"
|
|
128791
|
+
},
|
|
128792
|
+
signal
|
|
128793
|
+
});
|
|
128794
|
+
if (!res.ok) throw new ProviderApiError(await readApiErrorMessage(res, `Failed to list models (HTTP ${res.status}).`), res.status);
|
|
128795
|
+
const payload = await res.json();
|
|
128796
|
+
if (!isRecord(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
|
|
128797
|
+
for (const item of payload["data"]) {
|
|
128798
|
+
const info = anthropicModelToInfo(item);
|
|
128799
|
+
if (info !== void 0) collected.push(info);
|
|
128800
|
+
}
|
|
128801
|
+
const hasMore = payload["has_more"] === true;
|
|
128802
|
+
const lastId = typeof payload["last_id"] === "string" ? payload["last_id"] : void 0;
|
|
128803
|
+
if (!hasMore || lastId === void 0 || lastId.length === 0) break;
|
|
128804
|
+
afterId = lastId;
|
|
128805
|
+
}
|
|
128806
|
+
return collected;
|
|
128807
|
+
}
|
|
128808
|
+
function anthropicModelToInfo(item) {
|
|
128809
|
+
if (!isRecord(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
|
|
128810
|
+
const displayName = item["display_name"];
|
|
128811
|
+
return {
|
|
128812
|
+
id: item["id"],
|
|
128813
|
+
contextLength: 2e5,
|
|
128814
|
+
supportsReasoning: true,
|
|
128815
|
+
supportsImageIn: true,
|
|
128816
|
+
supportsVideoIn: false,
|
|
128817
|
+
displayName: typeof displayName === "string" && displayName.length > 0 ? displayName : void 0
|
|
128818
|
+
};
|
|
128819
|
+
}
|
|
128315
128820
|
function capabilitiesForModel(model) {
|
|
128316
128821
|
const caps = /* @__PURE__ */ new Set();
|
|
128317
128822
|
if (model.supportsReasoning) caps.add("thinking");
|
|
@@ -128325,7 +128830,7 @@ function applyProviderConfig(config, options) {
|
|
|
128325
128830
|
const providerKey = options.name;
|
|
128326
128831
|
const modelKey = `${providerKey}/${options.selectedModel.id}`;
|
|
128327
128832
|
config.providers[providerKey] = {
|
|
128328
|
-
type: "openai-completions",
|
|
128833
|
+
type: options.type ?? "openai-completions",
|
|
128329
128834
|
baseUrl: options.baseUrl,
|
|
128330
128835
|
apiKey: options.apiKey,
|
|
128331
128836
|
thinkingEffortKey: options.selectedModel.reasoningEffortKey
|
|
@@ -128351,4 +128856,4 @@ function applyProviderConfig(config, options) {
|
|
|
128351
128856
|
};
|
|
128352
128857
|
}
|
|
128353
128858
|
//#endregion
|
|
128354
|
-
export { BYF_ERROR_INFO, ByfAuthFacade, ByfError, ByfHarness, CatalogFetchError, DEFAULT_CATALOG_URL, ErrorCodes, MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, Session, applyCatalogProvider, applyProviderConfig, catalogBaseUrl, catalogIdMatchesModelId, catalogModelToAlias, catalogProviderModels, enrichWithCatalog, fetchCatalog, fetchModels, findCatalogModel, flushDiagnosticLogs, fromByfErrorPayload, __toESM as i, inferWireType, isByfError, loadBuiltInCatalog, log, __esmMin as n, __require as r, redact, resolveByfHome, resolveGlobalLogPath, __commonJSMin as t, toByfErrorPayload };
|
|
128859
|
+
export { BYF_ERROR_INFO, ByfAuthFacade, ByfError, ByfHarness, CatalogFetchError, DEFAULT_CATALOG_URL, ErrorCodes, MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, Session, applyCatalogProvider, applyProviderConfig, catalogBaseUrl, catalogIdMatchesModelId, catalogModelToAlias, catalogProviderModels, enrichWithCatalog, fetchCatalog, fetchModels, fetchModelsByType, findCatalogModel, flushDiagnosticLogs, fromByfErrorPayload, __toESM as i, inferWireType, isByfError, loadBuiltInCatalog, log, __esmMin as n, __require as r, redact, resolveByfHome, resolveGlobalLogPath, __commonJSMin as t, toByfErrorPayload };
|