kimiflare 0.84.1 → 0.85.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1318 -390
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.d.ts +12 -0
- package/dist/sdk/index.js +448 -40
- package/dist/sdk/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -4277,7 +4277,11 @@ ${sandboxResult.output}` : sandboxResult.output;
|
|
|
4277
4277
|
sessionId: opts2.sessionId,
|
|
4278
4278
|
githubToken: opts2.githubToken,
|
|
4279
4279
|
shell: opts2.shell,
|
|
4280
|
-
intentTier: opts2.intentClassification?.tier
|
|
4280
|
+
intentTier: opts2.intentClassification?.tier,
|
|
4281
|
+
accountId: opts2.accountId,
|
|
4282
|
+
apiToken: opts2.apiToken,
|
|
4283
|
+
model: opts2.model,
|
|
4284
|
+
gateway: opts2.gateway
|
|
4281
4285
|
},
|
|
4282
4286
|
opts2.onFileChange
|
|
4283
4287
|
);
|
|
@@ -5640,13 +5644,81 @@ function makeOutput(content) {
|
|
|
5640
5644
|
function getToken(ctx) {
|
|
5641
5645
|
return ctx.githubToken || process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
5642
5646
|
}
|
|
5643
|
-
var GITHUB_API_BASE, TIMEOUT_MS3, githubReadPrTool, githubReadIssueTool, githubReadCodeTool;
|
|
5647
|
+
var GITHUB_API_BASE, TIMEOUT_MS3, githubListMergedPrsTool, githubListReleasesTool, githubReadPrTool, githubReadIssueTool, githubReadCodeTool;
|
|
5644
5648
|
var init_github = __esm({
|
|
5645
5649
|
"src/tools/github.ts"() {
|
|
5646
5650
|
"use strict";
|
|
5647
5651
|
init_version();
|
|
5648
5652
|
GITHUB_API_BASE = "https://api.github.com";
|
|
5649
5653
|
TIMEOUT_MS3 = 2e4;
|
|
5654
|
+
githubListMergedPrsTool = {
|
|
5655
|
+
name: "github_list_merged_prs",
|
|
5656
|
+
description: "List merged pull requests for a repository within the last N days. Returns PR number, title, author, merge date, and URL for each merged PR.",
|
|
5657
|
+
parameters: {
|
|
5658
|
+
type: "object",
|
|
5659
|
+
properties: {
|
|
5660
|
+
owner: { type: "string", description: "Repository owner (user or organization)." },
|
|
5661
|
+
repo: { type: "string", description: "Repository name." },
|
|
5662
|
+
days: { type: "integer", description: "Number of days to look back. Default: 7.", minimum: 1, maximum: 90 }
|
|
5663
|
+
},
|
|
5664
|
+
required: ["owner", "repo"],
|
|
5665
|
+
additionalProperties: false
|
|
5666
|
+
},
|
|
5667
|
+
needsPermission: false,
|
|
5668
|
+
render: (args) => ({ title: `GitHub merged PRs ${args.owner ?? ""}/${args.repo ?? ""}` }),
|
|
5669
|
+
async run(args, ctx) {
|
|
5670
|
+
const token = getToken(ctx);
|
|
5671
|
+
const days = args.days ?? 7;
|
|
5672
|
+
const since = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString();
|
|
5673
|
+
const prs = await githubFetch(
|
|
5674
|
+
`/repos/${args.owner}/${args.repo}/pulls?state=closed&sort=updated&direction=desc&per_page=100`,
|
|
5675
|
+
token
|
|
5676
|
+
);
|
|
5677
|
+
const merged = prs.filter((p) => p.merged_at && p.merged_at >= since).sort((a, b) => (b.merged_at ?? "").localeCompare(a.merged_at ?? ""));
|
|
5678
|
+
if (merged.length === 0) {
|
|
5679
|
+
return makeOutput(`No merged PRs in ${args.owner}/${args.repo} within the last ${days} day(s).`);
|
|
5680
|
+
}
|
|
5681
|
+
const lines = merged.map(
|
|
5682
|
+
(p) => `#${p.number} ${p.title} \u2014 @${p.user.login} \u2014 merged ${p.merged_at.slice(0, 10)} \u2014 ${p.html_url}`
|
|
5683
|
+
);
|
|
5684
|
+
return makeOutput(
|
|
5685
|
+
[`Merged PRs in ${args.owner}/${args.repo} (last ${days} days):`, "", ...lines].join("\n")
|
|
5686
|
+
);
|
|
5687
|
+
}
|
|
5688
|
+
};
|
|
5689
|
+
githubListReleasesTool = {
|
|
5690
|
+
name: "github_list_releases",
|
|
5691
|
+
description: "List recent GitHub releases for a repository. Returns tag name, name, published date, and URL for each release.",
|
|
5692
|
+
parameters: {
|
|
5693
|
+
type: "object",
|
|
5694
|
+
properties: {
|
|
5695
|
+
owner: { type: "string", description: "Repository owner (user or organization)." },
|
|
5696
|
+
repo: { type: "string", description: "Repository name." },
|
|
5697
|
+
limit: { type: "integer", description: "Max releases to return. Default: 5.", minimum: 1, maximum: 20 }
|
|
5698
|
+
},
|
|
5699
|
+
required: ["owner", "repo"],
|
|
5700
|
+
additionalProperties: false
|
|
5701
|
+
},
|
|
5702
|
+
needsPermission: false,
|
|
5703
|
+
render: (args) => ({ title: `GitHub releases ${args.owner ?? ""}/${args.repo ?? ""}` }),
|
|
5704
|
+
async run(args, ctx) {
|
|
5705
|
+
const token = getToken(ctx);
|
|
5706
|
+
const limit = args.limit ?? 5;
|
|
5707
|
+
const releases = await githubFetch(
|
|
5708
|
+
`/repos/${args.owner}/${args.repo}/releases?per_page=${limit}`,
|
|
5709
|
+
token
|
|
5710
|
+
);
|
|
5711
|
+
if (releases.length === 0) {
|
|
5712
|
+
return makeOutput(`No releases found for ${args.owner}/${args.repo}.`);
|
|
5713
|
+
}
|
|
5714
|
+
const lines = releases.map(
|
|
5715
|
+
(r) => `${r.tag_name} \u2014 ${r.name} \u2014 published ${r.published_at.slice(0, 10)} \u2014 ${r.html_url}`
|
|
5716
|
+
);
|
|
5717
|
+
return makeOutput(
|
|
5718
|
+
[`Releases for ${args.owner}/${args.repo}:`, "", ...lines].join("\n")
|
|
5719
|
+
);
|
|
5720
|
+
}
|
|
5721
|
+
};
|
|
5650
5722
|
githubReadPrTool = {
|
|
5651
5723
|
name: "github_read_pr",
|
|
5652
5724
|
description: "Read a GitHub pull request by owner, repo, and PR number. Returns title, body, state, author, created/updated dates, and a summary of changed files. Use this in plan mode or when you need structured PR data without write permissions.",
|
|
@@ -5772,10 +5844,354 @@ var init_github = __esm({
|
|
|
5772
5844
|
}
|
|
5773
5845
|
});
|
|
5774
5846
|
|
|
5847
|
+
// src/tools/changelog-image.ts
|
|
5848
|
+
var changelog_image_exports = {};
|
|
5849
|
+
__export(changelog_image_exports, {
|
|
5850
|
+
changelogImageTool: () => changelogImageTool
|
|
5851
|
+
});
|
|
5852
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
5853
|
+
import { writeFile as writeFile5 } from "fs/promises";
|
|
5854
|
+
import { join as join11 } from "path";
|
|
5855
|
+
import { Resvg } from "@resvg/resvg-js";
|
|
5856
|
+
async function githubFetch2(path, token) {
|
|
5857
|
+
const controller = new AbortController();
|
|
5858
|
+
const timer2 = setTimeout(() => controller.abort(), TIMEOUT_MS4);
|
|
5859
|
+
try {
|
|
5860
|
+
const headers = {
|
|
5861
|
+
Accept: "application/vnd.github+json",
|
|
5862
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
5863
|
+
};
|
|
5864
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
5865
|
+
const res = await fetch(`${GITHUB_API_BASE2}${path}`, {
|
|
5866
|
+
signal: controller.signal,
|
|
5867
|
+
headers
|
|
5868
|
+
});
|
|
5869
|
+
if (!res.ok) {
|
|
5870
|
+
const body = await res.text().catch(() => "");
|
|
5871
|
+
throw new Error(`GitHub API ${res.status}: ${res.statusText}${body ? ` \u2014 ${body.slice(0, 200)}` : ""}`);
|
|
5872
|
+
}
|
|
5873
|
+
return await res.json();
|
|
5874
|
+
} finally {
|
|
5875
|
+
clearTimeout(timer2);
|
|
5876
|
+
}
|
|
5877
|
+
}
|
|
5878
|
+
function getToken2(ctx) {
|
|
5879
|
+
return ctx.githubToken;
|
|
5880
|
+
}
|
|
5881
|
+
function escapeXml(str) {
|
|
5882
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
5883
|
+
}
|
|
5884
|
+
async function loadLogoBase64() {
|
|
5885
|
+
try {
|
|
5886
|
+
const buf = await readFile7(join11(process.cwd(), "docs", "logo.png"));
|
|
5887
|
+
return `data:image/png;base64,${buf.toString("base64")}`;
|
|
5888
|
+
} catch {
|
|
5889
|
+
return null;
|
|
5890
|
+
}
|
|
5891
|
+
}
|
|
5892
|
+
function wrapText(text, maxWidth, fontSize) {
|
|
5893
|
+
const avgCharWidth = fontSize * 0.55;
|
|
5894
|
+
const maxChars = Math.floor(maxWidth / avgCharWidth);
|
|
5895
|
+
const lines = [];
|
|
5896
|
+
const rawLines = text.split("\n");
|
|
5897
|
+
for (const raw of rawLines) {
|
|
5898
|
+
const trimmed = raw.trim();
|
|
5899
|
+
if (!trimmed) {
|
|
5900
|
+
lines.push("");
|
|
5901
|
+
continue;
|
|
5902
|
+
}
|
|
5903
|
+
let remaining = trimmed;
|
|
5904
|
+
while (remaining.length > maxChars) {
|
|
5905
|
+
let cut = maxChars;
|
|
5906
|
+
while (cut > 0 && remaining[cut] !== " ") cut--;
|
|
5907
|
+
if (cut === 0) cut = maxChars;
|
|
5908
|
+
lines.push(remaining.slice(0, cut).trimEnd());
|
|
5909
|
+
remaining = remaining.slice(cut).trimStart();
|
|
5910
|
+
}
|
|
5911
|
+
if (remaining) lines.push(remaining);
|
|
5912
|
+
}
|
|
5913
|
+
return lines;
|
|
5914
|
+
}
|
|
5915
|
+
async function summarizeWithLlm(prs, ctx) {
|
|
5916
|
+
if (!ctx.accountId || !ctx.apiToken || !ctx.model) {
|
|
5917
|
+
return prs.map((p) => `\u2022 ${p.title} [PR #${p.number}]`).join("\n");
|
|
5918
|
+
}
|
|
5919
|
+
const prDescriptions = prs.map((p) => {
|
|
5920
|
+
const bodySnippet = p.body ? `
|
|
5921
|
+
${p.body.slice(0, 300).replace(/\n/g, " ")}` : "";
|
|
5922
|
+
return `PR #${p.number}: ${p.title} (merged ${p.merged_at.slice(0, 10)} by @${p.user.login})${bodySnippet}`;
|
|
5923
|
+
}).join("\n\n");
|
|
5924
|
+
let summary = "";
|
|
5925
|
+
const events = runKimi({
|
|
5926
|
+
accountId: ctx.accountId,
|
|
5927
|
+
apiToken: ctx.apiToken,
|
|
5928
|
+
model: ctx.model,
|
|
5929
|
+
messages: [
|
|
5930
|
+
{ role: "system", content: CHANGELOG_SYSTEM_PROMPT },
|
|
5931
|
+
{
|
|
5932
|
+
role: "user",
|
|
5933
|
+
content: `Write a changelog summary for the following merged pull requests:
|
|
5934
|
+
|
|
5935
|
+
${prDescriptions}`
|
|
5936
|
+
}
|
|
5937
|
+
],
|
|
5938
|
+
signal: ctx.signal,
|
|
5939
|
+
temperature: 0.4,
|
|
5940
|
+
reasoningEffort: "low",
|
|
5941
|
+
gateway: ctx.gateway,
|
|
5942
|
+
idleTimeoutMs: 6e4
|
|
5943
|
+
});
|
|
5944
|
+
for await (const ev of events) {
|
|
5945
|
+
if (ev.type === "text") summary += ev.delta;
|
|
5946
|
+
}
|
|
5947
|
+
return summary.trim() || prs.map((p) => `\u2022 ${p.title} [PR #${p.number}]`).join("\n");
|
|
5948
|
+
}
|
|
5949
|
+
function buildChangelogSvg(opts2) {
|
|
5950
|
+
const { owner, repo, version, writeUp, logoBase64 } = opts2;
|
|
5951
|
+
const width = 900;
|
|
5952
|
+
const padX = 72;
|
|
5953
|
+
const padTop = 64;
|
|
5954
|
+
const padBottom = 56;
|
|
5955
|
+
const contentW = width - padX * 2;
|
|
5956
|
+
const repoFontSize = 22;
|
|
5957
|
+
const labelFontSize = 12;
|
|
5958
|
+
const bodyFontSize = 16;
|
|
5959
|
+
const bodyLineHeight = 24;
|
|
5960
|
+
const bulletIndent = 20;
|
|
5961
|
+
const bulletGap = 32;
|
|
5962
|
+
const paraGap = 8;
|
|
5963
|
+
const logoW = 28;
|
|
5964
|
+
const logoH = 28;
|
|
5965
|
+
const logoY = padTop + 4;
|
|
5966
|
+
const repoTextX = padX + (logoBase64 ? logoW + 14 : 0);
|
|
5967
|
+
const repoTextY = padTop + 24;
|
|
5968
|
+
const labelY = repoTextY + 32;
|
|
5969
|
+
const headerBottom = labelY + 32;
|
|
5970
|
+
const rawLines = writeUp.split("\n").map((l) => l.trim());
|
|
5971
|
+
const blocks = [];
|
|
5972
|
+
let currentBlock = null;
|
|
5973
|
+
for (const raw of rawLines) {
|
|
5974
|
+
if (!raw) {
|
|
5975
|
+
if (currentBlock) {
|
|
5976
|
+
blocks.push(currentBlock);
|
|
5977
|
+
currentBlock = null;
|
|
5978
|
+
}
|
|
5979
|
+
continue;
|
|
5980
|
+
}
|
|
5981
|
+
const isBullet = raw.startsWith("\u2022");
|
|
5982
|
+
const text = isBullet ? raw.slice(1).trim() : raw;
|
|
5983
|
+
if (!currentBlock || currentBlock.type !== (isBullet ? "bullet" : "paragraph")) {
|
|
5984
|
+
if (currentBlock) blocks.push(currentBlock);
|
|
5985
|
+
currentBlock = { type: isBullet ? "bullet" : "paragraph", lines: [] };
|
|
5986
|
+
}
|
|
5987
|
+
const wrapW = isBullet ? contentW - bulletIndent : contentW;
|
|
5988
|
+
const wrapped = wrapText(text, wrapW, bodyFontSize);
|
|
5989
|
+
currentBlock.lines.push(...wrapped);
|
|
5990
|
+
}
|
|
5991
|
+
if (currentBlock) blocks.push(currentBlock);
|
|
5992
|
+
let bodyHeight = 0;
|
|
5993
|
+
const lineMeta = [];
|
|
5994
|
+
let y = headerBottom;
|
|
5995
|
+
for (let b = 0; b < blocks.length; b++) {
|
|
5996
|
+
const block = blocks[b];
|
|
5997
|
+
for (let i = 0; i < block.lines.length; i++) {
|
|
5998
|
+
const line = block.lines[i];
|
|
5999
|
+
lineMeta.push({
|
|
6000
|
+
text: line,
|
|
6001
|
+
y,
|
|
6002
|
+
isBullet: block.type === "bullet",
|
|
6003
|
+
isFirst: i === 0
|
|
6004
|
+
});
|
|
6005
|
+
y += bodyLineHeight;
|
|
6006
|
+
if (block.type === "bullet" && i < block.lines.length - 1) {
|
|
6007
|
+
y += paraGap;
|
|
6008
|
+
}
|
|
6009
|
+
}
|
|
6010
|
+
if (b < blocks.length - 1) {
|
|
6011
|
+
y += bulletGap;
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
6014
|
+
bodyHeight = y - headerBottom;
|
|
6015
|
+
const height = headerBottom + bodyHeight + padBottom;
|
|
6016
|
+
const logoEl = logoBase64 ? `<image x="${padX}" y="${logoY}" width="${logoW}" height="${logoH}" href="${logoBase64}"/>` : "";
|
|
6017
|
+
const bodySpans = lineMeta.map(({ text, y: ly, isBullet, isFirst }) => {
|
|
6018
|
+
const x = isBullet ? padX + bulletIndent : padX;
|
|
6019
|
+
const weight = isBullet ? 'font-weight="500"' : "";
|
|
6020
|
+
const fill = isBullet ? "#1f2937" : "#4b5563";
|
|
6021
|
+
return `<tspan x="${x}" y="${ly}" fill="${fill}" ${weight}>${escapeXml(text)}</tspan>`;
|
|
6022
|
+
}).join("");
|
|
6023
|
+
const bulletDots = lineMeta.filter((m) => m.isBullet && m.isFirst).map(({ y: ly }) => {
|
|
6024
|
+
const cy = ly - bodyFontSize * 0.35;
|
|
6025
|
+
return `<circle cx="${padX + 6}" cy="${cy}" r="3" fill="#f97316"/>`;
|
|
6026
|
+
}).join("");
|
|
6027
|
+
const today4 = escapeXml((/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
|
|
6028
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
6029
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
6030
|
+
<defs>
|
|
6031
|
+
<style>
|
|
6032
|
+
.font { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
|
|
6033
|
+
</style>
|
|
6034
|
+
</defs>
|
|
6035
|
+
|
|
6036
|
+
<!-- Background -->
|
|
6037
|
+
<rect width="${width}" height="${height}" fill="#ffffff"/>
|
|
6038
|
+
|
|
6039
|
+
<!-- Top accent bar -->
|
|
6040
|
+
<rect x="${padX}" y="${padTop}" width="36" height="3" fill="#f97316" rx="1.5"/>
|
|
6041
|
+
|
|
6042
|
+
<!-- Header -->
|
|
6043
|
+
<g class="font">
|
|
6044
|
+
${logoEl}
|
|
6045
|
+
<text x="${repoTextX}" y="${repoTextY}" fill="#111827" font-size="${repoFontSize}" font-weight="600">${escapeXml(owner)}/${escapeXml(repo)}</text>
|
|
6046
|
+
|
|
6047
|
+
<text x="${padX}" y="${labelY}" fill="#9ca3af" font-size="${labelFontSize}" font-weight="500" letter-spacing="0.08em">CHANGELOG</text>
|
|
6048
|
+
|
|
6049
|
+
<!-- Version pill -->
|
|
6050
|
+
<rect x="${padX + 88}" y="${labelY - 14}" width="${Math.max(40, version.length * 7 + 16)}" height="22" fill="#fff7ed" rx="11"/>
|
|
6051
|
+
<text x="${padX + 88 + 10}" y="${labelY}" fill="#f97316" font-size="${labelFontSize}" font-weight="500">${escapeXml(version)}</text>
|
|
6052
|
+
</g>
|
|
6053
|
+
|
|
6054
|
+
<!-- Separator -->
|
|
6055
|
+
<line x1="${padX}" y1="${headerBottom - 10}" x2="${width - padX}" y2="${headerBottom - 10}" stroke="#f3f4f6" stroke-width="1"/>
|
|
6056
|
+
|
|
6057
|
+
<!-- Body -->
|
|
6058
|
+
<g class="font">
|
|
6059
|
+
${bulletDots}
|
|
6060
|
+
<text font-size="${bodyFontSize}" line-height="${bodyLineHeight}">
|
|
6061
|
+
${bodySpans}
|
|
6062
|
+
</text>
|
|
6063
|
+
</g>
|
|
6064
|
+
|
|
6065
|
+
<!-- Footer -->
|
|
6066
|
+
<g class="font" transform="translate(0, ${height - padBottom + 20})">
|
|
6067
|
+
<text x="${padX}" y="0" fill="#d1d5db" font-size="11">Generated with KimiFlare \xB7 ${today4}</text>
|
|
6068
|
+
</g>
|
|
6069
|
+
</svg>`;
|
|
6070
|
+
}
|
|
6071
|
+
var GITHUB_API_BASE2, TIMEOUT_MS4, CHANGELOG_SYSTEM_PROMPT, changelogImageTool;
|
|
6072
|
+
var init_changelog_image = __esm({
|
|
6073
|
+
"src/tools/changelog-image.ts"() {
|
|
6074
|
+
"use strict";
|
|
6075
|
+
init_client();
|
|
6076
|
+
GITHUB_API_BASE2 = "https://api.github.com";
|
|
6077
|
+
TIMEOUT_MS4 = 2e4;
|
|
6078
|
+
CHANGELOG_SYSTEM_PROMPT = `You are a senior technical product writer. Your job is to write release notes that make users excited about new features while being completely accurate and grounded only in the provided pull requests.
|
|
6079
|
+
|
|
6080
|
+
Rules:
|
|
6081
|
+
- Write 3\u20136 bullet points maximum. Highlight only the most significant, user-facing changes.
|
|
6082
|
+
- Focus on USER VALUE and IMPACT, not implementation details or internal refactors.
|
|
6083
|
+
- Use confident, clear, engaging language \u2014 like Apple product release notes.
|
|
6084
|
+
- Group related changes under themes when it makes sense.
|
|
6085
|
+
- Each bullet should be 1\u20132 sentences.
|
|
6086
|
+
- Include the PR number in square brackets at the end of each bullet, e.g. [PR #123]
|
|
6087
|
+
- Do NOT include changes that are purely internal (chores, refactors, dependency updates, version bumps) unless they have clear user-facing impact.
|
|
6088
|
+
- Do NOT hallucinate features not present in the PRs.
|
|
6089
|
+
- If there are no meaningful user-facing changes, say so briefly.
|
|
6090
|
+
|
|
6091
|
+
Format your response as plain text bullet points, one per line, starting with "\u2022 ". Do not use markdown headers or bold/italic.`;
|
|
6092
|
+
changelogImageTool = {
|
|
6093
|
+
name: "changelog_image",
|
|
6094
|
+
description: "Generate a beautiful changelog image for a GitHub repository. Fetches merged PRs from the last N days, uses an LLM to write a creative summary, then renders a shareable PNG with the project logo, version, and highlights.",
|
|
6095
|
+
parameters: {
|
|
6096
|
+
type: "object",
|
|
6097
|
+
properties: {
|
|
6098
|
+
owner: { type: "string", description: "Repository owner (user or organization)." },
|
|
6099
|
+
repo: { type: "string", description: "Repository name." },
|
|
6100
|
+
days: { type: "integer", description: "Number of days to look back for merged PRs. Default: 7.", minimum: 1, maximum: 90 },
|
|
6101
|
+
output: { type: "string", description: "Output file path for the PNG. Default: ./changelog-<repo>-<version>.png" }
|
|
6102
|
+
},
|
|
6103
|
+
required: ["owner", "repo"],
|
|
6104
|
+
additionalProperties: false
|
|
6105
|
+
},
|
|
6106
|
+
needsPermission: false,
|
|
6107
|
+
render: (args) => ({ title: `Changelog image for ${args.owner ?? ""}/${args.repo ?? ""}` }),
|
|
6108
|
+
async run(args, ctx) {
|
|
6109
|
+
const token = getToken2(ctx);
|
|
6110
|
+
const days = args.days ?? 7;
|
|
6111
|
+
const tasks = [
|
|
6112
|
+
{ id: "1", title: "Fetch merged PRs from GitHub", status: "pending" },
|
|
6113
|
+
{ id: "2", title: "Determine latest version", status: "pending" },
|
|
6114
|
+
{ id: "3", title: "Summarize changes with LLM", status: "pending" },
|
|
6115
|
+
{ id: "4", title: "Render changelog image", status: "pending" },
|
|
6116
|
+
{ id: "5", title: "Save PNG to file", status: "pending" }
|
|
6117
|
+
];
|
|
6118
|
+
const setTask = (id, status) => {
|
|
6119
|
+
const t = tasks.find((x) => x.id === id);
|
|
6120
|
+
if (t) t.status = status;
|
|
6121
|
+
ctx.onTasks?.(tasks.map((x) => ({ ...x })));
|
|
6122
|
+
};
|
|
6123
|
+
setTask("1", "in_progress");
|
|
6124
|
+
const since = new Date(Date.now() - days * 24 * 60 * 60 * 1e3).toISOString();
|
|
6125
|
+
const prs = await githubFetch2(
|
|
6126
|
+
`/repos/${args.owner}/${args.repo}/pulls?state=closed&sort=updated&direction=desc&per_page=100`,
|
|
6127
|
+
token
|
|
6128
|
+
);
|
|
6129
|
+
const merged = prs.filter((p) => p.merged_at && p.merged_at >= since).sort((a, b) => (b.merged_at ?? "").localeCompare(a.merged_at ?? ""));
|
|
6130
|
+
if (merged.length === 0) {
|
|
6131
|
+
setTask("1", "completed");
|
|
6132
|
+
return {
|
|
6133
|
+
content: `No merged PRs in ${args.owner}/${args.repo} within the last ${days} day(s).`,
|
|
6134
|
+
rawBytes: 0,
|
|
6135
|
+
reducedBytes: 0
|
|
6136
|
+
};
|
|
6137
|
+
}
|
|
6138
|
+
setTask("1", "completed");
|
|
6139
|
+
setTask("2", "in_progress");
|
|
6140
|
+
let version = "latest";
|
|
6141
|
+
try {
|
|
6142
|
+
const releases = await githubFetch2(
|
|
6143
|
+
`/repos/${args.owner}/${args.repo}/releases?per_page=1`,
|
|
6144
|
+
token
|
|
6145
|
+
);
|
|
6146
|
+
if (releases.length > 0) {
|
|
6147
|
+
version = releases[0].tag_name;
|
|
6148
|
+
}
|
|
6149
|
+
} catch {
|
|
6150
|
+
try {
|
|
6151
|
+
const tags = await githubFetch2(
|
|
6152
|
+
`/repos/${args.owner}/${args.repo}/tags?per_page=1`,
|
|
6153
|
+
token
|
|
6154
|
+
);
|
|
6155
|
+
if (tags.length > 0) {
|
|
6156
|
+
version = tags[0].name;
|
|
6157
|
+
}
|
|
6158
|
+
} catch {
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
6161
|
+
setTask("2", "completed");
|
|
6162
|
+
setTask("3", "in_progress");
|
|
6163
|
+
const writeUp = await summarizeWithLlm(merged, ctx);
|
|
6164
|
+
setTask("3", "completed");
|
|
6165
|
+
setTask("4", "in_progress");
|
|
6166
|
+
const logoBase64 = await loadLogoBase64();
|
|
6167
|
+
const svg = buildChangelogSvg({ owner: args.owner, repo: args.repo, version, writeUp, logoBase64 });
|
|
6168
|
+
const resvg = new Resvg(svg, {
|
|
6169
|
+
fitTo: { mode: "zoom", value: 2 },
|
|
6170
|
+
font: {
|
|
6171
|
+
defaultFontFamily: "system-ui"
|
|
6172
|
+
}
|
|
6173
|
+
});
|
|
6174
|
+
const pngData = resvg.render();
|
|
6175
|
+
const pngBuffer = pngData.asPng();
|
|
6176
|
+
setTask("4", "completed");
|
|
6177
|
+
setTask("5", "in_progress");
|
|
6178
|
+
const outputPath = args.output ?? `./changelog-${args.repo}-${version.replace(/[^a-zA-Z0-9._-]/g, "_")}.png`;
|
|
6179
|
+
await writeFile5(outputPath, pngBuffer);
|
|
6180
|
+
setTask("5", "completed");
|
|
6181
|
+
const periodLabel = days === 1 ? "past day" : `past ${days} days`;
|
|
6182
|
+
const content = `\u2713 Changelog image saved to ${outputPath}
|
|
6183
|
+
${merged.length} PR${merged.length === 1 ? "" : "s"} from the ${periodLabel} \xB7 ${version} \xB7 ${resvg.width}\xD7${resvg.height}`;
|
|
6184
|
+
const bytes = Buffer.byteLength(content, "utf8");
|
|
6185
|
+
return { content, rawBytes: bytes, reducedBytes: bytes };
|
|
6186
|
+
}
|
|
6187
|
+
};
|
|
6188
|
+
}
|
|
6189
|
+
});
|
|
6190
|
+
|
|
5775
6191
|
// src/tools/browser.ts
|
|
5776
6192
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
5777
6193
|
import { tmpdir as tmpdir2 } from "os";
|
|
5778
|
-
import { join as
|
|
6194
|
+
import { join as join12, dirname as dirname5 } from "path";
|
|
5779
6195
|
async function autoScroll(page) {
|
|
5780
6196
|
await page.evaluate(async () => {
|
|
5781
6197
|
await new Promise((resolve5) => {
|
|
@@ -5797,11 +6213,11 @@ async function autoScroll(page) {
|
|
|
5797
6213
|
});
|
|
5798
6214
|
});
|
|
5799
6215
|
}
|
|
5800
|
-
var
|
|
6216
|
+
var TIMEOUT_MS5, NAV_TIMEOUT_MS, browserFetchTool;
|
|
5801
6217
|
var init_browser = __esm({
|
|
5802
6218
|
"src/tools/browser.ts"() {
|
|
5803
6219
|
"use strict";
|
|
5804
|
-
|
|
6220
|
+
TIMEOUT_MS5 = 3e4;
|
|
5805
6221
|
NAV_TIMEOUT_MS = 2e4;
|
|
5806
6222
|
browserFetchTool = {
|
|
5807
6223
|
name: "browser_fetch",
|
|
@@ -5844,14 +6260,14 @@ var init_browser = __esm({
|
|
|
5844
6260
|
const page = await browser.newPage();
|
|
5845
6261
|
await page.goto(args.url, { waitUntil: "networkidle", timeout: NAV_TIMEOUT_MS });
|
|
5846
6262
|
if (args.wait_for) {
|
|
5847
|
-
await page.waitForSelector(args.wait_for, { timeout:
|
|
6263
|
+
await page.waitForSelector(args.wait_for, { timeout: TIMEOUT_MS5 });
|
|
5848
6264
|
}
|
|
5849
6265
|
if (args.scroll) {
|
|
5850
6266
|
await autoScroll(page);
|
|
5851
6267
|
}
|
|
5852
6268
|
let screenshotPath;
|
|
5853
6269
|
if (args.screenshot) {
|
|
5854
|
-
screenshotPath =
|
|
6270
|
+
screenshotPath = join12(tmpdir2(), `kimiflare-browser-${Date.now()}.png`);
|
|
5855
6271
|
await mkdir5(dirname5(screenshotPath), { recursive: true });
|
|
5856
6272
|
await page.screenshot({ path: screenshotPath, fullPage: true });
|
|
5857
6273
|
}
|
|
@@ -6976,6 +7392,7 @@ var init_executor = __esm({
|
|
|
6976
7392
|
init_web_fetch();
|
|
6977
7393
|
init_web_search();
|
|
6978
7394
|
init_github();
|
|
7395
|
+
init_changelog_image();
|
|
6979
7396
|
init_browser();
|
|
6980
7397
|
init_tasks();
|
|
6981
7398
|
init_memory();
|
|
@@ -6996,6 +7413,9 @@ var init_executor = __esm({
|
|
|
6996
7413
|
githubReadPrTool,
|
|
6997
7414
|
githubReadIssueTool,
|
|
6998
7415
|
githubReadCodeTool,
|
|
7416
|
+
githubListMergedPrsTool,
|
|
7417
|
+
githubListReleasesTool,
|
|
7418
|
+
changelogImageTool,
|
|
6999
7419
|
browserFetchTool,
|
|
7000
7420
|
tasksSetTool,
|
|
7001
7421
|
memoryRememberTool,
|
|
@@ -7215,20 +7635,20 @@ var init_executor = __esm({
|
|
|
7215
7635
|
});
|
|
7216
7636
|
|
|
7217
7637
|
// src/util/update-check.ts
|
|
7218
|
-
import { readFile as
|
|
7638
|
+
import { readFile as readFile8, writeFile as writeFile7, mkdir as mkdir6 } from "fs/promises";
|
|
7219
7639
|
import { homedir as homedir6 } from "os";
|
|
7220
|
-
import { join as
|
|
7640
|
+
import { join as join13, dirname as dirname6 } from "path";
|
|
7221
7641
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7222
7642
|
function cachePath() {
|
|
7223
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
7224
|
-
return
|
|
7643
|
+
const xdg = process.env.XDG_CONFIG_HOME || join13(homedir6(), ".config");
|
|
7644
|
+
return join13(xdg, "kimiflare", "update-check.json");
|
|
7225
7645
|
}
|
|
7226
7646
|
async function findPackageJson(startDir) {
|
|
7227
7647
|
let dir = startDir;
|
|
7228
7648
|
while (true) {
|
|
7229
|
-
const candidate =
|
|
7649
|
+
const candidate = join13(dir, "package.json");
|
|
7230
7650
|
try {
|
|
7231
|
-
const raw = await
|
|
7651
|
+
const raw = await readFile8(candidate, "utf8");
|
|
7232
7652
|
const parsed = JSON.parse(raw);
|
|
7233
7653
|
if (parsed.name === "kimiflare" && parsed.version) {
|
|
7234
7654
|
return { path: candidate, version: parsed.version };
|
|
@@ -7248,7 +7668,7 @@ async function readLocalVersion() {
|
|
|
7248
7668
|
}
|
|
7249
7669
|
async function readCache() {
|
|
7250
7670
|
try {
|
|
7251
|
-
const raw = await
|
|
7671
|
+
const raw = await readFile8(cachePath(), "utf8");
|
|
7252
7672
|
const parsed = JSON.parse(raw);
|
|
7253
7673
|
if (Date.now() - parsed.checkedAt < CACHE_TTL_MS) {
|
|
7254
7674
|
return parsed;
|
|
@@ -7260,7 +7680,7 @@ async function readCache() {
|
|
|
7260
7680
|
async function writeCache(entry) {
|
|
7261
7681
|
const p = cachePath();
|
|
7262
7682
|
await mkdir6(dirname6(p), { recursive: true });
|
|
7263
|
-
await
|
|
7683
|
+
await writeFile7(p, JSON.stringify(entry), "utf8");
|
|
7264
7684
|
}
|
|
7265
7685
|
async function fetchLatestVersion() {
|
|
7266
7686
|
try {
|
|
@@ -7291,8 +7711,8 @@ function isNewer(local, remote) {
|
|
|
7291
7711
|
async function readOptionalDepVersion(name) {
|
|
7292
7712
|
try {
|
|
7293
7713
|
const here = dirname6(fileURLToPath2(import.meta.url));
|
|
7294
|
-
const candidate =
|
|
7295
|
-
const raw = await
|
|
7714
|
+
const candidate = join13(here, "..", "..", "node_modules", name, "package.json");
|
|
7715
|
+
const raw = await readFile8(candidate, "utf8");
|
|
7296
7716
|
const parsed = JSON.parse(raw);
|
|
7297
7717
|
return parsed.version ?? null;
|
|
7298
7718
|
} catch {
|
|
@@ -7352,23 +7772,23 @@ var init_update_check = __esm({
|
|
|
7352
7772
|
});
|
|
7353
7773
|
|
|
7354
7774
|
// src/remote/session-store.ts
|
|
7355
|
-
import { readFile as
|
|
7775
|
+
import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir7, readdir as readdir3 } from "fs/promises";
|
|
7356
7776
|
import { homedir as homedir7 } from "os";
|
|
7357
|
-
import { join as
|
|
7777
|
+
import { join as join14 } from "path";
|
|
7358
7778
|
function remoteDir() {
|
|
7359
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
7360
|
-
return
|
|
7779
|
+
const xdg = process.env.XDG_DATA_HOME || join14(homedir7(), ".config");
|
|
7780
|
+
return join14(xdg, "kimiflare", "remote");
|
|
7361
7781
|
}
|
|
7362
7782
|
async function saveRemoteSession(session) {
|
|
7363
7783
|
const dir = remoteDir();
|
|
7364
7784
|
await mkdir7(dir, { recursive: true });
|
|
7365
|
-
const path =
|
|
7366
|
-
await
|
|
7785
|
+
const path = join14(dir, `${session.sessionId}.json`);
|
|
7786
|
+
await writeFile8(path, JSON.stringify(session, null, 2) + "\n", "utf8");
|
|
7367
7787
|
}
|
|
7368
7788
|
async function loadRemoteSession(sessionId) {
|
|
7369
7789
|
try {
|
|
7370
|
-
const path =
|
|
7371
|
-
const raw = await
|
|
7790
|
+
const path = join14(remoteDir(), `${sessionId}.json`);
|
|
7791
|
+
const raw = await readFile9(path, "utf8");
|
|
7372
7792
|
return JSON.parse(raw);
|
|
7373
7793
|
} catch {
|
|
7374
7794
|
return null;
|
|
@@ -7382,7 +7802,7 @@ async function listRemoteSessions() {
|
|
|
7382
7802
|
for (const file of files) {
|
|
7383
7803
|
if (!file.endsWith(".json")) continue;
|
|
7384
7804
|
try {
|
|
7385
|
-
const raw = await
|
|
7805
|
+
const raw = await readFile9(join14(dir, file), "utf8");
|
|
7386
7806
|
sessions.push(JSON.parse(raw));
|
|
7387
7807
|
} catch {
|
|
7388
7808
|
}
|
|
@@ -7404,7 +7824,7 @@ var init_session_store = __esm({
|
|
|
7404
7824
|
|
|
7405
7825
|
// src/remote/deploy.ts
|
|
7406
7826
|
import { execSync } from "child_process";
|
|
7407
|
-
import { join as
|
|
7827
|
+
import { join as join15, dirname as dirname7 } from "path";
|
|
7408
7828
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7409
7829
|
import { randomBytes } from "crypto";
|
|
7410
7830
|
function generateSecret() {
|
|
@@ -7439,7 +7859,7 @@ async function* deployForTui() {
|
|
|
7439
7859
|
yield { message: "Docker OK" };
|
|
7440
7860
|
yield { message: "Building remote agent bundle..." };
|
|
7441
7861
|
try {
|
|
7442
|
-
runCapture("npm run build:remote-agent",
|
|
7862
|
+
runCapture("npm run build:remote-agent", join15(REMOTE_DIR, ".."));
|
|
7443
7863
|
yield { message: "Agent bundle built" };
|
|
7444
7864
|
} catch (err) {
|
|
7445
7865
|
yield { message: `Build failed: ${err instanceof Error ? err.message : String(err)}`, error: true };
|
|
@@ -7569,8 +7989,8 @@ var init_deploy = __esm({
|
|
|
7569
7989
|
"use strict";
|
|
7570
7990
|
init_config();
|
|
7571
7991
|
__dirname2 = dirname7(fileURLToPath3(import.meta.url));
|
|
7572
|
-
REMOTE_DIR =
|
|
7573
|
-
WORKER_DIR =
|
|
7992
|
+
REMOTE_DIR = join15(__dirname2, "..", "..", "..", "remote");
|
|
7993
|
+
WORKER_DIR = join15(REMOTE_DIR, "worker");
|
|
7574
7994
|
}
|
|
7575
7995
|
});
|
|
7576
7996
|
|
|
@@ -8084,12 +8504,12 @@ var init_heuristic = __esm({
|
|
|
8084
8504
|
});
|
|
8085
8505
|
|
|
8086
8506
|
// src/cost-attribution/classify-from-session.ts
|
|
8087
|
-
import { readFile as
|
|
8088
|
-
import { join as
|
|
8507
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
8508
|
+
import { join as join16 } from "path";
|
|
8089
8509
|
import { homedir as homedir8 } from "os";
|
|
8090
8510
|
function sessionsDir() {
|
|
8091
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8092
|
-
return
|
|
8511
|
+
const xdg = process.env.XDG_DATA_HOME || join16(homedir8(), ".local", "share");
|
|
8512
|
+
return join16(xdg, "kimiflare", "sessions");
|
|
8093
8513
|
}
|
|
8094
8514
|
function parseToolCalls(calls) {
|
|
8095
8515
|
return calls.map((c) => {
|
|
@@ -8103,7 +8523,7 @@ function parseToolCalls(calls) {
|
|
|
8103
8523
|
}
|
|
8104
8524
|
async function classifyFromSessionFile(sessionId) {
|
|
8105
8525
|
try {
|
|
8106
|
-
const raw = await
|
|
8526
|
+
const raw = await readFile10(join16(sessionsDir(), `${sessionId}.json`), "utf8");
|
|
8107
8527
|
const session = JSON.parse(raw);
|
|
8108
8528
|
const messages = session.messages ?? [];
|
|
8109
8529
|
const turns = [];
|
|
@@ -8136,15 +8556,15 @@ var cli_exports = {};
|
|
|
8136
8556
|
__export(cli_exports, {
|
|
8137
8557
|
runCostCommand: () => runCostCommand
|
|
8138
8558
|
});
|
|
8139
|
-
import { readFile as
|
|
8140
|
-
import { join as
|
|
8559
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
8560
|
+
import { join as join17 } from "path";
|
|
8141
8561
|
import { homedir as homedir9 } from "os";
|
|
8142
8562
|
function usageDir() {
|
|
8143
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8144
|
-
return
|
|
8563
|
+
const xdg = process.env.XDG_DATA_HOME || join17(homedir9(), ".local", "share");
|
|
8564
|
+
return join17(xdg, "kimiflare");
|
|
8145
8565
|
}
|
|
8146
8566
|
function usagePath() {
|
|
8147
|
-
return
|
|
8567
|
+
return join17(usageDir(), "usage.json");
|
|
8148
8568
|
}
|
|
8149
8569
|
function today() {
|
|
8150
8570
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -8156,7 +8576,7 @@ function daysAgo(n) {
|
|
|
8156
8576
|
}
|
|
8157
8577
|
async function loadLog() {
|
|
8158
8578
|
try {
|
|
8159
|
-
const raw = await
|
|
8579
|
+
const raw = await readFile11(usagePath(), "utf8");
|
|
8160
8580
|
return JSON.parse(raw);
|
|
8161
8581
|
} catch {
|
|
8162
8582
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -8255,12 +8675,12 @@ __export(sessions_exports, {
|
|
|
8255
8675
|
saveSession: () => saveSession,
|
|
8256
8676
|
sessionsDir: () => sessionsDir2
|
|
8257
8677
|
});
|
|
8258
|
-
import { readFile as
|
|
8678
|
+
import { readFile as readFile12, writeFile as writeFile9, mkdir as mkdir8, readdir as readdir4, stat as stat4 } from "fs/promises";
|
|
8259
8679
|
import { homedir as homedir10 } from "os";
|
|
8260
|
-
import { join as
|
|
8680
|
+
import { join as join18 } from "path";
|
|
8261
8681
|
function sessionsDir2() {
|
|
8262
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
8263
|
-
return
|
|
8682
|
+
const xdg = process.env.XDG_DATA_HOME || join18(homedir10(), ".local", "share");
|
|
8683
|
+
return join18(xdg, "kimiflare", "sessions");
|
|
8264
8684
|
}
|
|
8265
8685
|
function sanitize(text) {
|
|
8266
8686
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
@@ -8280,8 +8700,8 @@ function makeSessionId(firstPrompt) {
|
|
|
8280
8700
|
async function saveSession(file) {
|
|
8281
8701
|
const dir = sessionsDir2();
|
|
8282
8702
|
await mkdir8(dir, { recursive: true });
|
|
8283
|
-
const path =
|
|
8284
|
-
await
|
|
8703
|
+
const path = join18(dir, `${file.id}.json`);
|
|
8704
|
+
await writeFile9(path, JSON.stringify(file, null, 2), "utf8");
|
|
8285
8705
|
return path;
|
|
8286
8706
|
}
|
|
8287
8707
|
async function pruneSessions() {
|
|
@@ -8300,9 +8720,9 @@ async function listSessions(limit = 30, cwd) {
|
|
|
8300
8720
|
const summaries = [];
|
|
8301
8721
|
for (const name of entries) {
|
|
8302
8722
|
if (!name.endsWith(".json")) continue;
|
|
8303
|
-
const path =
|
|
8723
|
+
const path = join18(dir, name);
|
|
8304
8724
|
try {
|
|
8305
|
-
const [s, raw] = await Promise.all([stat4(path),
|
|
8725
|
+
const [s, raw] = await Promise.all([stat4(path), readFile12(path, "utf8")]);
|
|
8306
8726
|
const parsed = JSON.parse(raw);
|
|
8307
8727
|
if (cwd && parsed.cwd !== cwd) continue;
|
|
8308
8728
|
const firstUser = parsed.messages.find((m) => m.role === "user");
|
|
@@ -8324,7 +8744,7 @@ async function listSessions(limit = 30, cwd) {
|
|
|
8324
8744
|
return summaries.slice(0, limit);
|
|
8325
8745
|
}
|
|
8326
8746
|
async function loadSession(filePath) {
|
|
8327
|
-
const raw = await
|
|
8747
|
+
const raw = await readFile12(filePath, "utf8");
|
|
8328
8748
|
return JSON.parse(raw);
|
|
8329
8749
|
}
|
|
8330
8750
|
async function addCheckpoint(filePath, checkpoint) {
|
|
@@ -10599,20 +11019,20 @@ var init_pricing = __esm({
|
|
|
10599
11019
|
});
|
|
10600
11020
|
|
|
10601
11021
|
// src/usage-tracker.ts
|
|
10602
|
-
import { readFile as
|
|
11022
|
+
import { readFile as readFile13, writeFile as writeFile10, mkdir as mkdir9 } from "fs/promises";
|
|
10603
11023
|
import { homedir as homedir11 } from "os";
|
|
10604
|
-
import { join as
|
|
11024
|
+
import { join as join20 } from "path";
|
|
10605
11025
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
10606
11026
|
import { randomUUID } from "crypto";
|
|
10607
11027
|
function usageDir2() {
|
|
10608
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
10609
|
-
return
|
|
11028
|
+
const xdg = process.env.XDG_DATA_HOME || join20(homedir11(), ".local", "share");
|
|
11029
|
+
return join20(xdg, "kimiflare");
|
|
10610
11030
|
}
|
|
10611
11031
|
function usagePath2() {
|
|
10612
|
-
return
|
|
11032
|
+
return join20(usageDir2(), "usage.json");
|
|
10613
11033
|
}
|
|
10614
11034
|
function historyPath() {
|
|
10615
|
-
return
|
|
11035
|
+
return join20(usageDir2(), "history.jsonl");
|
|
10616
11036
|
}
|
|
10617
11037
|
function today2() {
|
|
10618
11038
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -10623,7 +11043,7 @@ function cutoffDate(daysBack) {
|
|
|
10623
11043
|
}
|
|
10624
11044
|
async function loadLog2() {
|
|
10625
11045
|
try {
|
|
10626
|
-
const raw = await
|
|
11046
|
+
const raw = await readFile13(usagePath2(), "utf8");
|
|
10627
11047
|
const parsed = JSON.parse(raw);
|
|
10628
11048
|
if (parsed.version === LOG_VERSION2) return parsed;
|
|
10629
11049
|
} catch {
|
|
@@ -10632,7 +11052,7 @@ async function loadLog2() {
|
|
|
10632
11052
|
}
|
|
10633
11053
|
async function saveLog(log2) {
|
|
10634
11054
|
await mkdir9(usageDir2(), { recursive: true });
|
|
10635
|
-
await
|
|
11055
|
+
await writeFile10(usagePath2(), JSON.stringify(log2, null, 2), "utf8");
|
|
10636
11056
|
}
|
|
10637
11057
|
function withLock(fn) {
|
|
10638
11058
|
const next = writeChain.then(fn, fn);
|
|
@@ -10641,7 +11061,7 @@ function withLock(fn) {
|
|
|
10641
11061
|
}
|
|
10642
11062
|
async function loadHistory() {
|
|
10643
11063
|
try {
|
|
10644
|
-
const raw = await
|
|
11064
|
+
const raw = await readFile13(historyPath(), "utf8");
|
|
10645
11065
|
const lines = raw.split("\n").filter((l) => l.trim());
|
|
10646
11066
|
const entries = [];
|
|
10647
11067
|
for (const line of lines) {
|
|
@@ -10666,7 +11086,7 @@ async function upsertHistoryDay(day) {
|
|
|
10666
11086
|
}
|
|
10667
11087
|
const lines = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
10668
11088
|
await mkdir9(usageDir2(), { recursive: true });
|
|
10669
|
-
await
|
|
11089
|
+
await writeFile10(historyPath(), lines, "utf8");
|
|
10670
11090
|
}
|
|
10671
11091
|
function getOrCreateDay(log2, date) {
|
|
10672
11092
|
let day = log2.days.find((d) => d.date === date);
|
|
@@ -11075,14 +11495,14 @@ var init_types2 = __esm({
|
|
|
11075
11495
|
// src/hooks/settings.ts
|
|
11076
11496
|
import { existsSync as existsSync2, readFileSync as readFileSync3, mkdirSync as mkdirSync3, writeFileSync } from "fs";
|
|
11077
11497
|
import { homedir as homedir12 } from "os";
|
|
11078
|
-
import { join as
|
|
11498
|
+
import { join as join21, dirname as dirname9 } from "path";
|
|
11079
11499
|
import { createHash } from "crypto";
|
|
11080
11500
|
function globalSettingsPath() {
|
|
11081
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
11082
|
-
return
|
|
11501
|
+
const xdg = process.env.XDG_CONFIG_HOME || join21(homedir12(), ".config");
|
|
11502
|
+
return join21(xdg, "kimiflare", "settings.json");
|
|
11083
11503
|
}
|
|
11084
11504
|
function projectSettingsPath(cwd) {
|
|
11085
|
-
return
|
|
11505
|
+
return join21(cwd, ".kimiflare", "settings.json");
|
|
11086
11506
|
}
|
|
11087
11507
|
function readSettingsFile(path) {
|
|
11088
11508
|
if (!existsSync2(path)) return null;
|
|
@@ -11407,7 +11827,7 @@ var init_manager3 = __esm({
|
|
|
11407
11827
|
// src/sdk/session.ts
|
|
11408
11828
|
import { resolve as resolve3 } from "path";
|
|
11409
11829
|
import { homedir as homedir13 } from "os";
|
|
11410
|
-
import { join as
|
|
11830
|
+
import { join as join22 } from "path";
|
|
11411
11831
|
import { existsSync as existsSync3 } from "fs";
|
|
11412
11832
|
async function createAgentSession(opts2) {
|
|
11413
11833
|
const config2 = await resolveSdkConfig(opts2);
|
|
@@ -11422,7 +11842,7 @@ async function createAgentSession(opts2) {
|
|
|
11422
11842
|
let memoryManager = null;
|
|
11423
11843
|
const memoryEnabled = opts2.memoryEnabled ?? config2.memoryEnabled ?? false;
|
|
11424
11844
|
if (memoryEnabled) {
|
|
11425
|
-
const dbPath = config2.memoryDbPath ??
|
|
11845
|
+
const dbPath = config2.memoryDbPath ?? join22(homedir13(), ".local", "share", "kimiflare", "memory.db");
|
|
11426
11846
|
memoryManager = new MemoryManager({
|
|
11427
11847
|
dbPath,
|
|
11428
11848
|
accountId: config2.accountId,
|
|
@@ -11453,7 +11873,7 @@ async function createAgentSession(opts2) {
|
|
|
11453
11873
|
}
|
|
11454
11874
|
let sessionFile;
|
|
11455
11875
|
if (opts2.sessionId) {
|
|
11456
|
-
const filePath =
|
|
11876
|
+
const filePath = join22(sessionsDir2(), `${opts2.sessionId}.json`);
|
|
11457
11877
|
try {
|
|
11458
11878
|
sessionFile = await loadSession(filePath);
|
|
11459
11879
|
} catch {
|
|
@@ -11612,8 +12032,8 @@ var init_session = __esm({
|
|
|
11612
12032
|
const parts = [{ type: "text", text }];
|
|
11613
12033
|
for (const img of options.images) {
|
|
11614
12034
|
if ("path" in img) {
|
|
11615
|
-
const { readFile:
|
|
11616
|
-
const data = await
|
|
12035
|
+
const { readFile: readFile23 } = await import("fs/promises");
|
|
12036
|
+
const data = await readFile23(img.path, "base64");
|
|
11617
12037
|
const mimeType = img.path.endsWith(".png") ? "image/png" : img.path.endsWith(".jpg") || img.path.endsWith(".jpeg") ? "image/jpeg" : "image/webp";
|
|
11618
12038
|
parts.push({ type: "image_url", image_url: { url: `data:${mimeType};base64,${data}` } });
|
|
11619
12039
|
} else {
|
|
@@ -11859,14 +12279,14 @@ var init_session = __esm({
|
|
|
11859
12279
|
this.lspManager?.notifyChange(path, content);
|
|
11860
12280
|
} else {
|
|
11861
12281
|
void import("fs/promises").then(
|
|
11862
|
-
({ readFile:
|
|
12282
|
+
({ readFile: readFile23 }) => readFile23(path, "utf8").then((c) => this.lspManager?.notifyChange(path, c)).catch(() => {
|
|
11863
12283
|
})
|
|
11864
12284
|
).catch(() => {
|
|
11865
12285
|
});
|
|
11866
12286
|
}
|
|
11867
12287
|
}
|
|
11868
12288
|
});
|
|
11869
|
-
if (existsSync3(
|
|
12289
|
+
if (existsSync3(join22(this.cwd, "KIMI.md"))) {
|
|
11870
12290
|
this.messages[0] = {
|
|
11871
12291
|
role: "system",
|
|
11872
12292
|
content: buildSystemPrompt({
|
|
@@ -12141,9 +12561,9 @@ var init_repo_info = __esm({
|
|
|
12141
12561
|
});
|
|
12142
12562
|
|
|
12143
12563
|
// src/agent/supervisor.ts
|
|
12144
|
-
import { readdir as readdir5, readFile as
|
|
12564
|
+
import { readdir as readdir5, readFile as readFile14, stat as stat5 } from "fs/promises";
|
|
12145
12565
|
import { createHash as createHash2 } from "crypto";
|
|
12146
|
-
import { resolve as resolve4, join as
|
|
12566
|
+
import { resolve as resolve4, join as join23 } from "path";
|
|
12147
12567
|
async function preReadFilesForWorkers(files, repoRoot, maxChars = DEFAULT_PRE_READ_MAX_CHARS) {
|
|
12148
12568
|
const results = [];
|
|
12149
12569
|
const filesRead = [];
|
|
@@ -12154,7 +12574,7 @@ async function preReadFilesForWorkers(files, repoRoot, maxChars = DEFAULT_PRE_RE
|
|
|
12154
12574
|
try {
|
|
12155
12575
|
const s = await stat5(path);
|
|
12156
12576
|
if (!s.isFile()) continue;
|
|
12157
|
-
const raw = await
|
|
12577
|
+
const raw = await readFile14(path, "utf8");
|
|
12158
12578
|
const remaining = maxChars - chars;
|
|
12159
12579
|
const content = raw.length > remaining ? raw.slice(0, remaining) + "\n\u2026 (truncated)" : raw;
|
|
12160
12580
|
results.push(`--- ${file} ---
|
|
@@ -12178,7 +12598,7 @@ ${results.join("\n\n")}`,
|
|
|
12178
12598
|
}
|
|
12179
12599
|
function getPreReadFilesFromMemory(cfg, repoRoot, limit = 10) {
|
|
12180
12600
|
if (!cfg.memoryEnabled) return [];
|
|
12181
|
-
const dbPath = cfg.memoryDbPath ??
|
|
12601
|
+
const dbPath = cfg.memoryDbPath ?? join23(repoRoot, ".kimiflare", "memory.db");
|
|
12182
12602
|
try {
|
|
12183
12603
|
const db = openMemoryDb(dbPath);
|
|
12184
12604
|
const files = getTopRelatedFiles(db, repoRoot, limit);
|
|
@@ -13440,9 +13860,9 @@ var init_emit_mode = __esm({
|
|
|
13440
13860
|
|
|
13441
13861
|
// src/remote/deploy-commute.ts
|
|
13442
13862
|
import { spawn as spawn4 } from "child_process";
|
|
13443
|
-
import { mkdtemp, readFile as
|
|
13863
|
+
import { mkdtemp, readFile as readFile15, writeFile as writeFile11, rm } from "fs/promises";
|
|
13444
13864
|
import { tmpdir as tmpdir3 } from "os";
|
|
13445
|
-
import { join as
|
|
13865
|
+
import { join as join24 } from "path";
|
|
13446
13866
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
13447
13867
|
async function cfApiFetch(accountId, apiToken, path, init) {
|
|
13448
13868
|
const url = `${CF_API}/accounts/${encodeURIComponent(accountId)}${path}`;
|
|
@@ -13673,8 +14093,8 @@ ${wranglerInstall.stderr.slice(-600)}`,
|
|
|
13673
14093
|
ok: true
|
|
13674
14094
|
};
|
|
13675
14095
|
yield { message: "Prerequisites ready", ok: true };
|
|
13676
|
-
const tmpRoot = await mkdtemp(
|
|
13677
|
-
const repoDir =
|
|
14096
|
+
const tmpRoot = await mkdtemp(join24(tmpdir3(), "kimiflare-commute-"));
|
|
14097
|
+
const repoDir = join24(tmpRoot, "kimiflare-commute");
|
|
13678
14098
|
yield { message: `Fetching worker source from GitHub (${COMMUTE_REPO})\u2026` };
|
|
13679
14099
|
const clone = await runCmd("git", ["clone", "--depth", "1", "--branch", COMMUTE_BRANCH, COMMUTE_REPO, repoDir], { timeoutMs: 6e4 });
|
|
13680
14100
|
if (clone.code !== 0) {
|
|
@@ -13683,8 +14103,8 @@ ${(clone.stderr || clone.stdout).slice(0, 400)}`, error: true };
|
|
|
13683
14103
|
throw new Error("clone failed");
|
|
13684
14104
|
}
|
|
13685
14105
|
yield { message: "Source fetched from GitHub", ok: true };
|
|
13686
|
-
const workerDir =
|
|
13687
|
-
const wranglerToml =
|
|
14106
|
+
const workerDir = join24(repoDir, "remote", "worker");
|
|
14107
|
+
const wranglerToml = join24(workerDir, "wrangler.toml");
|
|
13688
14108
|
yield { message: "Installing Worker dependencies (npm install)\u2026" };
|
|
13689
14109
|
const install = await runCmd("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], {
|
|
13690
14110
|
cwd: workerDir,
|
|
@@ -13773,7 +14193,7 @@ ${(install.stderr || install.stdout).slice(-1200).trim()}`,
|
|
|
13773
14193
|
ok: true
|
|
13774
14194
|
};
|
|
13775
14195
|
yield { message: "Patching wrangler.toml\u2026" };
|
|
13776
|
-
let toml = await
|
|
14196
|
+
let toml = await readFile15(wranglerToml, "utf8");
|
|
13777
14197
|
toml = toml.replace(/^name\s*=\s*"[^"]+"/m, `name = "${workerName}"`);
|
|
13778
14198
|
toml = toml.replace(
|
|
13779
14199
|
/(\[\[kv_namespaces\]\][\s\S]*?binding\s*=\s*"OAUTH_KV"[\s\S]*?id\s*=\s*")[^"]+(")/,
|
|
@@ -13806,7 +14226,7 @@ enabled = false
|
|
|
13806
14226
|
invocation_logs = true
|
|
13807
14227
|
`;
|
|
13808
14228
|
}
|
|
13809
|
-
await
|
|
14229
|
+
await writeFile11(wranglerToml, toml, "utf8");
|
|
13810
14230
|
yield {
|
|
13811
14231
|
message: workerExists ? "wrangler.toml patched (name, KV id, [[artifacts]] stripped)" : "wrangler.toml patched (name, KV id, [[artifacts]] stripped, DO migrations added)",
|
|
13812
14232
|
ok: true
|
|
@@ -14000,10 +14420,10 @@ var init_deploy_commute = __esm({
|
|
|
14000
14420
|
});
|
|
14001
14421
|
|
|
14002
14422
|
// src/util/image.ts
|
|
14003
|
-
import { readFile as
|
|
14423
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
14004
14424
|
import { basename as basename3 } from "path";
|
|
14005
14425
|
async function encodeImageFile(filePath) {
|
|
14006
|
-
const buf = await
|
|
14426
|
+
const buf = await readFile16(filePath);
|
|
14007
14427
|
if (buf.byteLength > MAX_IMAGE_BYTES) {
|
|
14008
14428
|
throw new Error(
|
|
14009
14429
|
`image too large (${(buf.byteLength / 1024 / 1024).toFixed(1)} MB); max is ${MAX_IMAGE_BYTES / 1024 / 1024} MB`
|
|
@@ -14039,9 +14459,33 @@ var init_image = __esm({
|
|
|
14039
14459
|
});
|
|
14040
14460
|
|
|
14041
14461
|
// src/ui/app-helpers.ts
|
|
14462
|
+
var app_helpers_exports = {};
|
|
14463
|
+
__export(app_helpers_exports, {
|
|
14464
|
+
AUTO_COMPACT_THRESHOLD: () => AUTO_COMPACT_THRESHOLD,
|
|
14465
|
+
CONTEXT_LIMIT: () => CONTEXT_LIMIT,
|
|
14466
|
+
DEFAULT_AUTO_FRESH_SUGGESTION_TURNS: () => DEFAULT_AUTO_FRESH_SUGGESTION_TURNS,
|
|
14467
|
+
FEEDBACK_WORKER_URL: () => FEEDBACK_WORKER_URL,
|
|
14468
|
+
MAX_EVENTS: () => MAX_EVENTS,
|
|
14469
|
+
MAX_IMAGES_PER_MESSAGE: () => MAX_IMAGES_PER_MESSAGE,
|
|
14470
|
+
buildFilePickerIgnoreList: () => buildFilePickerIgnoreList,
|
|
14471
|
+
capEvents: () => capEvents,
|
|
14472
|
+
compactEventsVisual: () => compactEventsVisual,
|
|
14473
|
+
detectGitBranch: () => detectGitBranch,
|
|
14474
|
+
detectGitHubRepo: () => detectGitHubRepo,
|
|
14475
|
+
findImagePaths: () => findImagePaths,
|
|
14476
|
+
formatTokens: () => formatTokens,
|
|
14477
|
+
gatewayFromConfig: () => gatewayFromConfig,
|
|
14478
|
+
gatewayUsageLookupFromConfig: () => gatewayUsageLookupFromConfig,
|
|
14479
|
+
makePrefixMessages: () => makePrefixMessages,
|
|
14480
|
+
mkAssistantId: () => mkAssistantId,
|
|
14481
|
+
mkKey: () => mkKey,
|
|
14482
|
+
openBrowser: () => openBrowser,
|
|
14483
|
+
rebuildSystemPromptForMode: () => rebuildSystemPromptForMode,
|
|
14484
|
+
trackRecentFile: () => trackRecentFile
|
|
14485
|
+
});
|
|
14042
14486
|
import { execSync as execSync3, spawn as spawn5 } from "child_process";
|
|
14043
14487
|
import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
14044
|
-
import { join as
|
|
14488
|
+
import { join as join25 } from "path";
|
|
14045
14489
|
import { platform as platform3 } from "os";
|
|
14046
14490
|
function buildFilePickerIgnoreList(cwd) {
|
|
14047
14491
|
const hardcoded = [
|
|
@@ -14113,7 +14557,7 @@ function buildFilePickerIgnoreList(cwd) {
|
|
|
14113
14557
|
];
|
|
14114
14558
|
const gitignorePatterns = [];
|
|
14115
14559
|
try {
|
|
14116
|
-
const gitignorePath =
|
|
14560
|
+
const gitignorePath = join25(cwd, ".gitignore");
|
|
14117
14561
|
const stats = statSync4(gitignorePath);
|
|
14118
14562
|
if (stats.size > MAX_GITIGNORE_SIZE) {
|
|
14119
14563
|
return hardcoded;
|
|
@@ -14171,7 +14615,7 @@ function detectGitHubRepo(cachedRepo) {
|
|
|
14171
14615
|
if (parts.length === 2) return { owner: parts[0], name: parts[1] };
|
|
14172
14616
|
}
|
|
14173
14617
|
try {
|
|
14174
|
-
const remoteUrl = execSync3("git remote get-url origin", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
14618
|
+
const remoteUrl = execSync3("git remote get-url origin", { cwd: process.cwd(), encoding: "utf8" }).trim().replace(/\/+$/, "");
|
|
14175
14619
|
const httpsMatch = remoteUrl.match(/github\.com\/([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
14176
14620
|
if (httpsMatch) return { owner: httpsMatch[1], name: httpsMatch[2] };
|
|
14177
14621
|
const sshMatch = remoteUrl.match(/github\.com:([^\/]+)\/([^\/]+?)(?:\.git)?$/);
|
|
@@ -14275,7 +14719,7 @@ function findImagePaths(text) {
|
|
|
14275
14719
|
}
|
|
14276
14720
|
return paths;
|
|
14277
14721
|
}
|
|
14278
|
-
var MAX_GITIGNORE_SIZE, CONTEXT_LIMIT, AUTO_COMPACT_THRESHOLD, MAX_EVENTS, MAX_IMAGES_PER_MESSAGE, FEEDBACK_WORKER_URL, nextKey, mkKey, nextAssistantId, mkAssistantId;
|
|
14722
|
+
var MAX_GITIGNORE_SIZE, CONTEXT_LIMIT, AUTO_COMPACT_THRESHOLD, MAX_EVENTS, DEFAULT_AUTO_FRESH_SUGGESTION_TURNS, MAX_IMAGES_PER_MESSAGE, FEEDBACK_WORKER_URL, nextKey, mkKey, nextAssistantId, mkAssistantId;
|
|
14279
14723
|
var init_app_helpers = __esm({
|
|
14280
14724
|
"src/ui/app-helpers.ts"() {
|
|
14281
14725
|
"use strict";
|
|
@@ -14285,6 +14729,7 @@ var init_app_helpers = __esm({
|
|
|
14285
14729
|
CONTEXT_LIMIT = 262e3;
|
|
14286
14730
|
AUTO_COMPACT_THRESHOLD = 0.8;
|
|
14287
14731
|
MAX_EVENTS = 500;
|
|
14732
|
+
DEFAULT_AUTO_FRESH_SUGGESTION_TURNS = 30;
|
|
14288
14733
|
MAX_IMAGES_PER_MESSAGE = 10;
|
|
14289
14734
|
FEEDBACK_WORKER_URL = "https://hello.kimiflare.com";
|
|
14290
14735
|
nextKey = 1;
|
|
@@ -14323,13 +14768,14 @@ var init_builtins = __esm({
|
|
|
14323
14768
|
{ name: "checkpoints", description: "List checkpoints in current session", source: "builtin" },
|
|
14324
14769
|
{ name: "compact", description: "Summarize old turns to free context", source: "builtin" },
|
|
14325
14770
|
{ name: "clear", description: "Clear current conversation", source: "builtin" },
|
|
14326
|
-
{ name: "fresh", description: "
|
|
14771
|
+
{ name: "fresh", description: "Start a fresh session with a summarized plan or continuation context", source: "builtin" },
|
|
14327
14772
|
{ name: "init", description: "Scan repo and write KIMI.md", source: "builtin" },
|
|
14328
14773
|
{ name: "remote", argHint: "<prompt>", description: "Run a remote session on Cloudflare", source: "builtin" },
|
|
14329
14774
|
{ name: "update", description: "Check for updates", source: "builtin" },
|
|
14330
14775
|
{ name: "hello", description: "Send a voice note to the creator", source: "builtin" },
|
|
14331
14776
|
{ name: "report", argHint: "[send] [note]", description: "Report the last API error with diagnostic logs", source: "builtin" },
|
|
14332
14777
|
{ name: "shell", argHint: "[auto|bash|cmd|powershell|<path>]", description: "Show or set shell for bash tool", source: "builtin" },
|
|
14778
|
+
{ name: "changelog-image", argHint: "[owner/repo] [days]", description: "Generate a changelog image from merged PRs", source: "builtin" },
|
|
14333
14779
|
{ name: "logout", description: "Clear stored credentials", source: "builtin" },
|
|
14334
14780
|
{ name: "exit", description: "Exit kimiflare", source: "builtin" }
|
|
14335
14781
|
];
|
|
@@ -14451,6 +14897,155 @@ var init_distill = __esm({
|
|
|
14451
14897
|
}
|
|
14452
14898
|
});
|
|
14453
14899
|
|
|
14900
|
+
// src/agent/continuation-summary.ts
|
|
14901
|
+
import { execSync as execSync4 } from "child_process";
|
|
14902
|
+
function extractFirstUserGoal(messages) {
|
|
14903
|
+
const texts = [];
|
|
14904
|
+
for (const m of messages) {
|
|
14905
|
+
if (m.role !== "user") continue;
|
|
14906
|
+
let text = "";
|
|
14907
|
+
if (typeof m.content === "string") {
|
|
14908
|
+
text = m.content;
|
|
14909
|
+
} else if (Array.isArray(m.content)) {
|
|
14910
|
+
text = m.content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
14911
|
+
}
|
|
14912
|
+
text = text.trim();
|
|
14913
|
+
if (text.length > 5) {
|
|
14914
|
+
texts.push(text);
|
|
14915
|
+
if (texts.length >= 3) break;
|
|
14916
|
+
}
|
|
14917
|
+
}
|
|
14918
|
+
return texts.join("\n---\n");
|
|
14919
|
+
}
|
|
14920
|
+
function extractRecentAssistantMessages(messages, count = 3) {
|
|
14921
|
+
const texts = [];
|
|
14922
|
+
for (let i = messages.length - 1; i >= 0 && texts.length < count; i--) {
|
|
14923
|
+
const m = messages[i];
|
|
14924
|
+
if (m?.role !== "assistant") continue;
|
|
14925
|
+
let text = "";
|
|
14926
|
+
if (typeof m.content === "string") {
|
|
14927
|
+
text = m.content;
|
|
14928
|
+
} else if (Array.isArray(m.content)) {
|
|
14929
|
+
text = m.content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
14930
|
+
}
|
|
14931
|
+
text = text.trim();
|
|
14932
|
+
if (text.length > 10) {
|
|
14933
|
+
texts.unshift(text);
|
|
14934
|
+
}
|
|
14935
|
+
}
|
|
14936
|
+
return texts.join("\n---\n");
|
|
14937
|
+
}
|
|
14938
|
+
function gatherGitEvidence() {
|
|
14939
|
+
const pieces = [];
|
|
14940
|
+
try {
|
|
14941
|
+
const branch = execSync4("git branch --show-current", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
14942
|
+
if (branch) pieces.push(`Branch: ${branch}`);
|
|
14943
|
+
} catch {
|
|
14944
|
+
}
|
|
14945
|
+
try {
|
|
14946
|
+
const log2 = execSync4("git log --oneline -5", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
14947
|
+
if (log2) pieces.push(`Recent commits:
|
|
14948
|
+
${log2}`);
|
|
14949
|
+
} catch {
|
|
14950
|
+
}
|
|
14951
|
+
try {
|
|
14952
|
+
const status = execSync4("git status --short", { cwd: process.cwd(), encoding: "utf8" }).trim();
|
|
14953
|
+
if (status) pieces.push(`Working tree changes:
|
|
14954
|
+
${status}`);
|
|
14955
|
+
} catch {
|
|
14956
|
+
}
|
|
14957
|
+
return pieces.join("\n\n");
|
|
14958
|
+
}
|
|
14959
|
+
async function gatherMemoryEvidence(manager, enabled, signal) {
|
|
14960
|
+
if (!enabled) return "";
|
|
14961
|
+
try {
|
|
14962
|
+
const cwd = process.cwd();
|
|
14963
|
+
const results = await manager.recall({ text: cwd, repoPath: cwd, limit: 10 });
|
|
14964
|
+
const highSignal = results.filter(
|
|
14965
|
+
(r) => ["edit_event", "task", "instruction"].includes(r.memory.category)
|
|
14966
|
+
);
|
|
14967
|
+
if (highSignal.length === 0) return "";
|
|
14968
|
+
const synthesized = await manager.synthesizeRecalled(highSignal, signal);
|
|
14969
|
+
return synthesized ? `Recorded work log:
|
|
14970
|
+
${synthesized}` : "";
|
|
14971
|
+
} catch {
|
|
14972
|
+
return "";
|
|
14973
|
+
}
|
|
14974
|
+
}
|
|
14975
|
+
async function runKimiText2(opts2) {
|
|
14976
|
+
const events = runKimi({
|
|
14977
|
+
accountId: opts2.accountId,
|
|
14978
|
+
apiToken: opts2.apiToken,
|
|
14979
|
+
model: opts2.model,
|
|
14980
|
+
messages: opts2.messages,
|
|
14981
|
+
temperature: 0.1,
|
|
14982
|
+
reasoningEffort: "low",
|
|
14983
|
+
gateway: opts2.gateway,
|
|
14984
|
+
signal: opts2.signal
|
|
14985
|
+
});
|
|
14986
|
+
let text = "";
|
|
14987
|
+
for await (const ev of events) {
|
|
14988
|
+
if (ev.type === "text") text += ev.delta;
|
|
14989
|
+
}
|
|
14990
|
+
return text.trim();
|
|
14991
|
+
}
|
|
14992
|
+
async function generateContinuationSummary(opts2) {
|
|
14993
|
+
const { messages, mode } = opts2;
|
|
14994
|
+
if (mode === "plan") {
|
|
14995
|
+
return distillSessionPlan(messages);
|
|
14996
|
+
}
|
|
14997
|
+
const goal = extractFirstUserGoal(messages);
|
|
14998
|
+
const recentAssistant = extractRecentAssistantMessages(messages);
|
|
14999
|
+
const gitEvidence = gatherGitEvidence();
|
|
15000
|
+
const memoryEvidence = opts2.memoryManager ? await gatherMemoryEvidence(opts2.memoryManager, opts2.memoryEnabled ?? false, opts2.signal) : "";
|
|
15001
|
+
const evidenceParts = [];
|
|
15002
|
+
if (goal) evidenceParts.push(`## Original goal(s)
|
|
15003
|
+
${goal}`);
|
|
15004
|
+
if (recentAssistant) evidenceParts.push(`## Recent assistant messages
|
|
15005
|
+
${recentAssistant}`);
|
|
15006
|
+
if (gitEvidence) evidenceParts.push(`## Git state
|
|
15007
|
+
${gitEvidence}`);
|
|
15008
|
+
if (memoryEvidence) evidenceParts.push(`## ${memoryEvidence}`);
|
|
15009
|
+
if (evidenceParts.length === 0) {
|
|
15010
|
+
return null;
|
|
15011
|
+
}
|
|
15012
|
+
const userPrompt = evidenceParts.join("\n\n");
|
|
15013
|
+
const summary = await runKimiText2({
|
|
15014
|
+
accountId: opts2.accountId,
|
|
15015
|
+
apiToken: opts2.apiToken,
|
|
15016
|
+
model: opts2.model,
|
|
15017
|
+
gateway: opts2.gateway,
|
|
15018
|
+
signal: opts2.signal,
|
|
15019
|
+
messages: [
|
|
15020
|
+
{ role: "system", content: HANDOFF_SYSTEM },
|
|
15021
|
+
{ role: "user", content: userPrompt }
|
|
15022
|
+
]
|
|
15023
|
+
});
|
|
15024
|
+
return summary || null;
|
|
15025
|
+
}
|
|
15026
|
+
var HANDOFF_SYSTEM;
|
|
15027
|
+
var init_continuation_summary = __esm({
|
|
15028
|
+
"src/agent/continuation-summary.ts"() {
|
|
15029
|
+
"use strict";
|
|
15030
|
+
init_client();
|
|
15031
|
+
init_distill();
|
|
15032
|
+
HANDOFF_SYSTEM = `You are a session-continuation engine. Given evidence from a coding session, produce a dense handoff document so a new agent can pick up exactly where this one left off.
|
|
15033
|
+
|
|
15034
|
+
Output format (use these exact headings):
|
|
15035
|
+
Goal: what the user originally asked for.
|
|
15036
|
+
Completed: files modified, tests added, key decisions, commits made.
|
|
15037
|
+
Remaining: what still needs to be done.
|
|
15038
|
+
Current state: any open errors, incomplete refactors, or pending work.
|
|
15039
|
+
Context: relevant file paths or architectural notes.
|
|
15040
|
+
|
|
15041
|
+
Rules:
|
|
15042
|
+
- Be terse but complete. A new agent with zero prior context must be able to continue.
|
|
15043
|
+
- Do not include chat-style pleasantries.
|
|
15044
|
+
- Do not speculate beyond the evidence provided.
|
|
15045
|
+
- Aim for ~300-600 tokens.`;
|
|
15046
|
+
}
|
|
15047
|
+
});
|
|
15048
|
+
|
|
14454
15049
|
// src/ui/greetings.ts
|
|
14455
15050
|
function pick(arr) {
|
|
14456
15051
|
if (arr.length === 0) throw new Error("pick() called with empty array");
|
|
@@ -15316,24 +15911,24 @@ var init_theme = __esm({
|
|
|
15316
15911
|
});
|
|
15317
15912
|
|
|
15318
15913
|
// src/util/clipboard.ts
|
|
15319
|
-
import { execSync as
|
|
15914
|
+
import { execSync as execSync5 } from "child_process";
|
|
15320
15915
|
import { platform as platform4 } from "os";
|
|
15321
15916
|
function writeToClipboard(text) {
|
|
15322
15917
|
const os2 = platform4();
|
|
15323
15918
|
try {
|
|
15324
15919
|
if (os2 === "darwin") {
|
|
15325
|
-
|
|
15920
|
+
execSync5("pbcopy", { input: text, timeout: 5e3 });
|
|
15326
15921
|
return { success: true, message: "Copied to clipboard" };
|
|
15327
15922
|
}
|
|
15328
15923
|
if (os2 === "win32") {
|
|
15329
|
-
|
|
15924
|
+
execSync5("clip", { input: text, timeout: 5e3 });
|
|
15330
15925
|
return { success: true, message: "Copied to clipboard" };
|
|
15331
15926
|
}
|
|
15332
15927
|
try {
|
|
15333
|
-
|
|
15928
|
+
execSync5("xclip -selection clipboard", { input: text, timeout: 5e3 });
|
|
15334
15929
|
return { success: true, message: "Copied to clipboard" };
|
|
15335
15930
|
} catch {
|
|
15336
|
-
|
|
15931
|
+
execSync5("xsel --clipboard --input", { input: text, timeout: 5e3 });
|
|
15337
15932
|
return { success: true, message: "Copied to clipboard" };
|
|
15338
15933
|
}
|
|
15339
15934
|
} catch {
|
|
@@ -15654,8 +16249,8 @@ var init_frontmatter = __esm({
|
|
|
15654
16249
|
});
|
|
15655
16250
|
|
|
15656
16251
|
// src/skills/loader.ts
|
|
15657
|
-
import { readFile as
|
|
15658
|
-
import { join as
|
|
16252
|
+
import { readFile as readFile17, readdir as readdir6, stat as stat6 } from "fs/promises";
|
|
16253
|
+
import { join as join26, extname } from "path";
|
|
15659
16254
|
function normalizeManifest(raw, filePath) {
|
|
15660
16255
|
const name = typeof raw.name === "string" ? raw.name : "";
|
|
15661
16256
|
const description = typeof raw.description === "string" ? raw.description : "";
|
|
@@ -15669,7 +16264,7 @@ function normalizeManifest(raw, filePath) {
|
|
|
15669
16264
|
return { name, description, match, scope, priority, enabled };
|
|
15670
16265
|
}
|
|
15671
16266
|
async function loadSkillFile(filePath) {
|
|
15672
|
-
const raw = await
|
|
16267
|
+
const raw = await readFile17(filePath, "utf-8");
|
|
15673
16268
|
const parsed = parseFrontmatter(raw);
|
|
15674
16269
|
const manifest = normalizeManifest(parsed.data, filePath);
|
|
15675
16270
|
const body = parsed.content.trim();
|
|
@@ -15691,7 +16286,7 @@ async function loadSkillsFromDir(dirPath) {
|
|
|
15691
16286
|
const entries = await readdir6(dirPath);
|
|
15692
16287
|
const files = [];
|
|
15693
16288
|
for (const entry of entries) {
|
|
15694
|
-
const full =
|
|
16289
|
+
const full = join26(dirPath, entry);
|
|
15695
16290
|
const s = await stat6(full);
|
|
15696
16291
|
if (s.isFile() && extname(entry) === ".md") {
|
|
15697
16292
|
files.push(full);
|
|
@@ -15719,12 +16314,12 @@ var init_loader = __esm({
|
|
|
15719
16314
|
});
|
|
15720
16315
|
|
|
15721
16316
|
// src/skills/manager.ts
|
|
15722
|
-
import { mkdir as mkdir10, writeFile as
|
|
15723
|
-
import { join as
|
|
16317
|
+
import { mkdir as mkdir10, writeFile as writeFile12, unlink as unlink2, readFile as readFile18 } from "fs/promises";
|
|
16318
|
+
import { join as join27 } from "path";
|
|
15724
16319
|
function getSkillDirs(cwd) {
|
|
15725
16320
|
return {
|
|
15726
|
-
projectDir:
|
|
15727
|
-
globalDir:
|
|
16321
|
+
projectDir: join27(cwd, ".kimiflare", "skills"),
|
|
16322
|
+
globalDir: join27(process.env.HOME ?? "", ".config", "kimiflare", "skills")
|
|
15728
16323
|
};
|
|
15729
16324
|
}
|
|
15730
16325
|
async function listAllSkills(cwd) {
|
|
@@ -15738,7 +16333,7 @@ async function listAllSkills(cwd) {
|
|
|
15738
16333
|
async function createSkill(opts2) {
|
|
15739
16334
|
const dirs = getSkillDirs(opts2.cwd);
|
|
15740
16335
|
const dir = opts2.scope === "project" ? dirs.projectDir : dirs.globalDir;
|
|
15741
|
-
const filepath =
|
|
16336
|
+
const filepath = join27(dir, `${opts2.name}.md`);
|
|
15742
16337
|
const frontmatter = {
|
|
15743
16338
|
name: opts2.name,
|
|
15744
16339
|
enabled: true,
|
|
@@ -15760,7 +16355,7 @@ ${yaml}
|
|
|
15760
16355
|
Add your instructions here.
|
|
15761
16356
|
`;
|
|
15762
16357
|
await mkdir10(dir, { recursive: true });
|
|
15763
|
-
await
|
|
16358
|
+
await writeFile12(filepath, content, "utf8");
|
|
15764
16359
|
return { filepath };
|
|
15765
16360
|
}
|
|
15766
16361
|
async function deleteSkill(name, cwd) {
|
|
@@ -15774,7 +16369,7 @@ async function setSkillEnabled(name, enabled, cwd) {
|
|
|
15774
16369
|
const all = await listAllSkills(cwd);
|
|
15775
16370
|
const skill = all.project.find((s) => s.name === name) ?? all.global.find((s) => s.name === name);
|
|
15776
16371
|
if (!skill) throw new Error(`skill "${name}" not found`);
|
|
15777
|
-
const raw = await
|
|
16372
|
+
const raw = await readFile18(skill.filePath, "utf-8");
|
|
15778
16373
|
const parsed = parseFrontmatter(raw);
|
|
15779
16374
|
parsed.data.enabled = enabled;
|
|
15780
16375
|
const yaml = Object.entries(parsed.data).map(([k, v]) => {
|
|
@@ -15786,7 +16381,7 @@ ${v.map((item) => ` - ${item}`).join("\n")}`;
|
|
|
15786
16381
|
${yaml}
|
|
15787
16382
|
---
|
|
15788
16383
|
${parsed.content}`;
|
|
15789
|
-
await
|
|
16384
|
+
await writeFile12(skill.filePath, content, "utf8");
|
|
15790
16385
|
return { filepath: skill.filePath };
|
|
15791
16386
|
}
|
|
15792
16387
|
async function findSkillFile(name, cwd) {
|
|
@@ -15859,13 +16454,13 @@ var init_frontmatter2 = __esm({
|
|
|
15859
16454
|
// src/commands/loader.ts
|
|
15860
16455
|
import { open, realpath as realpath2 } from "fs/promises";
|
|
15861
16456
|
import { homedir as homedir14 } from "os";
|
|
15862
|
-
import { join as
|
|
16457
|
+
import { join as join28, relative as relative5, sep as sep2 } from "path";
|
|
15863
16458
|
function projectCommandsDir(cwd = process.cwd()) {
|
|
15864
|
-
return
|
|
16459
|
+
return join28(cwd, ".kimiflare", "commands");
|
|
15865
16460
|
}
|
|
15866
16461
|
function globalCommandsDir() {
|
|
15867
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
15868
|
-
return
|
|
16462
|
+
const xdg = process.env.XDG_CONFIG_HOME || join28(homedir14(), ".config");
|
|
16463
|
+
return join28(xdg, "kimiflare", "commands");
|
|
15869
16464
|
}
|
|
15870
16465
|
async function loadCustomCommands(cwd = process.cwd()) {
|
|
15871
16466
|
const warnings = [];
|
|
@@ -16016,7 +16611,7 @@ var init_loader2 = __esm({
|
|
|
16016
16611
|
});
|
|
16017
16612
|
|
|
16018
16613
|
// src/commands/save.ts
|
|
16019
|
-
import { mkdir as mkdir11, writeFile as
|
|
16614
|
+
import { mkdir as mkdir11, writeFile as writeFile13, unlink as unlink3 } from "fs/promises";
|
|
16020
16615
|
import { dirname as dirname11 } from "path";
|
|
16021
16616
|
async function saveCustomCommand(opts2) {
|
|
16022
16617
|
const dir = opts2.source === "project" ? projectCommandsDir(opts2.cwd) : globalCommandsDir();
|
|
@@ -16029,7 +16624,7 @@ async function saveCustomCommand(opts2) {
|
|
|
16029
16624
|
const frontmatter = serializeFrontmatter(data);
|
|
16030
16625
|
const content = frontmatter + opts2.template;
|
|
16031
16626
|
await mkdir11(dirname11(filepath), { recursive: true });
|
|
16032
|
-
await
|
|
16627
|
+
await writeFile13(filepath, content, "utf8");
|
|
16033
16628
|
return { filepath };
|
|
16034
16629
|
}
|
|
16035
16630
|
async function deleteCustomCommand(cmd) {
|
|
@@ -16140,12 +16735,12 @@ var init_worker_client = __esm({
|
|
|
16140
16735
|
|
|
16141
16736
|
// src/init/context-generator.ts
|
|
16142
16737
|
import { existsSync as existsSync5, statSync as statSync5 } from "fs";
|
|
16143
|
-
import { join as
|
|
16738
|
+
import { join as join29 } from "path";
|
|
16144
16739
|
function detectFlavor(cwd) {
|
|
16145
16740
|
for (const [flavor, signatures] of Object.entries(FLAVOR_SIGNATURES)) {
|
|
16146
16741
|
if (flavor === "generic") continue;
|
|
16147
16742
|
for (const sig of signatures) {
|
|
16148
|
-
const path =
|
|
16743
|
+
const path = join29(cwd, sig);
|
|
16149
16744
|
if (sig.includes("*")) {
|
|
16150
16745
|
try {
|
|
16151
16746
|
const parts = sig.split("*");
|
|
@@ -16166,14 +16761,14 @@ function detectFlavor(cwd) {
|
|
|
16166
16761
|
}
|
|
16167
16762
|
function findFile(cwd, candidates) {
|
|
16168
16763
|
for (const c of candidates) {
|
|
16169
|
-
if (existsSync5(
|
|
16764
|
+
if (existsSync5(join29(cwd, c))) return c;
|
|
16170
16765
|
}
|
|
16171
16766
|
return null;
|
|
16172
16767
|
}
|
|
16173
16768
|
function findSourceRoots(cwd) {
|
|
16174
16769
|
const roots = [];
|
|
16175
16770
|
for (const r of SOURCE_ROOT_CANDIDATES) {
|
|
16176
|
-
const p =
|
|
16771
|
+
const p = join29(cwd, r);
|
|
16177
16772
|
try {
|
|
16178
16773
|
const s = statSync5(p);
|
|
16179
16774
|
if (s.isDirectory()) roots.push(r);
|
|
@@ -16184,9 +16779,9 @@ function findSourceRoots(cwd) {
|
|
|
16184
16779
|
}
|
|
16185
16780
|
function findCiConfig(cwd) {
|
|
16186
16781
|
for (const c of CI_PATHS) {
|
|
16187
|
-
if (existsSync5(
|
|
16782
|
+
if (existsSync5(join29(cwd, c))) {
|
|
16188
16783
|
try {
|
|
16189
|
-
const s = statSync5(
|
|
16784
|
+
const s = statSync5(join29(cwd, c));
|
|
16190
16785
|
return s.isDirectory() ? c : c;
|
|
16191
16786
|
} catch {
|
|
16192
16787
|
}
|
|
@@ -16323,7 +16918,7 @@ function analyzeProject(cwd) {
|
|
|
16323
16918
|
ciConfig: findCiConfig(cwd),
|
|
16324
16919
|
readme: findFile(cwd, ["README.md", "README.rst", "README.txt", "Readme.md"]),
|
|
16325
16920
|
sourceRoots: findSourceRoots(cwd),
|
|
16326
|
-
hasGit: existsSync5(
|
|
16921
|
+
hasGit: existsSync5(join29(cwd, ".git"))
|
|
16327
16922
|
};
|
|
16328
16923
|
}
|
|
16329
16924
|
function bashDiscoveryCommands(profile) {
|
|
@@ -16488,7 +17083,7 @@ Aim for 100\u2013200 lines total. Use markdown tables where they save space.
|
|
|
16488
17083
|
}
|
|
16489
17084
|
function buildInitPrompt(cwd) {
|
|
16490
17085
|
const existingName = ["KIMI.md", "KIMIFLARE.md", "AGENT.md"].find(
|
|
16491
|
-
(n) => existsSync5(
|
|
17086
|
+
(n) => existsSync5(join29(cwd, n))
|
|
16492
17087
|
);
|
|
16493
17088
|
const isRefresh = existingName !== void 0;
|
|
16494
17089
|
const targetFilename = existingName ?? "KIMI.md";
|
|
@@ -16576,10 +17171,10 @@ __export(ui_mode_exports, {
|
|
|
16576
17171
|
runCamouflageOnboarding: () => runCamouflageOnboarding,
|
|
16577
17172
|
runUiMode: () => runUiMode
|
|
16578
17173
|
});
|
|
16579
|
-
import { execSync as
|
|
17174
|
+
import { execSync as execSync6, spawn as spawn6 } from "child_process";
|
|
16580
17175
|
import { appendFileSync, openSync } from "fs";
|
|
16581
17176
|
import { readdir as readdir7, unlink as unlink4 } from "fs/promises";
|
|
16582
|
-
import { join as
|
|
17177
|
+
import { join as join30, relative as relative6 } from "path";
|
|
16583
17178
|
import { platform as platform5 } from "os";
|
|
16584
17179
|
function kimiLog(payload) {
|
|
16585
17180
|
if (!KIMI_LOG_PATH) return;
|
|
@@ -18567,41 +19162,50 @@ Executor opened PR: ${prUrl}` : plan });
|
|
|
18567
19162
|
cam.send("ShowToast", { text: "can't /fresh while model is running \u2014 press Esc to interrupt first", kind: "warn", ttl_ms: 2500 });
|
|
18568
19163
|
return true;
|
|
18569
19164
|
}
|
|
18570
|
-
|
|
18571
|
-
|
|
18572
|
-
|
|
18573
|
-
|
|
18574
|
-
|
|
18575
|
-
|
|
18576
|
-
|
|
18577
|
-
|
|
18578
|
-
|
|
18579
|
-
|
|
18580
|
-
|
|
18581
|
-
|
|
18582
|
-
|
|
18583
|
-
|
|
18584
|
-
|
|
18585
|
-
|
|
18586
|
-
|
|
18587
|
-
|
|
18588
|
-
|
|
18589
|
-
|
|
18590
|
-
|
|
18591
|
-
|
|
18592
|
-
|
|
18593
|
-
|
|
18594
|
-
|
|
18595
|
-
|
|
18596
|
-
|
|
18597
|
-
|
|
18598
|
-
|
|
18599
|
-
|
|
18600
|
-
|
|
18601
|
-
|
|
18602
|
-
|
|
18603
|
-
|
|
18604
|
-
|
|
19165
|
+
void (async () => {
|
|
19166
|
+
const summary = await generateContinuationSummary({
|
|
19167
|
+
messages,
|
|
19168
|
+
mode: currentMode,
|
|
19169
|
+
accountId: opts2.accountId,
|
|
19170
|
+
apiToken: opts2.apiToken,
|
|
19171
|
+
model: opts2.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
|
|
19172
|
+
gateway: gatewayFromOpts2(opts2)
|
|
19173
|
+
});
|
|
19174
|
+
if (!summary) {
|
|
19175
|
+
cam.send("ShowToast", { text: "No plan or summary found to start fresh with.", kind: "error", ttl_ms: 2500 });
|
|
19176
|
+
return;
|
|
19177
|
+
}
|
|
19178
|
+
const clipResult = writeToClipboard(summary);
|
|
19179
|
+
const systemMessages = messages.filter((m) => m.role === "system");
|
|
19180
|
+
messages.length = 0;
|
|
19181
|
+
messages.push(...systemMessages);
|
|
19182
|
+
sessionCostUsd = 0;
|
|
19183
|
+
promptTokens = 0;
|
|
19184
|
+
cachedTokens = 0;
|
|
19185
|
+
completionTokens = 0;
|
|
19186
|
+
sessionPlan = null;
|
|
19187
|
+
cam.send("TranscriptCleared", {});
|
|
19188
|
+
cam.send("StatusUpdate", {
|
|
19189
|
+
segments: { tokens: "in 0", cost: "$0.00", elapsed: "" }
|
|
19190
|
+
});
|
|
19191
|
+
rebuildSystemPromptForMode(
|
|
19192
|
+
messages,
|
|
19193
|
+
false,
|
|
19194
|
+
// Camouflage UI always uses single system message
|
|
19195
|
+
opts2.model,
|
|
19196
|
+
currentMode,
|
|
19197
|
+
ALL_TOOLS
|
|
19198
|
+
);
|
|
19199
|
+
messages.push({ role: "user", content: summary });
|
|
19200
|
+
cam.send("ShowToast", {
|
|
19201
|
+
text: clipResult.success ? "Summary copied to clipboard. Starting fresh session with continuation context\u2026" : "Clipboard unavailable. Starting fresh session with continuation context\u2026",
|
|
19202
|
+
kind: "info",
|
|
19203
|
+
ttl_ms: 3e3
|
|
19204
|
+
});
|
|
19205
|
+
if (!clipResult.success) {
|
|
19206
|
+
cam.send("UserMessageCreated", { text: "--- Continuation Context ---\n" + summary });
|
|
19207
|
+
}
|
|
19208
|
+
})();
|
|
18605
19209
|
return true;
|
|
18606
19210
|
}
|
|
18607
19211
|
case "logout": {
|
|
@@ -18666,7 +19270,7 @@ async function registerMentions(cam, recents) {
|
|
|
18666
19270
|
for (const e of entries) {
|
|
18667
19271
|
if (collected.length >= 200) return;
|
|
18668
19272
|
if (e.name.startsWith(".") || SKIP.has(e.name)) continue;
|
|
18669
|
-
const full =
|
|
19273
|
+
const full = join30(dir, e.name);
|
|
18670
19274
|
if (e.isDirectory()) {
|
|
18671
19275
|
await walk2(full, depth + 1);
|
|
18672
19276
|
} else if (e.isFile()) {
|
|
@@ -18736,7 +19340,7 @@ function formatElapsed2(secs) {
|
|
|
18736
19340
|
}
|
|
18737
19341
|
function tryGitBranch2() {
|
|
18738
19342
|
try {
|
|
18739
|
-
const out =
|
|
19343
|
+
const out = execSync6("git rev-parse --abbrev-ref HEAD 2>/dev/null", {
|
|
18740
19344
|
encoding: "utf8",
|
|
18741
19345
|
timeout: 200
|
|
18742
19346
|
}).trim();
|
|
@@ -18848,6 +19452,7 @@ var init_ui_mode = __esm({
|
|
|
18848
19452
|
init_sessions();
|
|
18849
19453
|
init_llm_summarize();
|
|
18850
19454
|
init_distill();
|
|
19455
|
+
init_continuation_summary();
|
|
18851
19456
|
init_greetings();
|
|
18852
19457
|
init_theme();
|
|
18853
19458
|
init_update_check();
|
|
@@ -23766,11 +24371,11 @@ var init_wcag = __esm({
|
|
|
23766
24371
|
});
|
|
23767
24372
|
|
|
23768
24373
|
// src/ui/theme-loader.ts
|
|
23769
|
-
import { readFile as
|
|
23770
|
-
import { join as
|
|
24374
|
+
import { readFile as readFile19, readdir as readdir8 } from "fs/promises";
|
|
24375
|
+
import { join as join31 } from "path";
|
|
23771
24376
|
import { homedir as homedir15 } from "os";
|
|
23772
24377
|
function projectThemesDir(cwd = process.cwd()) {
|
|
23773
|
-
return
|
|
24378
|
+
return join31(cwd, ".kimiflare", "themes");
|
|
23774
24379
|
}
|
|
23775
24380
|
function isHexColor(c) {
|
|
23776
24381
|
return /^#[0-9a-fA-F]{6}$/.test(c);
|
|
@@ -23859,10 +24464,10 @@ async function loadThemesFromDir(dir, source) {
|
|
|
23859
24464
|
return { themes, errors };
|
|
23860
24465
|
}
|
|
23861
24466
|
for (const file of files.filter((f) => f.endsWith(".json"))) {
|
|
23862
|
-
const path =
|
|
24467
|
+
const path = join31(dir, file);
|
|
23863
24468
|
let raw;
|
|
23864
24469
|
try {
|
|
23865
|
-
raw = await
|
|
24470
|
+
raw = await readFile19(path, "utf-8");
|
|
23866
24471
|
} catch (e) {
|
|
23867
24472
|
errors.push(`${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
23868
24473
|
continue;
|
|
@@ -24008,8 +24613,8 @@ var init_theme_loader = __esm({
|
|
|
24008
24613
|
"use strict";
|
|
24009
24614
|
init_wcag();
|
|
24010
24615
|
init_theme();
|
|
24011
|
-
USER_THEMES_DIR =
|
|
24012
|
-
process.env.XDG_CONFIG_HOME ||
|
|
24616
|
+
USER_THEMES_DIR = join31(
|
|
24617
|
+
process.env.XDG_CONFIG_HOME || join31(homedir15(), ".config"),
|
|
24013
24618
|
"kimiflare",
|
|
24014
24619
|
"themes"
|
|
24015
24620
|
);
|
|
@@ -24446,8 +25051,9 @@ function useModalHost() {
|
|
|
24446
25051
|
const [showSkillsPicker, setShowSkillsPicker] = useState16(false);
|
|
24447
25052
|
const [showShellPicker, setShowShellPicker] = useState16(false);
|
|
24448
25053
|
const [showPlanCompletePicker, setShowPlanCompletePicker] = useState16(false);
|
|
25054
|
+
const [showChangelogImagePicker, setShowChangelogImagePicker] = useState16(false);
|
|
24449
25055
|
const flags = useMemo4(() => {
|
|
24450
|
-
const hasFullscreenModal = commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || showThemePicker || showUiPicker || showModelPicker || showModePicker || keyEntryFor !== null || billingChooserFor !== null || unifiedProbeFor !== null || showRemoteDashboard || showInboxModal || showMultiAgentModal || showHooksDashboard || showHelpMenu || showMemoryPicker || showGatewayPicker || showSkillsPicker || showShellPicker;
|
|
25056
|
+
const hasFullscreenModal = commandWizard !== null || commandPicker !== null || commandToDelete !== null || showCommandList || showLspWizard || showThemePicker || showUiPicker || showModelPicker || showModePicker || keyEntryFor !== null || billingChooserFor !== null || unifiedProbeFor !== null || showRemoteDashboard || showInboxModal || showMultiAgentModal || showHooksDashboard || showHelpMenu || showMemoryPicker || showGatewayPicker || showSkillsPicker || showShellPicker || showChangelogImagePicker;
|
|
24451
25057
|
const hasOverlayModal = limitModal !== null || loopModal !== null || showPlanCompletePicker;
|
|
24452
25058
|
return {
|
|
24453
25059
|
hasFullscreenModal,
|
|
@@ -24477,6 +25083,7 @@ function useModalHost() {
|
|
|
24477
25083
|
showSkillsPicker,
|
|
24478
25084
|
showShellPicker,
|
|
24479
25085
|
showPlanCompletePicker,
|
|
25086
|
+
showChangelogImagePicker,
|
|
24480
25087
|
limitModal,
|
|
24481
25088
|
loopModal
|
|
24482
25089
|
]);
|
|
@@ -24529,6 +25136,8 @@ function useModalHost() {
|
|
|
24529
25136
|
setShowShellPicker,
|
|
24530
25137
|
showPlanCompletePicker,
|
|
24531
25138
|
setShowPlanCompletePicker,
|
|
25139
|
+
showChangelogImagePicker,
|
|
25140
|
+
setShowChangelogImagePicker,
|
|
24532
25141
|
...flags
|
|
24533
25142
|
};
|
|
24534
25143
|
}
|
|
@@ -27692,10 +28301,71 @@ var init_help_menu = __esm({
|
|
|
27692
28301
|
}
|
|
27693
28302
|
});
|
|
27694
28303
|
|
|
28304
|
+
// src/ui/changelog-image-picker.tsx
|
|
28305
|
+
import { useState as useState26 } from "react";
|
|
28306
|
+
import { Box as Box39, Text as Text40, useInput as useInput20 } from "ink";
|
|
28307
|
+
import { jsx as jsx41, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
28308
|
+
function ChangelogImagePicker({ owner, repo, onGenerate, onCancel }) {
|
|
28309
|
+
const theme = useTheme();
|
|
28310
|
+
const [selectedIndex, setSelectedIndex] = useState26(0);
|
|
28311
|
+
useInput20((_input, key) => {
|
|
28312
|
+
if (key.escape) {
|
|
28313
|
+
onCancel();
|
|
28314
|
+
return;
|
|
28315
|
+
}
|
|
28316
|
+
if (key.return) {
|
|
28317
|
+
const option = PERIODS[selectedIndex];
|
|
28318
|
+
if (option) {
|
|
28319
|
+
onGenerate(owner, repo, option.days);
|
|
28320
|
+
}
|
|
28321
|
+
return;
|
|
28322
|
+
}
|
|
28323
|
+
if (key.upArrow) {
|
|
28324
|
+
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
28325
|
+
return;
|
|
28326
|
+
}
|
|
28327
|
+
if (key.downArrow) {
|
|
28328
|
+
setSelectedIndex((i) => Math.min(PERIODS.length - 1, i + 1));
|
|
28329
|
+
return;
|
|
28330
|
+
}
|
|
28331
|
+
});
|
|
28332
|
+
return /* @__PURE__ */ jsxs39(Box39, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
28333
|
+
/* @__PURE__ */ jsxs39(Text40, { color: theme.accent, bold: true, children: [
|
|
28334
|
+
"Changelog Image: ",
|
|
28335
|
+
owner,
|
|
28336
|
+
"/",
|
|
28337
|
+
repo
|
|
28338
|
+
] }),
|
|
28339
|
+
/* @__PURE__ */ jsx41(Text40, { color: theme.info.color, dimColor: true, children: "Select a time period to summarize" }),
|
|
28340
|
+
/* @__PURE__ */ jsx41(Box39, { marginTop: 1, flexDirection: "column", children: PERIODS.map((period, i) => {
|
|
28341
|
+
const isSelected = i === selectedIndex;
|
|
28342
|
+
const marker = isSelected ? "\u25B8" : " ";
|
|
28343
|
+
return /* @__PURE__ */ jsx41(Box39, { children: /* @__PURE__ */ jsxs39(Text40, { color: isSelected ? theme.accent : theme.info.color, bold: isSelected, children: [
|
|
28344
|
+
marker,
|
|
28345
|
+
" ",
|
|
28346
|
+
period.label
|
|
28347
|
+
] }) }, period.label);
|
|
28348
|
+
}) }),
|
|
28349
|
+
/* @__PURE__ */ jsx41(Box39, { marginTop: 1, children: /* @__PURE__ */ jsx41(Text40, { color: theme.info.color, dimColor: theme.info.dim, children: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc cancel" }) })
|
|
28350
|
+
] });
|
|
28351
|
+
}
|
|
28352
|
+
var PERIODS;
|
|
28353
|
+
var init_changelog_image_picker = __esm({
|
|
28354
|
+
"src/ui/changelog-image-picker.tsx"() {
|
|
28355
|
+
"use strict";
|
|
28356
|
+
init_theme_context();
|
|
28357
|
+
PERIODS = [
|
|
28358
|
+
{ label: "Past 24 hours", days: 1 },
|
|
28359
|
+
{ label: "Past 7 days", days: 7 },
|
|
28360
|
+
{ label: "Past 30 days", days: 30 }
|
|
28361
|
+
];
|
|
28362
|
+
}
|
|
28363
|
+
});
|
|
28364
|
+
|
|
27695
28365
|
// src/ui/modal-host.tsx
|
|
27696
|
-
import { Box as
|
|
28366
|
+
import { Box as Box40, Text as Text41 } from "ink";
|
|
27697
28367
|
import SelectInput22 from "ink-select-input";
|
|
27698
|
-
import { jsx as
|
|
28368
|
+
import { jsx as jsx42, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
27699
28369
|
function ModalHost(props) {
|
|
27700
28370
|
const {
|
|
27701
28371
|
modals,
|
|
@@ -27728,7 +28398,7 @@ function ModalHost(props) {
|
|
|
27728
28398
|
onInboxOpen
|
|
27729
28399
|
} = props;
|
|
27730
28400
|
if (modals.showRemoteDashboard) {
|
|
27731
|
-
return /* @__PURE__ */
|
|
28401
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: selectedRemoteSession ? /* @__PURE__ */ jsx42(
|
|
27732
28402
|
RemoteSessionDetail,
|
|
27733
28403
|
{
|
|
27734
28404
|
session: selectedRemoteSession,
|
|
@@ -27737,7 +28407,7 @@ function ModalHost(props) {
|
|
|
27737
28407
|
void onCancelRemoteSession(session);
|
|
27738
28408
|
}
|
|
27739
28409
|
}
|
|
27740
|
-
) : /* @__PURE__ */
|
|
28410
|
+
) : /* @__PURE__ */ jsx42(
|
|
27741
28411
|
RemoteDashboard,
|
|
27742
28412
|
{
|
|
27743
28413
|
onSelect: (session) => onSelectRemoteSession(session),
|
|
@@ -27746,7 +28416,7 @@ function ModalHost(props) {
|
|
|
27746
28416
|
) }) });
|
|
27747
28417
|
}
|
|
27748
28418
|
if (modals.showInboxModal) {
|
|
27749
|
-
return /* @__PURE__ */
|
|
28419
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27750
28420
|
InboxModal,
|
|
27751
28421
|
{
|
|
27752
28422
|
onDone: () => modals.setShowInboxModal(false),
|
|
@@ -27755,7 +28425,7 @@ function ModalHost(props) {
|
|
|
27755
28425
|
) }) });
|
|
27756
28426
|
}
|
|
27757
28427
|
if (modals.showMultiAgentModal) {
|
|
27758
|
-
return /* @__PURE__ */
|
|
28428
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27759
28429
|
MultiAgentModal,
|
|
27760
28430
|
{
|
|
27761
28431
|
initial: props.multiAgentSettings ?? {},
|
|
@@ -27768,7 +28438,7 @@ function ModalHost(props) {
|
|
|
27768
28438
|
) }) });
|
|
27769
28439
|
}
|
|
27770
28440
|
if (modals.showHooksDashboard) {
|
|
27771
|
-
return /* @__PURE__ */
|
|
28441
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27772
28442
|
HooksDashboard,
|
|
27773
28443
|
{
|
|
27774
28444
|
getConfigured: props.getConfiguredHooks,
|
|
@@ -27779,7 +28449,7 @@ function ModalHost(props) {
|
|
|
27779
28449
|
) }) });
|
|
27780
28450
|
}
|
|
27781
28451
|
if (modals.showHelpMenu) {
|
|
27782
|
-
return /* @__PURE__ */
|
|
28452
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27783
28453
|
HelpMenu,
|
|
27784
28454
|
{
|
|
27785
28455
|
customCommands: customCommands.map((c) => ({ name: c.name, description: c.description })),
|
|
@@ -27793,10 +28463,10 @@ function ModalHost(props) {
|
|
|
27793
28463
|
) }) });
|
|
27794
28464
|
}
|
|
27795
28465
|
if (modals.showShellPicker) {
|
|
27796
|
-
return /* @__PURE__ */
|
|
28466
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(ShellPicker, { current: props.currentShell, onPick: props.onPickShell }) }) });
|
|
27797
28467
|
}
|
|
27798
28468
|
if (modals.showMemoryPicker) {
|
|
27799
|
-
return /* @__PURE__ */
|
|
28469
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27800
28470
|
MemoryPicker,
|
|
27801
28471
|
{
|
|
27802
28472
|
enabled: props.memoryEnabled,
|
|
@@ -27807,7 +28477,7 @@ function ModalHost(props) {
|
|
|
27807
28477
|
) }) });
|
|
27808
28478
|
}
|
|
27809
28479
|
if (modals.showGatewayPicker) {
|
|
27810
|
-
return /* @__PURE__ */
|
|
28480
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27811
28481
|
GatewayPicker,
|
|
27812
28482
|
{
|
|
27813
28483
|
gatewayId: props.gatewayId,
|
|
@@ -27820,10 +28490,10 @@ function ModalHost(props) {
|
|
|
27820
28490
|
) }) });
|
|
27821
28491
|
}
|
|
27822
28492
|
if (modals.showSkillsPicker) {
|
|
27823
|
-
return /* @__PURE__ */
|
|
28493
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(SkillsPicker, { onAction: props.onSkillsAction, onDone: props.onSkillsDone }) }) });
|
|
27824
28494
|
}
|
|
27825
28495
|
if (modals.showLspWizard) {
|
|
27826
|
-
return /* @__PURE__ */
|
|
28496
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27827
28497
|
LspWizard,
|
|
27828
28498
|
{
|
|
27829
28499
|
servers: lspServers,
|
|
@@ -27835,7 +28505,7 @@ function ModalHost(props) {
|
|
|
27835
28505
|
) }) });
|
|
27836
28506
|
}
|
|
27837
28507
|
if (modals.commandWizard) {
|
|
27838
|
-
return /* @__PURE__ */
|
|
28508
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27839
28509
|
CommandWizard,
|
|
27840
28510
|
{
|
|
27841
28511
|
mode: modals.commandWizard.mode,
|
|
@@ -27849,7 +28519,7 @@ function ModalHost(props) {
|
|
|
27849
28519
|
}
|
|
27850
28520
|
if (modals.commandPicker) {
|
|
27851
28521
|
const pickerMode = modals.commandPicker.mode;
|
|
27852
|
-
return /* @__PURE__ */
|
|
28522
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27853
28523
|
CommandPicker,
|
|
27854
28524
|
{
|
|
27855
28525
|
commands: customCommands,
|
|
@@ -27868,14 +28538,14 @@ function ModalHost(props) {
|
|
|
27868
28538
|
}
|
|
27869
28539
|
if (modals.commandToDelete) {
|
|
27870
28540
|
const cmd = modals.commandToDelete;
|
|
27871
|
-
return /* @__PURE__ */
|
|
27872
|
-
/* @__PURE__ */
|
|
28541
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs40(Box40, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
28542
|
+
/* @__PURE__ */ jsxs40(Text41, { color: theme.accent, bold: true, children: [
|
|
27873
28543
|
"Delete /",
|
|
27874
28544
|
cmd.name,
|
|
27875
28545
|
"?"
|
|
27876
28546
|
] }),
|
|
27877
|
-
/* @__PURE__ */
|
|
27878
|
-
/* @__PURE__ */
|
|
28547
|
+
/* @__PURE__ */ jsx42(Text41, { color: theme.info.color, children: cmd.filepath }),
|
|
28548
|
+
/* @__PURE__ */ jsx42(Box40, { marginTop: 1, children: /* @__PURE__ */ jsx42(
|
|
27879
28549
|
SelectInput22,
|
|
27880
28550
|
{
|
|
27881
28551
|
items: [
|
|
@@ -27894,7 +28564,7 @@ function ModalHost(props) {
|
|
|
27894
28564
|
] }) });
|
|
27895
28565
|
}
|
|
27896
28566
|
if (modals.showCommandList) {
|
|
27897
|
-
return /* @__PURE__ */
|
|
28567
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27898
28568
|
CommandList,
|
|
27899
28569
|
{
|
|
27900
28570
|
commands: customCommands,
|
|
@@ -27903,24 +28573,24 @@ function ModalHost(props) {
|
|
|
27903
28573
|
) }) });
|
|
27904
28574
|
}
|
|
27905
28575
|
if (modals.showThemePicker) {
|
|
27906
|
-
return /* @__PURE__ */
|
|
28576
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(ThemePicker, { themes, onPick: onPickTheme }) }) });
|
|
27907
28577
|
}
|
|
27908
28578
|
if (modals.showUiPicker) {
|
|
27909
|
-
return /* @__PURE__ */
|
|
28579
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(UiPicker, { current: currentUiEngine, onPick: onPickUi }) }) });
|
|
27910
28580
|
}
|
|
27911
28581
|
if (modals.showModelPicker) {
|
|
27912
|
-
return /* @__PURE__ */
|
|
28582
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(ModelPicker, { current: currentModel, onPick: onPickModel }) }) });
|
|
27913
28583
|
}
|
|
27914
28584
|
if (modals.showModePicker) {
|
|
27915
|
-
return /* @__PURE__ */
|
|
28585
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(ModePicker, { current: props.currentMode, onPick: props.onPickMode, multiAgentEnabled: props.multiAgentEnabled }) }) });
|
|
27916
28586
|
}
|
|
27917
28587
|
if (modals.billingChooserFor) {
|
|
27918
28588
|
const model = modals.billingChooserFor;
|
|
27919
|
-
return /* @__PURE__ */
|
|
28589
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(BillingChooser, { model, onPick: (choice) => onPickBilling(model, choice) }) }) });
|
|
27920
28590
|
}
|
|
27921
28591
|
if (modals.unifiedProbeFor) {
|
|
27922
28592
|
const model = modals.unifiedProbeFor;
|
|
27923
|
-
return /* @__PURE__ */
|
|
28593
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27924
28594
|
UnifiedBillingStatus,
|
|
27925
28595
|
{
|
|
27926
28596
|
model,
|
|
@@ -27933,7 +28603,7 @@ function ModalHost(props) {
|
|
|
27933
28603
|
}
|
|
27934
28604
|
if (modals.keyEntryFor) {
|
|
27935
28605
|
const model = modals.keyEntryFor;
|
|
27936
|
-
return /* @__PURE__ */
|
|
28606
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
27937
28607
|
KeyEntryModal,
|
|
27938
28608
|
{
|
|
27939
28609
|
model,
|
|
@@ -27945,6 +28615,17 @@ function ModalHost(props) {
|
|
|
27945
28615
|
}
|
|
27946
28616
|
) }) });
|
|
27947
28617
|
}
|
|
28618
|
+
if (modals.showChangelogImagePicker && props.changelogImageRepo) {
|
|
28619
|
+
return /* @__PURE__ */ jsx42(ThemeProvider, { theme, children: /* @__PURE__ */ jsx42(Box40, { flexDirection: "column", children: /* @__PURE__ */ jsx42(
|
|
28620
|
+
ChangelogImagePicker,
|
|
28621
|
+
{
|
|
28622
|
+
owner: props.changelogImageRepo.owner,
|
|
28623
|
+
repo: props.changelogImageRepo.name,
|
|
28624
|
+
onGenerate: props.onChangelogImageGenerate,
|
|
28625
|
+
onCancel: props.onChangelogImageCancel
|
|
28626
|
+
}
|
|
28627
|
+
) }) });
|
|
28628
|
+
}
|
|
27948
28629
|
return null;
|
|
27949
28630
|
}
|
|
27950
28631
|
function ModalOverlay({
|
|
@@ -27954,7 +28635,7 @@ function ModalOverlay({
|
|
|
27954
28635
|
}) {
|
|
27955
28636
|
if (modals.limitModal) {
|
|
27956
28637
|
const m = modals.limitModal;
|
|
27957
|
-
return /* @__PURE__ */
|
|
28638
|
+
return /* @__PURE__ */ jsx42(
|
|
27958
28639
|
LimitModal,
|
|
27959
28640
|
{
|
|
27960
28641
|
limit: m.limit,
|
|
@@ -27968,7 +28649,7 @@ function ModalOverlay({
|
|
|
27968
28649
|
}
|
|
27969
28650
|
if (modals.loopModal) {
|
|
27970
28651
|
const m = modals.loopModal;
|
|
27971
|
-
return /* @__PURE__ */
|
|
28652
|
+
return /* @__PURE__ */ jsx42(
|
|
27972
28653
|
LimitModal,
|
|
27973
28654
|
{
|
|
27974
28655
|
limit: 50,
|
|
@@ -28013,13 +28694,14 @@ var init_modal_host = __esm({
|
|
|
28013
28694
|
init_multi_agent_modal();
|
|
28014
28695
|
init_hooks_dashboard();
|
|
28015
28696
|
init_help_menu();
|
|
28697
|
+
init_changelog_image_picker();
|
|
28016
28698
|
}
|
|
28017
28699
|
});
|
|
28018
28700
|
|
|
28019
28701
|
// src/ui/plan-complete-picker.tsx
|
|
28020
|
-
import { Box as
|
|
28702
|
+
import { Box as Box41, Text as Text42 } from "ink";
|
|
28021
28703
|
import SelectInput23 from "ink-select-input";
|
|
28022
|
-
import { jsx as
|
|
28704
|
+
import { jsx as jsx43, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
28023
28705
|
function PlanCompletePicker({ onPick }) {
|
|
28024
28706
|
const theme = useTheme();
|
|
28025
28707
|
const items = [
|
|
@@ -28027,10 +28709,10 @@ function PlanCompletePicker({ onPick }) {
|
|
|
28027
28709
|
{ label: "\u25B8 Start building and ask for permission (edit mode)", value: "edit", key: "edit" },
|
|
28028
28710
|
{ label: "\u25B8 Continue planning / ask a question", value: "continue", key: "continue" }
|
|
28029
28711
|
];
|
|
28030
|
-
return /* @__PURE__ */
|
|
28031
|
-
/* @__PURE__ */
|
|
28032
|
-
/* @__PURE__ */
|
|
28033
|
-
/* @__PURE__ */
|
|
28712
|
+
return /* @__PURE__ */ jsxs41(Box41, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [
|
|
28713
|
+
/* @__PURE__ */ jsx43(Text42, { color: theme.accent, bold: true, children: "Plan complete \u2014 what next?" }),
|
|
28714
|
+
/* @__PURE__ */ jsx43(Text42, { color: theme.info.color, dimColor: false, children: "Arrow keys to navigate, Enter to select, Esc to cancel." }),
|
|
28715
|
+
/* @__PURE__ */ jsx43(Box41, { marginTop: 1, children: /* @__PURE__ */ jsx43(
|
|
28034
28716
|
SelectInput23,
|
|
28035
28717
|
{
|
|
28036
28718
|
items,
|
|
@@ -28049,7 +28731,7 @@ var init_plan_complete_picker = __esm({
|
|
|
28049
28731
|
});
|
|
28050
28732
|
|
|
28051
28733
|
// src/ui/use-session-manager.ts
|
|
28052
|
-
import { useCallback as useCallback8, useRef as useRef5, useState as
|
|
28734
|
+
import { useCallback as useCallback8, useRef as useRef5, useState as useState27 } from "react";
|
|
28053
28735
|
function extractFirstUserText(messages) {
|
|
28054
28736
|
const firstUser = messages.find((m) => m.role === "user");
|
|
28055
28737
|
if (!firstUser) return "session";
|
|
@@ -28066,9 +28748,9 @@ function useSessionManager(deps) {
|
|
|
28066
28748
|
const sessionIdRef = useRef5(null);
|
|
28067
28749
|
const sessionCreatedAtRef = useRef5(null);
|
|
28068
28750
|
const sessionTitleRef = useRef5(null);
|
|
28069
|
-
const [resumeSessions, setResumeSessions] =
|
|
28070
|
-
const [checkpointSession, setCheckpointSession] =
|
|
28071
|
-
const [checkpointList, setCheckpointList] =
|
|
28751
|
+
const [resumeSessions, setResumeSessions] = useState27(null);
|
|
28752
|
+
const [checkpointSession, setCheckpointSession] = useState27(null);
|
|
28753
|
+
const [checkpointList, setCheckpointList] = useState27([]);
|
|
28072
28754
|
const depsRef = useRef5(deps);
|
|
28073
28755
|
depsRef.current = deps;
|
|
28074
28756
|
const ensureSessionId = useCallback8(() => {
|
|
@@ -28140,8 +28822,22 @@ function useSessionManager(deps) {
|
|
|
28140
28822
|
} catch {
|
|
28141
28823
|
}
|
|
28142
28824
|
}
|
|
28143
|
-
const
|
|
28825
|
+
const nonSystemCount = file.messages.filter((m) => m.role !== "system").length;
|
|
28826
|
+
const msg = checkpointId ? `resumed session ${file.id} from checkpoint` : `resumed session ${file.id} (${nonSystemCount} msgs)`;
|
|
28144
28827
|
d.setEvents([{ kind: "info", key: d.mkKey(), text: msg }]);
|
|
28828
|
+
if (!checkpointId) {
|
|
28829
|
+
const threshold = d.cfg?.autoFreshSuggestionTurns ?? DEFAULT_AUTO_FRESH_SUGGESTION_TURNS;
|
|
28830
|
+
if (threshold > 0 && nonSystemCount >= threshold && (d.mode === "auto" || d.mode === "edit" || d.mode === "multi-agent-experimental")) {
|
|
28831
|
+
d.setEvents((es) => [
|
|
28832
|
+
...es,
|
|
28833
|
+
{
|
|
28834
|
+
kind: "info",
|
|
28835
|
+
key: d.mkKey(),
|
|
28836
|
+
text: `This session has ${nonSystemCount} turns. The model may slow down with accumulated context. Run /fresh to continue with a summarized state, or /compact to compress history.`
|
|
28837
|
+
}
|
|
28838
|
+
]);
|
|
28839
|
+
}
|
|
28840
|
+
}
|
|
28145
28841
|
const userMsgs = file.messages.filter((m) => m.role === "user" && m.content).map((m) => {
|
|
28146
28842
|
if (!m.content) return "";
|
|
28147
28843
|
if (typeof m.content === "string") return m.content;
|
|
@@ -28240,30 +28936,31 @@ var init_use_session_manager = __esm({
|
|
|
28240
28936
|
init_session_state();
|
|
28241
28937
|
init_usage_tracker();
|
|
28242
28938
|
init_log_sink();
|
|
28939
|
+
init_app_helpers();
|
|
28243
28940
|
}
|
|
28244
28941
|
});
|
|
28245
28942
|
|
|
28246
28943
|
// src/ui/use-turn-controller.ts
|
|
28247
|
-
import { useCallback as useCallback9, useRef as useRef6, useState as
|
|
28944
|
+
import { useCallback as useCallback9, useRef as useRef6, useState as useState28 } from "react";
|
|
28248
28945
|
function useTurnController() {
|
|
28249
|
-
const [busy, setBusy] =
|
|
28946
|
+
const [busy, setBusy] = useState28(false);
|
|
28250
28947
|
const busyRef = useRef6(false);
|
|
28251
28948
|
const isAbortingRef = useRef6(false);
|
|
28252
28949
|
const lastEscapeAtRef = useRef6(0);
|
|
28253
28950
|
const supervisorRef = useRef6(new TurnSupervisor());
|
|
28254
|
-
const [turnPhase, setTurnPhase] =
|
|
28255
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
28256
|
-
const [currentToolName, setCurrentToolName] =
|
|
28257
|
-
const [lastActivityAt, setLastActivityAt] =
|
|
28951
|
+
const [turnPhase, setTurnPhase] = useState28("waiting");
|
|
28952
|
+
const [turnStartedAt, setTurnStartedAt] = useState28(null);
|
|
28953
|
+
const [currentToolName, setCurrentToolName] = useState28(null);
|
|
28954
|
+
const [lastActivityAt, setLastActivityAt] = useState28(null);
|
|
28258
28955
|
const turnCounterRef = useRef6(0);
|
|
28259
|
-
const [showReasoning, setShowReasoning] =
|
|
28956
|
+
const [showReasoning, setShowReasoning] = useState28(false);
|
|
28260
28957
|
const toggleReasoning = useCallback9(() => {
|
|
28261
28958
|
setShowReasoning((s) => !s);
|
|
28262
28959
|
}, []);
|
|
28263
|
-
const [tasks, setTasks] =
|
|
28960
|
+
const [tasks, setTasks] = useState28([]);
|
|
28264
28961
|
const tasksRef = useRef6([]);
|
|
28265
|
-
const [tasksStartedAt, setTasksStartedAt] =
|
|
28266
|
-
const [tasksStartTokens, setTasksStartTokens] =
|
|
28962
|
+
const [tasksStartedAt, setTasksStartedAt] = useState28(null);
|
|
28963
|
+
const [tasksStartTokens, setTasksStartTokens] = useState28(0);
|
|
28267
28964
|
const beginTurn = useCallback9(() => {
|
|
28268
28965
|
setBusy(true);
|
|
28269
28966
|
busyRef.current = true;
|
|
@@ -28389,15 +29086,15 @@ var tui_report_exports = {};
|
|
|
28389
29086
|
__export(tui_report_exports, {
|
|
28390
29087
|
getCategoryReportText: () => getCategoryReportText
|
|
28391
29088
|
});
|
|
28392
|
-
import { readFile as
|
|
28393
|
-
import { join as
|
|
29089
|
+
import { readFile as readFile20 } from "fs/promises";
|
|
29090
|
+
import { join as join32 } from "path";
|
|
28394
29091
|
import { homedir as homedir16 } from "os";
|
|
28395
29092
|
function usageDir3() {
|
|
28396
|
-
const xdg = process.env.XDG_DATA_HOME ||
|
|
28397
|
-
return
|
|
29093
|
+
const xdg = process.env.XDG_DATA_HOME || join32(homedir16(), ".local", "share");
|
|
29094
|
+
return join32(xdg, "kimiflare");
|
|
28398
29095
|
}
|
|
28399
29096
|
function usagePath3() {
|
|
28400
|
-
return
|
|
29097
|
+
return join32(usageDir3(), "usage.json");
|
|
28401
29098
|
}
|
|
28402
29099
|
function today3() {
|
|
28403
29100
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -28409,7 +29106,7 @@ function daysAgo2(n) {
|
|
|
28409
29106
|
}
|
|
28410
29107
|
async function loadLog3() {
|
|
28411
29108
|
try {
|
|
28412
|
-
const raw = await
|
|
29109
|
+
const raw = await readFile20(usagePath3(), "utf8");
|
|
28413
29110
|
return JSON.parse(raw);
|
|
28414
29111
|
} catch {
|
|
28415
29112
|
return { version: 1, days: [], sessions: [] };
|
|
@@ -28466,10 +29163,10 @@ var init_tui_report = __esm({
|
|
|
28466
29163
|
});
|
|
28467
29164
|
|
|
28468
29165
|
// src/ui/slash-commands.ts
|
|
28469
|
-
import { join as
|
|
29166
|
+
import { join as join33 } from "path";
|
|
28470
29167
|
import { unlink as unlink5 } from "fs/promises";
|
|
28471
29168
|
import QRCode from "qrcode";
|
|
28472
|
-
function executeFreshStart(ctx, planText) {
|
|
29169
|
+
function executeFreshStart(ctx, planText, overrideMode) {
|
|
28473
29170
|
const oldSessionId = ctx.sessionIdRef.current;
|
|
28474
29171
|
if (ctx.cacheStableRef.current && ctx.messagesRef.current.length >= 2) {
|
|
28475
29172
|
ctx.messagesRef.current = [ctx.messagesRef.current[0], ctx.messagesRef.current[1]];
|
|
@@ -28495,12 +29192,13 @@ function executeFreshStart(ctx, planText) {
|
|
|
28495
29192
|
ctx.clearTaskTracking();
|
|
28496
29193
|
ctx.compactSuggestedRef.current = false;
|
|
28497
29194
|
ctx.updateNudgedRef.current = false;
|
|
29195
|
+
ctx.freshSuggestedRef.current = false;
|
|
28498
29196
|
ctx.sessionPlanRef.current = null;
|
|
28499
29197
|
rebuildSystemPromptForMode(
|
|
28500
29198
|
ctx.messagesRef.current,
|
|
28501
29199
|
ctx.cacheStableRef.current,
|
|
28502
29200
|
ctx.cfg?.model ?? "@cf/moonshotai/kimi-k2.6",
|
|
28503
|
-
ctx.mode,
|
|
29201
|
+
overrideMode ?? ctx.mode,
|
|
28504
29202
|
[...ALL_TOOLS, ...ctx.mcpToolsRef.current, ...ctx.lspToolsRef.current]
|
|
28505
29203
|
);
|
|
28506
29204
|
ctx.messagesRef.current.push({ role: "user", content: planText });
|
|
@@ -28521,7 +29219,7 @@ function dispatchSlashCommand(ctx, cmd) {
|
|
|
28521
29219
|
if (!handler) return false;
|
|
28522
29220
|
return handler(ctx, rest, arg);
|
|
28523
29221
|
}
|
|
28524
|
-
var handleExit, handleClear, handleFresh, handleReasoning, handleCost, handleShell, handleModel, handleGateway, handleMode, handleMultiAgent, handleTheme, handleUi, handlePlan, handleAuto, handleEdit, handleSkills, handleMemory, handleResume, handleCheckpoint, handleCompact, handleInit, handleUpdate, handleMcp, handleLsp, handleHooks, handleHello, handleInbox, handleLogout, handleCommand, handleRemote, handleHelp, handlers;
|
|
29222
|
+
var handleExit, handleClear, handleFresh, handleReasoning, handleCost, handleShell, handleModel, handleGateway, handleMode, handleMultiAgent, handleTheme, handleUi, handlePlan, handleAuto, handleEdit, handleSkills, handleMemory, handleResume, handleCheckpoint, handleCompact, handleInit, handleUpdate, handleMcp, handleLsp, handleHooks, handleHello, handleInbox, handleLogout, handleCommand, handleRemote, handleHelp, handleChangelogImage, handlers;
|
|
28525
29223
|
var init_slash_commands = __esm({
|
|
28526
29224
|
"src/ui/slash-commands.ts"() {
|
|
28527
29225
|
"use strict";
|
|
@@ -28546,7 +29244,7 @@ var init_slash_commands = __esm({
|
|
|
28546
29244
|
init_session_store();
|
|
28547
29245
|
init_deploy();
|
|
28548
29246
|
init_tui_auth();
|
|
28549
|
-
|
|
29247
|
+
init_continuation_summary();
|
|
28550
29248
|
init_clipboard();
|
|
28551
29249
|
handleExit = (ctx) => {
|
|
28552
29250
|
void ctx.lspManagerRef.current.stopAll().finally(() => ctx.exit());
|
|
@@ -28585,11 +29283,12 @@ var init_slash_commands = __esm({
|
|
|
28585
29283
|
ctx.clearTaskTracking();
|
|
28586
29284
|
ctx.compactSuggestedRef.current = false;
|
|
28587
29285
|
ctx.updateNudgedRef.current = false;
|
|
29286
|
+
ctx.freshSuggestedRef.current = false;
|
|
28588
29287
|
ctx.sessionPlanRef.current = null;
|
|
28589
29288
|
return true;
|
|
28590
29289
|
};
|
|
28591
|
-
handleFresh = (ctx) => {
|
|
28592
|
-
const { busy, mkKey: mkKey2, setEvents } = ctx;
|
|
29290
|
+
handleFresh = async (ctx) => {
|
|
29291
|
+
const { busy, mkKey: mkKey2, setEvents, cfg } = ctx;
|
|
28593
29292
|
if (busy) {
|
|
28594
29293
|
setEvents((e) => [
|
|
28595
29294
|
...e,
|
|
@@ -28597,27 +29296,42 @@ var init_slash_commands = __esm({
|
|
|
28597
29296
|
]);
|
|
28598
29297
|
return true;
|
|
28599
29298
|
}
|
|
28600
|
-
const
|
|
28601
|
-
|
|
29299
|
+
const summary = await generateContinuationSummary({
|
|
29300
|
+
messages: ctx.messagesRef.current,
|
|
29301
|
+
mode: ctx.mode,
|
|
29302
|
+
accountId: cfg?.accountId ?? "",
|
|
29303
|
+
apiToken: cfg?.apiToken ?? "",
|
|
29304
|
+
model: cfg?.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
|
|
29305
|
+
gateway: cfg?.aiGatewayId ? {
|
|
29306
|
+
id: cfg.aiGatewayId,
|
|
29307
|
+
cacheTtl: cfg.aiGatewayCacheTtl,
|
|
29308
|
+
skipCache: cfg.aiGatewaySkipCache,
|
|
29309
|
+
collectLogPayload: cfg.aiGatewayCollectLogPayload,
|
|
29310
|
+
metadata: cfg.aiGatewayMetadata
|
|
29311
|
+
} : void 0,
|
|
29312
|
+
memoryManager: ctx.memoryManagerRef.current,
|
|
29313
|
+
memoryEnabled: cfg?.memoryEnabled
|
|
29314
|
+
});
|
|
29315
|
+
if (!summary) {
|
|
28602
29316
|
setEvents((e) => [
|
|
28603
29317
|
...e,
|
|
28604
|
-
{ kind: "error", key: mkKey2(), text: "No plan found to start fresh with." }
|
|
29318
|
+
{ kind: "error", key: mkKey2(), text: "No plan or summary found to start fresh with." }
|
|
28605
29319
|
]);
|
|
28606
29320
|
return true;
|
|
28607
29321
|
}
|
|
28608
|
-
const clipResult = executeFreshStart(ctx,
|
|
29322
|
+
const clipResult = executeFreshStart(ctx, summary);
|
|
28609
29323
|
setEvents((e) => [
|
|
28610
29324
|
...e,
|
|
28611
29325
|
{
|
|
28612
29326
|
kind: "info",
|
|
28613
29327
|
key: mkKey2(),
|
|
28614
|
-
text: clipResult.success ? "
|
|
29328
|
+
text: clipResult.success ? "Summary copied to clipboard. Starting fresh session with continuation context\u2026" : "Clipboard unavailable. Starting fresh session with continuation context\u2026"
|
|
28615
29329
|
}
|
|
28616
29330
|
]);
|
|
28617
29331
|
if (!clipResult.success) {
|
|
28618
29332
|
setEvents((e) => [
|
|
28619
29333
|
...e,
|
|
28620
|
-
{ kind: "info", key: mkKey2(), text: "---
|
|
29334
|
+
{ kind: "info", key: mkKey2(), text: "--- Continuation Context ---\n" + summary }
|
|
28621
29335
|
]);
|
|
28622
29336
|
}
|
|
28623
29337
|
return true;
|
|
@@ -29288,7 +30002,7 @@ ${lines.join("\n")}` }]);
|
|
|
29288
30002
|
void (async () => {
|
|
29289
30003
|
try {
|
|
29290
30004
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
29291
|
-
const file = await loadSession(
|
|
30005
|
+
const file = await loadSession(join33(sessionsDir3(), `${currentId}.json`));
|
|
29292
30006
|
const cps = file.checkpoints ?? [];
|
|
29293
30007
|
if (cps.length === 0) {
|
|
29294
30008
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: "no checkpoints in this session" }]);
|
|
@@ -29333,7 +30047,7 @@ ${lines.join("\n")}` }]);
|
|
|
29333
30047
|
try {
|
|
29334
30048
|
ctx.ensureSessionId();
|
|
29335
30049
|
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
29336
|
-
const filePath =
|
|
30050
|
+
const filePath = join33(sessionsDir3(), `${ctx.sessionIdRef.current}.json`);
|
|
29337
30051
|
await addCheckpoint(filePath, cp);
|
|
29338
30052
|
setEvents((e) => [...e, { kind: "info", key: mkKey2(), text: `checkpoint saved: "${label}"` }]);
|
|
29339
30053
|
} catch (e) {
|
|
@@ -29820,6 +30534,115 @@ project: ${projectSettingsPath(cwd)}`
|
|
|
29820
30534
|
ctx.setShowHelpMenu(true);
|
|
29821
30535
|
return true;
|
|
29822
30536
|
};
|
|
30537
|
+
handleChangelogImage = (ctx, rest) => {
|
|
30538
|
+
const { cfg, setEvents, mkKey: mkKey2, setShowChangelogImagePicker, setChangelogImageRepo, setTasks, setTasksStartedAt } = ctx;
|
|
30539
|
+
if (!cfg) {
|
|
30540
|
+
setEvents((e) => [...e, { kind: "error", key: mkKey2(), text: "Not configured yet." }]);
|
|
30541
|
+
return true;
|
|
30542
|
+
}
|
|
30543
|
+
let owner = cfg.githubRepo?.split("/")[0];
|
|
30544
|
+
let repo = cfg.githubRepo?.split("/")[1];
|
|
30545
|
+
let days = 7;
|
|
30546
|
+
if (rest.length > 0 && rest[0].includes("/")) {
|
|
30547
|
+
const parts = rest[0].split("/");
|
|
30548
|
+
owner = parts[0];
|
|
30549
|
+
repo = parts[1];
|
|
30550
|
+
}
|
|
30551
|
+
if (rest.length > 1) {
|
|
30552
|
+
const d = parseInt(rest[1], 10);
|
|
30553
|
+
if (!Number.isNaN(d)) days = d;
|
|
30554
|
+
}
|
|
30555
|
+
const runGeneration = (o, r, d) => {
|
|
30556
|
+
const asstId = mkAssistantId();
|
|
30557
|
+
setEvents((e) => [
|
|
30558
|
+
...e,
|
|
30559
|
+
{
|
|
30560
|
+
kind: "assistant",
|
|
30561
|
+
key: `asst_${asstId}`,
|
|
30562
|
+
id: asstId,
|
|
30563
|
+
text: `Generating changelog image for ${o}/${r} (last ${d} day${d === 1 ? "" : "s"})\u2026`,
|
|
30564
|
+
reasoning: "",
|
|
30565
|
+
streaming: true
|
|
30566
|
+
}
|
|
30567
|
+
]);
|
|
30568
|
+
const taskList = [
|
|
30569
|
+
{ id: "fetch-prs", title: "Fetch merged PRs", status: "pending" },
|
|
30570
|
+
{ id: "fetch-release", title: "Fetch latest release", status: "pending" },
|
|
30571
|
+
{ id: "summarize", title: "Summarize with LLM", status: "pending" },
|
|
30572
|
+
{ id: "render", title: "Render changelog image", status: "pending" },
|
|
30573
|
+
{ id: "save", title: "Save PNG file", status: "pending" }
|
|
30574
|
+
];
|
|
30575
|
+
setTasks(taskList);
|
|
30576
|
+
setTasksStartedAt(Date.now());
|
|
30577
|
+
const updateTask = (id, status) => {
|
|
30578
|
+
setTasks((prev) => prev.map((t) => t.id === id ? { ...t, status } : t));
|
|
30579
|
+
};
|
|
30580
|
+
void (async () => {
|
|
30581
|
+
try {
|
|
30582
|
+
const { changelogImageTool: changelogImageTool2 } = await Promise.resolve().then(() => (init_changelog_image(), changelog_image_exports));
|
|
30583
|
+
const { gatewayFromConfig: gatewayFromConfig2 } = await Promise.resolve().then(() => (init_app_helpers(), app_helpers_exports));
|
|
30584
|
+
updateTask("fetch-prs", "in_progress");
|
|
30585
|
+
updateTask("fetch-release", "in_progress");
|
|
30586
|
+
const result = await changelogImageTool2.run({ owner: o, repo: r, days: d }, {
|
|
30587
|
+
cwd: process.cwd(),
|
|
30588
|
+
githubToken: cfg.githubOAuthToken,
|
|
30589
|
+
accountId: cfg.accountId,
|
|
30590
|
+
apiToken: cfg.apiToken,
|
|
30591
|
+
model: cfg.model,
|
|
30592
|
+
gateway: gatewayFromConfig2(cfg)
|
|
30593
|
+
});
|
|
30594
|
+
updateTask("fetch-prs", "completed");
|
|
30595
|
+
updateTask("fetch-release", "completed");
|
|
30596
|
+
updateTask("summarize", "completed");
|
|
30597
|
+
updateTask("render", "completed");
|
|
30598
|
+
updateTask("save", "completed");
|
|
30599
|
+
const text = typeof result === "string" ? result : result.content;
|
|
30600
|
+
setEvents(
|
|
30601
|
+
(e) => e.map(
|
|
30602
|
+
(ev) => ev.kind === "assistant" && ev.id === asstId ? { ...ev, text, streaming: false } : ev
|
|
30603
|
+
)
|
|
30604
|
+
);
|
|
30605
|
+
} catch (err) {
|
|
30606
|
+
const msg = `changelog-image failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
30607
|
+
setEvents(
|
|
30608
|
+
(e) => e.map(
|
|
30609
|
+
(ev) => ev.kind === "assistant" && ev.id === asstId ? { ...ev, text: msg, streaming: false } : ev
|
|
30610
|
+
)
|
|
30611
|
+
);
|
|
30612
|
+
} finally {
|
|
30613
|
+
setTasksStartedAt(null);
|
|
30614
|
+
}
|
|
30615
|
+
})();
|
|
30616
|
+
};
|
|
30617
|
+
const tryOpenPicker = (o, r) => {
|
|
30618
|
+
if (o && r) {
|
|
30619
|
+
if (rest.length === 0) {
|
|
30620
|
+
setChangelogImageRepo({ owner: o, name: r });
|
|
30621
|
+
setShowChangelogImagePicker(true);
|
|
30622
|
+
return;
|
|
30623
|
+
}
|
|
30624
|
+
runGeneration(o, r, days);
|
|
30625
|
+
return;
|
|
30626
|
+
}
|
|
30627
|
+
setEvents((e) => [
|
|
30628
|
+
...e,
|
|
30629
|
+
{
|
|
30630
|
+
kind: "error",
|
|
30631
|
+
key: mkKey2(),
|
|
30632
|
+
text: "Usage: /changelog-image [owner/repo] [days]\nSet githubRepo in config or pass owner/repo explicitly."
|
|
30633
|
+
}
|
|
30634
|
+
]);
|
|
30635
|
+
};
|
|
30636
|
+
if (owner && repo) {
|
|
30637
|
+
tryOpenPicker(owner, repo);
|
|
30638
|
+
return true;
|
|
30639
|
+
}
|
|
30640
|
+
void Promise.resolve().then(() => (init_app_helpers(), app_helpers_exports)).then(({ detectGitHubRepo: detectGitHubRepo3 }) => {
|
|
30641
|
+
const detected = detectGitHubRepo3();
|
|
30642
|
+
tryOpenPicker(detected?.owner, detected?.name);
|
|
30643
|
+
});
|
|
30644
|
+
return true;
|
|
30645
|
+
};
|
|
29823
30646
|
handlers = {
|
|
29824
30647
|
"/exit": handleExit,
|
|
29825
30648
|
"/clear": handleClear,
|
|
@@ -29851,6 +30674,7 @@ project: ${projectSettingsPath(cwd)}`
|
|
|
29851
30674
|
"/logout": handleLogout,
|
|
29852
30675
|
"/command": handleCommand,
|
|
29853
30676
|
"/remote": handleRemote,
|
|
30677
|
+
"/changelog-image": handleChangelogImage,
|
|
29854
30678
|
"/help": handleHelp
|
|
29855
30679
|
};
|
|
29856
30680
|
}
|
|
@@ -29858,7 +30682,7 @@ project: ${projectSettingsPath(cwd)}`
|
|
|
29858
30682
|
|
|
29859
30683
|
// src/init/run-init.ts
|
|
29860
30684
|
import { existsSync as existsSync6 } from "fs";
|
|
29861
|
-
import { join as
|
|
30685
|
+
import { join as join34 } from "path";
|
|
29862
30686
|
async function runInit(deps) {
|
|
29863
30687
|
const {
|
|
29864
30688
|
cfg,
|
|
@@ -29955,7 +30779,7 @@ async function runInit(deps) {
|
|
|
29955
30779
|
lspManagerRef.current.notifyChange(path, content);
|
|
29956
30780
|
} else {
|
|
29957
30781
|
void import("fs/promises").then(
|
|
29958
|
-
({ readFile:
|
|
30782
|
+
({ readFile: readFile23 }) => readFile23(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
29959
30783
|
})
|
|
29960
30784
|
);
|
|
29961
30785
|
}
|
|
@@ -30061,7 +30885,7 @@ async function runInit(deps) {
|
|
|
30061
30885
|
}
|
|
30062
30886
|
}
|
|
30063
30887
|
});
|
|
30064
|
-
if (existsSync6(
|
|
30888
|
+
if (existsSync6(join34(cwd, "KIMI.md"))) {
|
|
30065
30889
|
if (cacheStableRef.current) {
|
|
30066
30890
|
messagesRef.current[1] = {
|
|
30067
30891
|
role: "system",
|
|
@@ -30155,8 +30979,8 @@ var init_run_init = __esm({
|
|
|
30155
30979
|
});
|
|
30156
30980
|
|
|
30157
30981
|
// src/skills/discovery.ts
|
|
30158
|
-
import { readdir as readdir9, stat as stat7, readFile as
|
|
30159
|
-
import { join as
|
|
30982
|
+
import { readdir as readdir9, stat as stat7, readFile as readFile21 } from "fs/promises";
|
|
30983
|
+
import { join as join35, extname as extname2 } from "path";
|
|
30160
30984
|
async function dirExists(path) {
|
|
30161
30985
|
try {
|
|
30162
30986
|
const s = await stat7(path);
|
|
@@ -30180,20 +31004,20 @@ async function scanSkillDir(dirPath, source) {
|
|
|
30180
31004
|
for (const entry of entries) {
|
|
30181
31005
|
if (!entry.isFile()) continue;
|
|
30182
31006
|
if (!SKILL_EXTENSIONS.has(extname2(entry.name))) continue;
|
|
30183
|
-
files.push({ filePath:
|
|
31007
|
+
files.push({ filePath: join35(dirPath, entry.name), source });
|
|
30184
31008
|
}
|
|
30185
31009
|
return files;
|
|
30186
31010
|
}
|
|
30187
31011
|
async function discoverSkills(cwd) {
|
|
30188
|
-
const agentsSkills = await scanSkillDir(
|
|
30189
|
-
const agentsMd = await fileExists(
|
|
30190
|
-
const githubSkills = await scanSkillDir(
|
|
30191
|
-
const kimiflareSkills = await scanSkillDir(
|
|
31012
|
+
const agentsSkills = await scanSkillDir(join35(cwd, ".agents", "skills"), "agents");
|
|
31013
|
+
const agentsMd = await fileExists(join35(cwd, "AGENTS.md")) ? [{ filePath: join35(cwd, "AGENTS.md"), source: "agents-md" }] : [];
|
|
31014
|
+
const githubSkills = await scanSkillDir(join35(cwd, ".github", "skills"), "github");
|
|
31015
|
+
const kimiflareSkills = await scanSkillDir(join35(cwd, ".kimiflare", "skills"), "kimiflare");
|
|
30192
31016
|
const ordered = [...agentsSkills, ...agentsMd, ...githubSkills, ...kimiflareSkills];
|
|
30193
31017
|
return ordered;
|
|
30194
31018
|
}
|
|
30195
31019
|
async function readSkillFile(filePath) {
|
|
30196
|
-
const bytes = await
|
|
31020
|
+
const bytes = await readFile21(filePath);
|
|
30197
31021
|
return { bytes, text: bytes.toString("utf-8") };
|
|
30198
31022
|
}
|
|
30199
31023
|
var SKILL_EXTENSIONS;
|
|
@@ -30398,16 +31222,16 @@ var init_skills = __esm({
|
|
|
30398
31222
|
});
|
|
30399
31223
|
|
|
30400
31224
|
// src/util/state.ts
|
|
30401
|
-
import { readFile as
|
|
31225
|
+
import { readFile as readFile22, writeFile as writeFile14, mkdir as mkdir12 } from "fs/promises";
|
|
30402
31226
|
import { homedir as homedir17 } from "os";
|
|
30403
|
-
import { join as
|
|
31227
|
+
import { join as join36 } from "path";
|
|
30404
31228
|
function statePath() {
|
|
30405
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
30406
|
-
return
|
|
31229
|
+
const xdg = process.env.XDG_CONFIG_HOME || join36(homedir17(), ".config");
|
|
31230
|
+
return join36(xdg, "kimiflare", "state.json");
|
|
30407
31231
|
}
|
|
30408
31232
|
async function readState() {
|
|
30409
31233
|
try {
|
|
30410
|
-
const raw = await
|
|
31234
|
+
const raw = await readFile22(statePath(), "utf8");
|
|
30411
31235
|
return JSON.parse(raw);
|
|
30412
31236
|
} catch {
|
|
30413
31237
|
return {};
|
|
@@ -30415,8 +31239,8 @@ async function readState() {
|
|
|
30415
31239
|
}
|
|
30416
31240
|
async function writeState(state) {
|
|
30417
31241
|
const path = statePath();
|
|
30418
|
-
await mkdir12(
|
|
30419
|
-
await
|
|
31242
|
+
await mkdir12(join36(path, ".."), { recursive: true });
|
|
31243
|
+
await writeFile14(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
30420
31244
|
}
|
|
30421
31245
|
async function markCreatorMessageSeen(version) {
|
|
30422
31246
|
const state = await readState();
|
|
@@ -30435,7 +31259,7 @@ var init_state = __esm({
|
|
|
30435
31259
|
|
|
30436
31260
|
// src/ui/run-startup-tasks.ts
|
|
30437
31261
|
import { existsSync as existsSync7 } from "fs";
|
|
30438
|
-
import { join as
|
|
31262
|
+
import { join as join37 } from "path";
|
|
30439
31263
|
function runStartupTasks(deps) {
|
|
30440
31264
|
const {
|
|
30441
31265
|
cfg,
|
|
@@ -30486,7 +31310,7 @@ function runStartupTasks(deps) {
|
|
|
30486
31310
|
}
|
|
30487
31311
|
});
|
|
30488
31312
|
if (cfg.memoryEnabled) {
|
|
30489
|
-
const dbPath = cfg.memoryDbPath ??
|
|
31313
|
+
const dbPath = cfg.memoryDbPath ?? join37(process.cwd(), ".kimiflare", "memory.db");
|
|
30490
31314
|
const manager = new MemoryManager({
|
|
30491
31315
|
dbPath,
|
|
30492
31316
|
accountId: cfg.accountId,
|
|
@@ -30520,7 +31344,7 @@ function runStartupTasks(deps) {
|
|
|
30520
31344
|
});
|
|
30521
31345
|
const cwd = process.cwd();
|
|
30522
31346
|
sessionStartRecallRef.current = manager.recall({ text: cwd, repoPath: cwd, limit: 5 });
|
|
30523
|
-
if (existsSync7(
|
|
31347
|
+
if (existsSync7(join37(cwd, "KIMI.md"))) {
|
|
30524
31348
|
const lastRefresh = manager.getLastKimiMdRefreshTime(cwd);
|
|
30525
31349
|
const driftCount = manager.countHighSignalMemoriesSince(cwd, lastRefresh);
|
|
30526
31350
|
if (driftCount >= 5) {
|
|
@@ -30531,7 +31355,7 @@ function runStartupTasks(deps) {
|
|
|
30531
31355
|
memoryManagerRef.current?.close();
|
|
30532
31356
|
memoryManagerRef.current = null;
|
|
30533
31357
|
}
|
|
30534
|
-
const skillDbPath = cfg.memoryDbPath ??
|
|
31358
|
+
const skillDbPath = cfg.memoryDbPath ?? join37(process.cwd(), ".kimiflare", "memory.db");
|
|
30535
31359
|
const skillDb = getMemoryDb() ?? openMemoryDb(skillDbPath);
|
|
30536
31360
|
initSkillsSchema(skillDb);
|
|
30537
31361
|
void indexSkills({
|
|
@@ -30997,11 +31821,11 @@ var app_exports = {};
|
|
|
30997
31821
|
__export(app_exports, {
|
|
30998
31822
|
renderApp: () => renderApp
|
|
30999
31823
|
});
|
|
31000
|
-
import
|
|
31001
|
-
import { Box as
|
|
31824
|
+
import React25, { useState as useState29, useRef as useRef7, useEffect as useEffect11, useCallback as useCallback10, useMemo as useMemo6 } from "react";
|
|
31825
|
+
import { Box as Box42, Text as Text43, useApp, useInput as useInput21, render } from "ink";
|
|
31002
31826
|
import { existsSync as existsSync8 } from "fs";
|
|
31003
|
-
import { join as
|
|
31004
|
-
import { jsx as
|
|
31827
|
+
import { join as join38 } from "path";
|
|
31828
|
+
import { jsx as jsx44, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
31005
31829
|
function App({
|
|
31006
31830
|
initialCfg,
|
|
31007
31831
|
initialUpdateResult,
|
|
@@ -31009,14 +31833,14 @@ function App({
|
|
|
31009
31833
|
initialLspProjectPath
|
|
31010
31834
|
}) {
|
|
31011
31835
|
const { exit } = useApp();
|
|
31012
|
-
const [cfg, setCfg] =
|
|
31836
|
+
const [cfg, setCfg] = useState29(initialCfg);
|
|
31013
31837
|
const modelContextLimit = useMemo6(
|
|
31014
31838
|
() => cfg ? getModelOrInfer(cfg.model).contextWindow : CONTEXT_LIMIT,
|
|
31015
31839
|
[cfg?.model]
|
|
31016
31840
|
);
|
|
31017
|
-
const [lspScope, setLspScope] =
|
|
31018
|
-
const [lspProjectPath, setLspProjectPath] =
|
|
31019
|
-
const [events, setRawEvents] =
|
|
31841
|
+
const [lspScope, setLspScope] = useState29(initialLspScope);
|
|
31842
|
+
const [lspProjectPath, setLspProjectPath] = useState29(initialLspProjectPath);
|
|
31843
|
+
const [events, setRawEvents] = useState29([]);
|
|
31020
31844
|
const setEvents = useCallback10(
|
|
31021
31845
|
(updater) => {
|
|
31022
31846
|
setRawEvents((prev) => {
|
|
@@ -31026,9 +31850,9 @@ function App({
|
|
|
31026
31850
|
},
|
|
31027
31851
|
[]
|
|
31028
31852
|
);
|
|
31029
|
-
const [input, setInput] =
|
|
31030
|
-
const [usage, setUsage] =
|
|
31031
|
-
const [sessionUsage, setSessionUsage] =
|
|
31853
|
+
const [input, setInput] = useState29("");
|
|
31854
|
+
const [usage, setUsage] = useState29(null);
|
|
31855
|
+
const [sessionUsage, setSessionUsage] = useState29(null);
|
|
31032
31856
|
useEffect11(() => {
|
|
31033
31857
|
const handler = (sid) => {
|
|
31034
31858
|
if (sessionIdRef.current && sid === sessionIdRef.current) {
|
|
@@ -31040,7 +31864,7 @@ function App({
|
|
|
31040
31864
|
usageEvents.off("update", handler);
|
|
31041
31865
|
};
|
|
31042
31866
|
}, []);
|
|
31043
|
-
const [gatewayMeta, setGatewayMeta] =
|
|
31867
|
+
const [gatewayMeta, setGatewayMeta] = useState29(null);
|
|
31044
31868
|
const turn = useTurnController();
|
|
31045
31869
|
const {
|
|
31046
31870
|
busy,
|
|
@@ -31068,7 +31892,7 @@ function App({
|
|
|
31068
31892
|
endTurn,
|
|
31069
31893
|
clearTaskTracking
|
|
31070
31894
|
} = turn;
|
|
31071
|
-
const [planOptions, setPlanOptions] =
|
|
31895
|
+
const [planOptions, setPlanOptions] = useState29(null);
|
|
31072
31896
|
const planOptionsRef = useRef7(null);
|
|
31073
31897
|
const {
|
|
31074
31898
|
pending: perm,
|
|
@@ -31135,39 +31959,42 @@ function App({
|
|
|
31135
31959
|
setShowShellPicker,
|
|
31136
31960
|
showPlanCompletePicker,
|
|
31137
31961
|
setShowPlanCompletePicker,
|
|
31962
|
+
showChangelogImagePicker,
|
|
31963
|
+
setShowChangelogImagePicker,
|
|
31138
31964
|
hasFullscreenModal,
|
|
31139
31965
|
hasAnyModal
|
|
31140
31966
|
} = modals;
|
|
31141
|
-
const [queue2, setQueue] =
|
|
31142
|
-
const [history, setHistory] =
|
|
31143
|
-
const [historyIndex, setHistoryIndex] =
|
|
31144
|
-
const [draftInput, setDraftInput] =
|
|
31145
|
-
const [mode, setMode] =
|
|
31967
|
+
const [queue2, setQueue] = useState29([]);
|
|
31968
|
+
const [history, setHistory] = useState29([]);
|
|
31969
|
+
const [historyIndex, setHistoryIndex] = useState29(-1);
|
|
31970
|
+
const [draftInput, setDraftInput] = useState29("");
|
|
31971
|
+
const [mode, setMode] = useState29("edit");
|
|
31146
31972
|
useEffect11(() => {
|
|
31147
31973
|
if (mode === "multi-agent-experimental" && cfg && !cfg.workerEndpoint && !cfg.remoteWorkerUrl && !showMultiAgentModal) {
|
|
31148
31974
|
setShowMultiAgentModal(true);
|
|
31149
31975
|
}
|
|
31150
31976
|
}, [mode, cfg?.workerEndpoint, cfg?.remoteWorkerUrl]);
|
|
31151
|
-
const [codeMode, setCodeMode] =
|
|
31977
|
+
const [codeMode, setCodeMode] = useState29(false);
|
|
31152
31978
|
const filePickerEnabled = initialCfg?.filePicker ?? true;
|
|
31153
|
-
const [effort, setEffort] =
|
|
31979
|
+
const [effort, setEffort] = useState29(
|
|
31154
31980
|
initialCfg?.reasoningEffort ?? DEFAULT_REASONING_EFFORT
|
|
31155
31981
|
);
|
|
31156
|
-
const [selectedRemoteSession, setSelectedRemoteSession] =
|
|
31157
|
-
const [verbose, setVerbose] =
|
|
31158
|
-
const [hasUpdate, setHasUpdate] =
|
|
31159
|
-
const [latestVersion, setLatestVersion] =
|
|
31160
|
-
const [theme, setTheme] =
|
|
31161
|
-
const [originalTheme, setOriginalTheme] =
|
|
31162
|
-
const [skillsActive, setSkillsActive] =
|
|
31163
|
-
const [memoryRecalled, setMemoryRecalled] =
|
|
31164
|
-
const [intentTier, setIntentTier] =
|
|
31165
|
-
const [kimiMdStale, setKimiMdStale] =
|
|
31166
|
-
const [gitBranch, setGitBranch] =
|
|
31167
|
-
const [lastSessionTopic, setLastSessionTopic] =
|
|
31168
|
-
const [activeWorkers, setActiveWorkers] =
|
|
31169
|
-
const [isSynthesizing, setIsSynthesizing] =
|
|
31170
|
-
const [coordinatorNarration, setCoordinatorNarration] =
|
|
31982
|
+
const [selectedRemoteSession, setSelectedRemoteSession] = useState29(null);
|
|
31983
|
+
const [verbose, setVerbose] = useState29(false);
|
|
31984
|
+
const [hasUpdate, setHasUpdate] = useState29(initialUpdateResult?.hasUpdate ?? false);
|
|
31985
|
+
const [latestVersion, setLatestVersion] = useState29(initialUpdateResult?.latestVersion ?? null);
|
|
31986
|
+
const [theme, setTheme] = useState29(resolveTheme(initialCfg?.theme));
|
|
31987
|
+
const [originalTheme, setOriginalTheme] = useState29(null);
|
|
31988
|
+
const [skillsActive, setSkillsActive] = useState29(0);
|
|
31989
|
+
const [memoryRecalled, setMemoryRecalled] = useState29(false);
|
|
31990
|
+
const [intentTier, setIntentTier] = useState29(null);
|
|
31991
|
+
const [kimiMdStale, setKimiMdStale] = useState29(false);
|
|
31992
|
+
const [gitBranch, setGitBranch] = useState29(null);
|
|
31993
|
+
const [lastSessionTopic, setLastSessionTopic] = useState29(null);
|
|
31994
|
+
const [activeWorkers, setActiveWorkers] = useState29([]);
|
|
31995
|
+
const [isSynthesizing, setIsSynthesizing] = useState29(false);
|
|
31996
|
+
const [coordinatorNarration, setCoordinatorNarration] = useState29("");
|
|
31997
|
+
const [changelogImageRepo, setChangelogImageRepo] = useState29(null);
|
|
31171
31998
|
useEffect11(() => {
|
|
31172
31999
|
setGitBranch(detectGitBranch());
|
|
31173
32000
|
}, []);
|
|
@@ -31217,8 +32044,8 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31217
32044
|
cancelled = true;
|
|
31218
32045
|
};
|
|
31219
32046
|
}, []);
|
|
31220
|
-
const [cursorOffset, setCursorOffset] =
|
|
31221
|
-
const [customCommandsVersion, setCustomCommandsVersion] =
|
|
32047
|
+
const [cursorOffset, setCursorOffset] = useState29(0);
|
|
32048
|
+
const [customCommandsVersion, setCustomCommandsVersion] = useState29(0);
|
|
31222
32049
|
const cacheStableRef = useRef7(initialCfg?.cacheStablePrompts !== false);
|
|
31223
32050
|
const messagesRef = useRef7(
|
|
31224
32051
|
makePrefixMessages(cacheStableRef.current, cfg?.model ?? DEFAULT_MODEL, "edit", ALL_TOOLS)
|
|
@@ -31242,6 +32069,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31242
32069
|
const compiledContextRef = useRef7(initialCfg?.compiledContext === true);
|
|
31243
32070
|
const updateNudgedRef = useRef7(false);
|
|
31244
32071
|
const compactSuggestedRef = useRef7(false);
|
|
32072
|
+
const freshSuggestedRef = useRef7(false);
|
|
31245
32073
|
const mcpManagerRef = useRef7(new McpManager());
|
|
31246
32074
|
const mcpToolsRef = useRef7([]);
|
|
31247
32075
|
const mcpInitRef = useRef7(false);
|
|
@@ -31262,6 +32090,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31262
32090
|
const sessionPlanRef = useRef7(null);
|
|
31263
32091
|
const sessionMgr = useSessionManager({
|
|
31264
32092
|
cfg,
|
|
32093
|
+
mode,
|
|
31265
32094
|
messagesRef,
|
|
31266
32095
|
sessionStateRef,
|
|
31267
32096
|
artifactStoreRef,
|
|
@@ -31297,7 +32126,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31297
32126
|
const customCommandsRef = useRef7([]);
|
|
31298
32127
|
const recentFilesRef = useRef7(/* @__PURE__ */ new Map());
|
|
31299
32128
|
const MAX_RECENT_FILES = 10;
|
|
31300
|
-
const allSlashCommands =
|
|
32129
|
+
const allSlashCommands = React25.useMemo(() => {
|
|
31301
32130
|
const customs = customCommandsRef.current.filter((c) => !BUILTIN_COMMAND_NAMES.has(c.name.toLowerCase())).map((c) => ({
|
|
31302
32131
|
name: c.name,
|
|
31303
32132
|
description: c.description ?? "",
|
|
@@ -31663,7 +32492,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31663
32492
|
[cfg]
|
|
31664
32493
|
);
|
|
31665
32494
|
const interruptDepsRef = useRef7(null);
|
|
31666
|
-
|
|
32495
|
+
useInput21((inputChar, key) => {
|
|
31667
32496
|
if (key.ctrl && inputChar === "c") {
|
|
31668
32497
|
logger.info("input:ctrl+c", {
|
|
31669
32498
|
busy: busyRef.current,
|
|
@@ -31933,69 +32762,6 @@ ${wcagWarnings.join("\n")}` }
|
|
|
31933
32762
|
},
|
|
31934
32763
|
[mkKey, setShowUiPicker]
|
|
31935
32764
|
);
|
|
31936
|
-
const handlePlanCompletePick = useCallback10(
|
|
31937
|
-
(picked) => {
|
|
31938
|
-
setShowPlanCompletePicker(false);
|
|
31939
|
-
if (!picked || picked === "continue") return;
|
|
31940
|
-
const plan = sessionPlanRef.current ?? distillSessionPlan(messagesRef.current);
|
|
31941
|
-
if (!plan) {
|
|
31942
|
-
setEvents((e) => [
|
|
31943
|
-
...e,
|
|
31944
|
-
{ kind: "error", key: mkKey(), text: "No plan found to start fresh with." }
|
|
31945
|
-
]);
|
|
31946
|
-
setMode(picked);
|
|
31947
|
-
return;
|
|
31948
|
-
}
|
|
31949
|
-
const clipResult = writeToClipboard(plan);
|
|
31950
|
-
if (cacheStableRef.current && messagesRef.current.length >= 2) {
|
|
31951
|
-
messagesRef.current = [messagesRef.current[0], messagesRef.current[1]];
|
|
31952
|
-
} else {
|
|
31953
|
-
messagesRef.current = [messagesRef.current[0]];
|
|
31954
|
-
}
|
|
31955
|
-
resetSession();
|
|
31956
|
-
executorRef.current.clearArtifacts();
|
|
31957
|
-
if (flushTimeoutRef.current) {
|
|
31958
|
-
clearTimeout(flushTimeoutRef.current);
|
|
31959
|
-
flushTimeoutRef.current = null;
|
|
31960
|
-
}
|
|
31961
|
-
pendingTextRef.current.clear();
|
|
31962
|
-
activeAsstIdRef.current = null;
|
|
31963
|
-
pendingToolCallsRef.current.clear();
|
|
31964
|
-
usageRef.current = null;
|
|
31965
|
-
turnCounterRef.current = 0;
|
|
31966
|
-
setEvents([]);
|
|
31967
|
-
setUsage(null);
|
|
31968
|
-
setSessionUsage(null);
|
|
31969
|
-
gatewayMetaRef.current = null;
|
|
31970
|
-
setGatewayMeta(null);
|
|
31971
|
-
clearTaskTracking();
|
|
31972
|
-
compactSuggestedRef.current = false;
|
|
31973
|
-
updateNudgedRef.current = false;
|
|
31974
|
-
sessionPlanRef.current = null;
|
|
31975
|
-
setEvents((e) => [
|
|
31976
|
-
...e,
|
|
31977
|
-
{
|
|
31978
|
-
kind: "info",
|
|
31979
|
-
key: mkKey(),
|
|
31980
|
-
text: clipResult.success ? `Plan copied to clipboard. Starting fresh session in ${picked} mode with plan only\u2026` : `Clipboard unavailable. Starting fresh session in ${picked} mode with plan only\u2026`
|
|
31981
|
-
}
|
|
31982
|
-
]);
|
|
31983
|
-
if (!clipResult.success) {
|
|
31984
|
-
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "--- Plan ---\n" + plan }]);
|
|
31985
|
-
}
|
|
31986
|
-
setMode(picked);
|
|
31987
|
-
modeRef.current = picked;
|
|
31988
|
-
rebuildSystemPromptForMode(
|
|
31989
|
-
messagesRef.current,
|
|
31990
|
-
cacheStableRef.current,
|
|
31991
|
-
cfg?.model ?? DEFAULT_MODEL,
|
|
31992
|
-
picked,
|
|
31993
|
-
[...ALL_TOOLS, ...mcpToolsRef.current, ...lspToolsRef.current]
|
|
31994
|
-
);
|
|
31995
|
-
submitRef.current(plan);
|
|
31996
|
-
},
|
|
31997
|
-
[mkKey, setShowPlanCompletePicker, setMode, setEvents, setUsage, setSessionUsage, setGatewayMeta, clearTaskTracking, resetSession, submitRef]
|
|
31998
|
-
);
|
|
31999
32765
|
const handleModelPick = useCallback10(
|
|
32000
32766
|
(picked) => {
|
|
32001
32767
|
setShowModelPicker(false);
|
|
@@ -32170,6 +32936,10 @@ ${wcagWarnings.join("\n")}` }
|
|
|
32170
32936
|
setShowGatewayPicker,
|
|
32171
32937
|
setShowSkillsPicker,
|
|
32172
32938
|
setShowShellPicker,
|
|
32939
|
+
setShowChangelogImagePicker,
|
|
32940
|
+
setChangelogImageRepo,
|
|
32941
|
+
setTasks: turn.setTasks,
|
|
32942
|
+
setTasksStartedAt: turn.setTasksStartedAt,
|
|
32173
32943
|
lspScope,
|
|
32174
32944
|
lspProjectPath,
|
|
32175
32945
|
resetSession,
|
|
@@ -32200,6 +32970,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
32200
32970
|
sessionIdRef,
|
|
32201
32971
|
compactSuggestedRef,
|
|
32202
32972
|
updateNudgedRef,
|
|
32973
|
+
freshSuggestedRef,
|
|
32203
32974
|
memoryManagerRef,
|
|
32204
32975
|
artifactStoreRef,
|
|
32205
32976
|
sessionStateRef,
|
|
@@ -32234,12 +33005,16 @@ ${wcagWarnings.join("\n")}` }
|
|
|
32234
33005
|
setShowGatewayPicker,
|
|
32235
33006
|
setShowSkillsPicker,
|
|
32236
33007
|
setShowShellPicker,
|
|
33008
|
+
setShowChangelogImagePicker,
|
|
33009
|
+
setChangelogImageRepo,
|
|
32237
33010
|
setShowLspWizard,
|
|
32238
33011
|
setShowRemoteDashboard,
|
|
32239
33012
|
setShowCommandList,
|
|
32240
33013
|
setCommandWizard,
|
|
32241
33014
|
setCommandPicker,
|
|
32242
33015
|
turn.setShowReasoning,
|
|
33016
|
+
turn.setTasks,
|
|
33017
|
+
turn.setTasksStartedAt,
|
|
32243
33018
|
resetSession,
|
|
32244
33019
|
clearTaskTracking,
|
|
32245
33020
|
openResumePicker,
|
|
@@ -32249,8 +33024,39 @@ ${wcagWarnings.join("\n")}` }
|
|
|
32249
33024
|
initLsp2,
|
|
32250
33025
|
ensureSessionId
|
|
32251
33026
|
]);
|
|
33027
|
+
const handlePlanCompletePick = useCallback10(
|
|
33028
|
+
(picked) => {
|
|
33029
|
+
setShowPlanCompletePicker(false);
|
|
33030
|
+
if (!picked || picked === "continue") return;
|
|
33031
|
+
const plan = sessionPlanRef.current ?? distillSessionPlan(messagesRef.current);
|
|
33032
|
+
if (!plan) {
|
|
33033
|
+
setEvents((e) => [
|
|
33034
|
+
...e,
|
|
33035
|
+
{ kind: "error", key: mkKey(), text: "No plan found to start fresh with." }
|
|
33036
|
+
]);
|
|
33037
|
+
setMode(picked);
|
|
33038
|
+
return;
|
|
33039
|
+
}
|
|
33040
|
+
const clipResult = executeFreshStart(buildSlashContext(), plan, picked);
|
|
33041
|
+
setEvents((e) => [
|
|
33042
|
+
...e,
|
|
33043
|
+
{
|
|
33044
|
+
kind: "info",
|
|
33045
|
+
key: mkKey(),
|
|
33046
|
+
text: clipResult.success ? `Plan copied to clipboard. Starting fresh session in ${picked} mode with plan only\u2026` : `Clipboard unavailable. Starting fresh session in ${picked} mode with plan only\u2026`
|
|
33047
|
+
}
|
|
33048
|
+
]);
|
|
33049
|
+
if (!clipResult.success) {
|
|
33050
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "--- Plan ---\n" + plan }]);
|
|
33051
|
+
}
|
|
33052
|
+
setMode(picked);
|
|
33053
|
+
modeRef.current = picked;
|
|
33054
|
+
submitRef.current(plan);
|
|
33055
|
+
},
|
|
33056
|
+
[mkKey, setShowPlanCompletePicker, setMode, setEvents, submitRef, buildSlashContext]
|
|
33057
|
+
);
|
|
32252
33058
|
const handleSlash = useCallback10(
|
|
32253
|
-
(cmd) => dispatchSlashCommand(buildSlashContext(), cmd),
|
|
33059
|
+
async (cmd) => dispatchSlashCommand(buildSlashContext(), cmd),
|
|
32254
33060
|
[buildSlashContext]
|
|
32255
33061
|
);
|
|
32256
33062
|
const handleCommandSave2 = useCallback10(
|
|
@@ -32303,7 +33109,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
32303
33109
|
if (trimmed.startsWith("/")) {
|
|
32304
33110
|
const head = trimmed.split(/\s+/)[0].toLowerCase();
|
|
32305
33111
|
const selfManaged = ["/compact", "/init"].includes(head);
|
|
32306
|
-
if (handleSlash(trimmed)) {
|
|
33112
|
+
if (await handleSlash(trimmed)) {
|
|
32307
33113
|
if (!selfManaged) {
|
|
32308
33114
|
endTurn();
|
|
32309
33115
|
}
|
|
@@ -32422,12 +33228,68 @@ ${wcagWarnings.join("\n")}` }
|
|
|
32422
33228
|
}
|
|
32423
33229
|
}
|
|
32424
33230
|
turnCounterRef.current += 1;
|
|
32425
|
-
if (turnCounterRef.current % 15 === 0 && existsSync8(
|
|
33231
|
+
if (turnCounterRef.current % 15 === 0 && existsSync8(join38(process.cwd(), "KIMI.md")) && !kimiMdStale) {
|
|
32426
33232
|
setEvents((e) => [
|
|
32427
33233
|
...e,
|
|
32428
33234
|
{ kind: "info", key: mkKey(), text: "Tip: Rerunning /init occasionally helps KimiFlare stay accurate as your project evolves." }
|
|
32429
33235
|
]);
|
|
32430
33236
|
}
|
|
33237
|
+
const autoFreshThreshold = cfg?.autoFreshSuggestionTurns ?? DEFAULT_AUTO_FRESH_SUGGESTION_TURNS;
|
|
33238
|
+
if (autoFreshThreshold > 0 && turnCounterRef.current >= autoFreshThreshold && (modeRef.current === "auto" || modeRef.current === "edit" || modeRef.current === "multi-agent-experimental") && !freshSuggestedRef.current) {
|
|
33239
|
+
freshSuggestedRef.current = true;
|
|
33240
|
+
if (cfg?.autoFreshEnabled) {
|
|
33241
|
+
void (async () => {
|
|
33242
|
+
try {
|
|
33243
|
+
const turnIndex = messagesRef.current.length;
|
|
33244
|
+
if (turnIndex > 0) {
|
|
33245
|
+
const cp = {
|
|
33246
|
+
id: `cp_prefresh_${Date.now()}`,
|
|
33247
|
+
label: "pre-fresh auto-save",
|
|
33248
|
+
turnIndex,
|
|
33249
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
33250
|
+
sessionState: compiledContextRef.current ? sessionStateRef.current : void 0,
|
|
33251
|
+
artifactStore: serializeArtifactStore(artifactStoreRef.current)
|
|
33252
|
+
};
|
|
33253
|
+
ensureSessionId();
|
|
33254
|
+
const { sessionsDir: sessionsDir3 } = await Promise.resolve().then(() => (init_sessions(), sessions_exports));
|
|
33255
|
+
const filePath = join38(sessionsDir3(), `${sessionIdRef.current}.json`);
|
|
33256
|
+
await addCheckpoint(filePath, cp);
|
|
33257
|
+
}
|
|
33258
|
+
const summary = await generateContinuationSummary({
|
|
33259
|
+
messages: messagesRef.current,
|
|
33260
|
+
mode: modeRef.current,
|
|
33261
|
+
accountId: cfg.accountId,
|
|
33262
|
+
apiToken: cfg.apiToken,
|
|
33263
|
+
model: cfg.plumbingModel ?? "@cf/moonshotai/kimi-k2.5",
|
|
33264
|
+
gateway: gatewayFromConfig(cfg),
|
|
33265
|
+
memoryManager: memoryManagerRef.current,
|
|
33266
|
+
memoryEnabled: cfg.memoryEnabled
|
|
33267
|
+
});
|
|
33268
|
+
if (summary) {
|
|
33269
|
+
executeFreshStart(buildSlashContext(), summary);
|
|
33270
|
+
setEvents((e) => [
|
|
33271
|
+
...e,
|
|
33272
|
+
{ kind: "info", key: mkKey(), text: "Auto-fresh triggered: starting new session with continuation context\u2026" }
|
|
33273
|
+
]);
|
|
33274
|
+
}
|
|
33275
|
+
} catch (e) {
|
|
33276
|
+
setEvents((es) => [
|
|
33277
|
+
...es,
|
|
33278
|
+
{ kind: "error", key: mkKey(), text: `Auto-fresh failed: ${e.message}` }
|
|
33279
|
+
]);
|
|
33280
|
+
}
|
|
33281
|
+
})();
|
|
33282
|
+
} else {
|
|
33283
|
+
setEvents((e) => [
|
|
33284
|
+
...e,
|
|
33285
|
+
{
|
|
33286
|
+
kind: "info",
|
|
33287
|
+
key: mkKey(),
|
|
33288
|
+
text: `Session has run for ${turnCounterRef.current} turns. The model may slow down with accumulated context. Run /fresh to continue with a summarized state, or /compact to compress history.`
|
|
33289
|
+
}
|
|
33290
|
+
]);
|
|
33291
|
+
}
|
|
33292
|
+
}
|
|
32431
33293
|
gatewayMetaRef.current = null;
|
|
32432
33294
|
setGatewayMeta(null);
|
|
32433
33295
|
setIntentTier(classification.tier);
|
|
@@ -32749,7 +33611,7 @@ ${conflicts.join("\n")}` }
|
|
|
32749
33611
|
lspManagerRef.current.notifyChange(path, content2);
|
|
32750
33612
|
} else {
|
|
32751
33613
|
void import("fs/promises").then(
|
|
32752
|
-
({ readFile:
|
|
33614
|
+
({ readFile: readFile23 }) => readFile23(path, "utf8").then((c) => lspManagerRef.current.notifyChange(path, c)).catch(() => {
|
|
32753
33615
|
})
|
|
32754
33616
|
);
|
|
32755
33617
|
}
|
|
@@ -32967,7 +33829,7 @@ ${conflicts.join("\n")}` }
|
|
|
32967
33829
|
});
|
|
32968
33830
|
}, [usage, modelContextLimit, busy, runCompact2]);
|
|
32969
33831
|
if (!cfg) {
|
|
32970
|
-
return /* @__PURE__ */
|
|
33832
|
+
return /* @__PURE__ */ jsx44(ThemeProvider, { theme, children: /* @__PURE__ */ jsx44(
|
|
32971
33833
|
Onboarding,
|
|
32972
33834
|
{
|
|
32973
33835
|
onCancel: () => exit(),
|
|
@@ -32982,7 +33844,7 @@ ${conflicts.join("\n")}` }
|
|
|
32982
33844
|
) });
|
|
32983
33845
|
}
|
|
32984
33846
|
if (planOptions !== null) {
|
|
32985
|
-
return /* @__PURE__ */
|
|
33847
|
+
return /* @__PURE__ */ jsx44(ThemeProvider, { theme, children: /* @__PURE__ */ jsx44(Box42, { flexDirection: "column", children: /* @__PURE__ */ jsx44(
|
|
32986
33848
|
PlanOptionsPicker,
|
|
32987
33849
|
{
|
|
32988
33850
|
options: planOptions,
|
|
@@ -33012,7 +33874,7 @@ ${conflicts.join("\n")}` }
|
|
|
33012
33874
|
) }) });
|
|
33013
33875
|
}
|
|
33014
33876
|
if (checkpointSession !== null) {
|
|
33015
|
-
return /* @__PURE__ */
|
|
33877
|
+
return /* @__PURE__ */ jsx44(ThemeProvider, { theme, children: /* @__PURE__ */ jsx44(Box42, { flexDirection: "column", children: /* @__PURE__ */ jsx44(
|
|
33016
33878
|
CheckpointPicker,
|
|
33017
33879
|
{
|
|
33018
33880
|
session: checkpointSession,
|
|
@@ -33022,10 +33884,10 @@ ${conflicts.join("\n")}` }
|
|
|
33022
33884
|
) }) });
|
|
33023
33885
|
}
|
|
33024
33886
|
if (resumeSessions !== null) {
|
|
33025
|
-
return /* @__PURE__ */
|
|
33887
|
+
return /* @__PURE__ */ jsx44(ThemeProvider, { theme, children: /* @__PURE__ */ jsx44(Box42, { flexDirection: "column", children: /* @__PURE__ */ jsx44(ResumePicker, { sessions: resumeSessions, onPick: handleResumePick }) }) });
|
|
33026
33888
|
}
|
|
33027
33889
|
if (hasFullscreenModal) {
|
|
33028
|
-
return /* @__PURE__ */
|
|
33890
|
+
return /* @__PURE__ */ jsx44(
|
|
33029
33891
|
ModalHost,
|
|
33030
33892
|
{
|
|
33031
33893
|
modals,
|
|
@@ -33036,7 +33898,7 @@ ${conflicts.join("\n")}` }
|
|
|
33036
33898
|
onCommandDelete: handleCommandDelete2,
|
|
33037
33899
|
lspServers: cfg?.lspServers ?? {},
|
|
33038
33900
|
lspScope,
|
|
33039
|
-
hasProjectDir: existsSync8(
|
|
33901
|
+
hasProjectDir: existsSync8(join38(process.cwd(), ".kimiflare")),
|
|
33040
33902
|
onLspSave: handleLspSave2,
|
|
33041
33903
|
themes: themeList(),
|
|
33042
33904
|
onPickTheme: handleThemePick,
|
|
@@ -33164,14 +34026,80 @@ ${conflicts.join("\n")}` }
|
|
|
33164
34026
|
}
|
|
33165
34027
|
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: `Type /skills ${action} <name> to ${action} a skill.` }]);
|
|
33166
34028
|
},
|
|
33167
|
-
onSkillsDone: () => setShowSkillsPicker(false)
|
|
34029
|
+
onSkillsDone: () => setShowSkillsPicker(false),
|
|
34030
|
+
changelogImageRepo,
|
|
34031
|
+
onChangelogImageGenerate: (owner, repo, days) => {
|
|
34032
|
+
setShowChangelogImagePicker(false);
|
|
34033
|
+
const asstId = mkAssistantId();
|
|
34034
|
+
setEvents((e) => [
|
|
34035
|
+
...e,
|
|
34036
|
+
{
|
|
34037
|
+
kind: "assistant",
|
|
34038
|
+
key: `asst_${asstId}`,
|
|
34039
|
+
id: asstId,
|
|
34040
|
+
text: `Generating changelog image for ${owner}/${repo} (last ${days} day${days === 1 ? "" : "s"})\u2026`,
|
|
34041
|
+
reasoning: "",
|
|
34042
|
+
streaming: true
|
|
34043
|
+
}
|
|
34044
|
+
]);
|
|
34045
|
+
const taskList = [
|
|
34046
|
+
{ id: "fetch-prs", title: "Fetch merged PRs", status: "pending" },
|
|
34047
|
+
{ id: "fetch-release", title: "Fetch latest release", status: "pending" },
|
|
34048
|
+
{ id: "summarize", title: "Summarize with LLM", status: "pending" },
|
|
34049
|
+
{ id: "render", title: "Render changelog image", status: "pending" },
|
|
34050
|
+
{ id: "save", title: "Save PNG file", status: "pending" }
|
|
34051
|
+
];
|
|
34052
|
+
turn.setTasks(taskList);
|
|
34053
|
+
turn.setTasksStartedAt(Date.now());
|
|
34054
|
+
const updateTask = (id, status) => {
|
|
34055
|
+
turn.setTasks((prev) => prev.map((t) => t.id === id ? { ...t, status } : t));
|
|
34056
|
+
};
|
|
34057
|
+
setTimeout(() => {
|
|
34058
|
+
void (async () => {
|
|
34059
|
+
try {
|
|
34060
|
+
updateTask("fetch-prs", "in_progress");
|
|
34061
|
+
updateTask("fetch-release", "in_progress");
|
|
34062
|
+
const { changelogImageTool: changelogImageTool2 } = await Promise.resolve().then(() => (init_changelog_image(), changelog_image_exports));
|
|
34063
|
+
const result = await changelogImageTool2.run({ owner, repo, days }, {
|
|
34064
|
+
cwd: process.cwd(),
|
|
34065
|
+
githubToken: cfg?.githubOAuthToken,
|
|
34066
|
+
accountId: cfg?.accountId,
|
|
34067
|
+
apiToken: cfg?.apiToken,
|
|
34068
|
+
model: cfg?.model,
|
|
34069
|
+
gateway: gatewayFromConfig(cfg)
|
|
34070
|
+
});
|
|
34071
|
+
updateTask("fetch-prs", "completed");
|
|
34072
|
+
updateTask("fetch-release", "completed");
|
|
34073
|
+
updateTask("summarize", "completed");
|
|
34074
|
+
updateTask("render", "completed");
|
|
34075
|
+
updateTask("save", "completed");
|
|
34076
|
+
const text = typeof result === "string" ? result : result.content;
|
|
34077
|
+
setEvents(
|
|
34078
|
+
(e) => e.map(
|
|
34079
|
+
(ev) => ev.kind === "assistant" && ev.id === asstId ? { ...ev, text, streaming: false } : ev
|
|
34080
|
+
)
|
|
34081
|
+
);
|
|
34082
|
+
} catch (err) {
|
|
34083
|
+
const msg = `changelog-image failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
34084
|
+
setEvents(
|
|
34085
|
+
(e) => e.map(
|
|
34086
|
+
(ev) => ev.kind === "assistant" && ev.id === asstId ? { ...ev, text: msg, streaming: false } : ev
|
|
34087
|
+
)
|
|
34088
|
+
);
|
|
34089
|
+
} finally {
|
|
34090
|
+
turn.setTasksStartedAt(null);
|
|
34091
|
+
}
|
|
34092
|
+
})();
|
|
34093
|
+
}, 0);
|
|
34094
|
+
},
|
|
34095
|
+
onChangelogImageCancel: () => setShowChangelogImagePicker(false)
|
|
33168
34096
|
}
|
|
33169
34097
|
);
|
|
33170
34098
|
}
|
|
33171
34099
|
const hasConversation = events.some((e) => e.kind === "user" || e.kind === "assistant");
|
|
33172
|
-
return /* @__PURE__ */
|
|
33173
|
-
!hasConversation && events.length === 0 ? /* @__PURE__ */
|
|
33174
|
-
perm ? /* @__PURE__ */
|
|
34100
|
+
return /* @__PURE__ */ jsx44(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs42(Box42, { flexDirection: "column", children: [
|
|
34101
|
+
!hasConversation && events.length === 0 ? /* @__PURE__ */ jsx44(Welcome, {}) : /* @__PURE__ */ jsx44(ChatView, { events, showReasoning, verbose, intentTier: intentTier ?? void 0 }),
|
|
34102
|
+
perm ? /* @__PURE__ */ jsx44(
|
|
33175
34103
|
PermissionModal,
|
|
33176
34104
|
{
|
|
33177
34105
|
tool: perm.tool,
|
|
@@ -33181,7 +34109,7 @@ ${conflicts.join("\n")}` }
|
|
|
33181
34109
|
submitRef.current(text);
|
|
33182
34110
|
}
|
|
33183
34111
|
}
|
|
33184
|
-
) : limitModal || loopModal ? /* @__PURE__ */
|
|
34112
|
+
) : limitModal || loopModal ? /* @__PURE__ */ jsx44(
|
|
33185
34113
|
ModalOverlay,
|
|
33186
34114
|
{
|
|
33187
34115
|
modals,
|
|
@@ -33192,9 +34120,9 @@ ${conflicts.join("\n")}` }
|
|
|
33192
34120
|
loopResolveRef.current = null;
|
|
33193
34121
|
}
|
|
33194
34122
|
}
|
|
33195
|
-
) : showPlanCompletePicker ? /* @__PURE__ */
|
|
33196
|
-
(activeWorkers.length > 0 || coordinatorNarration) && /* @__PURE__ */
|
|
33197
|
-
tasks.length > 0 && /* @__PURE__ */
|
|
34123
|
+
) : showPlanCompletePicker ? /* @__PURE__ */ jsx44(PlanCompletePicker, { onPick: handlePlanCompletePick }) : /* @__PURE__ */ jsxs42(Box42, { flexDirection: "column", marginTop: 1, children: [
|
|
34124
|
+
(activeWorkers.length > 0 || coordinatorNarration) && /* @__PURE__ */ jsx44(WorkerList, { workers: activeWorkers, isSynthesizing, narration: coordinatorNarration }),
|
|
34125
|
+
tasks.length > 0 && /* @__PURE__ */ jsx44(
|
|
33198
34126
|
TaskList,
|
|
33199
34127
|
{
|
|
33200
34128
|
tasks,
|
|
@@ -33202,11 +34130,11 @@ ${conflicts.join("\n")}` }
|
|
|
33202
34130
|
tokensDelta: Math.max(0, (usage?.prompt_tokens ?? 0) - tasksStartTokens)
|
|
33203
34131
|
}
|
|
33204
34132
|
),
|
|
33205
|
-
queue2.length > 0 && /* @__PURE__ */
|
|
34133
|
+
queue2.length > 0 && /* @__PURE__ */ jsx44(Box42, { flexDirection: "column", marginBottom: 1, children: queue2.map((q, i) => /* @__PURE__ */ jsxs42(Text43, { color: theme.info.color, dimColor: theme.info.dim, children: [
|
|
33206
34134
|
"\u23F3 ",
|
|
33207
34135
|
q.display
|
|
33208
34136
|
] }, `queue_${i}`)) }),
|
|
33209
|
-
/* @__PURE__ */
|
|
34137
|
+
/* @__PURE__ */ jsx44(
|
|
33210
34138
|
StatusBar,
|
|
33211
34139
|
{
|
|
33212
34140
|
usage,
|
|
@@ -33228,7 +34156,7 @@ ${conflicts.join("\n")}` }
|
|
|
33228
34156
|
intentTier: intentTier ?? void 0
|
|
33229
34157
|
}
|
|
33230
34158
|
),
|
|
33231
|
-
picker.active?.kind === "file" && /* @__PURE__ */
|
|
34159
|
+
picker.active?.kind === "file" && /* @__PURE__ */ jsx44(
|
|
33232
34160
|
FilePicker,
|
|
33233
34161
|
{
|
|
33234
34162
|
items: picker.fileItems,
|
|
@@ -33237,7 +34165,7 @@ ${conflicts.join("\n")}` }
|
|
|
33237
34165
|
recentFiles: new Set(recentFilesRef.current.keys())
|
|
33238
34166
|
}
|
|
33239
34167
|
),
|
|
33240
|
-
picker.active?.kind === "slash" && /* @__PURE__ */
|
|
34168
|
+
picker.active?.kind === "slash" && /* @__PURE__ */ jsx44(
|
|
33241
34169
|
SlashPicker,
|
|
33242
34170
|
{
|
|
33243
34171
|
items: picker.slashItems,
|
|
@@ -33245,9 +34173,9 @@ ${conflicts.join("\n")}` }
|
|
|
33245
34173
|
query: picker.query
|
|
33246
34174
|
}
|
|
33247
34175
|
),
|
|
33248
|
-
/* @__PURE__ */
|
|
33249
|
-
/* @__PURE__ */
|
|
33250
|
-
/* @__PURE__ */
|
|
34176
|
+
/* @__PURE__ */ jsxs42(Box42, { marginTop: 1, children: [
|
|
34177
|
+
/* @__PURE__ */ jsx44(Text43, { color: theme.prompt ?? theme.accent, children: "\u203A " }),
|
|
34178
|
+
/* @__PURE__ */ jsx44(
|
|
33251
34179
|
CustomTextInput,
|
|
33252
34180
|
{
|
|
33253
34181
|
value: input,
|
|
@@ -33304,7 +34232,7 @@ ${conflicts.join("\n")}` }
|
|
|
33304
34232
|
}
|
|
33305
34233
|
async function renderApp(cfg, updateResult, lspScope = "global", lspProjectPath = null) {
|
|
33306
34234
|
const instance = render(
|
|
33307
|
-
/* @__PURE__ */
|
|
34235
|
+
/* @__PURE__ */ jsx44(
|
|
33308
34236
|
App,
|
|
33309
34237
|
{
|
|
33310
34238
|
initialCfg: cfg,
|
|
@@ -33383,12 +34311,12 @@ var init_app = __esm({
|
|
|
33383
34311
|
init_use_turn_controller();
|
|
33384
34312
|
init_input_handlers();
|
|
33385
34313
|
init_slash_commands();
|
|
34314
|
+
init_continuation_summary();
|
|
33386
34315
|
init_run_init();
|
|
33387
34316
|
init_run_startup_tasks();
|
|
33388
34317
|
init_manager_init();
|
|
33389
34318
|
init_run_compact();
|
|
33390
34319
|
init_distill();
|
|
33391
|
-
init_clipboard();
|
|
33392
34320
|
init_command_handlers();
|
|
33393
34321
|
init_app_helpers();
|
|
33394
34322
|
}
|