@kernelonpanic/kitcode 1.4.2 → 1.4.3
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.js +91 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -170,7 +170,10 @@ function describeProviderFailure(error, providerId, knownSecrets = []) {
|
|
|
170
170
|
}
|
|
171
171
|
function statusOf(error) {
|
|
172
172
|
const value = prop(error, "status") ?? prop(error, "statusCode");
|
|
173
|
-
|
|
173
|
+
if (typeof value === "number" && value >= 100) return value;
|
|
174
|
+
const code = prop(error, "code") ?? prop(prop(error, "error"), "code");
|
|
175
|
+
const numeric = typeof code === "string" && /^\d{3}$/.test(code) ? Number(code) : code;
|
|
176
|
+
return typeof numeric === "number" && numeric >= 400 && numeric <= 599 ? numeric : void 0;
|
|
174
177
|
}
|
|
175
178
|
function isUserAbort(error, signal) {
|
|
176
179
|
return signal?.aborted === true || abortKind(error) === "user";
|
|
@@ -1440,13 +1443,20 @@ function resolveEffort(effort, messages) {
|
|
|
1440
1443
|
return text.length > 500 || HARD_TASK.test(text) ? "high" : "medium";
|
|
1441
1444
|
}
|
|
1442
1445
|
var rejected = /* @__PURE__ */ new Set();
|
|
1446
|
+
var capped = /* @__PURE__ */ new Map();
|
|
1447
|
+
var RANK = { low: 0, medium: 1, high: 2, xhigh: 3, max: 4 };
|
|
1443
1448
|
function markEffortRejected(providerId, model) {
|
|
1444
1449
|
rejected.add(`${providerId}/${model}`);
|
|
1445
1450
|
}
|
|
1451
|
+
function markEffortCapped(providerId, model, level) {
|
|
1452
|
+
capped.set(`${providerId}/${model}`, level);
|
|
1453
|
+
}
|
|
1446
1454
|
function effectiveEffort(kind, model, effort, messages, providerId) {
|
|
1447
1455
|
if (providerId !== void 0 && rejected.has(`${providerId}/${model}`)) return void 0;
|
|
1448
1456
|
const requested = resolveEffort(effort, messages);
|
|
1449
|
-
|
|
1457
|
+
const level = kind === "openai" ? openAiEffort(model, requested) : anthropicEffort(model, requested);
|
|
1458
|
+
const cap = providerId === void 0 ? void 0 : capped.get(`${providerId}/${model}`);
|
|
1459
|
+
return level && cap && RANK[level] > RANK[cap] ? cap : level;
|
|
1450
1460
|
}
|
|
1451
1461
|
function anthropicEffort(model, effort) {
|
|
1452
1462
|
if (!effort) return void 0;
|
|
@@ -2137,18 +2147,18 @@ function sleep(ms, signal) {
|
|
|
2137
2147
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
2138
2148
|
});
|
|
2139
2149
|
}
|
|
2150
|
+
var CHARS_PER_TOKEN = 4;
|
|
2140
2151
|
function estimateRequestTokens(cfg, messages) {
|
|
2141
2152
|
let characters3 = cfg.system.length;
|
|
2142
2153
|
try {
|
|
2143
2154
|
characters3 += JSON.stringify(
|
|
2144
2155
|
messages,
|
|
2145
|
-
(_key, value) => typeof value === "object" && value !== null && value.type === "image" ? `[image:${"#".repeat(
|
|
2156
|
+
(_key, value) => typeof value === "object" && value !== null && value.type === "image" ? `[image:${"#".repeat(6e3)}]` : value
|
|
2146
2157
|
).length;
|
|
2147
2158
|
characters3 += JSON.stringify(cfg.tools.schemas()).length;
|
|
2148
2159
|
} catch {
|
|
2149
|
-
return Math.max(1, characters3);
|
|
2150
2160
|
}
|
|
2151
|
-
return Math.max(1, characters3);
|
|
2161
|
+
return Math.max(1, Math.ceil(characters3 / CHARS_PER_TOKEN));
|
|
2152
2162
|
}
|
|
2153
2163
|
async function runToolCalls(cfg, content, hooks, signal) {
|
|
2154
2164
|
const calls = content.filter((block) => block.type === "tool_use");
|
|
@@ -3789,6 +3799,7 @@ function withoutThinkingReplay(history) {
|
|
|
3789
3799
|
});
|
|
3790
3800
|
return changed ? out : history;
|
|
3791
3801
|
}
|
|
3802
|
+
var CHARS_PER_TOKEN2 = 4;
|
|
3792
3803
|
function estimateHistoryTokens(history) {
|
|
3793
3804
|
let chars = 0;
|
|
3794
3805
|
for (const message of history) {
|
|
@@ -3800,7 +3811,7 @@ function estimateHistoryTokens(history) {
|
|
|
3800
3811
|
else if (block.type === "image") chars += 6e3;
|
|
3801
3812
|
}
|
|
3802
3813
|
}
|
|
3803
|
-
return Math.round(chars /
|
|
3814
|
+
return Math.round(chars / CHARS_PER_TOKEN2);
|
|
3804
3815
|
}
|
|
3805
3816
|
function shouldAutoCompact(used, window) {
|
|
3806
3817
|
return window !== null && window > 0 && used / window >= 0.8;
|
|
@@ -3820,7 +3831,9 @@ function estimateCompactBudget(history, maxTokens = MERGE_MAX_TOKENS) {
|
|
|
3820
3831
|
const rendered = renderedMessages.join("\n\n");
|
|
3821
3832
|
if (rendered.length <= SINGLE_REQUEST_MAX_CHARS) {
|
|
3822
3833
|
return {
|
|
3823
|
-
|
|
3834
|
+
// Tokens, not characters: counting characters made a turn budget refuse
|
|
3835
|
+
// compaction (four times too expensive) just when the window was full.
|
|
3836
|
+
inputTokens: Math.max(1, Math.ceil(rendered.length / CHARS_PER_TOKEN2) + 1e3),
|
|
3824
3837
|
maxOutputTokens: Math.max(1, Math.min(SINGLE_MAX_TOKENS, Math.floor(maxTokens)))
|
|
3825
3838
|
};
|
|
3826
3839
|
}
|
|
@@ -3838,7 +3851,7 @@ function estimateCompactBudget(history, maxTokens = MERGE_MAX_TOKENS) {
|
|
|
3838
3851
|
const intermediateOutput = chunks.length * chunkOutput + Math.max(0, mergeRequests - 1) * mergeOutput;
|
|
3839
3852
|
const requestCount = chunks.length + mergeRequests;
|
|
3840
3853
|
return {
|
|
3841
|
-
inputTokens: Math.max(1, chunkInput + intermediateOutput *
|
|
3854
|
+
inputTokens: Math.max(1, Math.ceil(chunkInput / CHARS_PER_TOKEN2) + intermediateOutput * 2 + requestCount * 1e3),
|
|
3842
3855
|
maxOutputTokens: totalOutput
|
|
3843
3856
|
};
|
|
3844
3857
|
}
|
|
@@ -4400,7 +4413,7 @@ function clip(value) {
|
|
|
4400
4413
|
// package.json
|
|
4401
4414
|
var package_default = {
|
|
4402
4415
|
name: "@kernelonpanic/kitcode",
|
|
4403
|
-
version: "1.4.
|
|
4416
|
+
version: "1.4.3",
|
|
4404
4417
|
description: "Terminal coding agent with a config you never have to write by hand",
|
|
4405
4418
|
type: "module",
|
|
4406
4419
|
license: "MIT",
|
|
@@ -4468,7 +4481,22 @@ var package_default = {
|
|
|
4468
4481
|
|
|
4469
4482
|
// src/version.ts
|
|
4470
4483
|
var KITCODE_VERSION = package_default.version;
|
|
4471
|
-
var KITCODE_COMMIT = true ? "
|
|
4484
|
+
var KITCODE_COMMIT = true ? "586eb4def64a8ef824bf2fe2f58a9f71e18090f0" : "development";
|
|
4485
|
+
function kitcodeUserAgent(sdkUserAgent2) {
|
|
4486
|
+
return `KitCode/${KITCODE_VERSION} ${sdkUserAgent2}`.trim();
|
|
4487
|
+
}
|
|
4488
|
+
function sdkUserAgent(client) {
|
|
4489
|
+
const read = client?.getUserAgent;
|
|
4490
|
+
try {
|
|
4491
|
+
return typeof read === "function" ? String(read.call(client)) : "";
|
|
4492
|
+
} catch {
|
|
4493
|
+
return "";
|
|
4494
|
+
}
|
|
4495
|
+
}
|
|
4496
|
+
function withKitcodeUserAgent(sdkUserAgent2, configured = {}) {
|
|
4497
|
+
const overridden = Object.keys(configured).some((name) => name.toLowerCase() === "user-agent");
|
|
4498
|
+
return overridden ? { ...configured } : { "User-Agent": kitcodeUserAgent(sdkUserAgent2), ...configured };
|
|
4499
|
+
}
|
|
4472
4500
|
|
|
4473
4501
|
// src/mcp/client.ts
|
|
4474
4502
|
var clientInfo = { name: "kitcode", version: KITCODE_VERSION };
|
|
@@ -5047,13 +5075,14 @@ var KNOWN_MODELS = [
|
|
|
5047
5075
|
knownModel("claude-fable-5", "Claude Fable 5", 1e6, 128e3)
|
|
5048
5076
|
];
|
|
5049
5077
|
function createAnthropicProvider(args) {
|
|
5050
|
-
const
|
|
5078
|
+
const options = {
|
|
5051
5079
|
apiKey: args.apiKey,
|
|
5052
5080
|
baseURL: args.baseUrl,
|
|
5053
|
-
defaultHeaders: args.headers,
|
|
5054
5081
|
maxRetries: MAX_RETRIES,
|
|
5055
5082
|
timeout: args.timeoutMs ?? REQUEST_TIMEOUT_MS
|
|
5056
|
-
}
|
|
5083
|
+
};
|
|
5084
|
+
const userAgent = sdkUserAgent(new Anthropic2(options));
|
|
5085
|
+
const client = new Anthropic2({ ...options, defaultHeaders: withKitcodeUserAgent(userAgent, args.headers) });
|
|
5057
5086
|
return {
|
|
5058
5087
|
id: args.id,
|
|
5059
5088
|
kind: "anthropic",
|
|
@@ -5062,7 +5091,35 @@ function createAnthropicProvider(args) {
|
|
|
5062
5091
|
knownModels: () => KNOWN_MODELS
|
|
5063
5092
|
};
|
|
5064
5093
|
}
|
|
5094
|
+
var thinkingRejected = /* @__PURE__ */ new Set();
|
|
5065
5095
|
async function* streamTurn(client, providerId, apiKey2, req) {
|
|
5096
|
+
const key = `${providerId}/${req.model}`;
|
|
5097
|
+
let thinking = req.thinking === true && !thinkingRejected.has(key);
|
|
5098
|
+
for (; ; ) {
|
|
5099
|
+
let streamed = false;
|
|
5100
|
+
try {
|
|
5101
|
+
for await (const event of streamOnce(client, providerId, apiKey2, req, thinking)) {
|
|
5102
|
+
if (event.type !== "rate_limits" && event.type !== "usage") streamed = true;
|
|
5103
|
+
yield event;
|
|
5104
|
+
}
|
|
5105
|
+
return;
|
|
5106
|
+
} catch (error) {
|
|
5107
|
+
if (!streamed && thinking && refusesThinking(error)) {
|
|
5108
|
+
thinkingRejected.add(key);
|
|
5109
|
+
thinking = false;
|
|
5110
|
+
continue;
|
|
5111
|
+
}
|
|
5112
|
+
throw error;
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5115
|
+
}
|
|
5116
|
+
function refusesThinking(error) {
|
|
5117
|
+
if (!(error instanceof ProviderError)) return false;
|
|
5118
|
+
if (error.status !== void 0 && error.status !== 400 && error.status !== 422) return false;
|
|
5119
|
+
const cause = error.cause instanceof Error ? error.cause.message : "";
|
|
5120
|
+
return /thinking|budget_tokens|adaptive/i.test(`${error.message} ${cause}`);
|
|
5121
|
+
}
|
|
5122
|
+
async function* streamOnce(client, providerId, apiKey2, req, thinkingOn) {
|
|
5066
5123
|
const params = {
|
|
5067
5124
|
model: req.model,
|
|
5068
5125
|
max_tokens: req.maxTokens,
|
|
@@ -5070,7 +5127,7 @@ async function* streamTurn(client, providerId, apiKey2, req) {
|
|
|
5070
5127
|
messages: toMessageParams(req.messages),
|
|
5071
5128
|
tools: toToolParams(req.tools)
|
|
5072
5129
|
};
|
|
5073
|
-
if (
|
|
5130
|
+
if (thinkingOn) {
|
|
5074
5131
|
const thinking2 = thinkingParam(req.model, req.maxTokens);
|
|
5075
5132
|
if (thinking2) params.thinking = thinking2;
|
|
5076
5133
|
}
|
|
@@ -5232,7 +5289,7 @@ var THINKING_BUDGET = 16e3;
|
|
|
5232
5289
|
var MIN_THINKING_BUDGET = 1024;
|
|
5233
5290
|
function thinkingParam(model, maxTokens) {
|
|
5234
5291
|
const id = (model.split("/").at(-1) ?? model).replace(/^(?:[a-z]{2}\.)?anthropic\./, "");
|
|
5235
|
-
if (!BUDGET_THINKING.test(id)) return { type: "adaptive", display: "summarized" };
|
|
5292
|
+
if (id.startsWith("claude-") && !BUDGET_THINKING.test(id)) return { type: "adaptive", display: "summarized" };
|
|
5236
5293
|
const budget = Math.min(THINKING_BUDGET, maxTokens - 1);
|
|
5237
5294
|
return budget >= MIN_THINKING_BUDGET ? { type: "enabled", budget_tokens: budget } : void 0;
|
|
5238
5295
|
}
|
|
@@ -5252,13 +5309,14 @@ var FINISH_REASONS = {
|
|
|
5252
5309
|
content_filter: "refusal"
|
|
5253
5310
|
};
|
|
5254
5311
|
function createOpenAiProvider(args) {
|
|
5255
|
-
const
|
|
5312
|
+
const options = {
|
|
5256
5313
|
baseURL: args.baseUrl,
|
|
5257
5314
|
apiKey: args.apiKey,
|
|
5258
|
-
defaultHeaders: args.headers,
|
|
5259
5315
|
maxRetries: MAX_RETRIES,
|
|
5260
5316
|
timeout: args.timeoutMs ?? REQUEST_TIMEOUT_MS
|
|
5261
|
-
}
|
|
5317
|
+
};
|
|
5318
|
+
const userAgent = sdkUserAgent(new OpenAI2(options));
|
|
5319
|
+
const client = new OpenAI2({ ...options, defaultHeaders: withKitcodeUserAgent(userAgent, args.headers) });
|
|
5262
5320
|
return {
|
|
5263
5321
|
id: args.id,
|
|
5264
5322
|
kind: "openai",
|
|
@@ -5275,7 +5333,7 @@ async function* streamTurn2(client, providerId, apiKey2, req) {
|
|
|
5275
5333
|
for (; ; ) {
|
|
5276
5334
|
let streamed = false;
|
|
5277
5335
|
try {
|
|
5278
|
-
for await (const event of
|
|
5336
|
+
for await (const event of streamOnce2(client, providerId, apiKey2, req, effort, thinkingOff, tokenField)) {
|
|
5279
5337
|
if (event.type !== "rate_limits" && event.type !== "usage") streamed = true;
|
|
5280
5338
|
yield event;
|
|
5281
5339
|
}
|
|
@@ -5288,8 +5346,14 @@ async function* streamTurn2(client, providerId, apiKey2, req) {
|
|
|
5288
5346
|
continue;
|
|
5289
5347
|
}
|
|
5290
5348
|
if (effort && rejectsField(error, /reasoning|effort/i)) {
|
|
5291
|
-
|
|
5292
|
-
|
|
5349
|
+
const lower = effort === "xhigh" || effort === "max" ? "high" : effort === "high" ? "medium" : void 0;
|
|
5350
|
+
if (lower) {
|
|
5351
|
+
markEffortCapped(providerId, req.model, lower);
|
|
5352
|
+
effort = lower;
|
|
5353
|
+
} else {
|
|
5354
|
+
markEffortRejected(providerId, req.model);
|
|
5355
|
+
effort = void 0;
|
|
5356
|
+
}
|
|
5293
5357
|
continue;
|
|
5294
5358
|
}
|
|
5295
5359
|
if (thinkingOff && rejectsField(error, /thinking/i)) {
|
|
@@ -5314,11 +5378,12 @@ function thinkingOffParams(model) {
|
|
|
5314
5378
|
return void 0;
|
|
5315
5379
|
}
|
|
5316
5380
|
function rejectsField(error, field2) {
|
|
5317
|
-
if (!(error instanceof ProviderError)
|
|
5381
|
+
if (!(error instanceof ProviderError)) return false;
|
|
5382
|
+
if (error.status !== void 0 && error.status !== 400 && error.status !== 422) return false;
|
|
5318
5383
|
const cause = error.cause instanceof Error ? error.cause.message : "";
|
|
5319
5384
|
return field2.test(`${error.message} ${cause}`);
|
|
5320
5385
|
}
|
|
5321
|
-
async function*
|
|
5386
|
+
async function* streamOnce2(client, providerId, apiKey2, req, effort, thinkingOff, tokenField) {
|
|
5322
5387
|
let text = "";
|
|
5323
5388
|
let thinking = "";
|
|
5324
5389
|
let finishReason = null;
|
|
@@ -8041,7 +8106,7 @@ ${recovered.removed === 1 ? "The image was" : `${recovered.removed} images were`
|
|
|
8041
8106
|
}
|
|
8042
8107
|
function imageRejection(error, history) {
|
|
8043
8108
|
const status = error?.status;
|
|
8044
|
-
if (typeof status !== "number" || ![400, 413, 415, 422].includes(status)) return null;
|
|
8109
|
+
if (status !== void 0 && (typeof status !== "number" || ![400, 413, 415, 422].includes(status))) return null;
|
|
8045
8110
|
const message = error instanceof Error ? error.message : String(error);
|
|
8046
8111
|
if (status !== 413 && !/image|vision|multi-?modal/i.test(message)) return null;
|
|
8047
8112
|
const result = withoutImages(history);
|
|
@@ -8387,7 +8452,7 @@ function splitCommandLine(raw) {
|
|
|
8387
8452
|
}
|
|
8388
8453
|
|
|
8389
8454
|
// src/ui/speed.ts
|
|
8390
|
-
var
|
|
8455
|
+
var CHARS_PER_TOKEN3 = 4;
|
|
8391
8456
|
var MIN_LIVE_MS = 1e3;
|
|
8392
8457
|
function createSpeedMeter() {
|
|
8393
8458
|
return { streamedChars: 0, firstTokenAt: null, last: null };
|
|
@@ -8414,7 +8479,7 @@ function readSpeed(meter, busy, now = Date.now()) {
|
|
|
8414
8479
|
if (busy && meter.firstTokenAt !== null && meter.streamedChars > 0) {
|
|
8415
8480
|
const ms = now - meter.firstTokenAt;
|
|
8416
8481
|
if (ms >= MIN_LIVE_MS) {
|
|
8417
|
-
return { tokensPerSecond: meter.streamedChars /
|
|
8482
|
+
return { tokensPerSecond: meter.streamedChars / CHARS_PER_TOKEN3 / (ms / 1e3), live: true };
|
|
8418
8483
|
}
|
|
8419
8484
|
}
|
|
8420
8485
|
return meter.last === null || !Number.isFinite(meter.last) ? null : { tokensPerSecond: meter.last, live: false };
|