kimiflare 0.88.3 → 0.88.4
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 +1165 -955
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.js +290 -90
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1363,6 +1363,562 @@ var init_messages = __esm({
|
|
|
1363
1363
|
}
|
|
1364
1364
|
});
|
|
1365
1365
|
|
|
1366
|
+
// src/agent/session-state.ts
|
|
1367
|
+
function emptySessionState(task = "") {
|
|
1368
|
+
return {
|
|
1369
|
+
task,
|
|
1370
|
+
user_constraints: [],
|
|
1371
|
+
repo_facts: [],
|
|
1372
|
+
files_touched: [],
|
|
1373
|
+
files_modified: [],
|
|
1374
|
+
confirmed_findings: [],
|
|
1375
|
+
open_questions: [],
|
|
1376
|
+
recent_failures: [],
|
|
1377
|
+
decisions: [],
|
|
1378
|
+
next_actions: [],
|
|
1379
|
+
artifact_index: {}
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
function serializeArtifactStore(store) {
|
|
1383
|
+
const MAX_ARTIFACT_CHARS = 5e4;
|
|
1384
|
+
const out = [];
|
|
1385
|
+
for (const a of store.list()) {
|
|
1386
|
+
out.push({
|
|
1387
|
+
id: a.id,
|
|
1388
|
+
type: a.type,
|
|
1389
|
+
summary: a.summary,
|
|
1390
|
+
raw: a.raw.slice(0, MAX_ARTIFACT_CHARS),
|
|
1391
|
+
source: a.source,
|
|
1392
|
+
path: a.path,
|
|
1393
|
+
lineRange: a.lineRange,
|
|
1394
|
+
ts: a.ts
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
return out;
|
|
1398
|
+
}
|
|
1399
|
+
function deserializeArtifactStore(data) {
|
|
1400
|
+
const store = new ArtifactStore();
|
|
1401
|
+
for (const a of data) {
|
|
1402
|
+
store.add({
|
|
1403
|
+
id: a.id,
|
|
1404
|
+
type: a.type,
|
|
1405
|
+
summary: a.summary,
|
|
1406
|
+
raw: a.raw,
|
|
1407
|
+
source: a.source,
|
|
1408
|
+
path: a.path,
|
|
1409
|
+
lineRange: a.lineRange,
|
|
1410
|
+
ts: a.ts
|
|
1411
|
+
});
|
|
1412
|
+
}
|
|
1413
|
+
return store;
|
|
1414
|
+
}
|
|
1415
|
+
function formatRecalledArtifacts(recalled) {
|
|
1416
|
+
if (recalled.length === 0) return "";
|
|
1417
|
+
const lines = ["[recalled artifacts]"];
|
|
1418
|
+
for (const { id, artifact } of recalled) {
|
|
1419
|
+
lines.push(`--- artifact:${id} (${artifact.type} from ${artifact.source}) ---`);
|
|
1420
|
+
lines.push(artifact.raw);
|
|
1421
|
+
}
|
|
1422
|
+
return lines.join("\n");
|
|
1423
|
+
}
|
|
1424
|
+
function serializeSessionState(state) {
|
|
1425
|
+
const lines = [];
|
|
1426
|
+
lines.push(`task: ${state.task || "(none)"}`);
|
|
1427
|
+
if (state.user_constraints.length) lines.push(`constraints:
|
|
1428
|
+
${state.user_constraints.map((c) => " - " + c).join("\n")}`);
|
|
1429
|
+
if (state.repo_facts.length) lines.push(`repo_facts:
|
|
1430
|
+
${state.repo_facts.map((f) => " - " + f).join("\n")}`);
|
|
1431
|
+
if (state.files_touched.length) lines.push(`files_touched: ${state.files_touched.join(", ")}`);
|
|
1432
|
+
if (state.files_modified.length) lines.push(`files_modified: ${state.files_modified.join(", ")}`);
|
|
1433
|
+
if (state.confirmed_findings.length) lines.push(`findings:
|
|
1434
|
+
${state.confirmed_findings.map((f) => " - " + f).join("\n")}`);
|
|
1435
|
+
if (state.open_questions.length) lines.push(`open_questions:
|
|
1436
|
+
${state.open_questions.map((q) => " - " + q).join("\n")}`);
|
|
1437
|
+
if (state.recent_failures.length) lines.push(`recent_failures:
|
|
1438
|
+
${state.recent_failures.map((f) => " - " + f).join("\n")}`);
|
|
1439
|
+
if (state.decisions.length) lines.push(`decisions:
|
|
1440
|
+
${state.decisions.map((d) => " - " + d).join("\n")}`);
|
|
1441
|
+
if (state.next_actions.length) lines.push(`next_actions:
|
|
1442
|
+
${state.next_actions.map((a) => " - " + a).join("\n")}`);
|
|
1443
|
+
if (Object.keys(state.artifact_index).length) {
|
|
1444
|
+
lines.push("artifact_index:");
|
|
1445
|
+
for (const [id, meta] of Object.entries(state.artifact_index)) {
|
|
1446
|
+
lines.push(` ${id}: [${meta.type}] ${meta.summary}`);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
return lines.join("\n");
|
|
1450
|
+
}
|
|
1451
|
+
function buildSessionStateMessage(state) {
|
|
1452
|
+
return {
|
|
1453
|
+
role: "system",
|
|
1454
|
+
content: `[compiled session state]
|
|
1455
|
+
${serializeSessionState(state)}`
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
var ArtifactStore;
|
|
1459
|
+
var init_session_state = __esm({
|
|
1460
|
+
"src/agent/session-state.ts"() {
|
|
1461
|
+
"use strict";
|
|
1462
|
+
ArtifactStore = class {
|
|
1463
|
+
artifacts = /* @__PURE__ */ new Map();
|
|
1464
|
+
maxArtifacts;
|
|
1465
|
+
maxTotalChars;
|
|
1466
|
+
constructor(opts2) {
|
|
1467
|
+
this.maxArtifacts = opts2?.maxArtifacts ?? 200;
|
|
1468
|
+
this.maxTotalChars = opts2?.maxTotalChars ?? 5e5;
|
|
1469
|
+
}
|
|
1470
|
+
add(a) {
|
|
1471
|
+
while (this.totalChars() + a.raw.length > this.maxTotalChars && this.artifacts.size > 0) {
|
|
1472
|
+
this.evictSizeWeighted();
|
|
1473
|
+
}
|
|
1474
|
+
while (this.artifacts.size >= this.maxArtifacts) {
|
|
1475
|
+
this.evictOldest();
|
|
1476
|
+
}
|
|
1477
|
+
this.artifacts.set(a.id, a);
|
|
1478
|
+
}
|
|
1479
|
+
get(id) {
|
|
1480
|
+
return this.artifacts.get(id);
|
|
1481
|
+
}
|
|
1482
|
+
has(id) {
|
|
1483
|
+
return this.artifacts.has(id);
|
|
1484
|
+
}
|
|
1485
|
+
list() {
|
|
1486
|
+
return [...this.artifacts.values()].sort((a, b) => a.ts < b.ts ? -1 : 1);
|
|
1487
|
+
}
|
|
1488
|
+
recall(ids) {
|
|
1489
|
+
const out = [];
|
|
1490
|
+
for (const id of ids) {
|
|
1491
|
+
const a = this.artifacts.get(id);
|
|
1492
|
+
if (a) out.push({ id, artifact: a });
|
|
1493
|
+
}
|
|
1494
|
+
return out;
|
|
1495
|
+
}
|
|
1496
|
+
size() {
|
|
1497
|
+
return this.artifacts.size;
|
|
1498
|
+
}
|
|
1499
|
+
totalChars() {
|
|
1500
|
+
let sum = 0;
|
|
1501
|
+
for (const a of this.artifacts.values()) {
|
|
1502
|
+
sum += a.raw.length;
|
|
1503
|
+
}
|
|
1504
|
+
return sum;
|
|
1505
|
+
}
|
|
1506
|
+
evictOldest() {
|
|
1507
|
+
let oldest;
|
|
1508
|
+
for (const a of this.artifacts.values()) {
|
|
1509
|
+
if (!oldest || a.ts < oldest.ts) oldest = a;
|
|
1510
|
+
}
|
|
1511
|
+
if (oldest) this.artifacts.delete(oldest.id);
|
|
1512
|
+
}
|
|
1513
|
+
/** Evict the largest artifact among the oldest quartile (by timestamp).
|
|
1514
|
+
* Bounded by the oldest quartile so we never evict freshly-added artifacts;
|
|
1515
|
+
* size-weighted within that window so one big artifact gets dropped instead
|
|
1516
|
+
* of many small ones. */
|
|
1517
|
+
evictSizeWeighted() {
|
|
1518
|
+
const sorted = [...this.artifacts.values()].sort((a, b) => a.ts < b.ts ? -1 : 1);
|
|
1519
|
+
if (sorted.length === 0) return;
|
|
1520
|
+
const quartile = Math.max(1, Math.ceil(sorted.length / 4));
|
|
1521
|
+
const candidates = sorted.slice(0, quartile);
|
|
1522
|
+
let pick3 = candidates[0];
|
|
1523
|
+
for (const a of candidates) {
|
|
1524
|
+
if (a.raw.length > pick3.raw.length) pick3 = a;
|
|
1525
|
+
}
|
|
1526
|
+
this.artifacts.delete(pick3.id);
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
// src/agent/artifact-compaction.ts
|
|
1533
|
+
function approxTokens(n) {
|
|
1534
|
+
return Math.round(n / 3.5);
|
|
1535
|
+
}
|
|
1536
|
+
function estimateMessageTokens(m) {
|
|
1537
|
+
let chars = 0;
|
|
1538
|
+
if (typeof m.content === "string") {
|
|
1539
|
+
chars = m.content.length;
|
|
1540
|
+
} else if (Array.isArray(m.content)) {
|
|
1541
|
+
chars = m.content.map((p) => p.type === "text" ? p.text.length : 0).reduce((a, b) => a + b, 0);
|
|
1542
|
+
}
|
|
1543
|
+
if (m.reasoning_content) chars += m.reasoning_content.length;
|
|
1544
|
+
if (m.tool_calls) {
|
|
1545
|
+
for (const tc of m.tool_calls) {
|
|
1546
|
+
chars += tc.function.name.length + tc.function.arguments.length;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
return approxTokens(chars);
|
|
1550
|
+
}
|
|
1551
|
+
function estimatePromptTokens(messages) {
|
|
1552
|
+
return messages.reduce((sum, m) => sum + estimateMessageTokens(m), 0);
|
|
1553
|
+
}
|
|
1554
|
+
function groupIntoTurns(messages) {
|
|
1555
|
+
const prefix = [];
|
|
1556
|
+
let i = 0;
|
|
1557
|
+
while (i < messages.length && messages[i].role === "system") {
|
|
1558
|
+
prefix.push(messages[i]);
|
|
1559
|
+
i++;
|
|
1560
|
+
}
|
|
1561
|
+
const turns = [];
|
|
1562
|
+
while (i < messages.length) {
|
|
1563
|
+
if (messages[i].role !== "user") {
|
|
1564
|
+
i++;
|
|
1565
|
+
continue;
|
|
1566
|
+
}
|
|
1567
|
+
const user = messages[i];
|
|
1568
|
+
i++;
|
|
1569
|
+
if (i >= messages.length || messages[i].role !== "assistant") {
|
|
1570
|
+
continue;
|
|
1571
|
+
}
|
|
1572
|
+
const assistant = messages[i];
|
|
1573
|
+
i++;
|
|
1574
|
+
const tools = [];
|
|
1575
|
+
while (i < messages.length && messages[i].role === "tool") {
|
|
1576
|
+
tools.push(messages[i]);
|
|
1577
|
+
i++;
|
|
1578
|
+
}
|
|
1579
|
+
turns.push({ user, assistant, tools });
|
|
1580
|
+
}
|
|
1581
|
+
return { prefix, turns };
|
|
1582
|
+
}
|
|
1583
|
+
function makeArtifactId(type, index) {
|
|
1584
|
+
return `${type}_${Date.now()}_${index}`;
|
|
1585
|
+
}
|
|
1586
|
+
function extractArtifactsFromTurn(turn, startIndex, store) {
|
|
1587
|
+
const artifacts = [];
|
|
1588
|
+
const stateDelta = {
|
|
1589
|
+
files_touched: [],
|
|
1590
|
+
files_modified: [],
|
|
1591
|
+
confirmed_findings: [],
|
|
1592
|
+
recent_failures: [],
|
|
1593
|
+
decisions: [],
|
|
1594
|
+
next_actions: []
|
|
1595
|
+
};
|
|
1596
|
+
const toolCalls = turn.assistant.tool_calls ?? [];
|
|
1597
|
+
for (let ti = 0; ti < turn.tools.length; ti++) {
|
|
1598
|
+
const tm = turn.tools[ti];
|
|
1599
|
+
const tc = toolCalls[ti];
|
|
1600
|
+
const name = tm.name ?? tc?.function.name ?? "unknown";
|
|
1601
|
+
const content = typeof tm.content === "string" ? tm.content : "";
|
|
1602
|
+
let type = "tool_result";
|
|
1603
|
+
let summary = `${name} result`;
|
|
1604
|
+
let path;
|
|
1605
|
+
if (name === "read") {
|
|
1606
|
+
type = "read_slice";
|
|
1607
|
+
try {
|
|
1608
|
+
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
1609
|
+
path = args.path;
|
|
1610
|
+
summary = `read ${path ?? "file"}`;
|
|
1611
|
+
if (path && !stateDelta.files_touched.includes(path)) stateDelta.files_touched.push(path);
|
|
1612
|
+
} catch {
|
|
1613
|
+
summary = "read file";
|
|
1614
|
+
}
|
|
1615
|
+
} else if (name === "bash") {
|
|
1616
|
+
type = "bash_log";
|
|
1617
|
+
try {
|
|
1618
|
+
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
1619
|
+
const cmd = args.command ?? "";
|
|
1620
|
+
summary = `bash: ${cmd.slice(0, 60)}`;
|
|
1621
|
+
if (content.includes("Error") || content.includes("error") || content.includes("FAIL")) {
|
|
1622
|
+
stateDelta.recent_failures.push(`bash failed: ${cmd.slice(0, 80)}`);
|
|
1623
|
+
}
|
|
1624
|
+
} catch {
|
|
1625
|
+
summary = "bash command";
|
|
1626
|
+
}
|
|
1627
|
+
} else if (name === "grep") {
|
|
1628
|
+
type = "grep_result";
|
|
1629
|
+
summary = `grep results (${content.split("\n").length} lines)`;
|
|
1630
|
+
} else if (name === "web_fetch") {
|
|
1631
|
+
type = "web_fetch";
|
|
1632
|
+
try {
|
|
1633
|
+
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
1634
|
+
summary = `web_fetch: ${args.url ?? "url"}`;
|
|
1635
|
+
} catch {
|
|
1636
|
+
summary = "web_fetch";
|
|
1637
|
+
}
|
|
1638
|
+
} else if (name === "write" || name === "edit") {
|
|
1639
|
+
try {
|
|
1640
|
+
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
1641
|
+
path = args.path;
|
|
1642
|
+
if (path && !stateDelta.files_modified.includes(path)) stateDelta.files_modified.push(path);
|
|
1643
|
+
if (path && !stateDelta.files_touched.includes(path)) stateDelta.files_touched.push(path);
|
|
1644
|
+
} catch {
|
|
1645
|
+
}
|
|
1646
|
+
continue;
|
|
1647
|
+
} else if (name === "glob") {
|
|
1648
|
+
try {
|
|
1649
|
+
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
1650
|
+
summary = `glob: ${args.pattern ?? ""}`;
|
|
1651
|
+
} catch {
|
|
1652
|
+
summary = "glob";
|
|
1653
|
+
}
|
|
1654
|
+
} else if (name === "tasks_set") {
|
|
1655
|
+
try {
|
|
1656
|
+
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
1657
|
+
const tasks = args.tasks ?? [];
|
|
1658
|
+
const inProgress = tasks.filter((t) => t.status === "in_progress").map((t) => t.title);
|
|
1659
|
+
const pending = tasks.filter((t) => t.status === "pending").map((t) => t.title);
|
|
1660
|
+
if (inProgress.length) stateDelta.next_actions.push(...inProgress);
|
|
1661
|
+
if (pending.length) stateDelta.next_actions.push(...pending);
|
|
1662
|
+
summary = `tasks_set: ${tasks.length} tasks`;
|
|
1663
|
+
} catch {
|
|
1664
|
+
summary = "tasks_set";
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
const maxRaw = 5e4;
|
|
1668
|
+
const raw = content.length > maxRaw ? content.slice(0, maxRaw) + `
|
|
1669
|
+
...[${content.length - maxRaw} chars truncated]` : content;
|
|
1670
|
+
const artifact = {
|
|
1671
|
+
id: makeArtifactId(type, startIndex + ti),
|
|
1672
|
+
type,
|
|
1673
|
+
summary,
|
|
1674
|
+
raw,
|
|
1675
|
+
source: name,
|
|
1676
|
+
path,
|
|
1677
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
1678
|
+
};
|
|
1679
|
+
artifacts.push(artifact);
|
|
1680
|
+
if (!content.includes("Error") && !content.includes("error") && content.length > 0 && content.length < 2e3) {
|
|
1681
|
+
stateDelta.confirmed_findings.push(`${name}: ${content.slice(0, 200)}`);
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
const assistantText = typeof turn.assistant.content === "string" ? turn.assistant.content : "";
|
|
1685
|
+
if (assistantText.length > 0) {
|
|
1686
|
+
const decisionPatterns = [
|
|
1687
|
+
/(?:decided?|will|plan to|going to|should|need to)\s+(.{10,200})/gi,
|
|
1688
|
+
/(?:let's|let us)\s+(.{10,200})/gi
|
|
1689
|
+
];
|
|
1690
|
+
for (const pattern of decisionPatterns) {
|
|
1691
|
+
let match;
|
|
1692
|
+
while ((match = pattern.exec(assistantText)) !== null) {
|
|
1693
|
+
const decision = match[1].trim().replace(/\.$/, "");
|
|
1694
|
+
if (decision.length > 10 && !stateDelta.decisions.includes(decision)) {
|
|
1695
|
+
stateDelta.decisions.push(decision);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
return { artifacts, stateDelta };
|
|
1701
|
+
}
|
|
1702
|
+
function mergeState(state, delta) {
|
|
1703
|
+
const mergeArr = (a, b) => {
|
|
1704
|
+
if (!b) return a;
|
|
1705
|
+
const set = new Set(a);
|
|
1706
|
+
for (const item of b) set.add(item);
|
|
1707
|
+
return [...set];
|
|
1708
|
+
};
|
|
1709
|
+
return {
|
|
1710
|
+
...state,
|
|
1711
|
+
task: state.task || delta.task || "",
|
|
1712
|
+
user_constraints: mergeArr(state.user_constraints, delta.user_constraints),
|
|
1713
|
+
repo_facts: mergeArr(state.repo_facts, delta.repo_facts),
|
|
1714
|
+
files_touched: mergeArr(state.files_touched, delta.files_touched),
|
|
1715
|
+
files_modified: mergeArr(state.files_modified, delta.files_modified),
|
|
1716
|
+
confirmed_findings: mergeArr(state.confirmed_findings, delta.confirmed_findings),
|
|
1717
|
+
open_questions: mergeArr(state.open_questions, delta.open_questions),
|
|
1718
|
+
recent_failures: mergeArr(state.recent_failures, delta.recent_failures),
|
|
1719
|
+
decisions: mergeArr(state.decisions, delta.decisions),
|
|
1720
|
+
next_actions: mergeArr(state.next_actions, delta.next_actions),
|
|
1721
|
+
artifact_index: { ...state.artifact_index, ...delta.artifact_index }
|
|
1722
|
+
};
|
|
1723
|
+
}
|
|
1724
|
+
function shouldCompact(opts2) {
|
|
1725
|
+
const tokenThreshold = opts2.tokenThreshold ?? 8e4;
|
|
1726
|
+
const turnThreshold = opts2.turnThreshold ?? 12;
|
|
1727
|
+
const tokens = estimatePromptTokens(opts2.messages);
|
|
1728
|
+
const { turns } = groupIntoTurns(opts2.messages);
|
|
1729
|
+
return tokens > tokenThreshold || turns.length > turnThreshold;
|
|
1730
|
+
}
|
|
1731
|
+
function compactMessagesViaArtifacts(opts2) {
|
|
1732
|
+
const keepLastTurns = opts2.keepLastTurns ?? 4;
|
|
1733
|
+
const { prefix, turns } = groupIntoTurns(opts2.messages);
|
|
1734
|
+
const tokensBefore = estimatePromptTokens(opts2.messages);
|
|
1735
|
+
if (turns.length <= keepLastTurns) {
|
|
1736
|
+
return {
|
|
1737
|
+
newMessages: opts2.messages,
|
|
1738
|
+
newState: opts2.state,
|
|
1739
|
+
metrics: {
|
|
1740
|
+
estimatedTokensBefore: tokensBefore,
|
|
1741
|
+
estimatedTokensAfter: tokensBefore,
|
|
1742
|
+
archivedArtifacts: 0,
|
|
1743
|
+
recalledArtifacts: 0,
|
|
1744
|
+
rawTurnsRemoved: 0,
|
|
1745
|
+
rawTurnsKept: turns.length
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
const toCompact = turns.slice(0, turns.length - keepLastTurns);
|
|
1750
|
+
const toKeep = turns.slice(turns.length - keepLastTurns);
|
|
1751
|
+
let newState = { ...opts2.state };
|
|
1752
|
+
let archivedCount = 0;
|
|
1753
|
+
for (let i = 0; i < toCompact.length; i++) {
|
|
1754
|
+
const turn = toCompact[i];
|
|
1755
|
+
const { artifacts, stateDelta } = extractArtifactsFromTurn(turn, i, opts2.store);
|
|
1756
|
+
for (const artifact of artifacts) {
|
|
1757
|
+
opts2.store.add(artifact);
|
|
1758
|
+
archivedCount++;
|
|
1759
|
+
newState.artifact_index[artifact.id] = {
|
|
1760
|
+
type: artifact.type,
|
|
1761
|
+
summary: artifact.summary,
|
|
1762
|
+
source: artifact.source,
|
|
1763
|
+
path: artifact.path
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
newState = mergeState(newState, stateDelta);
|
|
1767
|
+
if (!newState.task && typeof turn.user.content === "string") {
|
|
1768
|
+
newState.task = turn.user.content.slice(0, 200);
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
const workingMemory = [];
|
|
1772
|
+
for (const turn of toKeep) {
|
|
1773
|
+
workingMemory.push(turn.user);
|
|
1774
|
+
workingMemory.push(turn.assistant);
|
|
1775
|
+
for (const tm of turn.tools) {
|
|
1776
|
+
workingMemory.push(tm);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
const stateMsg = buildSessionStateMessage(newState);
|
|
1780
|
+
const newMessages = [...prefix, stateMsg, ...workingMemory];
|
|
1781
|
+
const tokensAfter = estimatePromptTokens(newMessages);
|
|
1782
|
+
const metrics = {
|
|
1783
|
+
estimatedTokensBefore: tokensBefore,
|
|
1784
|
+
estimatedTokensAfter: tokensAfter,
|
|
1785
|
+
archivedArtifacts: archivedCount,
|
|
1786
|
+
recalledArtifacts: 0,
|
|
1787
|
+
rawTurnsRemoved: toCompact.length,
|
|
1788
|
+
rawTurnsKept: toKeep.length
|
|
1789
|
+
};
|
|
1790
|
+
return { newMessages, newState, metrics };
|
|
1791
|
+
}
|
|
1792
|
+
function recallArtifacts(messages, store, state) {
|
|
1793
|
+
const text = messages.map((m) => typeof m.content === "string" ? m.content : "").join(" ");
|
|
1794
|
+
const ids = [];
|
|
1795
|
+
for (const [id, meta] of Object.entries(state.artifact_index)) {
|
|
1796
|
+
if (meta.path && text.includes(meta.path)) {
|
|
1797
|
+
ids.push(id);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
for (const failure of state.recent_failures) {
|
|
1801
|
+
const keyword = failure.split(":")[0];
|
|
1802
|
+
if (!keyword) continue;
|
|
1803
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
1804
|
+
if (!text.toLowerCase().includes(lowerKeyword)) continue;
|
|
1805
|
+
for (const [id, meta] of Object.entries(state.artifact_index)) {
|
|
1806
|
+
if (meta.source === "bash" && !ids.includes(id) && meta.summary.toLowerCase().includes(lowerKeyword)) {
|
|
1807
|
+
ids.push(id);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
const uniqueIds = [...new Set(ids)].slice(0, 5);
|
|
1812
|
+
const recalled = store.recall(uniqueIds);
|
|
1813
|
+
return { ids: uniqueIds, recalled };
|
|
1814
|
+
}
|
|
1815
|
+
var init_artifact_compaction = __esm({
|
|
1816
|
+
"src/agent/artifact-compaction.ts"() {
|
|
1817
|
+
"use strict";
|
|
1818
|
+
init_session_state();
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
|
|
1822
|
+
// src/util/llm-dump.ts
|
|
1823
|
+
import { homedir as homedir5 } from "os";
|
|
1824
|
+
import { join as join8 } from "path";
|
|
1825
|
+
import { mkdirSync as mkdirSync2, appendFileSync, writeFileSync } from "fs";
|
|
1826
|
+
function isLlmDumpEnabled() {
|
|
1827
|
+
const raw = process.env.KIMIFLARE_DUMP_LLM;
|
|
1828
|
+
if (raw === void 0) return false;
|
|
1829
|
+
const v = raw.toLowerCase();
|
|
1830
|
+
return v === "1" || v === "true";
|
|
1831
|
+
}
|
|
1832
|
+
function defaultDumpRoot() {
|
|
1833
|
+
const override = process.env.KIMIFLARE_DUMP_LLM_DIR;
|
|
1834
|
+
if (override && override.trim()) return override;
|
|
1835
|
+
const xdg = process.env.XDG_CONFIG_HOME || join8(homedir5(), ".config");
|
|
1836
|
+
return join8(xdg, "kimiflare", "llm-dumps");
|
|
1837
|
+
}
|
|
1838
|
+
function dumpDir(sessionId) {
|
|
1839
|
+
return join8(defaultDumpRoot(), sessionId && sessionId.trim() ? sessionId : "nosession");
|
|
1840
|
+
}
|
|
1841
|
+
function messageChars(m) {
|
|
1842
|
+
let chars = 0;
|
|
1843
|
+
if (typeof m.content === "string") {
|
|
1844
|
+
chars = m.content.length;
|
|
1845
|
+
} else if (Array.isArray(m.content)) {
|
|
1846
|
+
chars = m.content.reduce((a, p) => a + (p.type === "text" ? p.text.length : 0), 0);
|
|
1847
|
+
}
|
|
1848
|
+
if (m.reasoning_content) chars += m.reasoning_content.length;
|
|
1849
|
+
if (m.tool_calls) {
|
|
1850
|
+
for (const tc of m.tool_calls) {
|
|
1851
|
+
chars += tc.function.name.length + tc.function.arguments.length;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
return chars;
|
|
1855
|
+
}
|
|
1856
|
+
function computeBreakdown(messages, tools) {
|
|
1857
|
+
const perMessage = [];
|
|
1858
|
+
let systemChars = 0;
|
|
1859
|
+
let historyChars = 0;
|
|
1860
|
+
messages.forEach((m, index) => {
|
|
1861
|
+
const chars = messageChars(m);
|
|
1862
|
+
if (m.role === "system") systemChars += chars;
|
|
1863
|
+
else historyChars += chars;
|
|
1864
|
+
perMessage.push({
|
|
1865
|
+
index,
|
|
1866
|
+
role: m.role,
|
|
1867
|
+
...m.name ? { name: m.name } : {},
|
|
1868
|
+
chars,
|
|
1869
|
+
estTokens: approxTokens(chars),
|
|
1870
|
+
...m.tool_calls && m.tool_calls.length ? { toolName: m.tool_calls.map((t) => t.function.name).join(",") } : {}
|
|
1871
|
+
});
|
|
1872
|
+
});
|
|
1873
|
+
const toolsChars = tools.reduce(
|
|
1874
|
+
(a, t) => a + t.function.name.length + t.function.description.length + JSON.stringify(t.function.parameters).length,
|
|
1875
|
+
0
|
|
1876
|
+
);
|
|
1877
|
+
const totalChars = systemChars + historyChars + toolsChars;
|
|
1878
|
+
return {
|
|
1879
|
+
totalChars,
|
|
1880
|
+
estTokens: approxTokens(totalChars),
|
|
1881
|
+
messageCount: messages.length,
|
|
1882
|
+
toolCount: tools.length,
|
|
1883
|
+
systemChars,
|
|
1884
|
+
toolsChars,
|
|
1885
|
+
historyChars,
|
|
1886
|
+
perMessage
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1889
|
+
function safeSegment(s) {
|
|
1890
|
+
return s.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
1891
|
+
}
|
|
1892
|
+
function writeLlmDump(record) {
|
|
1893
|
+
if (!isLlmDumpEnabled()) return;
|
|
1894
|
+
try {
|
|
1895
|
+
const dir = dumpDir(record.meta.sessionId);
|
|
1896
|
+
mkdirSync2(dir, { recursive: true });
|
|
1897
|
+
const tsPart = safeSegment(record.meta.ts);
|
|
1898
|
+
const turnPart = safeSegment(record.meta.turnId ?? "noturn");
|
|
1899
|
+
const reqPart = safeSegment(record.meta.requestId);
|
|
1900
|
+
const file = join8(dir, `${tsPart}-${turnPart}-${reqPart}.json`);
|
|
1901
|
+
writeFileSync(file, JSON.stringify(record, null, 2));
|
|
1902
|
+
const summary = {
|
|
1903
|
+
...record.meta,
|
|
1904
|
+
...record.breakdown,
|
|
1905
|
+
perMessage: void 0,
|
|
1906
|
+
// keep the index line thin
|
|
1907
|
+
finishReason: record.response.finishReason,
|
|
1908
|
+
usage: record.response.usage,
|
|
1909
|
+
file
|
|
1910
|
+
};
|
|
1911
|
+
appendFileSync(join8(dir, "index.jsonl"), JSON.stringify(summary) + "\n");
|
|
1912
|
+
} catch {
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
var init_llm_dump = __esm({
|
|
1916
|
+
"src/util/llm-dump.ts"() {
|
|
1917
|
+
"use strict";
|
|
1918
|
+
init_artifact_compaction();
|
|
1919
|
+
}
|
|
1920
|
+
});
|
|
1921
|
+
|
|
1366
1922
|
// src/models/registry.ts
|
|
1367
1923
|
function isUnifiedEligible(entry) {
|
|
1368
1924
|
if (entry.provider === "workers-ai") return false;
|
|
@@ -1485,6 +2041,38 @@ async function* runKimi(opts2) {
|
|
|
1485
2041
|
if (opts2.reasoningEffort && supportsReasoning) {
|
|
1486
2042
|
body.reasoning_effort = opts2.reasoningEffort;
|
|
1487
2043
|
}
|
|
2044
|
+
let dumpRecord = null;
|
|
2045
|
+
if (isLlmDumpEnabled()) {
|
|
2046
|
+
const dumpMessages = body.messages;
|
|
2047
|
+
const dumpTools = body.tools ?? [];
|
|
2048
|
+
const { messages: _m, tools: _t, ...params } = body;
|
|
2049
|
+
const dumpResponse = {
|
|
2050
|
+
text: "",
|
|
2051
|
+
reasoning: "",
|
|
2052
|
+
toolCalls: [],
|
|
2053
|
+
finishReason: null,
|
|
2054
|
+
usage: null
|
|
2055
|
+
};
|
|
2056
|
+
dumpRecord = {
|
|
2057
|
+
meta: {
|
|
2058
|
+
requestId,
|
|
2059
|
+
sessionId: opts2.sessionId ?? getLogSessionId(),
|
|
2060
|
+
turnId: getLogTurnId(),
|
|
2061
|
+
model: opts2.model,
|
|
2062
|
+
url,
|
|
2063
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
2064
|
+
},
|
|
2065
|
+
request: {
|
|
2066
|
+
system: dumpMessages.filter((m) => m.role === "system"),
|
|
2067
|
+
messages: dumpMessages,
|
|
2068
|
+
tools: dumpTools,
|
|
2069
|
+
params,
|
|
2070
|
+
rawSerialized: stableStringify(body, jsonReplacer)
|
|
2071
|
+
},
|
|
2072
|
+
breakdown: computeBreakdown(dumpMessages, dumpTools),
|
|
2073
|
+
response: dumpResponse
|
|
2074
|
+
};
|
|
2075
|
+
}
|
|
1488
2076
|
logger.debug("runKimi:request", { requestId, attempt: 0, model: opts2.model });
|
|
1489
2077
|
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
1490
2078
|
let res;
|
|
@@ -1565,13 +2153,41 @@ async function* runKimi(opts2) {
|
|
|
1565
2153
|
const meta = readGatewayMeta(res.headers);
|
|
1566
2154
|
if (meta) yield { type: "gateway_meta", meta };
|
|
1567
2155
|
logger.debug("runKimi:stream_start", { requestId });
|
|
1568
|
-
|
|
1569
|
-
|
|
2156
|
+
try {
|
|
2157
|
+
for await (const ev of parseStream(res.body, opts2.signal, opts2.idleTimeoutMs, opts2.postFirstByteIdleTimeoutMs)) {
|
|
2158
|
+
if (dumpRecord) accumulateDumpResponse(dumpRecord.response, ev);
|
|
2159
|
+
yield ev;
|
|
2160
|
+
}
|
|
2161
|
+
} finally {
|
|
2162
|
+
if (dumpRecord) {
|
|
2163
|
+
dumpRecord.meta.attempt = attempt;
|
|
2164
|
+
writeLlmDump(dumpRecord);
|
|
2165
|
+
}
|
|
1570
2166
|
}
|
|
1571
2167
|
logger.debug("runKimi:stream_end", { requestId });
|
|
1572
2168
|
return;
|
|
1573
2169
|
}
|
|
1574
2170
|
}
|
|
2171
|
+
function accumulateDumpResponse(resp, ev) {
|
|
2172
|
+
switch (ev.type) {
|
|
2173
|
+
case "text":
|
|
2174
|
+
resp.text += ev.delta;
|
|
2175
|
+
break;
|
|
2176
|
+
case "reasoning":
|
|
2177
|
+
resp.reasoning += ev.delta;
|
|
2178
|
+
break;
|
|
2179
|
+
case "tool_call_complete":
|
|
2180
|
+
resp.toolCalls.push({ name: ev.name, arguments: ev.arguments });
|
|
2181
|
+
break;
|
|
2182
|
+
case "usage":
|
|
2183
|
+
resp.usage = ev.usage;
|
|
2184
|
+
break;
|
|
2185
|
+
case "done":
|
|
2186
|
+
resp.finishReason = ev.finishReason;
|
|
2187
|
+
if (ev.usage) resp.usage = ev.usage;
|
|
2188
|
+
break;
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
1575
2191
|
function validateModelId(model) {
|
|
1576
2192
|
if (!model) throw new KimiApiError(`Invalid model ID: ${model}`, 400);
|
|
1577
2193
|
if (/^@[a-zA-Z0-9_-]+\/[a-zA-Z0-9._-]+(\/[a-zA-Z0-9._-]+)*$/.test(model)) return;
|
|
@@ -1823,6 +2439,8 @@ var init_client = __esm({
|
|
|
1823
2439
|
init_version();
|
|
1824
2440
|
init_messages();
|
|
1825
2441
|
init_logger();
|
|
2442
|
+
init_log_sink();
|
|
2443
|
+
init_llm_dump();
|
|
1826
2444
|
init_registry();
|
|
1827
2445
|
RETRYABLE_CODES = /* @__PURE__ */ new Set([3040]);
|
|
1828
2446
|
MAX_ATTEMPTS = 5;
|
|
@@ -1869,20 +2487,45 @@ var init_registry2 = __esm({
|
|
|
1869
2487
|
}
|
|
1870
2488
|
});
|
|
1871
2489
|
|
|
1872
|
-
// src/
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
2490
|
+
// src/memory/recall-inject.ts
|
|
2491
|
+
function hasRecalledMemory(messages) {
|
|
2492
|
+
return messages.some(
|
|
2493
|
+
(m) => m.role === "system" && typeof m.content === "string" && m.content.startsWith(RECALLED_MEMORY_HEADER)
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
2496
|
+
function injectRecalledMemoryOnce(messages, text) {
|
|
2497
|
+
if (!text || hasRecalledMemory(messages)) return false;
|
|
2498
|
+
const lastSystemIdx = messages.findLastIndex((m) => m.role === "system");
|
|
2499
|
+
const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : messages.length;
|
|
2500
|
+
messages.splice(insertIdx, 0, {
|
|
2501
|
+
role: "system",
|
|
2502
|
+
content: `${RECALLED_MEMORY_HEADER}
|
|
2503
|
+
${text}`
|
|
2504
|
+
});
|
|
2505
|
+
return true;
|
|
2506
|
+
}
|
|
2507
|
+
var RECALLED_MEMORY_HEADER;
|
|
2508
|
+
var init_recall_inject = __esm({
|
|
2509
|
+
"src/memory/recall-inject.ts"() {
|
|
2510
|
+
"use strict";
|
|
2511
|
+
RECALLED_MEMORY_HEADER = "[recalled project memory]";
|
|
2512
|
+
}
|
|
2513
|
+
});
|
|
2514
|
+
|
|
2515
|
+
// src/storage-limits.ts
|
|
2516
|
+
import { readdir as readdir2, stat as stat2, unlink } from "fs/promises";
|
|
2517
|
+
import { join as join9 } from "path";
|
|
2518
|
+
async function listFilesByMtime(dir, pattern = /.*/) {
|
|
2519
|
+
let entries;
|
|
2520
|
+
try {
|
|
2521
|
+
entries = await readdir2(dir);
|
|
1879
2522
|
} catch {
|
|
1880
2523
|
return [];
|
|
1881
2524
|
}
|
|
1882
2525
|
const files = [];
|
|
1883
2526
|
for (const name of entries) {
|
|
1884
2527
|
if (!pattern.test(name)) continue;
|
|
1885
|
-
const p =
|
|
2528
|
+
const p = join9(dir, name);
|
|
1886
2529
|
try {
|
|
1887
2530
|
const s = await stat2(p);
|
|
1888
2531
|
if (s.isFile()) files.push({ path: p, mtime: s.mtime });
|
|
@@ -1966,19 +2609,19 @@ var init_storage_limits = __esm({
|
|
|
1966
2609
|
|
|
1967
2610
|
// src/cost-debug.ts
|
|
1968
2611
|
import { appendFile, mkdir as mkdir5 } from "fs/promises";
|
|
1969
|
-
import { homedir as
|
|
1970
|
-
import { join as
|
|
2612
|
+
import { homedir as homedir6 } from "os";
|
|
2613
|
+
import { join as join10 } from "path";
|
|
1971
2614
|
function debugDir() {
|
|
1972
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
1973
|
-
return
|
|
2615
|
+
const xdg = process.env.XDG_DATA_HOME || join10(homedir6(), ".local", "share");
|
|
2616
|
+
return join10(xdg, "kimiflare");
|
|
1974
2617
|
}
|
|
1975
2618
|
function debugPath() {
|
|
1976
|
-
return
|
|
2619
|
+
return join10(debugDir(), "cost-debug.jsonl");
|
|
1977
2620
|
}
|
|
1978
2621
|
function now() {
|
|
1979
2622
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1980
2623
|
}
|
|
1981
|
-
function
|
|
2624
|
+
function approxTokens2(chars) {
|
|
1982
2625
|
return Math.round(chars / 4);
|
|
1983
2626
|
}
|
|
1984
2627
|
function analyzePrompt(messages) {
|
|
@@ -1994,14 +2637,14 @@ function analyzePrompt(messages) {
|
|
|
1994
2637
|
const base = {
|
|
1995
2638
|
role: m.role,
|
|
1996
2639
|
chars,
|
|
1997
|
-
approxTokens:
|
|
2640
|
+
approxTokens: approxTokens2(chars)
|
|
1998
2641
|
};
|
|
1999
2642
|
if (m.role === "assistant" && m.reasoning_content) {
|
|
2000
2643
|
sections.push({
|
|
2001
2644
|
...base,
|
|
2002
|
-
detail: `content+reasoning (${
|
|
2645
|
+
detail: `content+reasoning (${approxTokens2(m.reasoning_content.length)} reasoning tokens)`,
|
|
2003
2646
|
chars: chars + m.reasoning_content.length,
|
|
2004
|
-
approxTokens:
|
|
2647
|
+
approxTokens: approxTokens2(chars + m.reasoning_content.length)
|
|
2005
2648
|
});
|
|
2006
2649
|
} else if (m.role === "tool") {
|
|
2007
2650
|
sections.push({
|
|
@@ -2110,7 +2753,7 @@ async function logTurnDebug(ctx) {
|
|
|
2110
2753
|
usage: ctx.usage,
|
|
2111
2754
|
promptSections,
|
|
2112
2755
|
promptTotalChars,
|
|
2113
|
-
promptTotalApproxTokens:
|
|
2756
|
+
promptTotalApproxTokens: approxTokens2(promptTotalChars),
|
|
2114
2757
|
toolStats,
|
|
2115
2758
|
toolTotalRawBytes: toolTotalRaw,
|
|
2116
2759
|
toolTotalReducedBytes: toolTotalReduced,
|
|
@@ -2590,801 +3233,345 @@ var require_node_gyp_build = __commonJS({
|
|
|
2590
3233
|
}
|
|
2591
3234
|
function compareTuples(a, b) {
|
|
2592
3235
|
return a.architectures.length - b.architectures.length;
|
|
2593
|
-
}
|
|
2594
|
-
function parseTags(file) {
|
|
2595
|
-
var arr = file.split(".");
|
|
2596
|
-
var extension = arr.pop();
|
|
2597
|
-
var tags = { file, specificity: 0 };
|
|
2598
|
-
if (extension !== "node") return;
|
|
2599
|
-
for (var i = 0; i < arr.length; i++) {
|
|
2600
|
-
var tag2 = arr[i];
|
|
2601
|
-
if (tag2 === "node" || tag2 === "electron" || tag2 === "node-webkit") {
|
|
2602
|
-
tags.runtime = tag2;
|
|
2603
|
-
} else if (tag2 === "napi") {
|
|
2604
|
-
tags.napi = true;
|
|
2605
|
-
} else if (tag2.slice(0, 3) === "abi") {
|
|
2606
|
-
tags.abi = tag2.slice(3);
|
|
2607
|
-
} else if (tag2.slice(0, 2) === "uv") {
|
|
2608
|
-
tags.uv = tag2.slice(2);
|
|
2609
|
-
} else if (tag2.slice(0, 4) === "armv") {
|
|
2610
|
-
tags.armv = tag2.slice(4);
|
|
2611
|
-
} else if (tag2 === "glibc" || tag2 === "musl") {
|
|
2612
|
-
tags.libc = tag2;
|
|
2613
|
-
} else {
|
|
2614
|
-
continue;
|
|
2615
|
-
}
|
|
2616
|
-
tags.specificity++;
|
|
2617
|
-
}
|
|
2618
|
-
return tags;
|
|
2619
|
-
}
|
|
2620
|
-
function matchTags(runtime2, abi2) {
|
|
2621
|
-
return function(tags) {
|
|
2622
|
-
if (tags == null) return false;
|
|
2623
|
-
if (tags.runtime && tags.runtime !== runtime2 && !runtimeAgnostic(tags)) return false;
|
|
2624
|
-
if (tags.abi && tags.abi !== abi2 && !tags.napi) return false;
|
|
2625
|
-
if (tags.uv && tags.uv !== uv) return false;
|
|
2626
|
-
if (tags.armv && tags.armv !== armv) return false;
|
|
2627
|
-
if (tags.libc && tags.libc !== libc) return false;
|
|
2628
|
-
return true;
|
|
2629
|
-
};
|
|
2630
|
-
}
|
|
2631
|
-
function runtimeAgnostic(tags) {
|
|
2632
|
-
return tags.runtime === "node" && tags.napi;
|
|
2633
|
-
}
|
|
2634
|
-
function compareTags(runtime2) {
|
|
2635
|
-
return function(a, b) {
|
|
2636
|
-
if (a.runtime !== b.runtime) {
|
|
2637
|
-
return a.runtime === runtime2 ? -1 : 1;
|
|
2638
|
-
} else if (a.abi !== b.abi) {
|
|
2639
|
-
return a.abi ? -1 : 1;
|
|
2640
|
-
} else if (a.specificity !== b.specificity) {
|
|
2641
|
-
return a.specificity > b.specificity ? -1 : 1;
|
|
2642
|
-
} else {
|
|
2643
|
-
return 0;
|
|
2644
|
-
}
|
|
2645
|
-
};
|
|
2646
|
-
}
|
|
2647
|
-
function isNwjs() {
|
|
2648
|
-
return !!(process.versions && process.versions.nw);
|
|
2649
|
-
}
|
|
2650
|
-
function isElectron() {
|
|
2651
|
-
if (process.versions && process.versions.electron) return true;
|
|
2652
|
-
if (process.env.ELECTRON_RUN_AS_NODE) return true;
|
|
2653
|
-
return typeof window !== "undefined" && window.process && window.process.type === "renderer";
|
|
2654
|
-
}
|
|
2655
|
-
function isAlpine(platform9) {
|
|
2656
|
-
return platform9 === "linux" && fs.existsSync("/etc/alpine-release");
|
|
2657
|
-
}
|
|
2658
|
-
load.parseTags = parseTags;
|
|
2659
|
-
load.matchTags = matchTags;
|
|
2660
|
-
load.compareTags = compareTags;
|
|
2661
|
-
load.parseTuple = parseTuple;
|
|
2662
|
-
load.matchTuple = matchTuple;
|
|
2663
|
-
load.compareTuples = compareTuples;
|
|
2664
|
-
}
|
|
2665
|
-
});
|
|
2666
|
-
|
|
2667
|
-
// node_modules/node-gyp-build/index.js
|
|
2668
|
-
var require_node_gyp_build2 = __commonJS({
|
|
2669
|
-
"node_modules/node-gyp-build/index.js"(exports, module) {
|
|
2670
|
-
"use strict";
|
|
2671
|
-
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
2672
|
-
if (typeof runtimeRequire.addon === "function") {
|
|
2673
|
-
module.exports = runtimeRequire.addon.bind(runtimeRequire);
|
|
2674
|
-
} else {
|
|
2675
|
-
module.exports = require_node_gyp_build();
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
});
|
|
2679
|
-
|
|
2680
|
-
// node_modules/isolated-vm/isolated-vm.js
|
|
2681
|
-
var require_isolated_vm = __commonJS({
|
|
2682
|
-
"node_modules/isolated-vm/isolated-vm.js"(exports, module) {
|
|
2683
|
-
"use strict";
|
|
2684
|
-
module.exports = require_node_gyp_build2()(__dirname).ivm;
|
|
2685
|
-
}
|
|
2686
|
-
});
|
|
2687
|
-
|
|
2688
|
-
// src/code-mode/sandbox.ts
|
|
2689
|
-
import { join as join10, dirname as dirname5 } from "path";
|
|
2690
|
-
import { pathToFileURL } from "url";
|
|
2691
|
-
function stripTypescript(code) {
|
|
2692
|
-
let js = code;
|
|
2693
|
-
js = js.replace(/interface\s+\w+\s*\{[\s\S]*?\n\}/g, "");
|
|
2694
|
-
js = js.replace(/type\s+\w+\s*=\s*[^;]+;/g, "");
|
|
2695
|
-
js = js.replace(/(\w+)<[^>]+>(\s*\()/g, "$1$2");
|
|
2696
|
-
js = js.replace(/(\b(?:const|let|var)\s+\w+)\s*:\s*[^=;]+/g, "$1");
|
|
2697
|
-
js = js.replace(/(\(|,\s*)(\w+)\s*:\s*[^,)=]+/g, "$1$2");
|
|
2698
|
-
js = js.replace(/(\)[\s]*)\s*:\s*[^{]+(\s*\{)/g, "$1$2");
|
|
2699
|
-
js = js.replace(/(\)[\s]*)\s*:\s*Promise<[^>]+>(\s*\{)/g, "$1$2");
|
|
2700
|
-
js = js.replace(/\s+as\s+\w+(?:\[\])?/g, "");
|
|
2701
|
-
js = js.replace(/(\w+)(\??)!/g, "$1$2");
|
|
2702
|
-
js = js.replace(/import\s+type\s+[^;]+;/g, "");
|
|
2703
|
-
js = js.replace(/declare\s+[^;]+;/g, "");
|
|
2704
|
-
js = js.replace(/\n{3,}/g, "\n\n");
|
|
2705
|
-
return js.trim();
|
|
2706
|
-
}
|
|
2707
|
-
async function loadTypescript(cwd) {
|
|
2708
|
-
try {
|
|
2709
|
-
const tsPath = await import.meta.resolve("typescript");
|
|
2710
|
-
return await import(tsPath);
|
|
2711
|
-
} catch {
|
|
2712
|
-
}
|
|
2713
|
-
let dir = cwd;
|
|
2714
|
-
while (dir !== dirname5(dir)) {
|
|
2715
|
-
try {
|
|
2716
|
-
const tsPath = join10(dir, "node_modules", "typescript", "lib", "typescript.js");
|
|
2717
|
-
return await import(pathToFileURL(tsPath).href);
|
|
2718
|
-
} catch {
|
|
2719
|
-
}
|
|
2720
|
-
dir = dirname5(dir);
|
|
2721
|
-
}
|
|
2722
|
-
return null;
|
|
2723
|
-
}
|
|
2724
|
-
async function transpileOrStrip(code, cwd) {
|
|
2725
|
-
const ts = await loadTypescript(cwd);
|
|
2726
|
-
if (ts) {
|
|
2727
|
-
const result = ts.transpileModule(code, {
|
|
2728
|
-
compilerOptions: {
|
|
2729
|
-
module: ts.ModuleKind.ES2022,
|
|
2730
|
-
target: ts.ScriptTarget.ES2022,
|
|
2731
|
-
esModuleInterop: true,
|
|
2732
|
-
isolatedModules: true
|
|
2733
|
-
}
|
|
2734
|
-
});
|
|
2735
|
-
return { js: result.outputText, warnings: [] };
|
|
2736
|
-
}
|
|
2737
|
-
return {
|
|
2738
|
-
js: stripTypescript(code),
|
|
2739
|
-
warnings: ["TypeScript not found in node_modules. Using fallback parser; install typescript for reliable transpilation."]
|
|
2740
|
-
};
|
|
2741
|
-
}
|
|
2742
|
-
async function runWithIsolatedVm(opts2) {
|
|
2743
|
-
const { Isolate } = await Promise.resolve().then(() => __toESM(require_isolated_vm(), 1));
|
|
2744
|
-
const isolate = new Isolate({ memoryLimit: opts2.memoryLimitMB ?? 128 });
|
|
2745
|
-
const context = await isolate.createContext();
|
|
2746
|
-
const jail = context.global;
|
|
2747
|
-
await jail.set("global", jail.derefInto());
|
|
2748
|
-
const logs = [];
|
|
2749
|
-
const toolCalls = [];
|
|
2750
|
-
await context.evalClosure(
|
|
2751
|
-
`globalThis._log = function(...args) {
|
|
2752
|
-
$0.applySync(undefined, [args.map(String).join(" ")], { arguments: { copy: true } });
|
|
2753
|
-
};`,
|
|
2754
|
-
[(msg) => logs.push(msg)],
|
|
2755
|
-
{ arguments: { reference: true } }
|
|
2756
|
-
);
|
|
2757
|
-
await context.eval(`var console = { log: function(...args) { _log(args.map(String).join(" ")); } };`);
|
|
2758
|
-
const toolMap = new Map(opts2.tools.map((t) => [t.name, t]));
|
|
2759
|
-
for (const tool of opts2.tools) {
|
|
2760
|
-
const ref = new (await Promise.resolve().then(() => __toESM(require_isolated_vm(), 1))).Reference(
|
|
2761
|
-
async (argsJson) => {
|
|
2762
|
-
const args = JSON.parse(argsJson);
|
|
2763
|
-
const toolCallId = `code_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2764
|
-
const result = await opts2.executor.run(
|
|
2765
|
-
{ id: toolCallId, name: tool.name, arguments: JSON.stringify(args) },
|
|
2766
|
-
opts2.askPermission,
|
|
2767
|
-
opts2.ctx
|
|
2768
|
-
);
|
|
2769
|
-
toolCalls.push({
|
|
2770
|
-
name: tool.name,
|
|
2771
|
-
args,
|
|
2772
|
-
result: result.content
|
|
2773
|
-
});
|
|
2774
|
-
return result.content;
|
|
2775
|
-
}
|
|
2776
|
-
);
|
|
2777
|
-
await context.evalClosure(
|
|
2778
|
-
`globalThis["_api_${tool.name}"] = function(argsJson) {
|
|
2779
|
-
return $0.applySyncPromise(undefined, [argsJson], { arguments: { copy: true } });
|
|
2780
|
-
};`,
|
|
2781
|
-
[ref],
|
|
2782
|
-
{ arguments: { reference: true } }
|
|
2783
|
-
);
|
|
2784
|
-
}
|
|
2785
|
-
const apiMethods = opts2.tools.map((t) => ` ${t.name}: function(input) { return _api_${t.name}(JSON.stringify(input ?? {})); }`).join(",\n");
|
|
2786
|
-
await context.eval(`var api = {
|
|
2787
|
-
${apiMethods}
|
|
2788
|
-
};`);
|
|
2789
|
-
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
2790
|
-
const wrapped = `(async function() {
|
|
2791
|
-
${jsCode}
|
|
2792
|
-
})();`;
|
|
2793
|
-
try {
|
|
2794
|
-
const timeout = opts2.timeoutMs ?? 3e4;
|
|
2795
|
-
const script = await isolate.compileScript(wrapped);
|
|
2796
|
-
await script.run(context, { timeout, release: true });
|
|
2797
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
2798
|
-
} catch (err) {
|
|
2799
|
-
const message2 = err instanceof Error ? err.message : String(err);
|
|
2800
|
-
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
2801
|
-
} finally {
|
|
2802
|
-
isolate.dispose();
|
|
2803
|
-
}
|
|
2804
|
-
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
2805
|
-
}
|
|
2806
|
-
async function runWithNodeVm(opts2) {
|
|
2807
|
-
const { runInNewContext } = await import("vm");
|
|
2808
|
-
const logs = [];
|
|
2809
|
-
const toolCalls = [];
|
|
2810
|
-
const sandbox = {
|
|
2811
|
-
console: {
|
|
2812
|
-
log: (...args) => {
|
|
2813
|
-
logs.push(args.map(String).join(" "));
|
|
2814
|
-
}
|
|
2815
|
-
},
|
|
2816
|
-
api: {},
|
|
2817
|
-
setTimeout,
|
|
2818
|
-
clearTimeout,
|
|
2819
|
-
setInterval,
|
|
2820
|
-
clearInterval,
|
|
2821
|
-
Promise,
|
|
2822
|
-
JSON,
|
|
2823
|
-
Math,
|
|
2824
|
-
Date,
|
|
2825
|
-
Array,
|
|
2826
|
-
Object,
|
|
2827
|
-
String,
|
|
2828
|
-
Number,
|
|
2829
|
-
Boolean,
|
|
2830
|
-
RegExp,
|
|
2831
|
-
Error,
|
|
2832
|
-
TypeError,
|
|
2833
|
-
RangeError,
|
|
2834
|
-
SyntaxError,
|
|
2835
|
-
ReferenceError,
|
|
2836
|
-
Map,
|
|
2837
|
-
Set,
|
|
2838
|
-
WeakMap,
|
|
2839
|
-
WeakSet,
|
|
2840
|
-
Symbol,
|
|
2841
|
-
parseInt,
|
|
2842
|
-
parseFloat,
|
|
2843
|
-
isNaN,
|
|
2844
|
-
isFinite,
|
|
2845
|
-
encodeURI,
|
|
2846
|
-
decodeURI,
|
|
2847
|
-
encodeURIComponent,
|
|
2848
|
-
decodeURIComponent,
|
|
2849
|
-
escape,
|
|
2850
|
-
unescape,
|
|
2851
|
-
Infinity: Infinity,
|
|
2852
|
-
NaN: NaN,
|
|
2853
|
-
undefined: void 0
|
|
2854
|
-
};
|
|
2855
|
-
for (const tool of opts2.tools) {
|
|
2856
|
-
sandbox.api[tool.name] = async (input) => {
|
|
2857
|
-
const args = input ?? {};
|
|
2858
|
-
const toolCallId = `code_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2859
|
-
const result = await opts2.executor.run(
|
|
2860
|
-
{ id: toolCallId, name: tool.name, arguments: JSON.stringify(args) },
|
|
2861
|
-
opts2.askPermission,
|
|
2862
|
-
opts2.ctx
|
|
2863
|
-
);
|
|
2864
|
-
toolCalls.push({
|
|
2865
|
-
name: tool.name,
|
|
2866
|
-
args,
|
|
2867
|
-
result: result.content
|
|
2868
|
-
});
|
|
2869
|
-
return result.content;
|
|
2870
|
-
};
|
|
2871
|
-
}
|
|
2872
|
-
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
2873
|
-
const wrapped = `"use strict";
|
|
2874
|
-
(async function() {
|
|
2875
|
-
${jsCode}
|
|
2876
|
-
})();`;
|
|
2877
|
-
try {
|
|
2878
|
-
const timeout = opts2.timeoutMs ?? 3e4;
|
|
2879
|
-
await runInNewContext(wrapped, sandbox, { timeout, displayErrors: true });
|
|
2880
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
2881
|
-
} catch (err) {
|
|
2882
|
-
const message2 = err instanceof Error ? err.message : String(err);
|
|
2883
|
-
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
2884
|
-
}
|
|
2885
|
-
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
2886
|
-
}
|
|
2887
|
-
function buildFallbackWarning(errMessage) {
|
|
2888
|
-
let reason;
|
|
2889
|
-
let fix;
|
|
2890
|
-
if (errMessage.includes("Cannot find module") || errMessage.includes("isolated-vm")) {
|
|
2891
|
-
reason = "The optional dependency `isolated-vm` is not installed.";
|
|
2892
|
-
fix = "Run `npm install isolated-vm` in your project (or `npm install -g isolated-vm` if KimiFlare is installed globally).";
|
|
2893
|
-
} else if (errMessage.includes("bindings") || errMessage.includes(".node")) {
|
|
2894
|
-
reason = "The `isolated-vm` native bindings are incompatible with this Node version or architecture.";
|
|
2895
|
-
fix = "Try `npm rebuild isolated-vm`, or switch to Node 22 LTS if you're on Apple Silicon.";
|
|
2896
|
-
} else {
|
|
2897
|
-
reason = "The secure sandbox (`isolated-vm`) could not be loaded.";
|
|
2898
|
-
fix = "Ensure build tools are installed, then run `npm install isolated-vm`.";
|
|
2899
|
-
}
|
|
2900
|
-
return `Code Mode is using the built-in Node.js sandbox. Tool execution works normally, but without memory limits or full process isolation. ${reason} ${fix}`;
|
|
2901
|
-
}
|
|
2902
|
-
async function runInSandbox(opts2) {
|
|
2903
|
-
try {
|
|
2904
|
-
return await runWithIsolatedVm(opts2);
|
|
2905
|
-
} catch (err) {
|
|
2906
|
-
const message2 = err instanceof Error ? err.message : String(err);
|
|
2907
|
-
const result = await runWithNodeVm(opts2);
|
|
2908
|
-
const sessionKey = opts2.ctx.sessionId ?? NO_SESSION_KEY;
|
|
2909
|
-
if (!fallbackWarningShownSessions.has(sessionKey)) {
|
|
2910
|
-
fallbackWarningShownSessions.add(sessionKey);
|
|
2911
|
-
const warning = buildFallbackWarning(message2);
|
|
2912
|
-
return { ...result, warnings: [warning, ...result.warnings ?? []] };
|
|
2913
|
-
}
|
|
2914
|
-
return result;
|
|
2915
|
-
}
|
|
2916
|
-
}
|
|
2917
|
-
var fallbackWarningShownSessions, NO_SESSION_KEY;
|
|
2918
|
-
var init_sandbox = __esm({
|
|
2919
|
-
"src/code-mode/sandbox.ts"() {
|
|
2920
|
-
"use strict";
|
|
2921
|
-
fallbackWarningShownSessions = /* @__PURE__ */ new Set();
|
|
2922
|
-
NO_SESSION_KEY = "__no_session__";
|
|
2923
|
-
}
|
|
2924
|
-
});
|
|
2925
|
-
|
|
2926
|
-
// src/code-mode/index.ts
|
|
2927
|
-
var init_code_mode = __esm({
|
|
2928
|
-
"src/code-mode/index.ts"() {
|
|
2929
|
-
"use strict";
|
|
2930
|
-
init_api_generator();
|
|
2931
|
-
init_sandbox();
|
|
2932
|
-
}
|
|
2933
|
-
});
|
|
2934
|
-
|
|
2935
|
-
// src/agent/session-state.ts
|
|
2936
|
-
function emptySessionState(task = "") {
|
|
2937
|
-
return {
|
|
2938
|
-
task,
|
|
2939
|
-
user_constraints: [],
|
|
2940
|
-
repo_facts: [],
|
|
2941
|
-
files_touched: [],
|
|
2942
|
-
files_modified: [],
|
|
2943
|
-
confirmed_findings: [],
|
|
2944
|
-
open_questions: [],
|
|
2945
|
-
recent_failures: [],
|
|
2946
|
-
decisions: [],
|
|
2947
|
-
next_actions: [],
|
|
2948
|
-
artifact_index: {}
|
|
2949
|
-
};
|
|
2950
|
-
}
|
|
2951
|
-
function serializeArtifactStore(store) {
|
|
2952
|
-
const MAX_ARTIFACT_CHARS = 5e4;
|
|
2953
|
-
const out = [];
|
|
2954
|
-
for (const a of store.list()) {
|
|
2955
|
-
out.push({
|
|
2956
|
-
id: a.id,
|
|
2957
|
-
type: a.type,
|
|
2958
|
-
summary: a.summary,
|
|
2959
|
-
raw: a.raw.slice(0, MAX_ARTIFACT_CHARS),
|
|
2960
|
-
source: a.source,
|
|
2961
|
-
path: a.path,
|
|
2962
|
-
lineRange: a.lineRange,
|
|
2963
|
-
ts: a.ts
|
|
2964
|
-
});
|
|
2965
|
-
}
|
|
2966
|
-
return out;
|
|
2967
|
-
}
|
|
2968
|
-
function deserializeArtifactStore(data) {
|
|
2969
|
-
const store = new ArtifactStore();
|
|
2970
|
-
for (const a of data) {
|
|
2971
|
-
store.add({
|
|
2972
|
-
id: a.id,
|
|
2973
|
-
type: a.type,
|
|
2974
|
-
summary: a.summary,
|
|
2975
|
-
raw: a.raw,
|
|
2976
|
-
source: a.source,
|
|
2977
|
-
path: a.path,
|
|
2978
|
-
lineRange: a.lineRange,
|
|
2979
|
-
ts: a.ts
|
|
2980
|
-
});
|
|
2981
|
-
}
|
|
2982
|
-
return store;
|
|
2983
|
-
}
|
|
2984
|
-
function formatRecalledArtifacts(recalled) {
|
|
2985
|
-
if (recalled.length === 0) return "";
|
|
2986
|
-
const lines = ["[recalled artifacts]"];
|
|
2987
|
-
for (const { id, artifact } of recalled) {
|
|
2988
|
-
lines.push(`--- artifact:${id} (${artifact.type} from ${artifact.source}) ---`);
|
|
2989
|
-
lines.push(artifact.raw);
|
|
2990
|
-
}
|
|
2991
|
-
return lines.join("\n");
|
|
2992
|
-
}
|
|
2993
|
-
function serializeSessionState(state) {
|
|
2994
|
-
const lines = [];
|
|
2995
|
-
lines.push(`task: ${state.task || "(none)"}`);
|
|
2996
|
-
if (state.user_constraints.length) lines.push(`constraints:
|
|
2997
|
-
${state.user_constraints.map((c) => " - " + c).join("\n")}`);
|
|
2998
|
-
if (state.repo_facts.length) lines.push(`repo_facts:
|
|
2999
|
-
${state.repo_facts.map((f) => " - " + f).join("\n")}`);
|
|
3000
|
-
if (state.files_touched.length) lines.push(`files_touched: ${state.files_touched.join(", ")}`);
|
|
3001
|
-
if (state.files_modified.length) lines.push(`files_modified: ${state.files_modified.join(", ")}`);
|
|
3002
|
-
if (state.confirmed_findings.length) lines.push(`findings:
|
|
3003
|
-
${state.confirmed_findings.map((f) => " - " + f).join("\n")}`);
|
|
3004
|
-
if (state.open_questions.length) lines.push(`open_questions:
|
|
3005
|
-
${state.open_questions.map((q) => " - " + q).join("\n")}`);
|
|
3006
|
-
if (state.recent_failures.length) lines.push(`recent_failures:
|
|
3007
|
-
${state.recent_failures.map((f) => " - " + f).join("\n")}`);
|
|
3008
|
-
if (state.decisions.length) lines.push(`decisions:
|
|
3009
|
-
${state.decisions.map((d) => " - " + d).join("\n")}`);
|
|
3010
|
-
if (state.next_actions.length) lines.push(`next_actions:
|
|
3011
|
-
${state.next_actions.map((a) => " - " + a).join("\n")}`);
|
|
3012
|
-
if (Object.keys(state.artifact_index).length) {
|
|
3013
|
-
lines.push("artifact_index:");
|
|
3014
|
-
for (const [id, meta] of Object.entries(state.artifact_index)) {
|
|
3015
|
-
lines.push(` ${id}: [${meta.type}] ${meta.summary}`);
|
|
3016
|
-
}
|
|
3017
|
-
}
|
|
3018
|
-
return lines.join("\n");
|
|
3019
|
-
}
|
|
3020
|
-
function buildSessionStateMessage(state) {
|
|
3021
|
-
return {
|
|
3022
|
-
role: "system",
|
|
3023
|
-
content: `[compiled session state]
|
|
3024
|
-
${serializeSessionState(state)}`
|
|
3025
|
-
};
|
|
3026
|
-
}
|
|
3027
|
-
var ArtifactStore;
|
|
3028
|
-
var init_session_state = __esm({
|
|
3029
|
-
"src/agent/session-state.ts"() {
|
|
3030
|
-
"use strict";
|
|
3031
|
-
ArtifactStore = class {
|
|
3032
|
-
artifacts = /* @__PURE__ */ new Map();
|
|
3033
|
-
maxArtifacts;
|
|
3034
|
-
maxTotalChars;
|
|
3035
|
-
constructor(opts2) {
|
|
3036
|
-
this.maxArtifacts = opts2?.maxArtifacts ?? 200;
|
|
3037
|
-
this.maxTotalChars = opts2?.maxTotalChars ?? 5e5;
|
|
3038
|
-
}
|
|
3039
|
-
add(a) {
|
|
3040
|
-
while (this.totalChars() + a.raw.length > this.maxTotalChars && this.artifacts.size > 0) {
|
|
3041
|
-
this.evictSizeWeighted();
|
|
3042
|
-
}
|
|
3043
|
-
while (this.artifacts.size >= this.maxArtifacts) {
|
|
3044
|
-
this.evictOldest();
|
|
3045
|
-
}
|
|
3046
|
-
this.artifacts.set(a.id, a);
|
|
3047
|
-
}
|
|
3048
|
-
get(id) {
|
|
3049
|
-
return this.artifacts.get(id);
|
|
3050
|
-
}
|
|
3051
|
-
has(id) {
|
|
3052
|
-
return this.artifacts.has(id);
|
|
3053
|
-
}
|
|
3054
|
-
list() {
|
|
3055
|
-
return [...this.artifacts.values()].sort((a, b) => a.ts < b.ts ? -1 : 1);
|
|
3056
|
-
}
|
|
3057
|
-
recall(ids) {
|
|
3058
|
-
const out = [];
|
|
3059
|
-
for (const id of ids) {
|
|
3060
|
-
const a = this.artifacts.get(id);
|
|
3061
|
-
if (a) out.push({ id, artifact: a });
|
|
3062
|
-
}
|
|
3063
|
-
return out;
|
|
3064
|
-
}
|
|
3065
|
-
size() {
|
|
3066
|
-
return this.artifacts.size;
|
|
3067
|
-
}
|
|
3068
|
-
totalChars() {
|
|
3069
|
-
let sum = 0;
|
|
3070
|
-
for (const a of this.artifacts.values()) {
|
|
3071
|
-
sum += a.raw.length;
|
|
3072
|
-
}
|
|
3073
|
-
return sum;
|
|
3074
|
-
}
|
|
3075
|
-
evictOldest() {
|
|
3076
|
-
let oldest;
|
|
3077
|
-
for (const a of this.artifacts.values()) {
|
|
3078
|
-
if (!oldest || a.ts < oldest.ts) oldest = a;
|
|
3079
|
-
}
|
|
3080
|
-
if (oldest) this.artifacts.delete(oldest.id);
|
|
3081
|
-
}
|
|
3082
|
-
/** Evict the largest artifact among the oldest quartile (by timestamp).
|
|
3083
|
-
* Bounded by the oldest quartile so we never evict freshly-added artifacts;
|
|
3084
|
-
* size-weighted within that window so one big artifact gets dropped instead
|
|
3085
|
-
* of many small ones. */
|
|
3086
|
-
evictSizeWeighted() {
|
|
3087
|
-
const sorted = [...this.artifacts.values()].sort((a, b) => a.ts < b.ts ? -1 : 1);
|
|
3088
|
-
if (sorted.length === 0) return;
|
|
3089
|
-
const quartile = Math.max(1, Math.ceil(sorted.length / 4));
|
|
3090
|
-
const candidates = sorted.slice(0, quartile);
|
|
3091
|
-
let pick3 = candidates[0];
|
|
3092
|
-
for (const a of candidates) {
|
|
3093
|
-
if (a.raw.length > pick3.raw.length) pick3 = a;
|
|
3094
|
-
}
|
|
3095
|
-
this.artifacts.delete(pick3.id);
|
|
3096
|
-
}
|
|
3097
|
-
};
|
|
3098
|
-
}
|
|
3099
|
-
});
|
|
3100
|
-
|
|
3101
|
-
// src/agent/artifact-compaction.ts
|
|
3102
|
-
function approxTokens2(n) {
|
|
3103
|
-
return Math.round(n / 3.5);
|
|
3104
|
-
}
|
|
3105
|
-
function estimateMessageTokens(m) {
|
|
3106
|
-
let chars = 0;
|
|
3107
|
-
if (typeof m.content === "string") {
|
|
3108
|
-
chars = m.content.length;
|
|
3109
|
-
} else if (Array.isArray(m.content)) {
|
|
3110
|
-
chars = m.content.map((p) => p.type === "text" ? p.text.length : 0).reduce((a, b) => a + b, 0);
|
|
3111
|
-
}
|
|
3112
|
-
if (m.reasoning_content) chars += m.reasoning_content.length;
|
|
3113
|
-
if (m.tool_calls) {
|
|
3114
|
-
for (const tc of m.tool_calls) {
|
|
3115
|
-
chars += tc.function.name.length + tc.function.arguments.length;
|
|
3116
|
-
}
|
|
3117
|
-
}
|
|
3118
|
-
return approxTokens2(chars);
|
|
3119
|
-
}
|
|
3120
|
-
function estimatePromptTokens(messages) {
|
|
3121
|
-
return messages.reduce((sum, m) => sum + estimateMessageTokens(m), 0);
|
|
3122
|
-
}
|
|
3123
|
-
function groupIntoTurns(messages) {
|
|
3124
|
-
const prefix = [];
|
|
3125
|
-
let i = 0;
|
|
3126
|
-
while (i < messages.length && messages[i].role === "system") {
|
|
3127
|
-
prefix.push(messages[i]);
|
|
3128
|
-
i++;
|
|
3129
|
-
}
|
|
3130
|
-
const turns = [];
|
|
3131
|
-
while (i < messages.length) {
|
|
3132
|
-
if (messages[i].role !== "user") {
|
|
3133
|
-
i++;
|
|
3134
|
-
continue;
|
|
3135
|
-
}
|
|
3136
|
-
const user = messages[i];
|
|
3137
|
-
i++;
|
|
3138
|
-
if (i >= messages.length || messages[i].role !== "assistant") {
|
|
3139
|
-
continue;
|
|
3140
|
-
}
|
|
3141
|
-
const assistant = messages[i];
|
|
3142
|
-
i++;
|
|
3143
|
-
const tools = [];
|
|
3144
|
-
while (i < messages.length && messages[i].role === "tool") {
|
|
3145
|
-
tools.push(messages[i]);
|
|
3146
|
-
i++;
|
|
3147
|
-
}
|
|
3148
|
-
turns.push({ user, assistant, tools });
|
|
3149
|
-
}
|
|
3150
|
-
return { prefix, turns };
|
|
3151
|
-
}
|
|
3152
|
-
function makeArtifactId(type, index) {
|
|
3153
|
-
return `${type}_${Date.now()}_${index}`;
|
|
3154
|
-
}
|
|
3155
|
-
function extractArtifactsFromTurn(turn, startIndex, store) {
|
|
3156
|
-
const artifacts = [];
|
|
3157
|
-
const stateDelta = {
|
|
3158
|
-
files_touched: [],
|
|
3159
|
-
files_modified: [],
|
|
3160
|
-
confirmed_findings: [],
|
|
3161
|
-
recent_failures: [],
|
|
3162
|
-
decisions: [],
|
|
3163
|
-
next_actions: []
|
|
3164
|
-
};
|
|
3165
|
-
const toolCalls = turn.assistant.tool_calls ?? [];
|
|
3166
|
-
for (let ti = 0; ti < turn.tools.length; ti++) {
|
|
3167
|
-
const tm = turn.tools[ti];
|
|
3168
|
-
const tc = toolCalls[ti];
|
|
3169
|
-
const name = tm.name ?? tc?.function.name ?? "unknown";
|
|
3170
|
-
const content = typeof tm.content === "string" ? tm.content : "";
|
|
3171
|
-
let type = "tool_result";
|
|
3172
|
-
let summary = `${name} result`;
|
|
3173
|
-
let path;
|
|
3174
|
-
if (name === "read") {
|
|
3175
|
-
type = "read_slice";
|
|
3176
|
-
try {
|
|
3177
|
-
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
3178
|
-
path = args.path;
|
|
3179
|
-
summary = `read ${path ?? "file"}`;
|
|
3180
|
-
if (path && !stateDelta.files_touched.includes(path)) stateDelta.files_touched.push(path);
|
|
3181
|
-
} catch {
|
|
3182
|
-
summary = "read file";
|
|
3183
|
-
}
|
|
3184
|
-
} else if (name === "bash") {
|
|
3185
|
-
type = "bash_log";
|
|
3186
|
-
try {
|
|
3187
|
-
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
3188
|
-
const cmd = args.command ?? "";
|
|
3189
|
-
summary = `bash: ${cmd.slice(0, 60)}`;
|
|
3190
|
-
if (content.includes("Error") || content.includes("error") || content.includes("FAIL")) {
|
|
3191
|
-
stateDelta.recent_failures.push(`bash failed: ${cmd.slice(0, 80)}`);
|
|
3192
|
-
}
|
|
3193
|
-
} catch {
|
|
3194
|
-
summary = "bash command";
|
|
3195
|
-
}
|
|
3196
|
-
} else if (name === "grep") {
|
|
3197
|
-
type = "grep_result";
|
|
3198
|
-
summary = `grep results (${content.split("\n").length} lines)`;
|
|
3199
|
-
} else if (name === "web_fetch") {
|
|
3200
|
-
type = "web_fetch";
|
|
3201
|
-
try {
|
|
3202
|
-
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
3203
|
-
summary = `web_fetch: ${args.url ?? "url"}`;
|
|
3204
|
-
} catch {
|
|
3205
|
-
summary = "web_fetch";
|
|
3206
|
-
}
|
|
3207
|
-
} else if (name === "write" || name === "edit") {
|
|
3208
|
-
try {
|
|
3209
|
-
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
3210
|
-
path = args.path;
|
|
3211
|
-
if (path && !stateDelta.files_modified.includes(path)) stateDelta.files_modified.push(path);
|
|
3212
|
-
if (path && !stateDelta.files_touched.includes(path)) stateDelta.files_touched.push(path);
|
|
3213
|
-
} catch {
|
|
3214
|
-
}
|
|
3215
|
-
continue;
|
|
3216
|
-
} else if (name === "glob") {
|
|
3217
|
-
try {
|
|
3218
|
-
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
3219
|
-
summary = `glob: ${args.pattern ?? ""}`;
|
|
3220
|
-
} catch {
|
|
3221
|
-
summary = "glob";
|
|
3222
|
-
}
|
|
3223
|
-
} else if (name === "tasks_set") {
|
|
3224
|
-
try {
|
|
3225
|
-
const args = tc ? JSON.parse(tc.function.arguments) : {};
|
|
3226
|
-
const tasks = args.tasks ?? [];
|
|
3227
|
-
const inProgress = tasks.filter((t) => t.status === "in_progress").map((t) => t.title);
|
|
3228
|
-
const pending = tasks.filter((t) => t.status === "pending").map((t) => t.title);
|
|
3229
|
-
if (inProgress.length) stateDelta.next_actions.push(...inProgress);
|
|
3230
|
-
if (pending.length) stateDelta.next_actions.push(...pending);
|
|
3231
|
-
summary = `tasks_set: ${tasks.length} tasks`;
|
|
3232
|
-
} catch {
|
|
3233
|
-
summary = "tasks_set";
|
|
3236
|
+
}
|
|
3237
|
+
function parseTags(file) {
|
|
3238
|
+
var arr = file.split(".");
|
|
3239
|
+
var extension = arr.pop();
|
|
3240
|
+
var tags = { file, specificity: 0 };
|
|
3241
|
+
if (extension !== "node") return;
|
|
3242
|
+
for (var i = 0; i < arr.length; i++) {
|
|
3243
|
+
var tag2 = arr[i];
|
|
3244
|
+
if (tag2 === "node" || tag2 === "electron" || tag2 === "node-webkit") {
|
|
3245
|
+
tags.runtime = tag2;
|
|
3246
|
+
} else if (tag2 === "napi") {
|
|
3247
|
+
tags.napi = true;
|
|
3248
|
+
} else if (tag2.slice(0, 3) === "abi") {
|
|
3249
|
+
tags.abi = tag2.slice(3);
|
|
3250
|
+
} else if (tag2.slice(0, 2) === "uv") {
|
|
3251
|
+
tags.uv = tag2.slice(2);
|
|
3252
|
+
} else if (tag2.slice(0, 4) === "armv") {
|
|
3253
|
+
tags.armv = tag2.slice(4);
|
|
3254
|
+
} else if (tag2 === "glibc" || tag2 === "musl") {
|
|
3255
|
+
tags.libc = tag2;
|
|
3256
|
+
} else {
|
|
3257
|
+
continue;
|
|
3258
|
+
}
|
|
3259
|
+
tags.specificity++;
|
|
3234
3260
|
}
|
|
3261
|
+
return tags;
|
|
3235
3262
|
}
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
3247
|
-
};
|
|
3248
|
-
artifacts.push(artifact);
|
|
3249
|
-
if (!content.includes("Error") && !content.includes("error") && content.length > 0 && content.length < 2e3) {
|
|
3250
|
-
stateDelta.confirmed_findings.push(`${name}: ${content.slice(0, 200)}`);
|
|
3263
|
+
function matchTags(runtime2, abi2) {
|
|
3264
|
+
return function(tags) {
|
|
3265
|
+
if (tags == null) return false;
|
|
3266
|
+
if (tags.runtime && tags.runtime !== runtime2 && !runtimeAgnostic(tags)) return false;
|
|
3267
|
+
if (tags.abi && tags.abi !== abi2 && !tags.napi) return false;
|
|
3268
|
+
if (tags.uv && tags.uv !== uv) return false;
|
|
3269
|
+
if (tags.armv && tags.armv !== armv) return false;
|
|
3270
|
+
if (tags.libc && tags.libc !== libc) return false;
|
|
3271
|
+
return true;
|
|
3272
|
+
};
|
|
3251
3273
|
}
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3274
|
+
function runtimeAgnostic(tags) {
|
|
3275
|
+
return tags.runtime === "node" && tags.napi;
|
|
3276
|
+
}
|
|
3277
|
+
function compareTags(runtime2) {
|
|
3278
|
+
return function(a, b) {
|
|
3279
|
+
if (a.runtime !== b.runtime) {
|
|
3280
|
+
return a.runtime === runtime2 ? -1 : 1;
|
|
3281
|
+
} else if (a.abi !== b.abi) {
|
|
3282
|
+
return a.abi ? -1 : 1;
|
|
3283
|
+
} else if (a.specificity !== b.specificity) {
|
|
3284
|
+
return a.specificity > b.specificity ? -1 : 1;
|
|
3285
|
+
} else {
|
|
3286
|
+
return 0;
|
|
3265
3287
|
}
|
|
3266
|
-
}
|
|
3288
|
+
};
|
|
3289
|
+
}
|
|
3290
|
+
function isNwjs() {
|
|
3291
|
+
return !!(process.versions && process.versions.nw);
|
|
3292
|
+
}
|
|
3293
|
+
function isElectron() {
|
|
3294
|
+
if (process.versions && process.versions.electron) return true;
|
|
3295
|
+
if (process.env.ELECTRON_RUN_AS_NODE) return true;
|
|
3296
|
+
return typeof window !== "undefined" && window.process && window.process.type === "renderer";
|
|
3297
|
+
}
|
|
3298
|
+
function isAlpine(platform9) {
|
|
3299
|
+
return platform9 === "linux" && fs.existsSync("/etc/alpine-release");
|
|
3267
3300
|
}
|
|
3301
|
+
load.parseTags = parseTags;
|
|
3302
|
+
load.matchTags = matchTags;
|
|
3303
|
+
load.compareTags = compareTags;
|
|
3304
|
+
load.parseTuple = parseTuple;
|
|
3305
|
+
load.matchTuple = matchTuple;
|
|
3306
|
+
load.compareTuples = compareTuples;
|
|
3268
3307
|
}
|
|
3269
|
-
|
|
3308
|
+
});
|
|
3309
|
+
|
|
3310
|
+
// node_modules/node-gyp-build/index.js
|
|
3311
|
+
var require_node_gyp_build2 = __commonJS({
|
|
3312
|
+
"node_modules/node-gyp-build/index.js"(exports, module) {
|
|
3313
|
+
"use strict";
|
|
3314
|
+
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
3315
|
+
if (typeof runtimeRequire.addon === "function") {
|
|
3316
|
+
module.exports = runtimeRequire.addon.bind(runtimeRequire);
|
|
3317
|
+
} else {
|
|
3318
|
+
module.exports = require_node_gyp_build();
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3321
|
+
});
|
|
3322
|
+
|
|
3323
|
+
// node_modules/isolated-vm/isolated-vm.js
|
|
3324
|
+
var require_isolated_vm = __commonJS({
|
|
3325
|
+
"node_modules/isolated-vm/isolated-vm.js"(exports, module) {
|
|
3326
|
+
"use strict";
|
|
3327
|
+
module.exports = require_node_gyp_build2()(__dirname).ivm;
|
|
3328
|
+
}
|
|
3329
|
+
});
|
|
3330
|
+
|
|
3331
|
+
// src/code-mode/sandbox.ts
|
|
3332
|
+
import { join as join11, dirname as dirname5 } from "path";
|
|
3333
|
+
import { pathToFileURL } from "url";
|
|
3334
|
+
function stripTypescript(code) {
|
|
3335
|
+
let js = code;
|
|
3336
|
+
js = js.replace(/interface\s+\w+\s*\{[\s\S]*?\n\}/g, "");
|
|
3337
|
+
js = js.replace(/type\s+\w+\s*=\s*[^;]+;/g, "");
|
|
3338
|
+
js = js.replace(/(\w+)<[^>]+>(\s*\()/g, "$1$2");
|
|
3339
|
+
js = js.replace(/(\b(?:const|let|var)\s+\w+)\s*:\s*[^=;]+/g, "$1");
|
|
3340
|
+
js = js.replace(/(\(|,\s*)(\w+)\s*:\s*[^,)=]+/g, "$1$2");
|
|
3341
|
+
js = js.replace(/(\)[\s]*)\s*:\s*[^{]+(\s*\{)/g, "$1$2");
|
|
3342
|
+
js = js.replace(/(\)[\s]*)\s*:\s*Promise<[^>]+>(\s*\{)/g, "$1$2");
|
|
3343
|
+
js = js.replace(/\s+as\s+\w+(?:\[\])?/g, "");
|
|
3344
|
+
js = js.replace(/(\w+)(\??)!/g, "$1$2");
|
|
3345
|
+
js = js.replace(/import\s+type\s+[^;]+;/g, "");
|
|
3346
|
+
js = js.replace(/declare\s+[^;]+;/g, "");
|
|
3347
|
+
js = js.replace(/\n{3,}/g, "\n\n");
|
|
3348
|
+
return js.trim();
|
|
3270
3349
|
}
|
|
3271
|
-
function
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3350
|
+
async function loadTypescript(cwd) {
|
|
3351
|
+
try {
|
|
3352
|
+
const tsPath = await import.meta.resolve("typescript");
|
|
3353
|
+
return await import(tsPath);
|
|
3354
|
+
} catch {
|
|
3355
|
+
}
|
|
3356
|
+
let dir = cwd;
|
|
3357
|
+
while (dir !== dirname5(dir)) {
|
|
3358
|
+
try {
|
|
3359
|
+
const tsPath = join11(dir, "node_modules", "typescript", "lib", "typescript.js");
|
|
3360
|
+
return await import(pathToFileURL(tsPath).href);
|
|
3361
|
+
} catch {
|
|
3362
|
+
}
|
|
3363
|
+
dir = dirname5(dir);
|
|
3364
|
+
}
|
|
3365
|
+
return null;
|
|
3366
|
+
}
|
|
3367
|
+
async function transpileOrStrip(code, cwd) {
|
|
3368
|
+
const ts = await loadTypescript(cwd);
|
|
3369
|
+
if (ts) {
|
|
3370
|
+
const result = ts.transpileModule(code, {
|
|
3371
|
+
compilerOptions: {
|
|
3372
|
+
module: ts.ModuleKind.ES2022,
|
|
3373
|
+
target: ts.ScriptTarget.ES2022,
|
|
3374
|
+
esModuleInterop: true,
|
|
3375
|
+
isolatedModules: true
|
|
3376
|
+
}
|
|
3377
|
+
});
|
|
3378
|
+
return { js: result.outputText, warnings: [] };
|
|
3379
|
+
}
|
|
3278
3380
|
return {
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
user_constraints: mergeArr(state.user_constraints, delta.user_constraints),
|
|
3282
|
-
repo_facts: mergeArr(state.repo_facts, delta.repo_facts),
|
|
3283
|
-
files_touched: mergeArr(state.files_touched, delta.files_touched),
|
|
3284
|
-
files_modified: mergeArr(state.files_modified, delta.files_modified),
|
|
3285
|
-
confirmed_findings: mergeArr(state.confirmed_findings, delta.confirmed_findings),
|
|
3286
|
-
open_questions: mergeArr(state.open_questions, delta.open_questions),
|
|
3287
|
-
recent_failures: mergeArr(state.recent_failures, delta.recent_failures),
|
|
3288
|
-
decisions: mergeArr(state.decisions, delta.decisions),
|
|
3289
|
-
next_actions: mergeArr(state.next_actions, delta.next_actions),
|
|
3290
|
-
artifact_index: { ...state.artifact_index, ...delta.artifact_index }
|
|
3381
|
+
js: stripTypescript(code),
|
|
3382
|
+
warnings: ["TypeScript not found in node_modules. Using fallback parser; install typescript for reliable transpilation."]
|
|
3291
3383
|
};
|
|
3292
3384
|
}
|
|
3293
|
-
function
|
|
3294
|
-
const
|
|
3295
|
-
const
|
|
3296
|
-
const
|
|
3297
|
-
const
|
|
3298
|
-
|
|
3385
|
+
async function runWithIsolatedVm(opts2) {
|
|
3386
|
+
const { Isolate } = await Promise.resolve().then(() => __toESM(require_isolated_vm(), 1));
|
|
3387
|
+
const isolate = new Isolate({ memoryLimit: opts2.memoryLimitMB ?? 128 });
|
|
3388
|
+
const context = await isolate.createContext();
|
|
3389
|
+
const jail = context.global;
|
|
3390
|
+
await jail.set("global", jail.derefInto());
|
|
3391
|
+
const logs = [];
|
|
3392
|
+
const toolCalls = [];
|
|
3393
|
+
await context.evalClosure(
|
|
3394
|
+
`globalThis._log = function(...args) {
|
|
3395
|
+
$0.applySync(undefined, [args.map(String).join(" ")], { arguments: { copy: true } });
|
|
3396
|
+
};`,
|
|
3397
|
+
[(msg) => logs.push(msg)],
|
|
3398
|
+
{ arguments: { reference: true } }
|
|
3399
|
+
);
|
|
3400
|
+
await context.eval(`var console = { log: function(...args) { _log(args.map(String).join(" ")); } };`);
|
|
3401
|
+
const toolMap = new Map(opts2.tools.map((t) => [t.name, t]));
|
|
3402
|
+
for (const tool of opts2.tools) {
|
|
3403
|
+
const ref = new (await Promise.resolve().then(() => __toESM(require_isolated_vm(), 1))).Reference(
|
|
3404
|
+
async (argsJson) => {
|
|
3405
|
+
const args = JSON.parse(argsJson);
|
|
3406
|
+
const toolCallId = `code_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
3407
|
+
const result = await opts2.executor.run(
|
|
3408
|
+
{ id: toolCallId, name: tool.name, arguments: JSON.stringify(args) },
|
|
3409
|
+
opts2.askPermission,
|
|
3410
|
+
opts2.ctx
|
|
3411
|
+
);
|
|
3412
|
+
toolCalls.push({
|
|
3413
|
+
name: tool.name,
|
|
3414
|
+
args,
|
|
3415
|
+
result: result.content
|
|
3416
|
+
});
|
|
3417
|
+
return result.content;
|
|
3418
|
+
}
|
|
3419
|
+
);
|
|
3420
|
+
await context.evalClosure(
|
|
3421
|
+
`globalThis["_api_${tool.name}"] = function(argsJson) {
|
|
3422
|
+
return $0.applySyncPromise(undefined, [argsJson], { arguments: { copy: true } });
|
|
3423
|
+
};`,
|
|
3424
|
+
[ref],
|
|
3425
|
+
{ arguments: { reference: true } }
|
|
3426
|
+
);
|
|
3427
|
+
}
|
|
3428
|
+
const apiMethods = opts2.tools.map((t) => ` ${t.name}: function(input) { return _api_${t.name}(JSON.stringify(input ?? {})); }`).join(",\n");
|
|
3429
|
+
await context.eval(`var api = {
|
|
3430
|
+
${apiMethods}
|
|
3431
|
+
};`);
|
|
3432
|
+
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
3433
|
+
const wrapped = `(async function() {
|
|
3434
|
+
${jsCode}
|
|
3435
|
+
})();`;
|
|
3436
|
+
try {
|
|
3437
|
+
const timeout = opts2.timeoutMs ?? 3e4;
|
|
3438
|
+
const script = await isolate.compileScript(wrapped);
|
|
3439
|
+
await script.run(context, { timeout, release: true });
|
|
3440
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
3441
|
+
} catch (err) {
|
|
3442
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
3443
|
+
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
3444
|
+
} finally {
|
|
3445
|
+
isolate.dispose();
|
|
3446
|
+
}
|
|
3447
|
+
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
3299
3448
|
}
|
|
3300
|
-
function
|
|
3301
|
-
const
|
|
3302
|
-
const
|
|
3303
|
-
const
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
metrics: {
|
|
3309
|
-
estimatedTokensBefore: tokensBefore,
|
|
3310
|
-
estimatedTokensAfter: tokensBefore,
|
|
3311
|
-
archivedArtifacts: 0,
|
|
3312
|
-
recalledArtifacts: 0,
|
|
3313
|
-
rawTurnsRemoved: 0,
|
|
3314
|
-
rawTurnsKept: turns.length
|
|
3449
|
+
async function runWithNodeVm(opts2) {
|
|
3450
|
+
const { runInNewContext } = await import("vm");
|
|
3451
|
+
const logs = [];
|
|
3452
|
+
const toolCalls = [];
|
|
3453
|
+
const sandbox = {
|
|
3454
|
+
console: {
|
|
3455
|
+
log: (...args) => {
|
|
3456
|
+
logs.push(args.map(String).join(" "));
|
|
3315
3457
|
}
|
|
3458
|
+
},
|
|
3459
|
+
api: {},
|
|
3460
|
+
setTimeout,
|
|
3461
|
+
clearTimeout,
|
|
3462
|
+
setInterval,
|
|
3463
|
+
clearInterval,
|
|
3464
|
+
Promise,
|
|
3465
|
+
JSON,
|
|
3466
|
+
Math,
|
|
3467
|
+
Date,
|
|
3468
|
+
Array,
|
|
3469
|
+
Object,
|
|
3470
|
+
String,
|
|
3471
|
+
Number,
|
|
3472
|
+
Boolean,
|
|
3473
|
+
RegExp,
|
|
3474
|
+
Error,
|
|
3475
|
+
TypeError,
|
|
3476
|
+
RangeError,
|
|
3477
|
+
SyntaxError,
|
|
3478
|
+
ReferenceError,
|
|
3479
|
+
Map,
|
|
3480
|
+
Set,
|
|
3481
|
+
WeakMap,
|
|
3482
|
+
WeakSet,
|
|
3483
|
+
Symbol,
|
|
3484
|
+
parseInt,
|
|
3485
|
+
parseFloat,
|
|
3486
|
+
isNaN,
|
|
3487
|
+
isFinite,
|
|
3488
|
+
encodeURI,
|
|
3489
|
+
decodeURI,
|
|
3490
|
+
encodeURIComponent,
|
|
3491
|
+
decodeURIComponent,
|
|
3492
|
+
escape,
|
|
3493
|
+
unescape,
|
|
3494
|
+
Infinity: Infinity,
|
|
3495
|
+
NaN: NaN,
|
|
3496
|
+
undefined: void 0
|
|
3497
|
+
};
|
|
3498
|
+
for (const tool of opts2.tools) {
|
|
3499
|
+
sandbox.api[tool.name] = async (input) => {
|
|
3500
|
+
const args = input ?? {};
|
|
3501
|
+
const toolCallId = `code_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
3502
|
+
const result = await opts2.executor.run(
|
|
3503
|
+
{ id: toolCallId, name: tool.name, arguments: JSON.stringify(args) },
|
|
3504
|
+
opts2.askPermission,
|
|
3505
|
+
opts2.ctx
|
|
3506
|
+
);
|
|
3507
|
+
toolCalls.push({
|
|
3508
|
+
name: tool.name,
|
|
3509
|
+
args,
|
|
3510
|
+
result: result.content
|
|
3511
|
+
});
|
|
3512
|
+
return result.content;
|
|
3316
3513
|
};
|
|
3317
3514
|
}
|
|
3318
|
-
const
|
|
3319
|
-
const
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
const
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
summary: artifact.summary,
|
|
3331
|
-
source: artifact.source,
|
|
3332
|
-
path: artifact.path
|
|
3333
|
-
};
|
|
3334
|
-
}
|
|
3335
|
-
newState = mergeState(newState, stateDelta);
|
|
3336
|
-
if (!newState.task && typeof turn.user.content === "string") {
|
|
3337
|
-
newState.task = turn.user.content.slice(0, 200);
|
|
3338
|
-
}
|
|
3339
|
-
}
|
|
3340
|
-
const workingMemory = [];
|
|
3341
|
-
for (const turn of toKeep) {
|
|
3342
|
-
workingMemory.push(turn.user);
|
|
3343
|
-
workingMemory.push(turn.assistant);
|
|
3344
|
-
for (const tm of turn.tools) {
|
|
3345
|
-
workingMemory.push(tm);
|
|
3346
|
-
}
|
|
3515
|
+
const { js: jsCode, warnings } = await transpileOrStrip(opts2.code, opts2.ctx.cwd);
|
|
3516
|
+
const wrapped = `"use strict";
|
|
3517
|
+
(async function() {
|
|
3518
|
+
${jsCode}
|
|
3519
|
+
})();`;
|
|
3520
|
+
try {
|
|
3521
|
+
const timeout = opts2.timeoutMs ?? 3e4;
|
|
3522
|
+
await runInNewContext(wrapped, sandbox, { timeout, displayErrors: true });
|
|
3523
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
3524
|
+
} catch (err) {
|
|
3525
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
3526
|
+
return { output: "", logs, error: message2, toolCalls, warnings };
|
|
3347
3527
|
}
|
|
3348
|
-
|
|
3349
|
-
const newMessages = [...prefix, stateMsg, ...workingMemory];
|
|
3350
|
-
const tokensAfter = estimatePromptTokens(newMessages);
|
|
3351
|
-
const metrics = {
|
|
3352
|
-
estimatedTokensBefore: tokensBefore,
|
|
3353
|
-
estimatedTokensAfter: tokensAfter,
|
|
3354
|
-
archivedArtifacts: archivedCount,
|
|
3355
|
-
recalledArtifacts: 0,
|
|
3356
|
-
rawTurnsRemoved: toCompact.length,
|
|
3357
|
-
rawTurnsKept: toKeep.length
|
|
3358
|
-
};
|
|
3359
|
-
return { newMessages, newState, metrics };
|
|
3528
|
+
return { output: logs.join("\n"), logs, toolCalls, warnings };
|
|
3360
3529
|
}
|
|
3361
|
-
function
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3530
|
+
function buildFallbackWarning(errMessage) {
|
|
3531
|
+
let reason;
|
|
3532
|
+
let fix;
|
|
3533
|
+
if (errMessage.includes("Cannot find module") || errMessage.includes("isolated-vm")) {
|
|
3534
|
+
reason = "The optional dependency `isolated-vm` is not installed.";
|
|
3535
|
+
fix = "Run `npm install isolated-vm` in your project (or `npm install -g isolated-vm` if KimiFlare is installed globally).";
|
|
3536
|
+
} else if (errMessage.includes("bindings") || errMessage.includes(".node")) {
|
|
3537
|
+
reason = "The `isolated-vm` native bindings are incompatible with this Node version or architecture.";
|
|
3538
|
+
fix = "Try `npm rebuild isolated-vm`, or switch to Node 22 LTS if you're on Apple Silicon.";
|
|
3539
|
+
} else {
|
|
3540
|
+
reason = "The secure sandbox (`isolated-vm`) could not be loaded.";
|
|
3541
|
+
fix = "Ensure build tools are installed, then run `npm install isolated-vm`.";
|
|
3368
3542
|
}
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3543
|
+
return `Code Mode is using the built-in Node.js sandbox. Tool execution works normally, but without memory limits or full process isolation. ${reason} ${fix}`;
|
|
3544
|
+
}
|
|
3545
|
+
async function runInSandbox(opts2) {
|
|
3546
|
+
try {
|
|
3547
|
+
return await runWithIsolatedVm(opts2);
|
|
3548
|
+
} catch (err) {
|
|
3549
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
3550
|
+
const result = await runWithNodeVm(opts2);
|
|
3551
|
+
const sessionKey = opts2.ctx.sessionId ?? NO_SESSION_KEY;
|
|
3552
|
+
if (!fallbackWarningShownSessions.has(sessionKey)) {
|
|
3553
|
+
fallbackWarningShownSessions.add(sessionKey);
|
|
3554
|
+
const warning = buildFallbackWarning(message2);
|
|
3555
|
+
return { ...result, warnings: [warning, ...result.warnings ?? []] };
|
|
3378
3556
|
}
|
|
3557
|
+
return result;
|
|
3379
3558
|
}
|
|
3380
|
-
const uniqueIds = [...new Set(ids)].slice(0, 5);
|
|
3381
|
-
const recalled = store.recall(uniqueIds);
|
|
3382
|
-
return { ids: uniqueIds, recalled };
|
|
3383
3559
|
}
|
|
3384
|
-
var
|
|
3385
|
-
|
|
3560
|
+
var fallbackWarningShownSessions, NO_SESSION_KEY;
|
|
3561
|
+
var init_sandbox = __esm({
|
|
3562
|
+
"src/code-mode/sandbox.ts"() {
|
|
3386
3563
|
"use strict";
|
|
3387
|
-
|
|
3564
|
+
fallbackWarningShownSessions = /* @__PURE__ */ new Set();
|
|
3565
|
+
NO_SESSION_KEY = "__no_session__";
|
|
3566
|
+
}
|
|
3567
|
+
});
|
|
3568
|
+
|
|
3569
|
+
// src/code-mode/index.ts
|
|
3570
|
+
var init_code_mode = __esm({
|
|
3571
|
+
"src/code-mode/index.ts"() {
|
|
3572
|
+
"use strict";
|
|
3573
|
+
init_api_generator();
|
|
3574
|
+
init_sandbox();
|
|
3388
3575
|
}
|
|
3389
3576
|
});
|
|
3390
3577
|
|
|
@@ -3987,12 +4174,12 @@ var init_mode = __esm({
|
|
|
3987
4174
|
});
|
|
3988
4175
|
|
|
3989
4176
|
// src/agent/system-prompt.ts
|
|
3990
|
-
import { platform, release, homedir as
|
|
3991
|
-
import { basename, join as
|
|
4177
|
+
import { platform, release, homedir as homedir7 } from "os";
|
|
4178
|
+
import { basename, join as join12 } from "path";
|
|
3992
4179
|
import { readFileSync as readFileSync2, statSync as statSync2 } from "fs";
|
|
3993
4180
|
function loadContextFile(cwd) {
|
|
3994
4181
|
for (const name of CONTEXT_FILENAMES) {
|
|
3995
|
-
const path =
|
|
4182
|
+
const path = join12(cwd, name);
|
|
3996
4183
|
try {
|
|
3997
4184
|
const s = statSync2(path);
|
|
3998
4185
|
if (!s.isFile() || s.size > MAX_CONTEXT_BYTES) continue;
|
|
@@ -4042,7 +4229,7 @@ If the user asks what model you are, answer with exactly: \`${opts2.model}\`. Th
|
|
|
4042
4229
|
- Working directory: ${opts2.cwd}
|
|
4043
4230
|
- Platform: ${platform()} ${release()}
|
|
4044
4231
|
- Shell: ${shell}
|
|
4045
|
-
- Home: ${
|
|
4232
|
+
- Home: ${homedir7()}
|
|
4046
4233
|
- Today: ${date}`;
|
|
4047
4234
|
const hasLsp = opts2.tools.some((t) => t.name.startsWith("lsp_"));
|
|
4048
4235
|
const lspBlock = hasLsp ? "\n\nLSP tools are available for semantic code intelligence. Prefer `lsp_definition` over `grep` when looking for the source of a symbol. Prefer `lsp_references` over `grep` when finding usages. Use `lsp_hover` to confirm types before refactoring." : "";
|
|
@@ -4118,6 +4305,9 @@ function getSessionWebFetchHistory(sessionId) {
|
|
|
4118
4305
|
function isHighSignalMemory(memory) {
|
|
4119
4306
|
return memory.topicKey === "project_dependencies" || memory.topicKey === "project_tsconfig" || memory.topicKey === "project_entry_point" || memory.category === "instruction" || memory.category === "preference" || memory.category === "event" && memory.importance >= 3;
|
|
4120
4307
|
}
|
|
4308
|
+
function codeModeRedirectMessage(tool) {
|
|
4309
|
+
return `Code Mode is on: \`${tool}\` is not available as a direct tool because its full output would flood your context. Call \`api.${tool}({ ... })\` INSIDE an \`execute_code\` block instead \u2014 only what you \`console.log\` is returned to you. You can batch several reads/greps/commands in a single execute_code call.`;
|
|
4310
|
+
}
|
|
4121
4311
|
function extractLastUserText(messages) {
|
|
4122
4312
|
const lastUser = [...messages].reverse().find((m) => m.role === "user");
|
|
4123
4313
|
if (!lastUser) return "";
|
|
@@ -4162,7 +4352,7 @@ async function runAgentTurn(opts2) {
|
|
|
4162
4352
|
const lastUserPrompt = extractLastUserText(opts2.messages);
|
|
4163
4353
|
const userPromptPreview = lastUserPrompt.slice(0, 200);
|
|
4164
4354
|
const skipSkillRouting = opts2.intentClassification?.tier === "light" && lastUserPrompt.length < 40;
|
|
4165
|
-
const recallPromise = opts2.sessionStartRecall && opts2.memoryManager ? (async () => {
|
|
4355
|
+
const recallPromise = opts2.sessionStartRecall && opts2.memoryManager && !hasRecalledMemory(opts2.messages) ? (async () => {
|
|
4166
4356
|
const results = await opts2.sessionStartRecall;
|
|
4167
4357
|
if (results.length === 0 || !opts2.memoryManager) return null;
|
|
4168
4358
|
const text = await opts2.memoryManager.synthesizeRecalled(results, opts2.signal);
|
|
@@ -4193,11 +4383,10 @@ async function runAgentTurn(opts2) {
|
|
|
4193
4383
|
}
|
|
4194
4384
|
if (recallSettled.status === "fulfilled" && recallSettled.value) {
|
|
4195
4385
|
const { text, count } = recallSettled.value;
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
opts2.callbacks.onMemoryRecalled?.(count);
|
|
4386
|
+
if (injectRecalledMemoryOnce(opts2.messages, text)) {
|
|
4387
|
+
memoryRecalledCount = count;
|
|
4388
|
+
opts2.callbacks.onMemoryRecalled?.(count);
|
|
4389
|
+
}
|
|
4201
4390
|
}
|
|
4202
4391
|
if (skillsSettled.status === "fulfilled" && skillsSettled.value) {
|
|
4203
4392
|
skillResult = skillsSettled.value;
|
|
@@ -4257,7 +4446,9 @@ async function runAgentTurn(opts2) {
|
|
|
4257
4446
|
Available APIs:
|
|
4258
4447
|
${codeModeApiString}
|
|
4259
4448
|
|
|
4260
|
-
Use console.log() to return results. Only console.log output
|
|
4449
|
+
Use console.log() to return results. Only console.log output is sent back to you.
|
|
4450
|
+
|
|
4451
|
+
IMPORTANT \u2014 explore through code, not direct tools: to read files, run shell commands, grep, or glob, call api.read(...), api.bash(...), api.grep(...), api.glob(...) INSIDE this code block and console.log only what you need. Do NOT call read/bash/grep/glob as separate tools \u2014 their full output floods your context, while here only what you log returns. Batch multiple reads/greps/commands into a single execute_code call.`,
|
|
4261
4452
|
parameters: {
|
|
4262
4453
|
type: "object",
|
|
4263
4454
|
properties: {
|
|
@@ -4286,6 +4477,7 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
4286
4477
|
const LOOP_THRESHOLD = 2;
|
|
4287
4478
|
const webFetchHistory = getSessionWebFetchHistory(opts2.sessionId);
|
|
4288
4479
|
let webFetchesThisTurn = 0;
|
|
4480
|
+
let codeModeRedirects = 0;
|
|
4289
4481
|
const MAX_WEB_FETCH_PER_TURN = 5;
|
|
4290
4482
|
const WEB_FETCH_DOMAIN_THRESHOLD = 2;
|
|
4291
4483
|
let cumulativePromptTokens = 0;
|
|
@@ -4542,6 +4734,16 @@ Use console.log() to return results. Only console.log output will be sent back t
|
|
|
4542
4734
|
});
|
|
4543
4735
|
continue;
|
|
4544
4736
|
}
|
|
4737
|
+
if (codeMode && CODE_MODE_REDIRECT_TOOLS.has(tc.function.name) && codeModeRedirects < MAX_CODE_MODE_REDIRECTS) {
|
|
4738
|
+
codeModeRedirects++;
|
|
4739
|
+
items.push({
|
|
4740
|
+
kind: "blocked",
|
|
4741
|
+
tc,
|
|
4742
|
+
loopSignature,
|
|
4743
|
+
result: { tool_call_id: tc.id, name: tc.function.name, content: codeModeRedirectMessage(tc.function.name), ok: false }
|
|
4744
|
+
});
|
|
4745
|
+
continue;
|
|
4746
|
+
}
|
|
4545
4747
|
if (tc.function.name === "web_fetch") {
|
|
4546
4748
|
const args = JSON.parse(tc.function.arguments || "{}");
|
|
4547
4749
|
const url = args.url || "";
|
|
@@ -4906,6 +5108,13 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
4906
5108
|
opts2.callbacks.onToolResult?.(result);
|
|
4907
5109
|
recentToolCalls.push(loopSignature);
|
|
4908
5110
|
if (recentToolCalls.length > LOOP_WINDOW) recentToolCalls.shift();
|
|
5111
|
+
} else if (codeMode && CODE_MODE_REDIRECT_TOOLS.has(tc.function.name) && codeModeRedirects < MAX_CODE_MODE_REDIRECTS) {
|
|
5112
|
+
codeModeRedirects++;
|
|
5113
|
+
const msg = codeModeRedirectMessage(tc.function.name);
|
|
5114
|
+
const redirectResult = { tool_call_id: tc.id, name: tc.function.name, content: msg, ok: false };
|
|
5115
|
+
toolResults.push(redirectResult);
|
|
5116
|
+
opts2.messages.push({ role: "tool", tool_call_id: tc.id, content: msg, name: tc.function.name });
|
|
5117
|
+
opts2.callbacks.onToolResult?.(redirectResult);
|
|
4909
5118
|
} else {
|
|
4910
5119
|
opts2.callbacks.onToolWillExecute?.(tc.id, tc.function.name);
|
|
4911
5120
|
logger.debug("turn:tool_start", { sessionId: opts2.sessionId, tool: tc.function.name, toolCallId: tc.id });
|
|
@@ -5142,13 +5351,14 @@ function validateToolArguments(raw) {
|
|
|
5142
5351
|
return "{}";
|
|
5143
5352
|
}
|
|
5144
5353
|
}
|
|
5145
|
-
var BudgetExhaustedError, AgentLoopError, codeModeApiCache, driftEvents, DRIFT_WINDOW, DRIFT_THRESHOLD, memoryExtractionErrorCounts, sessionWebFetchHistory, SESSION_WEB_FETCH_CAP, DEFAULT_MAX_COMPLETION_TOKENS, BUDGET_SAFETY_MARGIN_TOKENS, MAX_TOOL_CONTENT_CHARS;
|
|
5354
|
+
var BudgetExhaustedError, AgentLoopError, codeModeApiCache, driftEvents, DRIFT_WINDOW, DRIFT_THRESHOLD, memoryExtractionErrorCounts, sessionWebFetchHistory, SESSION_WEB_FETCH_CAP, DEFAULT_MAX_COMPLETION_TOKENS, BUDGET_SAFETY_MARGIN_TOKENS, MAX_TOOL_CONTENT_CHARS, CODE_MODE_REDIRECT_TOOLS, MAX_CODE_MODE_REDIRECTS;
|
|
5146
5355
|
var init_loop = __esm({
|
|
5147
5356
|
"src/agent/loop.ts"() {
|
|
5148
5357
|
"use strict";
|
|
5149
5358
|
init_client();
|
|
5150
5359
|
init_registry2();
|
|
5151
5360
|
init_messages();
|
|
5361
|
+
init_recall_inject();
|
|
5152
5362
|
init_cost_debug();
|
|
5153
5363
|
init_extractors();
|
|
5154
5364
|
init_strip_reasoning();
|
|
@@ -5180,6 +5390,8 @@ var init_loop = __esm({
|
|
|
5180
5390
|
DEFAULT_MAX_COMPLETION_TOKENS = 16384;
|
|
5181
5391
|
BUDGET_SAFETY_MARGIN_TOKENS = 8192;
|
|
5182
5392
|
MAX_TOOL_CONTENT_CHARS = 1e4;
|
|
5393
|
+
CODE_MODE_REDIRECT_TOOLS = /* @__PURE__ */ new Set(["read", "bash", "grep", "glob"]);
|
|
5394
|
+
MAX_CODE_MODE_REDIRECTS = 4;
|
|
5183
5395
|
}
|
|
5184
5396
|
});
|
|
5185
5397
|
|
|
@@ -5243,10 +5455,10 @@ var init_tool_error = __esm({
|
|
|
5243
5455
|
|
|
5244
5456
|
// src/util/paths.ts
|
|
5245
5457
|
import { resolve, isAbsolute, relative, sep } from "path";
|
|
5246
|
-
import { homedir as
|
|
5458
|
+
import { homedir as homedir8 } from "os";
|
|
5247
5459
|
function resolvePath(cwd, input) {
|
|
5248
5460
|
if (input.startsWith("~/") || input === "~") {
|
|
5249
|
-
return resolve(
|
|
5461
|
+
return resolve(homedir8(), input === "~" ? "." : input.slice(2));
|
|
5250
5462
|
}
|
|
5251
5463
|
return isAbsolute(input) ? input : resolve(cwd, input);
|
|
5252
5464
|
}
|
|
@@ -5473,7 +5685,7 @@ var init_edit = __esm({
|
|
|
5473
5685
|
// src/tools/bash.ts
|
|
5474
5686
|
import { spawn } from "child_process";
|
|
5475
5687
|
import { tmpdir, platform as platform2 } from "os";
|
|
5476
|
-
import { join as
|
|
5688
|
+
import { join as join13 } from "path";
|
|
5477
5689
|
function getShellCommand(override) {
|
|
5478
5690
|
const raw = override?.trim();
|
|
5479
5691
|
if (raw && raw !== "auto") {
|
|
@@ -5519,7 +5731,7 @@ function injectCoauthor(command, coauthor) {
|
|
|
5519
5731
|
const mentionsGit = /\bgit\b/.test(trimmed);
|
|
5520
5732
|
if (!createsCommit && !isRebaseContinue && !mentionsGit) return command;
|
|
5521
5733
|
if (movesHeadOnly) return command;
|
|
5522
|
-
const tmpFile =
|
|
5734
|
+
const tmpFile = join13(tmpdir(), `kf-coauthor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
5523
5735
|
const amendBlock = `
|
|
5524
5736
|
if ! git log -1 --pretty=%B 2>/dev/null | grep -qF "${trailer}"; then
|
|
5525
5737
|
git log -1 --pretty=%B | git interpret-trailers --trailer "${trailer}" > "${tmpFile}" && git commit --amend -F "${tmpFile}" --no-edit && rm -f "${tmpFile}"
|
|
@@ -5635,7 +5847,7 @@ var init_bash = __esm({
|
|
|
5635
5847
|
|
|
5636
5848
|
// src/util/glob.ts
|
|
5637
5849
|
import { readdir as readdir3, lstat, realpath } from "fs/promises";
|
|
5638
|
-
import { join as
|
|
5850
|
+
import { join as join14, relative as relative2, resolve as resolve2 } from "path";
|
|
5639
5851
|
function parsePattern(pattern) {
|
|
5640
5852
|
const parts = pattern.split(/\//g);
|
|
5641
5853
|
return parts.map((p) => {
|
|
@@ -5744,7 +5956,7 @@ async function* walk(root, pattern, options) {
|
|
|
5744
5956
|
if (!dot && name.startsWith(".")) continue;
|
|
5745
5957
|
const matched = seg.type === "literal" ? seg.value === name : matchSegment(name, seg.value);
|
|
5746
5958
|
if (!matched) continue;
|
|
5747
|
-
const childPath =
|
|
5959
|
+
const childPath = join14(dirPath, name);
|
|
5748
5960
|
const childRel = [...relativeParts, name];
|
|
5749
5961
|
const childRelStr = childRel.join("/");
|
|
5750
5962
|
if (shouldIgnore(childRelStr, ignorePatterns)) continue;
|
|
@@ -5769,7 +5981,7 @@ async function* walk(root, pattern, options) {
|
|
|
5769
5981
|
if (!dot && name.startsWith(".")) continue;
|
|
5770
5982
|
const matched = seg.type === "literal" ? seg.value === name : matchSegment(name, seg.value);
|
|
5771
5983
|
if (!matched) continue;
|
|
5772
|
-
const childPath =
|
|
5984
|
+
const childPath = join14(dirPath, name);
|
|
5773
5985
|
const childRel = [...relativeParts, name];
|
|
5774
5986
|
const childRelStr = childRel.join("/");
|
|
5775
5987
|
if (shouldIgnore(childRelStr, ignorePatterns)) continue;
|
|
@@ -5811,7 +6023,7 @@ async function* walk(root, pattern, options) {
|
|
|
5811
6023
|
const name = String(ent.name);
|
|
5812
6024
|
if (name === "." || name === "..") continue;
|
|
5813
6025
|
if (!dot && name.startsWith(".")) continue;
|
|
5814
|
-
const childPath =
|
|
6026
|
+
const childPath = join14(dirPath, name);
|
|
5815
6027
|
const childRel = [...relativeParts, name];
|
|
5816
6028
|
const childRelStr = childRel.join("/");
|
|
5817
6029
|
if (shouldIgnore(childRelStr, ignorePatterns)) continue;
|
|
@@ -6497,7 +6709,7 @@ __export(changelog_image_exports, {
|
|
|
6497
6709
|
});
|
|
6498
6710
|
import { readFile as readFile9 } from "fs/promises";
|
|
6499
6711
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
6500
|
-
import { join as
|
|
6712
|
+
import { join as join15 } from "path";
|
|
6501
6713
|
import { Resvg } from "@resvg/resvg-js";
|
|
6502
6714
|
async function githubFetch2(path, token) {
|
|
6503
6715
|
const controller = new AbortController();
|
|
@@ -6529,7 +6741,7 @@ function escapeXml(str) {
|
|
|
6529
6741
|
}
|
|
6530
6742
|
async function loadLogoBase64() {
|
|
6531
6743
|
try {
|
|
6532
|
-
const buf = await readFile9(
|
|
6744
|
+
const buf = await readFile9(join15(process.cwd(), "docs", "logo.png"));
|
|
6533
6745
|
return `data:image/png;base64,${buf.toString("base64")}`;
|
|
6534
6746
|
} catch {
|
|
6535
6747
|
return null;
|
|
@@ -6837,7 +7049,7 @@ Format your response as plain text bullet points, one per line, starting with "\
|
|
|
6837
7049
|
// src/tools/browser.ts
|
|
6838
7050
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
6839
7051
|
import { tmpdir as tmpdir2 } from "os";
|
|
6840
|
-
import { join as
|
|
7052
|
+
import { join as join16, dirname as dirname7 } from "path";
|
|
6841
7053
|
async function autoScroll(page) {
|
|
6842
7054
|
await page.evaluate(async () => {
|
|
6843
7055
|
await new Promise((resolve8) => {
|
|
@@ -6913,7 +7125,7 @@ var init_browser = __esm({
|
|
|
6913
7125
|
}
|
|
6914
7126
|
let screenshotPath;
|
|
6915
7127
|
if (args.screenshot) {
|
|
6916
|
-
screenshotPath =
|
|
7128
|
+
screenshotPath = join16(tmpdir2(), `kimiflare-browser-${Date.now()}.png`);
|
|
6917
7129
|
await mkdir7(dirname7(screenshotPath), { recursive: true });
|
|
6918
7130
|
await page.screenshot({ path: screenshotPath, fullPage: true });
|
|
6919
7131
|
}
|
|
@@ -8295,11 +8507,11 @@ __export(sessions_exports, {
|
|
|
8295
8507
|
sessionsDir: () => sessionsDir
|
|
8296
8508
|
});
|
|
8297
8509
|
import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir8, readdir as readdir4, stat as stat4 } from "fs/promises";
|
|
8298
|
-
import { homedir as
|
|
8299
|
-
import { join as
|
|
8510
|
+
import { homedir as homedir9 } from "os";
|
|
8511
|
+
import { join as join17 } from "path";
|
|
8300
8512
|
function sessionsDir() {
|
|
8301
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8302
|
-
return
|
|
8513
|
+
const xdg = process.env.XDG_DATA_HOME || join17(homedir9(), ".local", "share");
|
|
8514
|
+
return join17(xdg, "kimiflare", "sessions");
|
|
8303
8515
|
}
|
|
8304
8516
|
function sanitize(text) {
|
|
8305
8517
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
@@ -8319,7 +8531,7 @@ function makeSessionId(firstPrompt) {
|
|
|
8319
8531
|
async function saveSession(file) {
|
|
8320
8532
|
const dir = sessionsDir();
|
|
8321
8533
|
await mkdir8(dir, { recursive: true });
|
|
8322
|
-
const path =
|
|
8534
|
+
const path = join17(dir, `${file.id}.json`);
|
|
8323
8535
|
await writeFile9(path, JSON.stringify(file, null, 2), "utf8");
|
|
8324
8536
|
return path;
|
|
8325
8537
|
}
|
|
@@ -8339,7 +8551,7 @@ async function listSessions(limit = 30, cwd) {
|
|
|
8339
8551
|
const summaries = [];
|
|
8340
8552
|
for (const name of entries) {
|
|
8341
8553
|
if (!name.endsWith(".json")) continue;
|
|
8342
|
-
const path =
|
|
8554
|
+
const path = join17(dir, name);
|
|
8343
8555
|
try {
|
|
8344
8556
|
const [s, raw] = await Promise.all([stat4(path), readFile10(path, "utf8")]);
|
|
8345
8557
|
const parsed = JSON.parse(raw);
|
|
@@ -8450,7 +8662,7 @@ var init_image = __esm({
|
|
|
8450
8662
|
|
|
8451
8663
|
// src/permissions-evaluator.ts
|
|
8452
8664
|
import { resolve as resolve3, relative as relative3 } from "path";
|
|
8453
|
-
import { homedir as
|
|
8665
|
+
import { homedir as homedir10 } from "os";
|
|
8454
8666
|
function evaluatePermissionRules(req, rules) {
|
|
8455
8667
|
const toolRules = rules[req.tool];
|
|
8456
8668
|
if (!toolRules) return "ask";
|
|
@@ -8466,7 +8678,7 @@ function evaluatePermissionRules(req, rules) {
|
|
|
8466
8678
|
}
|
|
8467
8679
|
function expandHome(path) {
|
|
8468
8680
|
if (path.startsWith("~/")) {
|
|
8469
|
-
return resolve3(
|
|
8681
|
+
return resolve3(homedir10(), path.slice(2));
|
|
8470
8682
|
}
|
|
8471
8683
|
return path;
|
|
8472
8684
|
}
|
|
@@ -8492,7 +8704,7 @@ function extractTarget(tool, args, cwd) {
|
|
|
8492
8704
|
function matchPattern(target, pattern, cwd) {
|
|
8493
8705
|
let expandedPattern = pattern;
|
|
8494
8706
|
if (pattern.startsWith("~/")) {
|
|
8495
|
-
expandedPattern = resolve3(
|
|
8707
|
+
expandedPattern = resolve3(homedir10(), pattern.slice(2));
|
|
8496
8708
|
}
|
|
8497
8709
|
if (target.startsWith(expandedPattern)) {
|
|
8498
8710
|
return true;
|
|
@@ -8539,16 +8751,16 @@ var init_types = __esm({
|
|
|
8539
8751
|
});
|
|
8540
8752
|
|
|
8541
8753
|
// src/hooks/settings.ts
|
|
8542
|
-
import { existsSync as existsSync2, readFileSync as readFileSync3, mkdirSync as
|
|
8543
|
-
import { homedir as
|
|
8544
|
-
import { join as
|
|
8754
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
8755
|
+
import { homedir as homedir11 } from "os";
|
|
8756
|
+
import { join as join18, dirname as dirname8 } from "path";
|
|
8545
8757
|
import { createHash } from "crypto";
|
|
8546
8758
|
function globalSettingsPath() {
|
|
8547
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
8548
|
-
return
|
|
8759
|
+
const xdg = process.env.XDG_CONFIG_HOME || join18(homedir11(), ".config");
|
|
8760
|
+
return join18(xdg, "kimiflare", "settings.json");
|
|
8549
8761
|
}
|
|
8550
8762
|
function projectSettingsPath(cwd) {
|
|
8551
|
-
return
|
|
8763
|
+
return join18(cwd, ".kimiflare", "settings.json");
|
|
8552
8764
|
}
|
|
8553
8765
|
function readSettingsFile(path) {
|
|
8554
8766
|
if (!existsSync2(path)) return null;
|
|
@@ -8624,8 +8836,8 @@ function appendHook(scope, cwd, event, hook) {
|
|
|
8624
8836
|
return rest;
|
|
8625
8837
|
});
|
|
8626
8838
|
existing.hooks = hooks;
|
|
8627
|
-
|
|
8628
|
-
|
|
8839
|
+
mkdirSync3(dirname8(path), { recursive: true });
|
|
8840
|
+
writeFileSync2(path, JSON.stringify(existing, null, 2) + "\n", "utf8");
|
|
8629
8841
|
return path;
|
|
8630
8842
|
}
|
|
8631
8843
|
function setHookEnabled(cwd, id, enabled) {
|
|
@@ -8650,8 +8862,8 @@ function setHookEnabled(cwd, id, enabled) {
|
|
|
8650
8862
|
}
|
|
8651
8863
|
}
|
|
8652
8864
|
if (changed) {
|
|
8653
|
-
|
|
8654
|
-
|
|
8865
|
+
mkdirSync3(dirname8(path), { recursive: true });
|
|
8866
|
+
writeFileSync2(path, JSON.stringify(existing, null, 2) + "\n", "utf8");
|
|
8655
8867
|
return path;
|
|
8656
8868
|
}
|
|
8657
8869
|
void scope;
|
|
@@ -9381,11 +9593,11 @@ var init_heuristic = __esm({
|
|
|
9381
9593
|
|
|
9382
9594
|
// src/cost-attribution/classify-from-session.ts
|
|
9383
9595
|
import { readFile as readFile13 } from "fs/promises";
|
|
9384
|
-
import { join as
|
|
9385
|
-
import { homedir as
|
|
9596
|
+
import { join as join19 } from "path";
|
|
9597
|
+
import { homedir as homedir12 } from "os";
|
|
9386
9598
|
function sessionsDir2() {
|
|
9387
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
9388
|
-
return
|
|
9599
|
+
const xdg = process.env.XDG_DATA_HOME || join19(homedir12(), ".local", "share");
|
|
9600
|
+
return join19(xdg, "kimiflare", "sessions");
|
|
9389
9601
|
}
|
|
9390
9602
|
function parseToolCalls(calls) {
|
|
9391
9603
|
return calls.map((c) => {
|
|
@@ -9399,7 +9611,7 @@ function parseToolCalls(calls) {
|
|
|
9399
9611
|
}
|
|
9400
9612
|
async function classifyFromSessionFile(sessionId) {
|
|
9401
9613
|
try {
|
|
9402
|
-
const raw = await readFile13(
|
|
9614
|
+
const raw = await readFile13(join19(sessionsDir2(), `${sessionId}.json`), "utf8");
|
|
9403
9615
|
const session = JSON.parse(raw);
|
|
9404
9616
|
const messages = session.messages ?? [];
|
|
9405
9617
|
const turns = [];
|
|
@@ -9433,14 +9645,14 @@ __export(cli_exports, {
|
|
|
9433
9645
|
runCostCommand: () => runCostCommand
|
|
9434
9646
|
});
|
|
9435
9647
|
import { readFile as readFile14 } from "fs/promises";
|
|
9436
|
-
import { join as
|
|
9437
|
-
import { homedir as
|
|
9648
|
+
import { join as join20 } from "path";
|
|
9649
|
+
import { homedir as homedir13 } from "os";
|
|
9438
9650
|
function usageDir() {
|
|
9439
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
9440
|
-
return
|
|
9651
|
+
const xdg = process.env.XDG_DATA_HOME || join20(homedir13(), ".local", "share");
|
|
9652
|
+
return join20(xdg, "kimiflare");
|
|
9441
9653
|
}
|
|
9442
9654
|
function usagePath() {
|
|
9443
|
-
return
|
|
9655
|
+
return join20(usageDir(), "usage.json");
|
|
9444
9656
|
}
|
|
9445
9657
|
function today() {
|
|
9446
9658
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -10442,7 +10654,7 @@ __export(db_exports, {
|
|
|
10442
10654
|
});
|
|
10443
10655
|
import Database from "better-sqlite3";
|
|
10444
10656
|
import { dirname as dirname9 } from "path";
|
|
10445
|
-
import { mkdirSync as
|
|
10657
|
+
import { mkdirSync as mkdirSync4, statSync as statSync3 } from "fs";
|
|
10446
10658
|
function initSchema(db) {
|
|
10447
10659
|
db.exec(`
|
|
10448
10660
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -10526,7 +10738,7 @@ function openMemoryDb(dbPath) {
|
|
|
10526
10738
|
if (dbInstance) {
|
|
10527
10739
|
dbInstance.close();
|
|
10528
10740
|
}
|
|
10529
|
-
|
|
10741
|
+
mkdirSync4(dirname9(dbPath), { recursive: true });
|
|
10530
10742
|
dbInstance = new Database(dbPath);
|
|
10531
10743
|
dbInstance.pragma("journal_mode = WAL");
|
|
10532
10744
|
dbInstance.pragma("foreign_keys = ON");
|
|
@@ -12515,19 +12727,19 @@ var init_pricing = __esm({
|
|
|
12515
12727
|
|
|
12516
12728
|
// src/usage-tracker.ts
|
|
12517
12729
|
import { readFile as readFile16, writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
|
|
12518
|
-
import { homedir as
|
|
12519
|
-
import { join as
|
|
12730
|
+
import { homedir as homedir14 } from "os";
|
|
12731
|
+
import { join as join22 } from "path";
|
|
12520
12732
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
12521
12733
|
import { randomUUID } from "crypto";
|
|
12522
12734
|
function usageDir2() {
|
|
12523
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
12524
|
-
return
|
|
12735
|
+
const xdg = process.env.XDG_DATA_HOME || join22(homedir14(), ".local", "share");
|
|
12736
|
+
return join22(xdg, "kimiflare");
|
|
12525
12737
|
}
|
|
12526
12738
|
function usagePath2() {
|
|
12527
|
-
return
|
|
12739
|
+
return join22(usageDir2(), "usage.json");
|
|
12528
12740
|
}
|
|
12529
12741
|
function historyPath() {
|
|
12530
|
-
return
|
|
12742
|
+
return join22(usageDir2(), "history.jsonl");
|
|
12531
12743
|
}
|
|
12532
12744
|
function today2() {
|
|
12533
12745
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -12974,8 +13186,8 @@ var init_permissions = __esm({
|
|
|
12974
13186
|
|
|
12975
13187
|
// src/sdk/session.ts
|
|
12976
13188
|
import { resolve as resolve6 } from "path";
|
|
12977
|
-
import { homedir as
|
|
12978
|
-
import { join as
|
|
13189
|
+
import { homedir as homedir15 } from "os";
|
|
13190
|
+
import { join as join23 } from "path";
|
|
12979
13191
|
import { existsSync as existsSync3 } from "fs";
|
|
12980
13192
|
async function createAgentSession(opts2) {
|
|
12981
13193
|
const config2 = await resolveSdkConfig(opts2);
|
|
@@ -12990,7 +13202,7 @@ async function createAgentSession(opts2) {
|
|
|
12990
13202
|
let memoryManager = null;
|
|
12991
13203
|
const memoryEnabled = opts2.memoryEnabled ?? config2.memoryEnabled ?? false;
|
|
12992
13204
|
if (memoryEnabled) {
|
|
12993
|
-
const dbPath = config2.memoryDbPath ??
|
|
13205
|
+
const dbPath = config2.memoryDbPath ?? join23(homedir15(), ".local", "share", "kimiflare", "memory.db");
|
|
12994
13206
|
memoryManager = new MemoryManager({
|
|
12995
13207
|
dbPath,
|
|
12996
13208
|
accountId: config2.accountId,
|
|
@@ -13021,7 +13233,7 @@ async function createAgentSession(opts2) {
|
|
|
13021
13233
|
}
|
|
13022
13234
|
let sessionFile;
|
|
13023
13235
|
if (opts2.sessionId) {
|
|
13024
|
-
const filePath =
|
|
13236
|
+
const filePath = join23(sessionsDir(), `${opts2.sessionId}.json`);
|
|
13025
13237
|
try {
|
|
13026
13238
|
sessionFile = await loadSession(filePath);
|
|
13027
13239
|
} catch {
|
|
@@ -13434,7 +13646,7 @@ var init_session = __esm({
|
|
|
13434
13646
|
}
|
|
13435
13647
|
}
|
|
13436
13648
|
});
|
|
13437
|
-
if (existsSync3(
|
|
13649
|
+
if (existsSync3(join23(this.cwd, "KIMI.md"))) {
|
|
13438
13650
|
this.messages[0] = {
|
|
13439
13651
|
role: "system",
|
|
13440
13652
|
content: buildSystemPrompt({
|
|
@@ -13711,7 +13923,7 @@ var init_repo_info = __esm({
|
|
|
13711
13923
|
// src/agent/supervisor.ts
|
|
13712
13924
|
import { readdir as readdir5, readFile as readFile17, stat as stat5 } from "fs/promises";
|
|
13713
13925
|
import { createHash as createHash2 } from "crypto";
|
|
13714
|
-
import { resolve as resolve7, join as
|
|
13926
|
+
import { resolve as resolve7, join as join24 } from "path";
|
|
13715
13927
|
async function preReadFilesForWorkers(files, repoRoot, maxChars = DEFAULT_PRE_READ_MAX_CHARS) {
|
|
13716
13928
|
const results = [];
|
|
13717
13929
|
const filesRead = [];
|
|
@@ -13746,7 +13958,7 @@ ${results.join("\n\n")}`,
|
|
|
13746
13958
|
}
|
|
13747
13959
|
function getPreReadFilesFromMemory(cfg, repoRoot, limit = 10) {
|
|
13748
13960
|
if (!cfg.memoryEnabled) return [];
|
|
13749
|
-
const dbPath = cfg.memoryDbPath ??
|
|
13961
|
+
const dbPath = cfg.memoryDbPath ?? join24(repoRoot, ".kimiflare", "memory.db");
|
|
13750
13962
|
try {
|
|
13751
13963
|
const db = openMemoryDb(dbPath);
|
|
13752
13964
|
const files = getTopRelatedFiles(db, repoRoot, limit);
|
|
@@ -15247,7 +15459,7 @@ var init_attach_mode = __esm({
|
|
|
15247
15459
|
import { spawn as spawn4 } from "child_process";
|
|
15248
15460
|
import { mkdtemp, readFile as readFile18, writeFile as writeFile11, rm } from "fs/promises";
|
|
15249
15461
|
import { tmpdir as tmpdir3 } from "os";
|
|
15250
|
-
import { join as
|
|
15462
|
+
import { join as join25 } from "path";
|
|
15251
15463
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
15252
15464
|
async function cfApiFetch(accountId, apiToken, path, init) {
|
|
15253
15465
|
const url = `${CF_API}/accounts/${encodeURIComponent(accountId)}${path}`;
|
|
@@ -15478,8 +15690,8 @@ ${wranglerInstall.stderr.slice(-600)}`,
|
|
|
15478
15690
|
ok: true
|
|
15479
15691
|
};
|
|
15480
15692
|
yield { message: "Prerequisites ready", ok: true };
|
|
15481
|
-
const tmpRoot = await mkdtemp(
|
|
15482
|
-
const repoDir =
|
|
15693
|
+
const tmpRoot = await mkdtemp(join25(tmpdir3(), "kimiflare-commute-"));
|
|
15694
|
+
const repoDir = join25(tmpRoot, "kimiflare-commute");
|
|
15483
15695
|
yield { message: `Fetching worker source from GitHub (${COMMUTE_REPO})\u2026` };
|
|
15484
15696
|
const clone = await runCmd("git", ["clone", "--depth", "1", "--branch", COMMUTE_BRANCH, COMMUTE_REPO, repoDir], { timeoutMs: 6e4 });
|
|
15485
15697
|
if (clone.code !== 0) {
|
|
@@ -15488,8 +15700,8 @@ ${(clone.stderr || clone.stdout).slice(0, 400)}`, error: true };
|
|
|
15488
15700
|
throw new Error("clone failed");
|
|
15489
15701
|
}
|
|
15490
15702
|
yield { message: "Source fetched from GitHub", ok: true };
|
|
15491
|
-
const workerDir =
|
|
15492
|
-
const wranglerToml =
|
|
15703
|
+
const workerDir = join25(repoDir, "remote", "worker");
|
|
15704
|
+
const wranglerToml = join25(workerDir, "wrangler.toml");
|
|
15493
15705
|
yield { message: "Installing Worker dependencies (npm install)\u2026" };
|
|
15494
15706
|
const install = await runCmd("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], {
|
|
15495
15707
|
cwd: workerDir,
|
|
@@ -15831,7 +16043,7 @@ __export(app_helpers_exports, {
|
|
|
15831
16043
|
});
|
|
15832
16044
|
import { execSync as execSync3, spawn as spawn5 } from "child_process";
|
|
15833
16045
|
import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
15834
|
-
import { join as
|
|
16046
|
+
import { join as join26 } from "path";
|
|
15835
16047
|
import { platform as platform3 } from "os";
|
|
15836
16048
|
function buildFilePickerIgnoreList(cwd) {
|
|
15837
16049
|
const hardcoded = [
|
|
@@ -15903,7 +16115,7 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
15903
16115
|
];
|
|
15904
16116
|
const gitignorePatterns = [];
|
|
15905
16117
|
try {
|
|
15906
|
-
const gitignorePath =
|
|
16118
|
+
const gitignorePath = join26(cwd, ".gitignore");
|
|
15907
16119
|
const stats = statSync4(gitignorePath);
|
|
15908
16120
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
15909
16121
|
return hardcoded;
|
|
@@ -16449,7 +16661,7 @@ var init_frontmatter = __esm({
|
|
|
16449
16661
|
|
|
16450
16662
|
// src/skills/loader.ts
|
|
16451
16663
|
import { readFile as readFile19, readdir as readdir6, stat as stat6 } from "fs/promises";
|
|
16452
|
-
import { join as
|
|
16664
|
+
import { join as join27, extname } from "path";
|
|
16453
16665
|
function normalizeManifest(raw, filePath) {
|
|
16454
16666
|
const name = typeof raw.name === "string" ? raw.name : "";
|
|
16455
16667
|
const description = typeof raw.description === "string" ? raw.description : "";
|
|
@@ -16485,7 +16697,7 @@ async function loadSkillsFromDir(dirPath) {
|
|
|
16485
16697
|
const entries = await readdir6(dirPath);
|
|
16486
16698
|
const files = [];
|
|
16487
16699
|
for (const entry of entries) {
|
|
16488
|
-
const full =
|
|
16700
|
+
const full = join27(dirPath, entry);
|
|
16489
16701
|
const s = await stat6(full);
|
|
16490
16702
|
if (s.isFile() && extname(entry) === ".md") {
|
|
16491
16703
|
files.push(full);
|
|
@@ -16514,7 +16726,7 @@ var init_loader = __esm({
|
|
|
16514
16726
|
|
|
16515
16727
|
// src/skills/discovery.ts
|
|
16516
16728
|
import { readdir as readdir7, stat as stat7, readFile as readFile20 } from "fs/promises";
|
|
16517
|
-
import { join as
|
|
16729
|
+
import { join as join28, extname as extname2 } from "path";
|
|
16518
16730
|
async function dirExists(path) {
|
|
16519
16731
|
try {
|
|
16520
16732
|
const s = await stat7(path);
|
|
@@ -16538,15 +16750,15 @@ async function scanSkillDir(dirPath, source) {
|
|
|
16538
16750
|
for (const entry of entries) {
|
|
16539
16751
|
if (!entry.isFile()) continue;
|
|
16540
16752
|
if (!SKILL_EXTENSIONS.has(extname2(entry.name))) continue;
|
|
16541
|
-
files.push({ filePath:
|
|
16753
|
+
files.push({ filePath: join28(dirPath, entry.name), source });
|
|
16542
16754
|
}
|
|
16543
16755
|
return files;
|
|
16544
16756
|
}
|
|
16545
16757
|
async function discoverSkills(cwd) {
|
|
16546
|
-
const agentsSkills = await scanSkillDir(
|
|
16547
|
-
const agentsMd = await fileExists(
|
|
16548
|
-
const githubSkills = await scanSkillDir(
|
|
16549
|
-
const kimiflareSkills = await scanSkillDir(
|
|
16758
|
+
const agentsSkills = await scanSkillDir(join28(cwd, ".agents", "skills"), "agents");
|
|
16759
|
+
const agentsMd = await fileExists(join28(cwd, "AGENTS.md")) ? [{ filePath: join28(cwd, "AGENTS.md"), source: "agents-md" }] : [];
|
|
16760
|
+
const githubSkills = await scanSkillDir(join28(cwd, ".github", "skills"), "github");
|
|
16761
|
+
const kimiflareSkills = await scanSkillDir(join28(cwd, ".kimiflare", "skills"), "kimiflare");
|
|
16550
16762
|
const ordered = [...agentsSkills, ...agentsMd, ...githubSkills, ...kimiflareSkills];
|
|
16551
16763
|
return ordered;
|
|
16552
16764
|
}
|
|
@@ -18085,11 +18297,11 @@ var init_ai_gateway_api = __esm({
|
|
|
18085
18297
|
|
|
18086
18298
|
// src/skills/manager.ts
|
|
18087
18299
|
import { mkdir as mkdir10, writeFile as writeFile12, unlink as unlink2, readFile as readFile21 } from "fs/promises";
|
|
18088
|
-
import { join as
|
|
18300
|
+
import { join as join29 } from "path";
|
|
18089
18301
|
function getSkillDirs(cwd) {
|
|
18090
18302
|
return {
|
|
18091
|
-
projectDir:
|
|
18092
|
-
globalDir:
|
|
18303
|
+
projectDir: join29(cwd, ".kimiflare", "skills"),
|
|
18304
|
+
globalDir: join29(process.env.HOME ?? "", ".config", "kimiflare", "skills")
|
|
18093
18305
|
};
|
|
18094
18306
|
}
|
|
18095
18307
|
async function listAllSkills(cwd) {
|
|
@@ -18103,7 +18315,7 @@ async function listAllSkills(cwd) {
|
|
|
18103
18315
|
async function createSkill(opts2) {
|
|
18104
18316
|
const dirs = getSkillDirs(opts2.cwd);
|
|
18105
18317
|
const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
|
|
18106
|
-
const filepath =
|
|
18318
|
+
const filepath = join29(dir, `${opts2.name}.md`);
|
|
18107
18319
|
const frontmatter = {
|
|
18108
18320
|
name: opts2.name,
|
|
18109
18321
|
enabled: true,
|
|
@@ -18223,14 +18435,14 @@ var init_frontmatter2 = __esm({
|
|
|
18223
18435
|
|
|
18224
18436
|
// src/commands/loader.ts
|
|
18225
18437
|
import { open, realpath as realpath2 } from "fs/promises";
|
|
18226
|
-
import { homedir as
|
|
18227
|
-
import { join as
|
|
18438
|
+
import { homedir as homedir16 } from "os";
|
|
18439
|
+
import { join as join30, relative as relative6, sep as sep2 } from "path";
|
|
18228
18440
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
18229
|
-
return
|
|
18441
|
+
return join30(cwd, ".kimiflare", "commands");
|
|
18230
18442
|
}
|
|
18231
18443
|
function globalCommandsDir() {
|
|
18232
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
18233
|
-
return
|
|
18444
|
+
const xdg = process.env.XDG_CONFIG_HOME || join30(homedir16(), ".config");
|
|
18445
|
+
return join30(xdg, "kimiflare", "commands");
|
|
18234
18446
|
}
|
|
18235
18447
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
18236
18448
|
const warnings = [];
|
|
@@ -18601,12 +18813,12 @@ var init_recommended = __esm({
|
|
|
18601
18813
|
|
|
18602
18814
|
// src/init/context-generator.ts
|
|
18603
18815
|
import { existsSync as existsSync5, statSync as statSync5 } from "fs";
|
|
18604
|
-
import { join as
|
|
18816
|
+
import { join as join31 } from "path";
|
|
18605
18817
|
function detectFlavor(cwd) {
|
|
18606
18818
|
for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
|
|
18607
18819
|
if (flavor === "generic") continue;
|
|
18608
18820
|
for (const sig of signatures) {
|
|
18609
|
-
const path =
|
|
18821
|
+
const path = join31(cwd, sig);
|
|
18610
18822
|
if (sig.includes("*")) {
|
|
18611
18823
|
try {
|
|
18612
18824
|
const parts = sig.split("*");
|
|
@@ -18627,14 +18839,14 @@ function detectFlavor(cwd) {
|
|
|
18627
18839
|
}
|
|
18628
18840
|
function findFile(cwd, candidates) {
|
|
18629
18841
|
for (const c of candidates) {
|
|
18630
|
-
if (existsSync5(
|
|
18842
|
+
if (existsSync5(join31(cwd, c))) return c;
|
|
18631
18843
|
}
|
|
18632
18844
|
return null;
|
|
18633
18845
|
}
|
|
18634
18846
|
function findSourceRoots(cwd) {
|
|
18635
18847
|
const roots = [];
|
|
18636
18848
|
for (const r of SOURCE_ROOT_CANDIDATES) {
|
|
18637
|
-
const p =
|
|
18849
|
+
const p = join31(cwd, r);
|
|
18638
18850
|
try {
|
|
18639
18851
|
const s = statSync5(p);
|
|
18640
18852
|
if (s.isDirectory()) roots.push(r);
|
|
@@ -18645,9 +18857,9 @@ function findSourceRoots(cwd) {
|
|
|
18645
18857
|
}
|
|
18646
18858
|
function findCiConfig(cwd) {
|
|
18647
18859
|
for (const c of CI_PATHS) {
|
|
18648
|
-
if (existsSync5(
|
|
18860
|
+
if (existsSync5(join31(cwd, c))) {
|
|
18649
18861
|
try {
|
|
18650
|
-
const s = statSync5(
|
|
18862
|
+
const s = statSync5(join31(cwd, c));
|
|
18651
18863
|
return s.isDirectory() ? c : c;
|
|
18652
18864
|
} catch {
|
|
18653
18865
|
}
|
|
@@ -18784,7 +18996,7 @@ function analyzeProject(cwd) {
|
|
|
18784
18996
|
ciConfig: findCiConfig(cwd),
|
|
18785
18997
|
readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
|
|
18786
18998
|
sourceRoots: findSourceRoots(cwd),
|
|
18787
|
-
hasGit: existsSync5(
|
|
18999
|
+
hasGit: existsSync5(join31(cwd, ".git"))
|
|
18788
19000
|
};
|
|
18789
19001
|
}
|
|
18790
19002
|
function bashDiscoveryCommands(profile) {
|
|
@@ -18949,7 +19161,7 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
|
|
|
18949
19161
|
}
|
|
18950
19162
|
function buildInitPrompt(cwd) {
|
|
18951
19163
|
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
|
|
18952
|
-
(n) => existsSync5(
|
|
19164
|
+
(n) => existsSync5(join31(cwd, n))
|
|
18953
19165
|
);
|
|
18954
19166
|
const isRefresh = existingName !== void 0;
|
|
18955
19167
|
const targetFilename = existingName ?? "KIMI.md";
|
|
@@ -19038,10 +19250,10 @@ __export(ui_mode_exports, {
|
|
|
19038
19250
|
runUiMode: () => runUiMode
|
|
19039
19251
|
});
|
|
19040
19252
|
import { execSync as execSync6, spawn as spawn6 } from "child_process";
|
|
19041
|
-
import { appendFileSync, mkdirSync as
|
|
19253
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync5, openSync } from "fs";
|
|
19042
19254
|
import { unlink as unlink4 } from "fs/promises";
|
|
19043
|
-
import { join as
|
|
19044
|
-
import { homedir as
|
|
19255
|
+
import { join as join32 } from "path";
|
|
19256
|
+
import { homedir as homedir17, platform as platform6 } from "os";
|
|
19045
19257
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
19046
19258
|
import { readFile as readFile22 } from "fs/promises";
|
|
19047
19259
|
import QRCode from "qrcode";
|
|
@@ -19049,7 +19261,7 @@ function kimiLog(payload) {
|
|
|
19049
19261
|
if (!KIMI_LOG_PATH) return;
|
|
19050
19262
|
try {
|
|
19051
19263
|
const line = JSON.stringify({ ts: Date.now() / 1e3, ...payload }) + "\n";
|
|
19052
|
-
|
|
19264
|
+
appendFileSync2(KIMI_LOG_PATH, line);
|
|
19053
19265
|
} catch {
|
|
19054
19266
|
}
|
|
19055
19267
|
}
|
|
@@ -19081,13 +19293,13 @@ function gatewayFromOpts2(opts2) {
|
|
|
19081
19293
|
}
|
|
19082
19294
|
async function runUiMode(opts2) {
|
|
19083
19295
|
await loadCamouflage();
|
|
19084
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
19085
|
-
const camoDbDir =
|
|
19296
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join32(homedir17(), ".config");
|
|
19297
|
+
const camoDbDir = join32(xdgConfig, "kimiflare");
|
|
19086
19298
|
try {
|
|
19087
|
-
|
|
19299
|
+
mkdirSync5(camoDbDir, { recursive: true });
|
|
19088
19300
|
} catch {
|
|
19089
19301
|
}
|
|
19090
|
-
const camoDbPath =
|
|
19302
|
+
const camoDbPath = join32(camoDbDir, "camouflage-sessions.db");
|
|
19091
19303
|
let cam;
|
|
19092
19304
|
try {
|
|
19093
19305
|
cam = await mount({
|
|
@@ -19143,7 +19355,7 @@ ${err instanceof Error ? err.message : err}`);
|
|
|
19143
19355
|
let mcpInit = false;
|
|
19144
19356
|
let lspInit = false;
|
|
19145
19357
|
if (startupCfg?.memoryEnabled) {
|
|
19146
|
-
const dbPath = startupCfg.memoryDbPath ??
|
|
19358
|
+
const dbPath = startupCfg.memoryDbPath ?? join32(process.cwd(), ".kimiflare", "memory.db");
|
|
19147
19359
|
memoryManager = new MemoryManager({
|
|
19148
19360
|
dbPath,
|
|
19149
19361
|
accountId: opts2.accountId,
|
|
@@ -19169,7 +19381,7 @@ ${err instanceof Error ? err.message : err}`);
|
|
|
19169
19381
|
}
|
|
19170
19382
|
});
|
|
19171
19383
|
}
|
|
19172
|
-
const skillDbPath = startupCfg?.memoryDbPath ??
|
|
19384
|
+
const skillDbPath = startupCfg?.memoryDbPath ?? join32(process.cwd(), ".kimiflare", "memory.db");
|
|
19173
19385
|
const skillDb = getMemoryDb() ?? openMemoryDb(skillDbPath);
|
|
19174
19386
|
initSkillsSchema(skillDb);
|
|
19175
19387
|
void indexSkills({
|
|
@@ -26813,10 +27025,10 @@ var init_wcag = __esm({
|
|
|
26813
27025
|
|
|
26814
27026
|
// src/ui/theme-loader.ts
|
|
26815
27027
|
import { readFile as readFile23, readdir as readdir9 } from "fs/promises";
|
|
26816
|
-
import { join as
|
|
26817
|
-
import { homedir as
|
|
27028
|
+
import { join as join33 } from "path";
|
|
27029
|
+
import { homedir as homedir18 } from "os";
|
|
26818
27030
|
function projectThemesDir(cwd = process.cwd()) {
|
|
26819
|
-
return
|
|
27031
|
+
return join33(cwd, ".kimiflare", "themes");
|
|
26820
27032
|
}
|
|
26821
27033
|
function isHexColor(c) {
|
|
26822
27034
|
return /^#[0-9a-fA-F]{6}$/.test(c);
|
|
@@ -26905,7 +27117,7 @@ async function loadThemesFromDir(dir, source) {
|
|
|
26905
27117
|
return { themes, errors };
|
|
26906
27118
|
}
|
|
26907
27119
|
for (const file of files.filter((f) => f.endsWith(".json"))) {
|
|
26908
|
-
const path =
|
|
27120
|
+
const path = join33(dir, file);
|
|
26909
27121
|
let raw;
|
|
26910
27122
|
try {
|
|
26911
27123
|
raw = await readFile23(path, "utf-8");
|
|
@@ -27054,8 +27266,8 @@ var init_theme_loader = __esm({
|
|
|
27054
27266
|
"use strict";
|
|
27055
27267
|
init_wcag();
|
|
27056
27268
|
init_theme();
|
|
27057
|
-
USER_THEMES_DIR =
|
|
27058
|
-
process.env.XDG_CONFIG_HOME ||
|
|
27269
|
+
USER_THEMES_DIR = join33(
|
|
27270
|
+
process.env.XDG_CONFIG_HOME || join33(homedir18(), ".config"),
|
|
27059
27271
|
"kimiflare",
|
|
27060
27272
|
"themes"
|
|
27061
27273
|
);
|
|
@@ -31160,9 +31372,7 @@ function useSessionManager(deps) {
|
|
|
31160
31372
|
const results = await manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
|
|
31161
31373
|
if (results.length > 0) {
|
|
31162
31374
|
const text = await manager.synthesizeRecalled(results);
|
|
31163
|
-
|
|
31164
|
-
const insertIdx = lastSystemIdx >= 0 ? lastSystemIdx + 1 : d.messagesRef.current.length;
|
|
31165
|
-
d.messagesRef.current.splice(insertIdx, 0, { role: "system", content: text });
|
|
31375
|
+
injectRecalledMemoryOnce(d.messagesRef.current, text);
|
|
31166
31376
|
}
|
|
31167
31377
|
} catch {
|
|
31168
31378
|
}
|
|
@@ -31279,6 +31489,7 @@ var init_use_session_manager = __esm({
|
|
|
31279
31489
|
"use strict";
|
|
31280
31490
|
init_sessions();
|
|
31281
31491
|
init_session_state();
|
|
31492
|
+
init_recall_inject();
|
|
31282
31493
|
init_usage_tracker();
|
|
31283
31494
|
init_log_sink();
|
|
31284
31495
|
init_app_helpers();
|
|
@@ -31432,14 +31643,14 @@ __export(tui_report_exports, {
|
|
|
31432
31643
|
getCategoryReportText: () => getCategoryReportText
|
|
31433
31644
|
});
|
|
31434
31645
|
import { readFile as readFile24 } from "fs/promises";
|
|
31435
|
-
import { join as
|
|
31436
|
-
import { homedir as
|
|
31646
|
+
import { join as join34 } from "path";
|
|
31647
|
+
import { homedir as homedir19 } from "os";
|
|
31437
31648
|
function usageDir3() {
|
|
31438
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
31439
|
-
return
|
|
31649
|
+
const xdg = process.env.XDG_DATA_HOME || join34(homedir19(), ".local", "share");
|
|
31650
|
+
return join34(xdg, "kimiflare");
|
|
31440
31651
|
}
|
|
31441
31652
|
function usagePath3() {
|
|
31442
|
-
return
|
|
31653
|
+
return join34(usageDir3(), "usage.json");
|
|
31443
31654
|
}
|
|
31444
31655
|
function today3() {
|
|
31445
31656
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -31508,7 +31719,7 @@ var init_tui_report = __esm({
|
|
|
31508
31719
|
});
|
|
31509
31720
|
|
|
31510
31721
|
// src/ui/slash-commands.ts
|
|
31511
|
-
import { join as
|
|
31722
|
+
import { join as join35 } from "path";
|
|
31512
31723
|
import { unlink as unlink5 } from "fs/promises";
|
|
31513
31724
|
import QRCode2 from "qrcode";
|
|
31514
31725
|
function executeFreshStart(ctx, planText, overrideMode) {
|
|
@@ -32366,7 +32577,7 @@ ${lines.join("\n")}` }]);
|
|
|
32366
32577
|
void (async () => {
|
|
32367
32578
|
try {
|
|
32368
32579
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
32369
|
-
const file = await loadSession(
|
|
32580
|
+
const file = await loadSession(join35(sessionsDir3(), `${currentId}.json`));
|
|
32370
32581
|
const cps = file.checkpoints ?? [];
|
|
32371
32582
|
if (cps.length === 0) {
|
|
32372
32583
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: "no checkpoints in this session" }]);
|
|
@@ -32411,7 +32622,7 @@ ${lines.join("\n")}` }]);
|
|
|
32411
32622
|
try {
|
|
32412
32623
|
ctx.ensureSessionId();
|
|
32413
32624
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
32414
|
-
const filePath =
|
|
32625
|
+
const filePath = join35(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
|
|
32415
32626
|
await addCheckpoint(filePath, cp);
|
|
32416
32627
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: `checkpoint saved: "${label}"` }]);
|
|
32417
32628
|
} catch (e) {
|
|
@@ -33046,7 +33257,7 @@ project: ${projectSettingsPath(cwd)}`
|
|
|
33046
33257
|
|
|
33047
33258
|
// src/init/run-init.ts
|
|
33048
33259
|
import { existsSync as existsSync6 } from "fs";
|
|
33049
|
-
import { join as
|
|
33260
|
+
import { join as join36 } from "path";
|
|
33050
33261
|
async function runInit(deps) {
|
|
33051
33262
|
const {
|
|
33052
33263
|
cfg,
|
|
@@ -33249,7 +33460,7 @@ async function runInit(deps) {
|
|
|
33249
33460
|
}
|
|
33250
33461
|
}
|
|
33251
33462
|
});
|
|
33252
|
-
if (existsSync6(
|
|
33463
|
+
if (existsSync6(join36(cwd, "KIMI.md"))) {
|
|
33253
33464
|
if (cacheStableRef.current) {
|
|
33254
33465
|
messagesRef.current[1] = {
|
|
33255
33466
|
role: "system",
|
|
@@ -33344,7 +33555,7 @@ var init_run_init = __esm({
|
|
|
33344
33555
|
|
|
33345
33556
|
// src/ui/run-startup-tasks.ts
|
|
33346
33557
|
import { existsSync as existsSync7 } from "fs";
|
|
33347
|
-
import { join as
|
|
33558
|
+
import { join as join37 } from "path";
|
|
33348
33559
|
function runStartupTasks(deps) {
|
|
33349
33560
|
const {
|
|
33350
33561
|
cfg,
|
|
@@ -33365,7 +33576,7 @@ function runStartupTasks(deps) {
|
|
|
33365
33576
|
}
|
|
33366
33577
|
});
|
|
33367
33578
|
if (cfg.memoryEnabled) {
|
|
33368
|
-
const dbPath = cfg.memoryDbPath ??
|
|
33579
|
+
const dbPath = cfg.memoryDbPath ?? join37(process.cwd(), ".kimiflare", "memory.db");
|
|
33369
33580
|
const manager = new MemoryManager({
|
|
33370
33581
|
dbPath,
|
|
33371
33582
|
accountId: cfg.accountId,
|
|
@@ -33399,7 +33610,7 @@ function runStartupTasks(deps) {
|
|
|
33399
33610
|
});
|
|
33400
33611
|
const cwd = process.cwd();
|
|
33401
33612
|
sessionStartRecallRef.current = manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
|
|
33402
|
-
if (existsSync7(
|
|
33613
|
+
if (existsSync7(join37(cwd, "KIMI.md"))) {
|
|
33403
33614
|
const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
|
|
33404
33615
|
const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
|
|
33405
33616
|
if (driftCount >= 5) {
|
|
@@ -33410,7 +33621,7 @@ function runStartupTasks(deps) {
|
|
|
33410
33621
|
memoryManagerRef.current?.close();
|
|
33411
33622
|
memoryManagerRef.current = null;
|
|
33412
33623
|
}
|
|
33413
|
-
const skillDbPath = cfg.memoryDbPath ??
|
|
33624
|
+
const skillDbPath = cfg.memoryDbPath ?? join37(process.cwd(), ".kimiflare", "memory.db");
|
|
33414
33625
|
const skillDb = getMemoryDb() ?? openMemoryDb(skillDbPath);
|
|
33415
33626
|
initSkillsSchema(skillDb);
|
|
33416
33627
|
void indexSkills({
|
|
@@ -33874,7 +34085,7 @@ __export(app_exports, {
|
|
|
33874
34085
|
import React25, { useState as useState29, useRef as useRef7, useEffect as useEffect11, useCallback as useCallback10, useMemo as useMemo6 } from "react";
|
|
33875
34086
|
import { Box as Box42, Text as Text43, useApp, useInput as useInput21, render } from "ink";
|
|
33876
34087
|
import { existsSync as existsSync8 } from "fs";
|
|
33877
|
-
import { join as
|
|
34088
|
+
import { join as join38 } from "path";
|
|
33878
34089
|
import { jsx as jsx44, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
33879
34090
|
function App({
|
|
33880
34091
|
initialCfg,
|
|
@@ -34494,18 +34705,17 @@ ${wcagWarnings.join("\n")}` }
|
|
|
34494
34705
|
const results = await manager.recall({ text: queryText, repoPath: cwd, limit: 5 });
|
|
34495
34706
|
if (results.length > 0 && !signal.aborted) {
|
|
34496
34707
|
const text = await manager.synthesizeRecalled(results);
|
|
34497
|
-
|
|
34498
|
-
|
|
34499
|
-
|
|
34500
|
-
|
|
34501
|
-
|
|
34502
|
-
|
|
34503
|
-
|
|
34504
|
-
|
|
34505
|
-
|
|
34506
|
-
|
|
34507
|
-
|
|
34508
|
-
await saveSessionSafe();
|
|
34708
|
+
if (injectRecalledMemoryOnce(result.newMessages, text)) {
|
|
34709
|
+
setEvents((e) => [
|
|
34710
|
+
...e,
|
|
34711
|
+
{
|
|
34712
|
+
kind: "memory",
|
|
34713
|
+
key: mkKey(),
|
|
34714
|
+
text: `recalled ${results.length} memory${results.length === 1 ? "" : "ies"} after compaction`
|
|
34715
|
+
}
|
|
34716
|
+
]);
|
|
34717
|
+
await saveSessionSafe();
|
|
34718
|
+
}
|
|
34509
34719
|
}
|
|
34510
34720
|
} catch {
|
|
34511
34721
|
}
|
|
@@ -35296,7 +35506,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
35296
35506
|
}
|
|
35297
35507
|
}
|
|
35298
35508
|
turnCounterRef.current += 1;
|
|
35299
|
-
if (turnCounterRef.current % 15 === 0 && existsSync8(
|
|
35509
|
+
if (turnCounterRef.current % 15 === 0 && existsSync8(join38(process.cwd(), "KIMI.md")) && !kimiMdStale) {
|
|
35300
35510
|
setEvents((e) => [
|
|
35301
35511
|
...e,
|
|
35302
35512
|
{ kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps KimiFlare stay accurate as your project evolves." }
|
|
@@ -35320,7 +35530,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
35320
35530
|
};
|
|
35321
35531
|
ensureSessionId();
|
|
35322
35532
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
35323
|
-
const filePath =
|
|
35533
|
+
const filePath = join38(sessionsDir3(), `${sessionIdRef.current}.json`);
|
|
35324
35534
|
await addCheckpoint(filePath, cp);
|
|
35325
35535
|
}
|
|
35326
35536
|
const summary = await generateContinuationSummary({
|
|
@@ -35776,18 +35986,17 @@ ${conflicts.join("\n")}` }
|
|
|
35776
35986
|
const results = await manager.recall({ text: queryText, repoPath: cwd, limit: 5 });
|
|
35777
35987
|
if (results.length > 0) {
|
|
35778
35988
|
const text2 = await manager.synthesizeRecalled(results);
|
|
35779
|
-
|
|
35780
|
-
|
|
35781
|
-
|
|
35782
|
-
|
|
35783
|
-
|
|
35784
|
-
|
|
35785
|
-
|
|
35786
|
-
|
|
35787
|
-
|
|
35788
|
-
|
|
35789
|
-
|
|
35790
|
-
await saveSessionSafe();
|
|
35989
|
+
if (injectRecalledMemoryOnce(messagesRef.current, text2)) {
|
|
35990
|
+
setEvents((e) => [
|
|
35991
|
+
...e,
|
|
35992
|
+
{
|
|
35993
|
+
kind: "memory",
|
|
35994
|
+
key: mkKey(),
|
|
35995
|
+
text: `recalled ${results.length} memory${results.length === 1 ? "" : "ies"} after compaction`
|
|
35996
|
+
}
|
|
35997
|
+
]);
|
|
35998
|
+
await saveSessionSafe();
|
|
35999
|
+
}
|
|
35791
36000
|
}
|
|
35792
36001
|
} catch {
|
|
35793
36002
|
}
|
|
@@ -35973,7 +36182,7 @@ ${conflicts.join("\n")}` }
|
|
|
35973
36182
|
onCommandDelete: handleCommandDelete2,
|
|
35974
36183
|
lspServers: cfg?.lspServers ?? {},
|
|
35975
36184
|
lspScope,
|
|
35976
|
-
hasProjectDir: existsSync8(
|
|
36185
|
+
hasProjectDir: existsSync8(join38(process.cwd(), ".kimiflare")),
|
|
35977
36186
|
onLspSave: handleLspSave2,
|
|
35978
36187
|
themes: themeList(),
|
|
35979
36188
|
onPickTheme: handleThemePick,
|
|
@@ -36366,6 +36575,7 @@ var init_app = __esm({
|
|
|
36366
36575
|
init_sessions();
|
|
36367
36576
|
init_image();
|
|
36368
36577
|
init_usage_tracker();
|
|
36578
|
+
init_recall_inject();
|
|
36369
36579
|
init_loader2();
|
|
36370
36580
|
init_renderer2();
|
|
36371
36581
|
init_builtins();
|