autopilot-ai 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -8
- package/dist/index.js +2340 -2731
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.d.ts +16 -3
- package/dist/sdk/index.js +323 -71
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
package/dist/sdk/index.js
CHANGED
|
@@ -2023,7 +2023,6 @@ async function loadConfig() {
|
|
|
2023
2023
|
lspServers: persisted.lspServers,
|
|
2024
2024
|
costAttribution: readBooleanEnv("KIMI_COST_ATTRIBUTION") ?? persisted.costAttribution ?? true,
|
|
2025
2025
|
filePicker: readBooleanEnv("KIMIFLARE_FILE_PICKER") ?? persisted.filePicker ?? true,
|
|
2026
|
-
theme: persisted.theme,
|
|
2027
2026
|
shell: process.env.KIMIFLARE_SHELL ?? persisted.shell,
|
|
2028
2027
|
remoteWorkerUrl: persisted.remoteWorkerUrl,
|
|
2029
2028
|
remoteAuthSecret: persisted.remoteAuthSecret,
|
|
@@ -3176,6 +3175,146 @@ var init_redact = __esm({
|
|
|
3176
3175
|
}
|
|
3177
3176
|
});
|
|
3178
3177
|
|
|
3178
|
+
// src/util/line-diff.ts
|
|
3179
|
+
function splitLines(text3) {
|
|
3180
|
+
if (text3 === "") return [];
|
|
3181
|
+
const lines = text3.split("\n");
|
|
3182
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
3183
|
+
return lines;
|
|
3184
|
+
}
|
|
3185
|
+
function myers(a, b) {
|
|
3186
|
+
const n = a.length;
|
|
3187
|
+
const m = b.length;
|
|
3188
|
+
const max = n + m;
|
|
3189
|
+
if (max === 0) return [];
|
|
3190
|
+
const offset = max;
|
|
3191
|
+
let v = new Int32Array(2 * max + 2);
|
|
3192
|
+
const trace = [];
|
|
3193
|
+
for (let d = 0; d <= max; d++) {
|
|
3194
|
+
if ((n + m) * d > MAX_MYERS_COST) return null;
|
|
3195
|
+
trace.push(v.slice());
|
|
3196
|
+
const next = v;
|
|
3197
|
+
for (let k = -d; k <= d; k += 2) {
|
|
3198
|
+
let x;
|
|
3199
|
+
if (k === -d || k !== d && next[offset + k - 1] < next[offset + k + 1]) x = next[offset + k + 1];
|
|
3200
|
+
else x = next[offset + k - 1] + 1;
|
|
3201
|
+
let y = x - k;
|
|
3202
|
+
while (x < n && y < m && a[x] === b[y]) {
|
|
3203
|
+
x++;
|
|
3204
|
+
y++;
|
|
3205
|
+
}
|
|
3206
|
+
next[offset + k] = x;
|
|
3207
|
+
if (x >= n && y >= m) {
|
|
3208
|
+
trace.push(next.slice());
|
|
3209
|
+
return backtrack(trace, a, b, offset);
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
v = next;
|
|
3213
|
+
}
|
|
3214
|
+
return null;
|
|
3215
|
+
}
|
|
3216
|
+
function backtrack(trace, a, b, offset) {
|
|
3217
|
+
const ops = [];
|
|
3218
|
+
let x = a.length;
|
|
3219
|
+
let y = b.length;
|
|
3220
|
+
for (let d = trace.length - 2; d >= 0; d--) {
|
|
3221
|
+
const v = trace[d];
|
|
3222
|
+
const k = x - y;
|
|
3223
|
+
let prevK;
|
|
3224
|
+
if (k === -d || k !== d && v[offset + k - 1] < v[offset + k + 1]) prevK = k + 1;
|
|
3225
|
+
else prevK = k - 1;
|
|
3226
|
+
const prevX = d === 0 ? 0 : v[offset + prevK];
|
|
3227
|
+
const prevY = prevX - prevK;
|
|
3228
|
+
while (x > prevX && y > prevY) {
|
|
3229
|
+
ops.push({ kind: " ", text: a[x - 1] });
|
|
3230
|
+
x--;
|
|
3231
|
+
y--;
|
|
3232
|
+
}
|
|
3233
|
+
if (d === 0) break;
|
|
3234
|
+
if (x === prevX) ops.push({ kind: "+", text: b[y - 1] });
|
|
3235
|
+
else ops.push({ kind: "-", text: a[x - 1] });
|
|
3236
|
+
x = prevX;
|
|
3237
|
+
y = prevY;
|
|
3238
|
+
}
|
|
3239
|
+
while (x > 0 && y > 0) {
|
|
3240
|
+
ops.push({ kind: " ", text: a[x - 1] });
|
|
3241
|
+
x--;
|
|
3242
|
+
y--;
|
|
3243
|
+
}
|
|
3244
|
+
return ops.reverse();
|
|
3245
|
+
}
|
|
3246
|
+
function editScript(a, b) {
|
|
3247
|
+
let pre = 0;
|
|
3248
|
+
while (pre < a.length && pre < b.length && a[pre] === b[pre]) pre++;
|
|
3249
|
+
let suf = 0;
|
|
3250
|
+
while (suf < a.length - pre && suf < b.length - pre && a[a.length - 1 - suf] === b[b.length - 1 - suf]) suf++;
|
|
3251
|
+
const midA = a.slice(pre, a.length - suf);
|
|
3252
|
+
const midB = b.slice(pre, b.length - suf);
|
|
3253
|
+
const mid = myers(midA, midB) ?? [
|
|
3254
|
+
...midA.map((text3) => ({ kind: "-", text: text3 })),
|
|
3255
|
+
...midB.map((text3) => ({ kind: "+", text: text3 }))
|
|
3256
|
+
];
|
|
3257
|
+
return [
|
|
3258
|
+
...a.slice(0, pre).map((text3) => ({ kind: " ", text: text3 })),
|
|
3259
|
+
...mid,
|
|
3260
|
+
...a.slice(a.length - suf).map((text3) => ({ kind: " ", text: text3 }))
|
|
3261
|
+
];
|
|
3262
|
+
}
|
|
3263
|
+
function structuredPatch(oldText, newText, context = DEFAULT_CONTEXT) {
|
|
3264
|
+
const ops = editScript(splitLines(oldText), splitLines(newText));
|
|
3265
|
+
const hunks = [];
|
|
3266
|
+
let oldNo = 1;
|
|
3267
|
+
let newNo = 1;
|
|
3268
|
+
const pos = ops.map((op) => {
|
|
3269
|
+
const at = { old: oldNo, new: newNo };
|
|
3270
|
+
if (op.kind !== "+") oldNo++;
|
|
3271
|
+
if (op.kind !== "-") newNo++;
|
|
3272
|
+
return at;
|
|
3273
|
+
});
|
|
3274
|
+
let i = 0;
|
|
3275
|
+
while (i < ops.length) {
|
|
3276
|
+
if (ops[i].kind === " ") {
|
|
3277
|
+
i++;
|
|
3278
|
+
continue;
|
|
3279
|
+
}
|
|
3280
|
+
const start = Math.max(0, i - context);
|
|
3281
|
+
let end = i;
|
|
3282
|
+
for (; ; ) {
|
|
3283
|
+
while (end < ops.length && ops[end].kind !== " ") end++;
|
|
3284
|
+
let gap = end;
|
|
3285
|
+
while (gap < ops.length && ops[gap].kind === " ") gap++;
|
|
3286
|
+
if (gap < ops.length && gap - end <= 2 * context) {
|
|
3287
|
+
end = gap;
|
|
3288
|
+
continue;
|
|
3289
|
+
}
|
|
3290
|
+
end = Math.min(ops.length, end + context);
|
|
3291
|
+
break;
|
|
3292
|
+
}
|
|
3293
|
+
const slice = ops.slice(start, end);
|
|
3294
|
+
const oldLines = slice.filter((o) => o.kind !== "+").length;
|
|
3295
|
+
const newLines = slice.filter((o) => o.kind !== "-").length;
|
|
3296
|
+
const first = pos[start];
|
|
3297
|
+
hunks.push({
|
|
3298
|
+
// jsdiff's convention: a hunk with no old (or new) lines starts one line earlier.
|
|
3299
|
+
oldStart: oldLines === 0 ? first.old - 1 : first.old,
|
|
3300
|
+
oldLines,
|
|
3301
|
+
newStart: newLines === 0 ? first.new - 1 : first.new,
|
|
3302
|
+
newLines,
|
|
3303
|
+
lines: slice.map((o) => o.kind + o.text)
|
|
3304
|
+
});
|
|
3305
|
+
i = end;
|
|
3306
|
+
}
|
|
3307
|
+
return hunks;
|
|
3308
|
+
}
|
|
3309
|
+
var DEFAULT_CONTEXT, MAX_MYERS_COST;
|
|
3310
|
+
var init_line_diff = __esm({
|
|
3311
|
+
"src/util/line-diff.ts"() {
|
|
3312
|
+
"use strict";
|
|
3313
|
+
DEFAULT_CONTEXT = 3;
|
|
3314
|
+
MAX_MYERS_COST = 4e6;
|
|
3315
|
+
}
|
|
3316
|
+
});
|
|
3317
|
+
|
|
3179
3318
|
// src/hooks/claude-compat.ts
|
|
3180
3319
|
function claudeToolName(tool, args) {
|
|
3181
3320
|
if (tool === "edit" && Array.isArray(args.edits)) return "MultiEdit";
|
|
@@ -3260,9 +3399,35 @@ function claudeToolResponse(tool, args, cwd, result2) {
|
|
|
3260
3399
|
}
|
|
3261
3400
|
if ((tool === "write" || tool === "edit") && isStr(args.path) && !failed) {
|
|
3262
3401
|
response.filePath = resolvePath(cwd, args.path);
|
|
3402
|
+
if (result2.fileChange) Object.assign(response, claudeFileChangeFields(tool, args, result2.fileChange));
|
|
3263
3403
|
}
|
|
3264
3404
|
return response;
|
|
3265
3405
|
}
|
|
3406
|
+
function claudeFileChangeFields(tool, args, change) {
|
|
3407
|
+
const fields = {};
|
|
3408
|
+
if (tool === "write") {
|
|
3409
|
+
fields.type = change.existed ? "update" : "create";
|
|
3410
|
+
if (isStr(args.content)) fields.content = args.content;
|
|
3411
|
+
} else if (Array.isArray(args.edits)) {
|
|
3412
|
+
fields.edits = editPairs(args);
|
|
3413
|
+
} else {
|
|
3414
|
+
fields.oldString = args.old_string;
|
|
3415
|
+
fields.newString = args.new_string;
|
|
3416
|
+
fields.replaceAll = args.replace_all === true;
|
|
3417
|
+
}
|
|
3418
|
+
if (!change.existed) {
|
|
3419
|
+
fields.originalFile = null;
|
|
3420
|
+
fields.structuredPatch = [];
|
|
3421
|
+
} else {
|
|
3422
|
+
if (change.original !== null && Buffer.byteLength(change.original, "utf8") <= ORIGINAL_FILE_CAP_BYTES) {
|
|
3423
|
+
fields.originalFile = change.original;
|
|
3424
|
+
}
|
|
3425
|
+
if (change.original !== null && change.updated !== null) {
|
|
3426
|
+
fields.structuredPatch = structuredPatch(change.original, change.updated);
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
return fields;
|
|
3430
|
+
}
|
|
3266
3431
|
function claudeError(result2) {
|
|
3267
3432
|
if (isNum(result2.exitCode) && result2.exitCode !== 0) {
|
|
3268
3433
|
const output = [result2.stdout, result2.stderr].filter((s) => s && s.trim()).map((s) => s.trimEnd()).join("\n");
|
|
@@ -3295,12 +3460,13 @@ function claudeToolFields(payload) {
|
|
|
3295
3460
|
}
|
|
3296
3461
|
return { tool_name: toolName, ...fields };
|
|
3297
3462
|
}
|
|
3298
|
-
var CLAUDE_TOOL_NAMES, FILE_EDIT_NAMES, isStr, isNum;
|
|
3463
|
+
var CLAUDE_TOOL_NAMES, FILE_EDIT_NAMES, isStr, isNum, ORIGINAL_FILE_CAP_BYTES;
|
|
3299
3464
|
var init_claude_compat = __esm({
|
|
3300
3465
|
"src/hooks/claude-compat.ts"() {
|
|
3301
3466
|
"use strict";
|
|
3302
3467
|
init_edit();
|
|
3303
3468
|
init_paths();
|
|
3469
|
+
init_line_diff();
|
|
3304
3470
|
CLAUDE_TOOL_NAMES = {
|
|
3305
3471
|
bash: "Bash",
|
|
3306
3472
|
edit: "Edit",
|
|
@@ -3315,6 +3481,7 @@ var init_claude_compat = __esm({
|
|
|
3315
3481
|
FILE_EDIT_NAMES = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit"]);
|
|
3316
3482
|
isStr = (v) => typeof v === "string";
|
|
3317
3483
|
isNum = (v) => typeof v === "number";
|
|
3484
|
+
ORIGINAL_FILE_CAP_BYTES = 256 * 1024;
|
|
3318
3485
|
}
|
|
3319
3486
|
});
|
|
3320
3487
|
|
|
@@ -3921,6 +4088,10 @@ function hookWirePayload(payload) {
|
|
|
3921
4088
|
if (payload.session_id) Object.assign(wire, hookTranscriptFields(payload.session_id));
|
|
3922
4089
|
if (isToolEventPayload(payload)) {
|
|
3923
4090
|
Object.assign(wire, claudeToolFields(payload));
|
|
4091
|
+
if ((payload.event === "PostToolUse" || payload.event === "PostToolUseFailure") && payload.result.fileChange) {
|
|
4092
|
+
const { fileChange: _fileChange, ...result2 } = payload.result;
|
|
4093
|
+
wire.result = result2;
|
|
4094
|
+
}
|
|
3924
4095
|
if (payload.tool_call_id) wire.tool_use_id = payload.tool_call_id;
|
|
3925
4096
|
if (payload.event === "PermissionRequest") wire.permission_mode = claudePermissionMode(payload.mode);
|
|
3926
4097
|
}
|
|
@@ -4743,7 +4914,7 @@ __export(openrouter_catalog_exports, {
|
|
|
4743
4914
|
loadOpenRouterCatalog: () => loadOpenRouterCatalog,
|
|
4744
4915
|
mapOpenRouterModel: () => mapOpenRouterModel
|
|
4745
4916
|
});
|
|
4746
|
-
import { readFile as
|
|
4917
|
+
import { readFile as readFile17, writeFile as writeFile9, mkdir as mkdir10 } from "fs/promises";
|
|
4747
4918
|
import { homedir as homedir17 } from "os";
|
|
4748
4919
|
import { join as join29, dirname as dirname14 } from "path";
|
|
4749
4920
|
function catalogCachePath() {
|
|
@@ -4799,7 +4970,7 @@ async function fetchOpenRouterCatalog(fetchImpl2 = fetch) {
|
|
|
4799
4970
|
}
|
|
4800
4971
|
async function readCache2() {
|
|
4801
4972
|
try {
|
|
4802
|
-
const raw = await
|
|
4973
|
+
const raw = await readFile17(catalogCachePath(), "utf8");
|
|
4803
4974
|
const parsed = JSON.parse(raw);
|
|
4804
4975
|
return parsed.version === CACHE_VERSION ? parsed : null;
|
|
4805
4976
|
} catch {
|
|
@@ -4858,7 +5029,7 @@ __export(requesty_catalog_exports, {
|
|
|
4858
5029
|
loadRequestyCatalog: () => loadRequestyCatalog,
|
|
4859
5030
|
mapRequestyModel: () => mapRequestyModel
|
|
4860
5031
|
});
|
|
4861
|
-
import { readFile as
|
|
5032
|
+
import { readFile as readFile18, writeFile as writeFile10, mkdir as mkdir11 } from "fs/promises";
|
|
4862
5033
|
import { homedir as homedir18 } from "os";
|
|
4863
5034
|
import { join as join30, dirname as dirname15 } from "path";
|
|
4864
5035
|
function catalogCachePath2() {
|
|
@@ -4919,7 +5090,7 @@ async function fetchRequestyCatalog(fetchImpl2 = fetch) {
|
|
|
4919
5090
|
}
|
|
4920
5091
|
async function readCache3() {
|
|
4921
5092
|
try {
|
|
4922
|
-
const raw = await
|
|
5093
|
+
const raw = await readFile18(catalogCachePath2(), "utf8");
|
|
4923
5094
|
const parsed = JSON.parse(raw);
|
|
4924
5095
|
if (parsed.version !== CACHE_VERSION2) return null;
|
|
4925
5096
|
return {
|
|
@@ -4997,7 +5168,7 @@ __export(provider_catalog_exports, {
|
|
|
4997
5168
|
mapModelsDevModel: () => mapModelsDevModel,
|
|
4998
5169
|
mapModelsDevProvider: () => mapModelsDevProvider
|
|
4999
5170
|
});
|
|
5000
|
-
import { readFile as
|
|
5171
|
+
import { readFile as readFile19, writeFile as writeFile11, mkdir as mkdir12 } from "fs/promises";
|
|
5001
5172
|
import { homedir as homedir19 } from "os";
|
|
5002
5173
|
import { join as join31, dirname as dirname16 } from "path";
|
|
5003
5174
|
function mapModelsDevModel(m) {
|
|
@@ -5037,7 +5208,7 @@ function cachePath() {
|
|
|
5037
5208
|
}
|
|
5038
5209
|
async function readCache4() {
|
|
5039
5210
|
try {
|
|
5040
|
-
const parsed = JSON.parse(await
|
|
5211
|
+
const parsed = JSON.parse(await readFile19(cachePath(), "utf8"));
|
|
5041
5212
|
return parsed.version === CACHE_VERSION3 ? parsed : null;
|
|
5042
5213
|
} catch {
|
|
5043
5214
|
return null;
|
|
@@ -5413,6 +5584,89 @@ async function endSessions(reason = "exit", timeoutMs = 3e3) {
|
|
|
5413
5584
|
await Promise.all([...[...started.keys()].map((id) => endSession(id, reason, timeoutMs)), ...ending]);
|
|
5414
5585
|
}
|
|
5415
5586
|
|
|
5587
|
+
// src/intent/classify.ts
|
|
5588
|
+
var INTENT_PATTERNS = {
|
|
5589
|
+
qa: /\b(what|how|why|explain|describe|what's|what is)\b/i,
|
|
5590
|
+
diagnose: /\b(broken|failing|error|bug|crash|why.*fail|not working)\b/i,
|
|
5591
|
+
verify: /\b(correct|right|verify|review|check|is this|does this)\b/i,
|
|
5592
|
+
polish: /\b(rename|refactor|extract|move|clean|lint|format)\b/i,
|
|
5593
|
+
small_edit: /\b(add|change|update|fix|remove|delete)\b.+\b(line|here|this|variable|function)\b/i,
|
|
5594
|
+
feature_bounded: /\b(add|implement|create|support)\b.+\b(flag|option|param|arg|field)\b/i,
|
|
5595
|
+
feature_exploratory: /\b(add|implement|migrate|integrate|build)\b.+\b(module|system|auth|oauth|framework|service)\b/i,
|
|
5596
|
+
explore: /\b(how.*work|architecture|structure|where.*used|find.*all|understand)\b/i,
|
|
5597
|
+
meta: /\b(plan|design|strategy|ontology|roadmap|approach)\b/i
|
|
5598
|
+
};
|
|
5599
|
+
var HEAVY_SIGNAL = /\b(research|investigat\w*|audit|deep[\s-]?(dive|thinking)|explorat\w*|comprehensive|end[\s-]?to[\s-]?end|entire\s+(code\s?base|repo\w*|project|app)|whole\s+(code\s?base|repo\w*|project|app)|across\s+the\s+(code\s?base|repo\w*|project)|security|vulnerab\w*|loophole|exploit\w*|threat\s?model|attack\s+surface|penetration)\b/i;
|
|
5600
|
+
function classifyIntent(prompt) {
|
|
5601
|
+
let intentScore = 0;
|
|
5602
|
+
let matchedIntent = "other";
|
|
5603
|
+
for (const [intent, pattern] of Object.entries(INTENT_PATTERNS)) {
|
|
5604
|
+
const matches = (prompt.match(pattern) || []).length;
|
|
5605
|
+
if (matches > intentScore) {
|
|
5606
|
+
intentScore = matches;
|
|
5607
|
+
matchedIntent = intent;
|
|
5608
|
+
}
|
|
5609
|
+
}
|
|
5610
|
+
const hasFileMentions = (prompt.match(/@\w+|\b[\w/-]+\.(ts|tsx|js|jsx|py|go|rs)\b/g) || []).length;
|
|
5611
|
+
const hasMutatingVerb = /\b(add|create|write|edit|delete|remove|rename|migrate|implement)\b/i.test(prompt);
|
|
5612
|
+
const isQuestion = prompt.trim().endsWith("?") || /\b(what|how|why|is|does|can)\b/i.test(prompt.split(" ")[0] || "");
|
|
5613
|
+
const hasHeavySignal = HEAVY_SIGNAL.test(prompt);
|
|
5614
|
+
const rawScore = Math.min(
|
|
5615
|
+
1,
|
|
5616
|
+
intentScore * 0.25 + (hasFileMentions > 2 ? 0.3 : hasFileMentions * 0.1) + (hasMutatingVerb ? 0.25 : 0) + (isQuestion ? 0 : 0.1) + (hasHeavySignal ? 0.6 : 0)
|
|
5617
|
+
);
|
|
5618
|
+
const tier = rawScore < 0.3 ? "light" : rawScore < 0.65 ? "medium" : "heavy";
|
|
5619
|
+
return {
|
|
5620
|
+
intent: hasHeavySignal && matchedIntent === "other" ? "explore" : matchedIntent,
|
|
5621
|
+
rawScore,
|
|
5622
|
+
tier,
|
|
5623
|
+
confidence: 0.5 + (intentScore > 0 || hasHeavySignal ? 0.3 : 0) + (hasFileMentions > 0 ? 0.1 : 0)
|
|
5624
|
+
};
|
|
5625
|
+
}
|
|
5626
|
+
|
|
5627
|
+
// src/hooks/prompt-submit.ts
|
|
5628
|
+
init_llm_auth();
|
|
5629
|
+
var PROMPT_BLOCKED_DEFAULT_REASON = "UserPromptSubmit hook blocked the prompt";
|
|
5630
|
+
var PromptBlockedError = class extends Error {
|
|
5631
|
+
reason;
|
|
5632
|
+
code = "prompt_blocked";
|
|
5633
|
+
constructor(reason) {
|
|
5634
|
+
super(`prompt blocked by a UserPromptSubmit hook: ${reason}`);
|
|
5635
|
+
this.name = "PromptBlockedError";
|
|
5636
|
+
this.reason = reason;
|
|
5637
|
+
}
|
|
5638
|
+
};
|
|
5639
|
+
async function submitUserPrompt(info) {
|
|
5640
|
+
let provider;
|
|
5641
|
+
try {
|
|
5642
|
+
provider = info.auth ? providerPresetOf(info.auth).id : void 0;
|
|
5643
|
+
} catch {
|
|
5644
|
+
provider = void 0;
|
|
5645
|
+
}
|
|
5646
|
+
await noteSessionStart({
|
|
5647
|
+
...info.hooks ? { hooks: info.hooks } : {},
|
|
5648
|
+
sessionId: info.sessionId,
|
|
5649
|
+
cwd: info.cwd,
|
|
5650
|
+
resumed: info.resumed,
|
|
5651
|
+
model: info.model,
|
|
5652
|
+
...provider ? { provider } : {}
|
|
5653
|
+
});
|
|
5654
|
+
if (!info.hooks?.hasEnabledHooks("UserPromptSubmit")) return { blocked: false };
|
|
5655
|
+
const outcome = await info.hooks.fire(
|
|
5656
|
+
"UserPromptSubmit",
|
|
5657
|
+
{
|
|
5658
|
+
event: "UserPromptSubmit",
|
|
5659
|
+
session_id: info.sessionId,
|
|
5660
|
+
cwd: info.cwd,
|
|
5661
|
+
prompt: info.prompt,
|
|
5662
|
+
tier: info.tier ?? classifyIntent(info.prompt).tier
|
|
5663
|
+
},
|
|
5664
|
+
null
|
|
5665
|
+
);
|
|
5666
|
+
if (!outcome.vetoed) return { blocked: false };
|
|
5667
|
+
return { blocked: true, reason: outcome.vetoReason || PROMPT_BLOCKED_DEFAULT_REASON };
|
|
5668
|
+
}
|
|
5669
|
+
|
|
5416
5670
|
// src/sdk/process-exit.ts
|
|
5417
5671
|
init_otel_sink();
|
|
5418
5672
|
init_logger();
|
|
@@ -9186,15 +9440,15 @@ async function gitNumstat(cwd, opts = {}) {
|
|
|
9186
9440
|
if (opts.includeUntracked) {
|
|
9187
9441
|
try {
|
|
9188
9442
|
const { stdout } = await execFileAsync("git", ["ls-files", "--others", "--exclude-standard"], { cwd, timeout: 5e3 });
|
|
9189
|
-
const { readFile:
|
|
9443
|
+
const { readFile: readFile21, stat: stat9 } = await import("fs/promises");
|
|
9190
9444
|
const { join: join36 } = await import("path");
|
|
9191
9445
|
for (const file of stdout.split("\n").filter(Boolean)) {
|
|
9192
9446
|
let lines = 0;
|
|
9193
9447
|
try {
|
|
9194
9448
|
const path = join36(cwd, file);
|
|
9195
|
-
const size = (await
|
|
9449
|
+
const size = (await stat9(path)).size;
|
|
9196
9450
|
if (size > 0 && size <= 1024 * 1024) {
|
|
9197
|
-
const text3 = await
|
|
9451
|
+
const text3 = await readFile21(path, "utf8");
|
|
9198
9452
|
lines = text3.split("\n").length - (text3.endsWith("\n") ? 1 : 0);
|
|
9199
9453
|
}
|
|
9200
9454
|
} catch {
|
|
@@ -14613,8 +14867,8 @@ function waitForProcessStartTime(pid, jobId, exitPath) {
|
|
|
14613
14867
|
function readProcessStartTime(pid) {
|
|
14614
14868
|
if (process.platform === "linux") {
|
|
14615
14869
|
try {
|
|
14616
|
-
const
|
|
14617
|
-
const fieldsAfterCommand =
|
|
14870
|
+
const stat9 = readFileSync6(`/proc/${pid}/stat`, "utf8");
|
|
14871
|
+
const fieldsAfterCommand = stat9.slice(stat9.lastIndexOf(")") + 1).trim().split(/\s+/);
|
|
14618
14872
|
return fieldsAfterCommand[19] ? `linux:${fieldsAfterCommand[19]}` : null;
|
|
14619
14873
|
} catch {
|
|
14620
14874
|
return null;
|
|
@@ -15485,7 +15739,8 @@ var waitForTool = {
|
|
|
15485
15739
|
};
|
|
15486
15740
|
|
|
15487
15741
|
// src/tools/executor.ts
|
|
15488
|
-
|
|
15742
|
+
init_paths();
|
|
15743
|
+
import { readFile as readFile15, realpath as realpath4, stat as stat6 } from "fs/promises";
|
|
15489
15744
|
import { isAbsolute as isAbsolute3, relative as relative4, resolve as resolve5, sep as sep3 } from "path";
|
|
15490
15745
|
var ALL_TOOLS = [
|
|
15491
15746
|
{ ...readTool, isReadOnly: true },
|
|
@@ -15538,6 +15793,17 @@ function toPermissionResult(d) {
|
|
|
15538
15793
|
return d;
|
|
15539
15794
|
}
|
|
15540
15795
|
var HOOK_RESULT_CONTENT_CAP_BYTES = 4 * 1024;
|
|
15796
|
+
var HOOK_FILE_SNAPSHOT_MAX_BYTES = 1024 * 1024;
|
|
15797
|
+
async function snapshotForHook(abs) {
|
|
15798
|
+
try {
|
|
15799
|
+
const st = await stat6(abs);
|
|
15800
|
+
if (!st.isFile()) return { existed: true, content: null };
|
|
15801
|
+
if (st.size > HOOK_FILE_SNAPSHOT_MAX_BYTES) return { existed: true, content: null };
|
|
15802
|
+
return { existed: true, content: await readFile15(abs, "utf8") };
|
|
15803
|
+
} catch {
|
|
15804
|
+
return { existed: false, content: null };
|
|
15805
|
+
}
|
|
15806
|
+
}
|
|
15541
15807
|
function shellResultForHook(meta) {
|
|
15542
15808
|
if (!meta || meta.exitCode === void 0) return {};
|
|
15543
15809
|
return {
|
|
@@ -15556,6 +15822,15 @@ function capContentForHook(s) {
|
|
|
15556
15822
|
return `${cut}
|
|
15557
15823
|
[\u2026truncated for hook payload]`;
|
|
15558
15824
|
}
|
|
15825
|
+
async function fileChangeAfter(tool, args, cwd, before) {
|
|
15826
|
+
let updated = null;
|
|
15827
|
+
if (tool === "write" && typeof args.content === "string") {
|
|
15828
|
+
updated = Buffer.byteLength(args.content, "utf8") <= HOOK_FILE_SNAPSHOT_MAX_BYTES ? args.content : null;
|
|
15829
|
+
} else {
|
|
15830
|
+
updated = (await snapshotForHook(resolvePath(cwd, args.path))).content;
|
|
15831
|
+
}
|
|
15832
|
+
return { existed: before.existed, original: before.content, updated };
|
|
15833
|
+
}
|
|
15559
15834
|
var ToolExecutor = class {
|
|
15560
15835
|
sessionAllowed = /* @__PURE__ */ new Set();
|
|
15561
15836
|
tools;
|
|
@@ -15733,8 +16008,10 @@ var ToolExecutor = class {
|
|
|
15733
16008
|
runStore.recordToolIntent(ctx.runId, call.id, call.name, args);
|
|
15734
16009
|
intentRecorded = true;
|
|
15735
16010
|
}
|
|
16011
|
+
const before = this.wantsFileChange(call.name, args) ? await snapshotForHook(resolvePath(ctx.cwd, args.path)) : void 0;
|
|
15736
16012
|
const result2 = await tool.run(args, ctx);
|
|
15737
16013
|
toolCompleted = true;
|
|
16014
|
+
const fileChange = before ? await fileChangeAfter(call.name, args, ctx.cwd, before) : void 0;
|
|
15738
16015
|
const normalized = normalizeToolOutput(result2);
|
|
15739
16016
|
tr?.raw(normalized);
|
|
15740
16017
|
if (runStore && ctx.runId) {
|
|
@@ -15786,7 +16063,7 @@ var ToolExecutor = class {
|
|
|
15786
16063
|
artifactId: reduced.artifactId,
|
|
15787
16064
|
...normalized.waitRequest ? { waitRequest: normalized.waitRequest } : {}
|
|
15788
16065
|
};
|
|
15789
|
-
this.firePostToolUse(call, args, success, ctx, normalized.meta);
|
|
16066
|
+
this.firePostToolUse(call, args, success, ctx, normalized.meta, fileChange);
|
|
15790
16067
|
return success;
|
|
15791
16068
|
} catch (e) {
|
|
15792
16069
|
if (e instanceof RunToolBudgetExceededError) ctx.onRunBudgetExceeded?.(e.reason);
|
|
@@ -15857,7 +16134,7 @@ var ToolExecutor = class {
|
|
|
15857
16134
|
* `content` field is capped via `capContentForHook` to keep large tool
|
|
15858
16135
|
* outputs from blowing the OS env-var limits on `KIMIFLARE_HOOK_PAYLOAD`.
|
|
15859
16136
|
*/
|
|
15860
|
-
firePostToolUse(call, args, result2, ctx, meta) {
|
|
16137
|
+
firePostToolUse(call, args, result2, ctx, meta, fileChange) {
|
|
15861
16138
|
const hooks = this.hooks;
|
|
15862
16139
|
if (!hooks) return;
|
|
15863
16140
|
const post = hooks.hasEnabledHooks("PostToolUse");
|
|
@@ -15867,7 +16144,8 @@ var ToolExecutor = class {
|
|
|
15867
16144
|
ok: result2.ok,
|
|
15868
16145
|
content: capContentForHook(result2.content),
|
|
15869
16146
|
errorCode: result2.errorCode,
|
|
15870
|
-
...shellResultForHook(meta)
|
|
16147
|
+
...shellResultForHook(meta),
|
|
16148
|
+
...fileChange ? { fileChange } : {}
|
|
15871
16149
|
};
|
|
15872
16150
|
const base = {
|
|
15873
16151
|
session_id: ctx.sessionId ?? null,
|
|
@@ -15885,6 +16163,11 @@ var ToolExecutor = class {
|
|
|
15885
16163
|
void hooks.fire("PostToolUseFailure", { event: "PostToolUseFailure", ...base, error: claudeError(resultFields) }, call.name, ctx.signal).catch(swallow);
|
|
15886
16164
|
}
|
|
15887
16165
|
}
|
|
16166
|
+
/** True when a PostToolUse hook would get this write / edit call's diff. */
|
|
16167
|
+
wantsFileChange(tool, args) {
|
|
16168
|
+
if (tool !== "write" && tool !== "edit" || typeof args.path !== "string" || !args.path) return false;
|
|
16169
|
+
return !!this.hooks && (this.hooks.hasEnabledHooks("PostToolUse") || this.hooks.hasEnabledHooks("PostToolUseFailure"));
|
|
16170
|
+
}
|
|
15888
16171
|
permissionKey(tool, args) {
|
|
15889
16172
|
if (tool.name === "bash" && typeof args.command === "string") {
|
|
15890
16173
|
const firstToken = args.command.trim().split(/\s+/)[0] ?? "";
|
|
@@ -17603,7 +17886,7 @@ function makeLspTools(manager) {
|
|
|
17603
17886
|
init_sessions();
|
|
17604
17887
|
|
|
17605
17888
|
// src/usage-tracker.ts
|
|
17606
|
-
import { readFile as
|
|
17889
|
+
import { readFile as readFile16, rename as rename3 } from "fs/promises";
|
|
17607
17890
|
import { homedir as homedir16 } from "os";
|
|
17608
17891
|
import { join as join28 } from "path";
|
|
17609
17892
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -17635,7 +17918,7 @@ init_openrouter();
|
|
|
17635
17918
|
init_storage_limits();
|
|
17636
17919
|
|
|
17637
17920
|
// src/util/atomic-file.ts
|
|
17638
|
-
import { mkdir as mkdir9, rename as rename2, rm as rm3, stat as
|
|
17921
|
+
import { mkdir as mkdir9, rename as rename2, rm as rm3, stat as stat7, writeFile as writeFile8 } from "fs/promises";
|
|
17639
17922
|
import { dirname as dirname13 } from "path";
|
|
17640
17923
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
17641
17924
|
async function writeFileAtomic(path, data) {
|
|
@@ -17662,7 +17945,7 @@ async function withFileLock2(lockPath, fn) {
|
|
|
17662
17945
|
held = true;
|
|
17663
17946
|
} catch (err) {
|
|
17664
17947
|
if (err.code !== "EEXIST") break;
|
|
17665
|
-
const age = await
|
|
17948
|
+
const age = await stat7(lockPath).then((s) => Date.now() - s.mtimeMs, () => 0);
|
|
17666
17949
|
if (age > LOCK_STALE_MS) {
|
|
17667
17950
|
await rm3(lockPath, { recursive: true, force: true }).catch(() => void 0);
|
|
17668
17951
|
continue;
|
|
@@ -17712,7 +17995,7 @@ function cutoffDate(daysBack) {
|
|
|
17712
17995
|
async function loadLog() {
|
|
17713
17996
|
let raw;
|
|
17714
17997
|
try {
|
|
17715
|
-
raw = await
|
|
17998
|
+
raw = await readFile16(usagePath(), "utf8");
|
|
17716
17999
|
} catch {
|
|
17717
18000
|
return { version: LOG_VERSION2, days: [], sessions: [] };
|
|
17718
18001
|
}
|
|
@@ -17738,7 +18021,7 @@ function withLock(fn) {
|
|
|
17738
18021
|
}
|
|
17739
18022
|
async function loadHistory() {
|
|
17740
18023
|
try {
|
|
17741
|
-
const raw = await
|
|
18024
|
+
const raw = await readFile16(historyPath(), "utf8");
|
|
17742
18025
|
const lines = raw.split("\n").filter((l) => l.trim());
|
|
17743
18026
|
const entries = [];
|
|
17744
18027
|
for (const line of lines) {
|
|
@@ -17927,48 +18210,6 @@ init_llm_auth();
|
|
|
17927
18210
|
|
|
17928
18211
|
// src/agent/session-core.ts
|
|
17929
18212
|
init_llm_auth();
|
|
17930
|
-
|
|
17931
|
-
// src/intent/classify.ts
|
|
17932
|
-
var INTENT_PATTERNS = {
|
|
17933
|
-
qa: /\b(what|how|why|explain|describe|what's|what is)\b/i,
|
|
17934
|
-
diagnose: /\b(broken|failing|error|bug|crash|why.*fail|not working)\b/i,
|
|
17935
|
-
verify: /\b(correct|right|verify|review|check|is this|does this)\b/i,
|
|
17936
|
-
polish: /\b(rename|refactor|extract|move|clean|lint|format)\b/i,
|
|
17937
|
-
small_edit: /\b(add|change|update|fix|remove|delete)\b.+\b(line|here|this|variable|function)\b/i,
|
|
17938
|
-
feature_bounded: /\b(add|implement|create|support)\b.+\b(flag|option|param|arg|field)\b/i,
|
|
17939
|
-
feature_exploratory: /\b(add|implement|migrate|integrate|build)\b.+\b(module|system|auth|oauth|framework|service)\b/i,
|
|
17940
|
-
explore: /\b(how.*work|architecture|structure|where.*used|find.*all|understand)\b/i,
|
|
17941
|
-
meta: /\b(plan|design|strategy|ontology|roadmap|approach)\b/i
|
|
17942
|
-
};
|
|
17943
|
-
var HEAVY_SIGNAL = /\b(research|investigat\w*|audit|deep[\s-]?(dive|thinking)|explorat\w*|comprehensive|end[\s-]?to[\s-]?end|entire\s+(code\s?base|repo\w*|project|app)|whole\s+(code\s?base|repo\w*|project|app)|across\s+the\s+(code\s?base|repo\w*|project)|security|vulnerab\w*|loophole|exploit\w*|threat\s?model|attack\s+surface|penetration)\b/i;
|
|
17944
|
-
function classifyIntent(prompt) {
|
|
17945
|
-
let intentScore = 0;
|
|
17946
|
-
let matchedIntent = "other";
|
|
17947
|
-
for (const [intent, pattern] of Object.entries(INTENT_PATTERNS)) {
|
|
17948
|
-
const matches = (prompt.match(pattern) || []).length;
|
|
17949
|
-
if (matches > intentScore) {
|
|
17950
|
-
intentScore = matches;
|
|
17951
|
-
matchedIntent = intent;
|
|
17952
|
-
}
|
|
17953
|
-
}
|
|
17954
|
-
const hasFileMentions = (prompt.match(/@\w+|\b[\w/-]+\.(ts|tsx|js|jsx|py|go|rs)\b/g) || []).length;
|
|
17955
|
-
const hasMutatingVerb = /\b(add|create|write|edit|delete|remove|rename|migrate|implement)\b/i.test(prompt);
|
|
17956
|
-
const isQuestion = prompt.trim().endsWith("?") || /\b(what|how|why|is|does|can)\b/i.test(prompt.split(" ")[0] || "");
|
|
17957
|
-
const hasHeavySignal = HEAVY_SIGNAL.test(prompt);
|
|
17958
|
-
const rawScore = Math.min(
|
|
17959
|
-
1,
|
|
17960
|
-
intentScore * 0.25 + (hasFileMentions > 2 ? 0.3 : hasFileMentions * 0.1) + (hasMutatingVerb ? 0.25 : 0) + (isQuestion ? 0 : 0.1) + (hasHeavySignal ? 0.6 : 0)
|
|
17961
|
-
);
|
|
17962
|
-
const tier = rawScore < 0.3 ? "light" : rawScore < 0.65 ? "medium" : "heavy";
|
|
17963
|
-
return {
|
|
17964
|
-
intent: hasHeavySignal && matchedIntent === "other" ? "explore" : matchedIntent,
|
|
17965
|
-
rawScore,
|
|
17966
|
-
tier,
|
|
17967
|
-
confidence: 0.5 + (intentScore > 0 || hasHeavySignal ? 0.3 : 0) + (hasFileMentions > 0 ? 0.1 : 0)
|
|
17968
|
-
};
|
|
17969
|
-
}
|
|
17970
|
-
|
|
17971
|
-
// src/agent/session-core.ts
|
|
17972
18213
|
function lastUserText(messages) {
|
|
17973
18214
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
17974
18215
|
const m = messages[i];
|
|
@@ -18097,7 +18338,7 @@ init_redact();
|
|
|
18097
18338
|
|
|
18098
18339
|
// src/trace/retention.ts
|
|
18099
18340
|
init_storage_limits();
|
|
18100
|
-
import { readdir as readdir5, rm as rm4, stat as
|
|
18341
|
+
import { readdir as readdir5, rm as rm4, stat as stat8 } from "fs/promises";
|
|
18101
18342
|
import { join as join32 } from "path";
|
|
18102
18343
|
|
|
18103
18344
|
// src/trace/session-start.ts
|
|
@@ -18412,6 +18653,16 @@ var InternalSession = class {
|
|
|
18412
18653
|
return;
|
|
18413
18654
|
}
|
|
18414
18655
|
const mode = options?.mode ?? this.currentMode;
|
|
18656
|
+
const gate = await submitUserPrompt({
|
|
18657
|
+
...this.hooks ? { hooks: this.hooks } : {},
|
|
18658
|
+
sessionId: this.sessionId,
|
|
18659
|
+
cwd: this.cwd,
|
|
18660
|
+
prompt: text3,
|
|
18661
|
+
resumed: this.messages.some((m) => m.role === "assistant"),
|
|
18662
|
+
model: this.model,
|
|
18663
|
+
auth: llmAuthFromConfig(this.config)
|
|
18664
|
+
});
|
|
18665
|
+
if (gate.blocked) throw new PromptBlockedError(gate.reason);
|
|
18415
18666
|
const messageId = `msg_${this.nextMessageId++}`;
|
|
18416
18667
|
let userContent2 = text3;
|
|
18417
18668
|
if (options?.images && options.images.length > 0) {
|
|
@@ -18757,7 +19008,7 @@ ${notes.join("\n")}` };
|
|
|
18757
19008
|
this.lspManager?.notifyChange(path, content);
|
|
18758
19009
|
} else {
|
|
18759
19010
|
void import("fs/promises").then(
|
|
18760
|
-
({ readFile:
|
|
19011
|
+
({ readFile: readFile21 }) => readFile21(path, "utf8").then((c) => this.lspManager?.notifyChange(path, c)).catch(() => {
|
|
18761
19012
|
})
|
|
18762
19013
|
).catch(() => {
|
|
18763
19014
|
});
|
|
@@ -18964,7 +19215,7 @@ async function startRpcServer(input = process.stdin, output = process.stdout, cr
|
|
|
18964
19215
|
}
|
|
18965
19216
|
|
|
18966
19217
|
// src/sdk/aster-cell.ts
|
|
18967
|
-
import { appendFile as appendFile3, mkdir as mkdir13, readFile as
|
|
19218
|
+
import { appendFile as appendFile3, mkdir as mkdir13, readFile as readFile20, unlink as unlink3, writeFile as writeFile12 } from "fs/promises";
|
|
18968
19219
|
import { createServer as createServer2 } from "http";
|
|
18969
19220
|
import { PassThrough, Writable } from "stream";
|
|
18970
19221
|
import { join as join35, resolve as resolvePath2 } from "path";
|
|
@@ -19163,13 +19414,13 @@ async function readCommand(req) {
|
|
|
19163
19414
|
async function readState() {
|
|
19164
19415
|
let state;
|
|
19165
19416
|
try {
|
|
19166
|
-
state = JSON.parse(await
|
|
19417
|
+
state = JSON.parse(await readFile20(TURN_STATE, "utf8"));
|
|
19167
19418
|
} catch {
|
|
19168
19419
|
state = { sessionId: null, activeRunId: null, initialized: false, cursor: 0 };
|
|
19169
19420
|
}
|
|
19170
19421
|
let last;
|
|
19171
19422
|
try {
|
|
19172
|
-
const lines = (await
|
|
19423
|
+
const lines = (await readFile20(EVENT_LOG, "utf8")).trim().split("\n").filter(Boolean);
|
|
19173
19424
|
last = lines.length ? JSON.parse(lines.at(-1)) : void 0;
|
|
19174
19425
|
} catch {
|
|
19175
19426
|
}
|
|
@@ -19197,7 +19448,7 @@ async function persistState(state) {
|
|
|
19197
19448
|
async function readEvents(after) {
|
|
19198
19449
|
let contents;
|
|
19199
19450
|
try {
|
|
19200
|
-
contents = await
|
|
19451
|
+
contents = await readFile20(EVENT_LOG, "utf8");
|
|
19201
19452
|
} catch {
|
|
19202
19453
|
return [];
|
|
19203
19454
|
}
|
|
@@ -19218,7 +19469,7 @@ async function executeAsterCellControl(requestId) {
|
|
|
19218
19469
|
if (!CONTROL_UUID_RE.test(requestId)) throw new Error("invalid_control_request");
|
|
19219
19470
|
const requestPath = resolvePath2(REQUEST_DIR, requestId + ".json");
|
|
19220
19471
|
if (!requestPath.startsWith(REQUEST_DIR + "/")) throw new Error("invalid_control_request");
|
|
19221
|
-
const request = JSON.parse(await
|
|
19472
|
+
const request = JSON.parse(await readFile20(requestPath, "utf8"));
|
|
19222
19473
|
await unlink3(requestPath).catch(() => {
|
|
19223
19474
|
});
|
|
19224
19475
|
if (request.method === "GET" && request.path.startsWith("/events?after=")) {
|
|
@@ -19363,6 +19614,7 @@ var RunWakeScheduler = class {
|
|
|
19363
19614
|
export {
|
|
19364
19615
|
DEFAULT_MODEL,
|
|
19365
19616
|
DEFAULT_REASONING_EFFORT,
|
|
19617
|
+
PromptBlockedError,
|
|
19366
19618
|
RunStore,
|
|
19367
19619
|
RunWakeScheduler,
|
|
19368
19620
|
createAgentSession,
|