blun-king-cli 9.1.596 → 9.1.599
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/CHANGELOG.md +32 -0
- package/README.md +6 -0
- package/blun.mjs +706 -117
- package/package.json +1 -1
- package/worker-host.mjs +134 -63
package/package.json
CHANGED
package/worker-host.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:25c271186c418490335e30ef395705d13d90d816c66cac47bb57835f2482f093
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -1311,7 +1311,7 @@ function normalizeBlunToolSchema(schema) {
|
|
|
1311
1311
|
}
|
|
1312
1312
|
function ensureBlunPropertyTypes(schema) {
|
|
1313
1313
|
const normalized = cloneJsonValue(schema);
|
|
1314
|
-
if (!isRecord$
|
|
1314
|
+
if (!isRecord$10(normalized)) throw new Error("JSON Schema root must normalize to an object.");
|
|
1315
1315
|
recurseSchema(normalized);
|
|
1316
1316
|
return normalized;
|
|
1317
1317
|
}
|
|
@@ -1372,7 +1372,7 @@ function resolveLocalJsonPointer(root, ref) {
|
|
|
1372
1372
|
let current = root;
|
|
1373
1373
|
for (const rawPart of ref.slice(2).split("/")) {
|
|
1374
1374
|
const part = unescapeJsonPointerPart(rawPart);
|
|
1375
|
-
if (isRecord$
|
|
1375
|
+
if (isRecord$10(current)) {
|
|
1376
1376
|
if (!hasOwn(current, part)) return { found: false };
|
|
1377
1377
|
current = current[part];
|
|
1378
1378
|
} else if (Array.isArray(current)) {
|
|
@@ -1394,20 +1394,20 @@ function parseJsonPointerArrayIndex(part) {
|
|
|
1394
1394
|
return Number(part);
|
|
1395
1395
|
}
|
|
1396
1396
|
function recurseSchema(node) {
|
|
1397
|
-
if (!isRecord$
|
|
1397
|
+
if (!isRecord$10(node)) return;
|
|
1398
1398
|
visitChildSchemas(node, normalizeProperty);
|
|
1399
1399
|
}
|
|
1400
1400
|
function visitChildSchemas(node, visit) {
|
|
1401
1401
|
for (const { key, kind } of CHILD_SCHEMA_SLOTS) {
|
|
1402
1402
|
const value = node[key];
|
|
1403
1403
|
if (kind === "single") {
|
|
1404
|
-
if (isRecord$
|
|
1404
|
+
if (isRecord$10(value)) visit(value);
|
|
1405
1405
|
} else if (kind === "array") {
|
|
1406
1406
|
if (Array.isArray(value)) for (const item of value) visit(item);
|
|
1407
1407
|
} else if (kind === "map") {
|
|
1408
|
-
if (isRecord$
|
|
1408
|
+
if (isRecord$10(value)) for (const item of Object.values(value)) visit(item);
|
|
1409
1409
|
} else if (kind === "schema-or-array") {
|
|
1410
|
-
if (isRecord$
|
|
1410
|
+
if (isRecord$10(value)) visit(value);
|
|
1411
1411
|
else if (Array.isArray(value)) for (const item of value) visit(item);
|
|
1412
1412
|
}
|
|
1413
1413
|
}
|
|
@@ -1419,7 +1419,7 @@ function childSchemaKeysForParentType(parentType) {
|
|
|
1419
1419
|
});
|
|
1420
1420
|
}
|
|
1421
1421
|
function normalizeProperty(node) {
|
|
1422
|
-
if (!isRecord$
|
|
1422
|
+
if (!isRecord$10(node)) return;
|
|
1423
1423
|
if (!hasOwn(node, "type") && !hasAnyKey(node, TYPE_COMPLETION_SKIP_KEYS)) {
|
|
1424
1424
|
const enumValues = node["enum"];
|
|
1425
1425
|
if (Array.isArray(enumValues) && enumValues.length > 0) node["type"] = inferTypeFromValues(enumValues);
|
|
@@ -1503,14 +1503,14 @@ function hasAnyKey(obj, keys) {
|
|
|
1503
1503
|
}
|
|
1504
1504
|
function cloneJsonValue(value) {
|
|
1505
1505
|
if (Array.isArray(value)) return value.map((item) => cloneJsonValue(item));
|
|
1506
|
-
if (isRecord$
|
|
1506
|
+
if (isRecord$10(value)) {
|
|
1507
1507
|
const cloned = {};
|
|
1508
1508
|
for (const [key, child] of Object.entries(value)) cloned[key] = cloneJsonValue(child);
|
|
1509
1509
|
return cloned;
|
|
1510
1510
|
}
|
|
1511
1511
|
return value;
|
|
1512
1512
|
}
|
|
1513
|
-
function isRecord$
|
|
1513
|
+
function isRecord$10(value) {
|
|
1514
1514
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1515
1515
|
}
|
|
1516
1516
|
function hasOwn(obj, key) {
|
|
@@ -1664,6 +1664,7 @@ var CompactionStallError$1 = class extends ChatProviderError {
|
|
|
1664
1664
|
}
|
|
1665
1665
|
};
|
|
1666
1666
|
function isRetryableGenerateError(error) {
|
|
1667
|
+
if (error instanceof APIContextOverflowError) return false;
|
|
1667
1668
|
if (error instanceof CompactionStallError$1) return true;
|
|
1668
1669
|
if (error instanceof APIConnectionError || error instanceof APITimeoutError) return true;
|
|
1669
1670
|
if (error instanceof APIEmptyResponseError) return true;
|
|
@@ -1728,7 +1729,8 @@ function isProviderQuotaExhaustedMessage(message) {
|
|
|
1728
1729
|
return PROVIDER_QUOTA_EXHAUSTED_MESSAGE_PATTERN.test(lowerMessage) && PROVIDER_QUOTA_EXHAUSTED_CONTEXT_PATTERNS.some((pattern) => pattern.test(lowerMessage));
|
|
1729
1730
|
}
|
|
1730
1731
|
function isContextOverflowStatusError(statusCode, message) {
|
|
1731
|
-
|
|
1732
|
+
const wrappedRejection = statusCode === 502 && /\bHTTP(?: Error)? (?:400|413|422):/i.test(message);
|
|
1733
|
+
if (statusCode !== 400 && statusCode !== 413 && statusCode !== 422 && !wrappedRejection) return false;
|
|
1732
1734
|
const lowerMessage = message.toLowerCase();
|
|
1733
1735
|
return CONTEXT_OVERFLOW_MESSAGE_PATTERNS.some((pattern) => pattern.test(lowerMessage));
|
|
1734
1736
|
}
|
|
@@ -1854,7 +1856,8 @@ var FetchTransport = class {
|
|
|
1854
1856
|
const startedAt = performance.now();
|
|
1855
1857
|
try {
|
|
1856
1858
|
const response = await this.fetch(`${this.baseUrl}${pathname}`, init);
|
|
1857
|
-
const
|
|
1859
|
+
const gatewayError = response.status === 502 ? await responseError(response) : void 0;
|
|
1860
|
+
const willRetry = attempt < maxRetries && shouldRetryResponse(response) && !(gatewayError instanceof APIContextOverflowError);
|
|
1858
1861
|
notifyTransportAttempt(requestOptions?.onTransportAttempt, {
|
|
1859
1862
|
transportAttempt: attempt + 1,
|
|
1860
1863
|
...requestBytes === void 0 ? {} : { requestBytes },
|
|
@@ -1866,12 +1869,12 @@ var FetchTransport = class {
|
|
|
1866
1869
|
if (response.ok) return response;
|
|
1867
1870
|
if (willRetry) {
|
|
1868
1871
|
const delayMs = retryDelayMs(response.headers, attempt);
|
|
1869
|
-
await response.body?.cancel();
|
|
1872
|
+
if (gatewayError === void 0) await response.body?.cancel();
|
|
1870
1873
|
await waitForRetry(delayMs, init.signal);
|
|
1871
1874
|
attempt += 1;
|
|
1872
1875
|
continue;
|
|
1873
1876
|
}
|
|
1874
|
-
throw await responseError(response);
|
|
1877
|
+
throw gatewayError ?? await responseError(response);
|
|
1875
1878
|
} catch (error) {
|
|
1876
1879
|
if (error instanceof ChatProviderError) throw error;
|
|
1877
1880
|
const willRetry = attempt < maxRetries && init.signal?.aborted !== true && isRetryableTransportFailure(error);
|
|
@@ -2698,6 +2701,19 @@ var BlunStreamedMessage = class {
|
|
|
2698
2701
|
}
|
|
2699
2702
|
}
|
|
2700
2703
|
};
|
|
2704
|
+
function contextOverflowOutputCap(error, currentCap) {
|
|
2705
|
+
const maxContext = error.maxContextTokens;
|
|
2706
|
+
const counts = /requested ([\d,_]+) output tokens and your prompt contains (at least )?([\d,_]+) input tokens/i.exec(error.message);
|
|
2707
|
+
if (maxContext === void 0 || counts === null || !Number.isSafeInteger(maxContext) || maxContext <= 0) return;
|
|
2708
|
+
const requestedOutput = Number(counts[1].replaceAll(/[,_]/g, ""));
|
|
2709
|
+
const input = Number(counts[3].replaceAll(/[,_]/g, ""));
|
|
2710
|
+
if (!Number.isSafeInteger(input) || input < 0 || !Number.isSafeInteger(requestedOutput) || requestedOutput <= 0 || !Number.isSafeInteger(input + requestedOutput) || input + requestedOutput <= maxContext) return;
|
|
2711
|
+
const available = maxContext - input;
|
|
2712
|
+
const headroom = Math.min(1024, Math.max(1, Math.ceil(available * .01)));
|
|
2713
|
+
const cap = Math.min(counts[2] === void 0 ? requestedOutput - 1 : Math.floor(requestedOutput / 2), available - headroom);
|
|
2714
|
+
if (cap < 1 || currentCap !== void 0 && (typeof currentCap !== "number" || !Number.isSafeInteger(currentCap) || cap >= currentCap)) return;
|
|
2715
|
+
return cap;
|
|
2716
|
+
}
|
|
2701
2717
|
var BlunChatProvider = class {
|
|
2702
2718
|
name = "blun";
|
|
2703
2719
|
_model;
|
|
@@ -2852,8 +2868,23 @@ var BlunChatProvider = class {
|
|
|
2852
2868
|
...options.onTransportAttempt !== void 0 ? { onTransportAttempt: options.onTransportAttempt } : {}
|
|
2853
2869
|
} : void 0;
|
|
2854
2870
|
options?.onRequestSent?.();
|
|
2855
|
-
|
|
2871
|
+
let response;
|
|
2872
|
+
try {
|
|
2873
|
+
response = await client.chat.completions.create(createParams, requestOptions);
|
|
2874
|
+
} catch (error) {
|
|
2875
|
+
const rejection = normalizeFetchHttpError(error);
|
|
2876
|
+
const cap = rejection instanceof APIContextOverflowError ? contextOverflowOutputCap(rejection, createParams["max_completion_tokens"]) : void 0;
|
|
2877
|
+
if (cap === void 0) throw rejection;
|
|
2878
|
+
options?.signal?.throwIfAborted();
|
|
2879
|
+
options?.onRequestSent?.();
|
|
2880
|
+
response = await client.chat.completions.create({
|
|
2881
|
+
...createParams,
|
|
2882
|
+
max_completion_tokens: cap
|
|
2883
|
+
}, requestOptions);
|
|
2884
|
+
}
|
|
2885
|
+
return new BlunStreamedMessage(response, this._stream, reasoningRequested);
|
|
2856
2886
|
} catch (error) {
|
|
2887
|
+
if (options?.signal?.aborted === true) throw options.signal.reason ?? error;
|
|
2857
2888
|
throw normalizeFetchHttpError(error);
|
|
2858
2889
|
}
|
|
2859
2890
|
}
|
|
@@ -10248,7 +10279,7 @@ function tokenFromWire(wire) {
|
|
|
10248
10279
|
}
|
|
10249
10280
|
//#endregion
|
|
10250
10281
|
//#region ../../packages/oauth/src/utils.ts
|
|
10251
|
-
function isRecord$
|
|
10282
|
+
function isRecord$9(value) {
|
|
10252
10283
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10253
10284
|
}
|
|
10254
10285
|
//#endregion
|
|
@@ -10563,7 +10594,7 @@ var FileTokenStorage = class {
|
|
|
10563
10594
|
} catch {
|
|
10564
10595
|
return;
|
|
10565
10596
|
}
|
|
10566
|
-
if (!isRecord$
|
|
10597
|
+
if (!isRecord$9(parsed)) return void 0;
|
|
10567
10598
|
return tokenFromWire(parsed);
|
|
10568
10599
|
}
|
|
10569
10600
|
async save(name, token) {
|
|
@@ -10668,7 +10699,7 @@ function extractApiErrorMessage(value) {
|
|
|
10668
10699
|
}
|
|
10669
10700
|
return;
|
|
10670
10701
|
}
|
|
10671
|
-
if (!isRecord$
|
|
10702
|
+
if (!isRecord$9(value)) return void 0;
|
|
10672
10703
|
for (const key of DIRECT_ERROR_KEYS) {
|
|
10673
10704
|
const message = stringField$1(value, key);
|
|
10674
10705
|
if (message !== void 0) return message;
|
|
@@ -10676,7 +10707,7 @@ function extractApiErrorMessage(value) {
|
|
|
10676
10707
|
const error = value["error"];
|
|
10677
10708
|
const errorString = nonEmptyString$6(error);
|
|
10678
10709
|
if (errorString !== void 0) return errorString;
|
|
10679
|
-
if (isRecord$
|
|
10710
|
+
if (isRecord$9(error)) for (const key of NESTED_ERROR_KEYS) {
|
|
10680
10711
|
const message = stringField$1(error, key);
|
|
10681
10712
|
if (message !== void 0) return message;
|
|
10682
10713
|
}
|
|
@@ -10770,7 +10801,7 @@ async function postForm(url, params, deviceHeaders, options) {
|
|
|
10770
10801
|
let data = {};
|
|
10771
10802
|
try {
|
|
10772
10803
|
const parsed = await response.json();
|
|
10773
|
-
if (isRecord$
|
|
10804
|
+
if (isRecord$9(parsed)) data = parsed;
|
|
10774
10805
|
} catch {}
|
|
10775
10806
|
return {
|
|
10776
10807
|
status,
|
|
@@ -12687,9 +12718,9 @@ function blunContextWindowsUrl(oauthHost) {
|
|
|
12687
12718
|
return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}/api/verbrauch/tarife`;
|
|
12688
12719
|
}
|
|
12689
12720
|
function parseManagedContextWindow(payload, plan) {
|
|
12690
|
-
if (!isRecord$
|
|
12721
|
+
if (!isRecord$9(payload)) return void 0;
|
|
12691
12722
|
const contextWindows = payload["kontext"];
|
|
12692
|
-
if (!isRecord$
|
|
12723
|
+
if (!isRecord$9(contextWindows)) return void 0;
|
|
12693
12724
|
const value = contextWindows[plan];
|
|
12694
12725
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
|
|
12695
12726
|
}
|
|
@@ -12724,7 +12755,7 @@ function parseManagedUsagePayload(payload) {
|
|
|
12724
12755
|
const plan = typeof rec["plan"] === "string" && rec["plan"].trim().length > 0 ? rec["plan"].trim() : void 0;
|
|
12725
12756
|
const contextWindowTokens = managedContextWindowFrom(rec);
|
|
12726
12757
|
const unlimited = rec["unlimited"] === true;
|
|
12727
|
-
const stand = isRecord$
|
|
12758
|
+
const stand = isRecord$9(rec["stand"]) ? rec["stand"] : void 0;
|
|
12728
12759
|
if (stand !== void 0) for (const [sourceKey, id, label] of ACCOUNT_USAGE_WINDOWS) {
|
|
12729
12760
|
const row = toAccountUsageRow(stand[sourceKey], id, label, unlimited);
|
|
12730
12761
|
if (row !== null) limits.push(row);
|
|
@@ -12734,9 +12765,9 @@ function parseManagedUsagePayload(payload) {
|
|
|
12734
12765
|
const item = rawLimits[idx];
|
|
12735
12766
|
if (!item || typeof item !== "object") continue;
|
|
12736
12767
|
const detailRaw = item["detail"];
|
|
12737
|
-
const detail = isRecord$
|
|
12768
|
+
const detail = isRecord$9(detailRaw) ? detailRaw : item;
|
|
12738
12769
|
const windowRaw = item["window"];
|
|
12739
|
-
const row = toUsageRow(detail, limitLabel(item, detail, isRecord$
|
|
12770
|
+
const row = toUsageRow(detail, limitLabel(item, detail, isRecord$9(windowRaw) ? windowRaw : {}, idx));
|
|
12740
12771
|
if (row !== null) limits.push(row);
|
|
12741
12772
|
}
|
|
12742
12773
|
return {
|
|
@@ -12777,7 +12808,7 @@ const ACCOUNT_USAGE_WINDOWS = [
|
|
|
12777
12808
|
]
|
|
12778
12809
|
];
|
|
12779
12810
|
function toAccountUsageRow(raw, id, label, accountUnlimited) {
|
|
12780
|
-
if (!isRecord$
|
|
12811
|
+
if (!isRecord$9(raw)) return null;
|
|
12781
12812
|
const used = toInt(raw["verbraucht"]);
|
|
12782
12813
|
const unlimited = accountUnlimited || raw["unlimited"] === true;
|
|
12783
12814
|
const fraction = raw["anteil"];
|
|
@@ -12810,7 +12841,7 @@ function toAccountUsageRow(raw, id, label, accountUnlimited) {
|
|
|
12810
12841
|
};
|
|
12811
12842
|
}
|
|
12812
12843
|
function toUsageRow(raw, defaultLabel) {
|
|
12813
|
-
if (!isRecord$
|
|
12844
|
+
if (!isRecord$9(raw)) return null;
|
|
12814
12845
|
const unlimited = raw["unlimited"] === true;
|
|
12815
12846
|
const limit = toInt(raw["limit"]);
|
|
12816
12847
|
let used = toInt(raw["used"]);
|
|
@@ -12931,7 +12962,7 @@ function isManagedQuotaErrorMessage(message) {
|
|
|
12931
12962
|
return /you(?:'|’)?ve reached your usage limit/.test(normalized) && /billing cycle|quota will be (?:refreshed|reset)|purchase extra usage/.test(normalized);
|
|
12932
12963
|
}
|
|
12933
12964
|
function hasManagedUsageShape(payload) {
|
|
12934
|
-
if (!isRecord$
|
|
12965
|
+
if (!isRecord$9(payload)) return false;
|
|
12935
12966
|
let recognized = false;
|
|
12936
12967
|
if ("context_window_tokens" in payload || "contextWindowTokens" in payload) {
|
|
12937
12968
|
recognized = true;
|
|
@@ -12947,15 +12978,15 @@ function hasManagedUsageShape(payload) {
|
|
|
12947
12978
|
if (!Array.isArray(limits)) return false;
|
|
12948
12979
|
for (let index = 0; index < limits.length; index++) {
|
|
12949
12980
|
const item = limits[index];
|
|
12950
|
-
if (!isRecord$
|
|
12951
|
-
const detail = isRecord$
|
|
12952
|
-
if (toUsageRow(detail, limitLabel(item, detail, isRecord$
|
|
12981
|
+
if (!isRecord$9(item)) return false;
|
|
12982
|
+
const detail = isRecord$9(item["detail"]) ? item["detail"] : item;
|
|
12983
|
+
if (toUsageRow(detail, limitLabel(item, detail, isRecord$9(item["window"]) ? item["window"] : {}, index)) === null) return false;
|
|
12953
12984
|
}
|
|
12954
12985
|
}
|
|
12955
12986
|
if ("stand" in payload) {
|
|
12956
12987
|
recognized = true;
|
|
12957
12988
|
const stand = payload["stand"];
|
|
12958
|
-
if (!isRecord$
|
|
12989
|
+
if (!isRecord$9(stand)) return false;
|
|
12959
12990
|
const windows = ACCOUNT_USAGE_WINDOWS.filter(([sourceKey]) => sourceKey in stand);
|
|
12960
12991
|
if (windows.length === 0) return false;
|
|
12961
12992
|
const unlimited = payload["unlimited"] === true;
|
|
@@ -13038,8 +13069,8 @@ function userExtras(existing, remoteOwnedFields) {
|
|
|
13038
13069
|
return out;
|
|
13039
13070
|
}
|
|
13040
13071
|
function mergeRefreshedModelAlias(existing, remote, remoteOwnedFields) {
|
|
13041
|
-
const current = isRecord$
|
|
13042
|
-
const overrides = cloneOverrides(isRecord$
|
|
13072
|
+
const current = isRecord$9(existing) ? existing : {};
|
|
13073
|
+
const overrides = cloneOverrides(isRecord$9(current["overrides"]) ? current["overrides"] : void 0);
|
|
13043
13074
|
return {
|
|
13044
13075
|
...userExtras(current, remoteOwnedFields),
|
|
13045
13076
|
...remote,
|
|
@@ -13241,7 +13272,7 @@ function parseModelContextLength(item, modelId) {
|
|
|
13241
13272
|
return values[0];
|
|
13242
13273
|
}
|
|
13243
13274
|
function toModelInfo(item) {
|
|
13244
|
-
if (!isRecord$
|
|
13275
|
+
if (!isRecord$9(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
|
|
13245
13276
|
const contextLength = parseModelContextLength(item, item["id"]);
|
|
13246
13277
|
const displayName = item["display_name"];
|
|
13247
13278
|
const normalizedDisplayName = typeof displayName === "string" && displayName.length > 0 ? displayName : void 0;
|
|
@@ -13328,7 +13359,7 @@ async function fetchManagedBlunCodeModels(options) {
|
|
|
13328
13359
|
throw new Error(message);
|
|
13329
13360
|
}
|
|
13330
13361
|
const payload = await response.json();
|
|
13331
|
-
if (!isRecord$
|
|
13362
|
+
if (!isRecord$9(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
|
|
13332
13363
|
return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
|
|
13333
13364
|
}
|
|
13334
13365
|
throw new Error(`Failed to list BLUN models for ${baseUrl}.`);
|
|
@@ -13371,11 +13402,11 @@ function applyManagedBlunCodeConfig(config, options) {
|
|
|
13371
13402
|
apiKey
|
|
13372
13403
|
};
|
|
13373
13404
|
const upstreamKeys = new Set(options.models.map((m) => managedModelKey(m.id)));
|
|
13374
|
-
for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$
|
|
13405
|
+
for (const [key, model] of Object.entries(existingModels)) if (RETIRED_BLUN_MODEL_KEYS.has(key) || isRecord$9(model) && model["provider"] === "managed:blun" && !upstreamKeys.has(key)) delete existingModels[key];
|
|
13375
13406
|
for (const model of options.models) {
|
|
13376
13407
|
const capabilities = capabilitiesForModel(model);
|
|
13377
13408
|
const key = managedModelKey(model.id);
|
|
13378
|
-
const existing = isRecord$
|
|
13409
|
+
const existing = isRecord$9(existingModels[key]) ? existingModels[key] : {};
|
|
13379
13410
|
const supportsAdaptiveThinking = capabilities?.includes("thinking") === true || capabilities?.includes("always_thinking") === true;
|
|
13380
13411
|
existingModels[key] = mergeRefreshedModelAlias(existing, {
|
|
13381
13412
|
provider: BLUN_PROVIDER_NAME$1,
|
|
@@ -13423,7 +13454,7 @@ function applyManagedBlunCodeLogoutConfig(config) {
|
|
|
13423
13454
|
let removedDefaultModel = false;
|
|
13424
13455
|
const existingModels = config.models ?? {};
|
|
13425
13456
|
for (const [key, model] of Object.entries(existingModels)) {
|
|
13426
|
-
if (!isRecord$
|
|
13457
|
+
if (!isRecord$9(model) || model["provider"] !== "managed:blun") continue;
|
|
13427
13458
|
delete existingModels[key];
|
|
13428
13459
|
if (config.defaultModel === key) removedDefaultModel = true;
|
|
13429
13460
|
}
|
|
@@ -13463,7 +13494,7 @@ function selectDefaultModel(config, models, options) {
|
|
|
13463
13494
|
function canPreserveDefaultModel(existingModels, defaultModel, managedModels) {
|
|
13464
13495
|
if (managedModels.has(defaultModel)) return true;
|
|
13465
13496
|
const existing = existingModels[defaultModel];
|
|
13466
|
-
return isRecord$
|
|
13497
|
+
return isRecord$9(existing) && existing["provider"] !== "managed:blun";
|
|
13467
13498
|
}
|
|
13468
13499
|
function assertPositiveContextLength(model) {
|
|
13469
13500
|
if (!Number.isInteger(model.contextLength) || model.contextLength <= 0) throw new Error(`BLUN model "${model.id}" must include a positive context_length.`);
|
|
@@ -13501,13 +13532,13 @@ function blunManagedQuotaUrl(oauthHost) {
|
|
|
13501
13532
|
return `${(oauthHost ?? process.env["BLUN_OAUTH_HOST"] ?? "https://account.blun.ai").replace(/\/+$/, "")}${MANAGED_QUOTA_PATH}`;
|
|
13502
13533
|
}
|
|
13503
13534
|
function parseManagedQuotaPayload(payload) {
|
|
13504
|
-
if (!isRecord$
|
|
13535
|
+
if (!isRecord$9(payload)) return void 0;
|
|
13505
13536
|
const plan = nonEmptyString$5(payload["plan"]);
|
|
13506
13537
|
const paid = payload["bezahlt"];
|
|
13507
13538
|
const creditCents = payload["guthaben_cent"];
|
|
13508
13539
|
const billingKind = nonEmptyString$5(payload["art"]);
|
|
13509
13540
|
const globalUnlimited = payload["unlimited"];
|
|
13510
|
-
if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$
|
|
13541
|
+
if (plan === void 0 || typeof paid !== "boolean" || !Number.isSafeInteger(creditCents) || creditCents < 0 || billingKind === void 0 || globalUnlimited !== void 0 && typeof globalUnlimited !== "boolean" || !isRecord$9(payload["stand"])) return;
|
|
13511
13542
|
if (!hasStrictQuotaStand(payload["stand"], globalUnlimited === true)) return void 0;
|
|
13512
13543
|
const limits = parseManagedUsagePayload(payload).limits;
|
|
13513
13544
|
if (limits.length !== REQUIRED_WINDOWS.length || REQUIRED_WINDOWS.some(([, id]) => limits.filter((row) => row.id === id).length !== 1)) return;
|
|
@@ -13577,7 +13608,7 @@ function nonEmptyString$5(value) {
|
|
|
13577
13608
|
function hasStrictQuotaStand(stand, globalUnlimited) {
|
|
13578
13609
|
return REQUIRED_WINDOWS.every(([sourceKey]) => {
|
|
13579
13610
|
const row = stand[sourceKey];
|
|
13580
|
-
if (!isRecord$
|
|
13611
|
+
if (!isRecord$9(row)) return false;
|
|
13581
13612
|
const used = row["verbraucht"];
|
|
13582
13613
|
const rowUnlimited = row["unlimited"];
|
|
13583
13614
|
if (rowUnlimited !== void 0 && typeof rowUnlimited !== "boolean") return false;
|
|
@@ -20674,7 +20705,7 @@ function parseSkillText(options) {
|
|
|
20674
20705
|
throw error;
|
|
20675
20706
|
}
|
|
20676
20707
|
const frontmatter = parsed.data ?? {};
|
|
20677
|
-
if (!isRecord$
|
|
20708
|
+
if (!isRecord$8(frontmatter)) throw new SkillParseError(`Frontmatter in ${options.skillMdPath} must be a mapping at the top level`);
|
|
20678
20709
|
const metadata = normalizeMetadata(frontmatter);
|
|
20679
20710
|
if (!isSupportedSkillType(metadata.type)) throw new UnsupportedSkillTypeError(metadata.type ?? String(frontmatter["type"]));
|
|
20680
20711
|
const name = nonEmptyString$3(metadata.name);
|
|
@@ -20787,7 +20818,7 @@ function tokenizeArgs(raw) {
|
|
|
20787
20818
|
function nonEmptyString$3(value) {
|
|
20788
20819
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
20789
20820
|
}
|
|
20790
|
-
function isRecord$
|
|
20821
|
+
function isRecord$8(value) {
|
|
20791
20822
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20792
20823
|
}
|
|
20793
20824
|
//#endregion
|
|
@@ -20795,7 +20826,7 @@ function isRecord$7(value) {
|
|
|
20795
20826
|
function parseCommandText(input) {
|
|
20796
20827
|
const { text, commandPath, pluginId } = input;
|
|
20797
20828
|
const parsed = parseFrontmatter(text);
|
|
20798
|
-
const frontmatter = isRecord$
|
|
20829
|
+
const frontmatter = isRecord$7(parsed.data) ? parsed.data : {};
|
|
20799
20830
|
const baseName = input.fallbackName ?? path.basename(commandPath).replace(/\.md$/i, "");
|
|
20800
20831
|
const name = nonEmptyString$2(frontmatter["name"]) ?? baseName;
|
|
20801
20832
|
const body = parsed.body.trim();
|
|
@@ -20837,7 +20868,7 @@ function descriptionFromBody(body) {
|
|
|
20837
20868
|
if (firstLine === void 0) return "No description provided.";
|
|
20838
20869
|
return firstLine.length > 240 ? `${firstLine.slice(0, 239)}…` : firstLine;
|
|
20839
20870
|
}
|
|
20840
|
-
function isRecord$
|
|
20871
|
+
function isRecord$7(value) {
|
|
20841
20872
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20842
20873
|
}
|
|
20843
20874
|
//#endregion
|
|
@@ -28345,7 +28376,7 @@ const ResumeIntentSchema = object({
|
|
|
28345
28376
|
startedAt: timestamp$2.nullable()
|
|
28346
28377
|
}).strict();
|
|
28347
28378
|
const hash$2 = (value) => createHash("sha256").update(value).digest("hex");
|
|
28348
|
-
const isRecord$
|
|
28379
|
+
const isRecord$6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
28349
28380
|
/** Explicit resume intents, isolated from ordinary task status and output files. */
|
|
28350
28381
|
var TaskResumeStore = class {
|
|
28351
28382
|
home;
|
|
@@ -28401,9 +28432,9 @@ var TaskResumeStore = class {
|
|
|
28401
28432
|
}
|
|
28402
28433
|
async readOwnedTask(taskId) {
|
|
28403
28434
|
const task = await this.read("tasks", taskId);
|
|
28404
|
-
if (!isRecord$
|
|
28435
|
+
if (!isRecord$6(task)) throw new Error("Task has no persisted local record.");
|
|
28405
28436
|
const owner = task["resumeOwnership"];
|
|
28406
|
-
if (!isRecord$
|
|
28437
|
+
if (!isRecord$6(owner) || owner["version"] !== 1 || owner["scope"] !== hash$2(await this.root()) || owner["taskId"] !== taskId || task["taskId"] !== taskId || task["kind"] !== "agent" || owner["agentId"] !== task["agentId"] || owner["startedAt"] !== task["startedAt"]) throw new Error("Task ownership is unverified; historical or foreign records cannot be resumed automatically.");
|
|
28407
28438
|
const { resumeOwnership: _ownership, ...info } = task;
|
|
28408
28439
|
return info;
|
|
28409
28440
|
}
|
|
@@ -28655,12 +28686,12 @@ function legacyStatusToCurrent(task) {
|
|
|
28655
28686
|
return task.status;
|
|
28656
28687
|
}
|
|
28657
28688
|
function isReadablePersistedTask(obj) {
|
|
28658
|
-
return isRecord$
|
|
28689
|
+
return isRecord$5(obj) && (typeof obj["taskId"] === "string" || typeof obj["task_id"] === "string");
|
|
28659
28690
|
}
|
|
28660
28691
|
function isLegacyPersistedTask(task) {
|
|
28661
28692
|
return "task_id" in task;
|
|
28662
28693
|
}
|
|
28663
|
-
function isRecord$
|
|
28694
|
+
function isRecord$5(value) {
|
|
28664
28695
|
return typeof value === "object" && value !== null;
|
|
28665
28696
|
}
|
|
28666
28697
|
function optionalNonEmptyString(value) {
|
|
@@ -227987,7 +228018,7 @@ var HttpVisionReader = class {
|
|
|
227987
228018
|
reason: "malformed"
|
|
227988
228019
|
};
|
|
227989
228020
|
}
|
|
227990
|
-
if (!isRecord$
|
|
228021
|
+
if (!isRecord$4(payload) || payload["done"] !== true || typeof payload["response"] !== "string" || !isNonNegativeInteger(payload["prompt_eval_count"]) || !isNonNegativeInteger(payload["eval_count"])) return {
|
|
227991
228022
|
ok: false,
|
|
227992
228023
|
reason: "malformed"
|
|
227993
228024
|
};
|
|
@@ -228411,7 +228442,7 @@ function escapeXml(value) {
|
|
|
228411
228442
|
function locationKey(messageIndex, partIndex) {
|
|
228412
228443
|
return `${String(messageIndex)}:${String(partIndex)}`;
|
|
228413
228444
|
}
|
|
228414
|
-
function isRecord$
|
|
228445
|
+
function isRecord$4(value) {
|
|
228415
228446
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
228416
228447
|
}
|
|
228417
228448
|
function isNonNegativeInteger(value) {
|
|
@@ -234208,7 +234239,7 @@ const OptionalStringSchema = preprocess((value) => {
|
|
|
234208
234239
|
if (typeof value === "string") return value;
|
|
234209
234240
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
234210
234241
|
}, string().optional());
|
|
234211
|
-
const HookSpecificOutputSchema = preprocess((value) => isRecord$
|
|
234242
|
+
const HookSpecificOutputSchema = preprocess((value) => isRecord$3(value) ? value : void 0, looseObject({
|
|
234212
234243
|
message: OptionalStringSchema,
|
|
234213
234244
|
additionalContext: OptionalStringSchema,
|
|
234214
234245
|
permissionDecision: unknown().optional(),
|
|
@@ -234360,7 +234391,7 @@ function structuredOutput(stdout, input) {
|
|
|
234360
234391
|
return {
|
|
234361
234392
|
...result,
|
|
234362
234393
|
additionalContext: input["hook_event_name"] === "UserPromptSubmit" && hookSpecificOutput?.hookEventName === "UserPromptSubmit" ? hookSpecificOutput.additionalContext : void 0,
|
|
234363
|
-
updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$
|
|
234394
|
+
updatedInput: input["hook_event_name"] === "PreToolUse" && hookSpecificOutput?.hookEventName === "PreToolUse" && isRecord$3(hookSpecificOutput.updatedInput) ? hookSpecificOutput.updatedInput : void 0
|
|
234364
234395
|
};
|
|
234365
234396
|
}
|
|
234366
234397
|
return {
|
|
@@ -234429,7 +234460,7 @@ function killProcessTreeWindows(child, force) {
|
|
|
234429
234460
|
} catch {}
|
|
234430
234461
|
}
|
|
234431
234462
|
}
|
|
234432
|
-
function isRecord$
|
|
234463
|
+
function isRecord$3(value) {
|
|
234433
234464
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
234434
234465
|
}
|
|
234435
234466
|
function errorMessage$3(error) {
|
|
@@ -234550,7 +234581,16 @@ var HookEngine = class {
|
|
|
234550
234581
|
};
|
|
234551
234582
|
}
|
|
234552
234583
|
if (this.admissionClosed) return void 0;
|
|
234553
|
-
|
|
234584
|
+
let hookInput;
|
|
234585
|
+
try {
|
|
234586
|
+
hookInput = this.options.runtimeInput?.(hook, inputData) ?? inputData;
|
|
234587
|
+
} catch {
|
|
234588
|
+
return {
|
|
234589
|
+
action: "block",
|
|
234590
|
+
reason: "Hook input preparation failed."
|
|
234591
|
+
};
|
|
234592
|
+
}
|
|
234593
|
+
return runHook(hook.command, hookInput, {
|
|
234554
234594
|
timeout: hook.timeout ?? DEFAULT_HOOK_TIMEOUT_SECONDS,
|
|
234555
234595
|
cwd: hook.cwd ?? (this.options.cwd === "" ? void 0 : this.options.cwd),
|
|
234556
234596
|
env: hook.env,
|
|
@@ -235785,7 +235825,7 @@ function parsePersonalMemoryRecall(output) {
|
|
|
235785
235825
|
} catch {
|
|
235786
235826
|
return { kind: "invalid" };
|
|
235787
235827
|
}
|
|
235788
|
-
if (!isRecord$
|
|
235828
|
+
if (!isRecord$2(parsed) || !isRecord$2(parsed["personal_memory"])) return { kind: "invalid" };
|
|
235789
235829
|
const memory = parsed["personal_memory"];
|
|
235790
235830
|
const savedRaw = memory["saved"];
|
|
235791
235831
|
const threadsRaw = memory["threads"];
|
|
@@ -235794,7 +235834,7 @@ function parsePersonalMemoryRecall(output) {
|
|
|
235794
235834
|
if (savedRaw.length > MAX_SAVED_MEMORIES || threadsRaw.length > MAX_THREADS || historyRaw.length > 0) return { kind: "invalid" };
|
|
235795
235835
|
const saved = [];
|
|
235796
235836
|
for (const value of savedRaw) {
|
|
235797
|
-
if (!isRecord$
|
|
235837
|
+
if (!isRecord$2(value)) return { kind: "invalid" };
|
|
235798
235838
|
const text = boundedTrimmedString(value["text"], MAX_MEMORY_TEXT_CHARS);
|
|
235799
235839
|
const confidence = value["confidence"];
|
|
235800
235840
|
if (text === void 0 || typeof confidence !== "string" || !CONFIDENCE_VALUES.has(confidence)) return { kind: "invalid" };
|
|
@@ -235805,7 +235845,7 @@ function parsePersonalMemoryRecall(output) {
|
|
|
235805
235845
|
}
|
|
235806
235846
|
const threads = [];
|
|
235807
235847
|
for (const value of threadsRaw) {
|
|
235808
|
-
if (!isRecord$
|
|
235848
|
+
if (!isRecord$2(value)) return { kind: "invalid" };
|
|
235809
235849
|
const title = boundedTrimmedString(value["title"], MAX_THREAD_TITLE_CHARS);
|
|
235810
235850
|
const summary = boundedTrimmedString(value["summary"], MAX_THREAD_SUMMARY_CHARS);
|
|
235811
235851
|
if (title === void 0 || summary === void 0) return { kind: "invalid" };
|
|
@@ -235859,7 +235899,7 @@ function boundedTrimmedString(value, maxChars) {
|
|
|
235859
235899
|
const trimmed = value.trim();
|
|
235860
235900
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
235861
235901
|
}
|
|
235862
|
-
function isRecord$
|
|
235902
|
+
function isRecord$2(value) {
|
|
235863
235903
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
235864
235904
|
}
|
|
235865
235905
|
//#endregion
|
|
@@ -299908,6 +299948,36 @@ function mergeCallerMcpServers(base, callerServers) {
|
|
|
299908
299948
|
}
|
|
299909
299949
|
//#endregion
|
|
299910
299950
|
//#region ../../packages/agent-core/src/plugin/agent-spine-runtime.ts
|
|
299951
|
+
const PROMPT_EVENTS = new Set([
|
|
299952
|
+
"UserPromptSubmit",
|
|
299953
|
+
"TurnStart",
|
|
299954
|
+
"SubagentStart"
|
|
299955
|
+
]);
|
|
299956
|
+
/** AgentSpine reads prompt text; binary media stays in the original model input. */
|
|
299957
|
+
function projectAgentSpinePrompt(input) {
|
|
299958
|
+
if (typeof input["hook_event_name"] !== "string" || !PROMPT_EVENTS.has(input["hook_event_name"]) || !Array.isArray(input["prompt"])) return input;
|
|
299959
|
+
let changed = false;
|
|
299960
|
+
const prompt = input["prompt"].map((part) => {
|
|
299961
|
+
if (!isRecord$1(part)) return part;
|
|
299962
|
+
const field = part["type"] === "image_url" ? "imageUrl" : part["type"] === "audio_url" ? "audioUrl" : part["type"] === "video_url" ? "videoUrl" : void 0;
|
|
299963
|
+
if (field === void 0 || !isRecord$1(part[field]) || typeof part[field]["url"] !== "string") return part;
|
|
299964
|
+
const serialized = JSON.stringify(part);
|
|
299965
|
+
changed = true;
|
|
299966
|
+
return {
|
|
299967
|
+
type: "media_reference",
|
|
299968
|
+
media_type: part["type"],
|
|
299969
|
+
sha256: createHash("sha256").update(serialized).digest("hex"),
|
|
299970
|
+
original_bytes: Buffer.byteLength(serialized)
|
|
299971
|
+
};
|
|
299972
|
+
});
|
|
299973
|
+
return changed ? {
|
|
299974
|
+
...input,
|
|
299975
|
+
prompt
|
|
299976
|
+
} : input;
|
|
299977
|
+
}
|
|
299978
|
+
function isRecord$1(value) {
|
|
299979
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
299980
|
+
}
|
|
299911
299981
|
const EMPTY_RUNTIME = Object.freeze({
|
|
299912
299982
|
AGENTSPINE_KING_TIMELINE_SOURCE: "",
|
|
299913
299983
|
AGENTSPINE_KING_WIRE_PROTOCOL_VERSION: "",
|
|
@@ -300454,9 +300524,11 @@ var Session$1 = class {
|
|
|
300454
300524
|
this.experimentalFlags = options.experimentalFlags ?? new FlagResolver();
|
|
300455
300525
|
this.agentSpineRuntime = this.experimentalFlags.enabled("agent_spine_timeline") ? new AgentSpineSessionRuntime(options.agentSpineRuntime) : void 0;
|
|
300456
300526
|
this.visionReader = (this.experimentalFlags.enabled("vision_reader") ? createVisionReader(options.config?.services?.visionReader) : void 0) ?? createManagedMediaVisionReader(options.toolServices?.media);
|
|
300527
|
+
const agentSpineHooks = new Set(options.agentSpineRuntime?.hooks);
|
|
300457
300528
|
this.hookEngine = new HookEngine(options.hooks, {
|
|
300458
300529
|
cwd: options.kaos.getcwd(),
|
|
300459
300530
|
sessionId: options.id,
|
|
300531
|
+
runtimeInput: (hook, input) => agentSpineHooks.has(hook) ? projectAgentSpinePrompt(input) : input,
|
|
300460
300532
|
runtimeEnv: (hook) => {
|
|
300461
300533
|
const hostEnv = options.hookRuntimeEnv?.(hook);
|
|
300462
300534
|
const timelineEnv = this.agentSpineRuntime?.forHook(hook);
|
|
@@ -335738,7 +335810,6 @@ var BlunCore = class {
|
|
|
335738
335810
|
};
|
|
335739
335811
|
}
|
|
335740
335812
|
agentSpineRuntimeRecipients(pluginHooks, mcpConfig) {
|
|
335741
|
-
if (!this.experimentalFlags.enabled("agent_spine_timeline")) return void 0;
|
|
335742
335813
|
const plugin = this.plugins.get("agent-spine");
|
|
335743
335814
|
if (plugin?.state !== "ok" || !plugin.enabled) return void 0;
|
|
335744
335815
|
const hooks = pluginHooks.filter((hook) => hook.env?.["BLUN_PLUGIN_ROOT"] === plugin.root);
|