kimiflare 0.77.0 → 0.79.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 +301 -45
- package/dist/index.js.map +1 -1
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11985,7 +11985,7 @@ var init_supervisor = __esm({
|
|
|
11985
11985
|
* Future: the coordinator will call this automatically when intent classification
|
|
11986
11986
|
* signals a "heavy" task (see docs/plans/multi-agent-standalone-workers-plan.md).
|
|
11987
11987
|
*/
|
|
11988
|
-
async spawnWorkers(workers, onUpdate) {
|
|
11988
|
+
async spawnWorkers(workers, onUpdate, signal) {
|
|
11989
11989
|
const cfg = await loadConfig().catch(() => null);
|
|
11990
11990
|
const endpoint = process.env.KIMIFLARE_WORKER_ENDPOINT ?? cfg?.workerEndpoint ?? cfg?.remoteWorkerUrl;
|
|
11991
11991
|
if (!endpoint) {
|
|
@@ -12068,7 +12068,7 @@ var init_supervisor = __esm({
|
|
|
12068
12068
|
prBody: w.prBody
|
|
12069
12069
|
} : {}
|
|
12070
12070
|
};
|
|
12071
|
-
const timeoutMs = parseInt(process.env.KIMIFLARE_WORKER_TIMEOUT_MS ?? "
|
|
12071
|
+
const timeoutMs = parseInt(process.env.KIMIFLARE_WORKER_TIMEOUT_MS ?? "900000", 10);
|
|
12072
12072
|
worker.logs.push(`[coordinator] Sending payload (${JSON.stringify(payload).length} bytes)`);
|
|
12073
12073
|
worker.logs.push(`[coordinator] Worker will clone ${repo.owner}/${repo.repo} and run kimiflare inside Cloudflare Sandbox`);
|
|
12074
12074
|
worker.logs.push(`[coordinator] Typical runtime: 1\u20134 min. Timeout: ${Math.round(timeoutMs / 1e3)}s`);
|
|
@@ -12086,13 +12086,27 @@ var init_supervisor = __esm({
|
|
|
12086
12086
|
throw new Error(`Worker start failed: ${startRes.status} ${text.slice(0, 200)}`);
|
|
12087
12087
|
}
|
|
12088
12088
|
const { workerId: remoteWorkerId } = await startRes.json();
|
|
12089
|
+
worker.remoteWorkerId = remoteWorkerId;
|
|
12089
12090
|
worker.logs.push(`[coordinator] Worker started (id: ${remoteWorkerId}) \u2014 polling for progress\u2026`);
|
|
12090
12091
|
onUpdate?.([...activeWorkers.values()]);
|
|
12091
12092
|
const pollInterval = 3e3;
|
|
12092
12093
|
const startTime = Date.now();
|
|
12093
12094
|
let lastLogCount = 0;
|
|
12095
|
+
let lastStep = "";
|
|
12094
12096
|
let data;
|
|
12095
12097
|
while (Date.now() - startTime < timeoutMs) {
|
|
12098
|
+
if (signal?.aborted) {
|
|
12099
|
+
worker.logs.push(`[coordinator] Cancelling worker (id: ${remoteWorkerId})\u2026`);
|
|
12100
|
+
onUpdate?.([...activeWorkers.values()]);
|
|
12101
|
+
try {
|
|
12102
|
+
await fetch(`${endpoint}/worker/${remoteWorkerId}/cancel`, {
|
|
12103
|
+
method: "POST",
|
|
12104
|
+
headers: apiKey ? { "X-Worker-Api-Key": apiKey } : {}
|
|
12105
|
+
});
|
|
12106
|
+
} catch {
|
|
12107
|
+
}
|
|
12108
|
+
throw new Error("Cancelled by user");
|
|
12109
|
+
}
|
|
12096
12110
|
await new Promise((r) => setTimeout(r, pollInterval));
|
|
12097
12111
|
let progressRes;
|
|
12098
12112
|
let lastPollErr;
|
|
@@ -12120,13 +12134,30 @@ var init_supervisor = __esm({
|
|
|
12120
12134
|
continue;
|
|
12121
12135
|
}
|
|
12122
12136
|
const progress = await progressRes.json();
|
|
12137
|
+
const allSteps = [];
|
|
12138
|
+
for (let i = 0; i < progress.totalSteps; i++) {
|
|
12139
|
+
const isCompleted = i < progress.completedSteps.length;
|
|
12140
|
+
const isActive = i === progress.stepIndex - 1 && !isCompleted && progress.status === "running";
|
|
12141
|
+
const isFailed = progress.status === "failed" && i === progress.stepIndex - 1;
|
|
12142
|
+
allSteps.push({
|
|
12143
|
+
label: progress.completedSteps[i] ?? progress.step,
|
|
12144
|
+
status: isFailed ? "failed" : isCompleted ? "completed" : isActive ? "active" : "pending"
|
|
12145
|
+
});
|
|
12146
|
+
}
|
|
12147
|
+
worker.steps = allSteps;
|
|
12123
12148
|
const newLogs = progress.logs.slice(lastLogCount);
|
|
12124
12149
|
lastLogCount = progress.logs.length;
|
|
12125
12150
|
for (const logLine of newLogs) {
|
|
12126
12151
|
worker.logs.push(`[worker] ${logLine}`);
|
|
12127
12152
|
}
|
|
12128
|
-
|
|
12129
|
-
|
|
12153
|
+
const stepKey = `${progress.stepIndex}:${progress.step}`;
|
|
12154
|
+
if (stepKey !== lastStep) {
|
|
12155
|
+
lastStep = stepKey;
|
|
12156
|
+
worker.logs.push(`[coordinator] Step ${progress.stepIndex}/${progress.totalSteps}: ${progress.message}`);
|
|
12157
|
+
onUpdate?.([...activeWorkers.values()]);
|
|
12158
|
+
} else if (newLogs.length > 0) {
|
|
12159
|
+
onUpdate?.([...activeWorkers.values()]);
|
|
12160
|
+
}
|
|
12130
12161
|
if (progress.status === "completed" || progress.status === "failed") {
|
|
12131
12162
|
if (progress.result) {
|
|
12132
12163
|
data = progress.result;
|
|
@@ -12155,6 +12186,13 @@ var init_supervisor = __esm({
|
|
|
12155
12186
|
worker.result = data;
|
|
12156
12187
|
worker.rawOutput = data.rawOutput;
|
|
12157
12188
|
worker.reasoning = data.reasoning;
|
|
12189
|
+
if (worker.steps && worker.steps.length > 0) {
|
|
12190
|
+
for (const s of worker.steps) {
|
|
12191
|
+
if (s.status === "pending" || s.status === "active") {
|
|
12192
|
+
s.status = worker.status === "completed" ? "completed" : "failed";
|
|
12193
|
+
}
|
|
12194
|
+
}
|
|
12195
|
+
}
|
|
12158
12196
|
worker.logs.push(`[coordinator] Worker finished with status: ${data.status}`);
|
|
12159
12197
|
if (data.phases && data.phases.length > 0) {
|
|
12160
12198
|
const timeline = data.phases.map((p) => `${p.name}: ${Math.round(p.ms / 1e3)}s`).join(" \xB7 ");
|
|
@@ -12272,11 +12310,21 @@ var init_supervisor = __esm({
|
|
|
12272
12310
|
*
|
|
12273
12311
|
* Returns the synthesized plan after all workers complete.
|
|
12274
12312
|
*/
|
|
12275
|
-
async autoSpawnWorkers(prompt, context, onUpdate, onPhaseChange) {
|
|
12313
|
+
async autoSpawnWorkers(prompt, context, onUpdate, onPhaseChange, signal, onNarration) {
|
|
12314
|
+
if (this._activeWorkers.size > 0) {
|
|
12315
|
+
throw new Error(
|
|
12316
|
+
`Multi-agent already active (${this._activeWorkers.size} worker(s) in flight). Wait for completion or cancel before starting a new heavy task.`
|
|
12317
|
+
);
|
|
12318
|
+
}
|
|
12276
12319
|
const workers = decomposePrompt(prompt, context);
|
|
12320
|
+
const narrationLines = [
|
|
12321
|
+
`Decomposing your request into ${workers.length} parallel research task${workers.length > 1 ? "s" : ""}:`,
|
|
12322
|
+
...workers.map((w, i) => ` ${i + 1}. ${w.task.slice(0, 200)}${w.task.length > 200 ? "\u2026" : ""}`)
|
|
12323
|
+
];
|
|
12324
|
+
onNarration?.(narrationLines.join("\n"));
|
|
12277
12325
|
onPhaseChange?.("spawning");
|
|
12278
12326
|
try {
|
|
12279
|
-
const results = await this.spawnWorkers(workers, onUpdate);
|
|
12327
|
+
const results = await this.spawnWorkers(workers, onUpdate, signal);
|
|
12280
12328
|
onPhaseChange?.("synthesizing");
|
|
12281
12329
|
const synth = this.synthesizeFindings(results);
|
|
12282
12330
|
const cfg = await loadConfig().catch(() => null);
|
|
@@ -12294,7 +12342,8 @@ var init_supervisor = __esm({
|
|
|
12294
12342
|
try {
|
|
12295
12343
|
const execResults = await this.spawnWorkers(
|
|
12296
12344
|
[{ mode: "execute", task: executeTask, context }],
|
|
12297
|
-
onUpdate
|
|
12345
|
+
onUpdate,
|
|
12346
|
+
signal
|
|
12298
12347
|
);
|
|
12299
12348
|
const exec2 = execResults[0];
|
|
12300
12349
|
if (!exec2) {
|
|
@@ -12719,6 +12768,70 @@ import { mkdtemp, readFile as readFile13, writeFile as writeFile10, rm } from "f
|
|
|
12719
12768
|
import { tmpdir as tmpdir3 } from "os";
|
|
12720
12769
|
import { join as join22 } from "path";
|
|
12721
12770
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
12771
|
+
async function cfApiFetch(accountId, apiToken, path, init) {
|
|
12772
|
+
const url = `${CF_API}/accounts/${encodeURIComponent(accountId)}${path}`;
|
|
12773
|
+
const res = await fetch(url, {
|
|
12774
|
+
...init,
|
|
12775
|
+
headers: {
|
|
12776
|
+
Authorization: `Bearer ${apiToken}`,
|
|
12777
|
+
"Content-Type": "application/json",
|
|
12778
|
+
"User-Agent": getUserAgent(),
|
|
12779
|
+
...init?.headers
|
|
12780
|
+
}
|
|
12781
|
+
});
|
|
12782
|
+
const json = await res.json();
|
|
12783
|
+
return json;
|
|
12784
|
+
}
|
|
12785
|
+
async function listDurableObjectNamespaces(accountId, apiToken) {
|
|
12786
|
+
const json = await cfApiFetch(
|
|
12787
|
+
accountId,
|
|
12788
|
+
apiToken,
|
|
12789
|
+
"/workers/durable_objects/namespaces"
|
|
12790
|
+
);
|
|
12791
|
+
if (!json.success || !json.result) {
|
|
12792
|
+
throw new Error(
|
|
12793
|
+
json.errors?.map((e) => e.message).join(", ") ?? "Failed to list DO namespaces"
|
|
12794
|
+
);
|
|
12795
|
+
}
|
|
12796
|
+
return json.result;
|
|
12797
|
+
}
|
|
12798
|
+
async function deleteDurableObjectNamespace(accountId, apiToken, namespaceId) {
|
|
12799
|
+
const json = await cfApiFetch(
|
|
12800
|
+
accountId,
|
|
12801
|
+
apiToken,
|
|
12802
|
+
`/workers/durable_objects/namespaces/${encodeURIComponent(namespaceId)}`,
|
|
12803
|
+
{ method: "DELETE" }
|
|
12804
|
+
);
|
|
12805
|
+
if (!json.success) {
|
|
12806
|
+
throw new Error(
|
|
12807
|
+
json.errors?.map((e) => e.message).join(", ") ?? "Failed to delete DO namespace"
|
|
12808
|
+
);
|
|
12809
|
+
}
|
|
12810
|
+
}
|
|
12811
|
+
async function listContainerApplications(accountId, apiToken) {
|
|
12812
|
+
const json = await cfApiFetch(
|
|
12813
|
+
accountId,
|
|
12814
|
+
apiToken,
|
|
12815
|
+
"/containers/applications"
|
|
12816
|
+
);
|
|
12817
|
+
if (!json.success || !json.result) {
|
|
12818
|
+
return [];
|
|
12819
|
+
}
|
|
12820
|
+
return json.result;
|
|
12821
|
+
}
|
|
12822
|
+
async function deleteContainerApplication(accountId, apiToken, appId) {
|
|
12823
|
+
const json = await cfApiFetch(
|
|
12824
|
+
accountId,
|
|
12825
|
+
apiToken,
|
|
12826
|
+
`/containers/applications/${encodeURIComponent(appId)}`,
|
|
12827
|
+
{ method: "DELETE" }
|
|
12828
|
+
);
|
|
12829
|
+
if (!json.success) {
|
|
12830
|
+
throw new Error(
|
|
12831
|
+
json.errors?.map((e) => e.message).join(", ") ?? "Failed to delete container application"
|
|
12832
|
+
);
|
|
12833
|
+
}
|
|
12834
|
+
}
|
|
12722
12835
|
function generateSecret2() {
|
|
12723
12836
|
return randomBytes2(32).toString("hex");
|
|
12724
12837
|
}
|
|
@@ -12991,21 +13104,23 @@ ${(install.stderr || install.stdout).slice(-1200).trim()}`,
|
|
|
12991
13104
|
`$1${finalKvId}$2`
|
|
12992
13105
|
);
|
|
12993
13106
|
toml = toml.replace(/\n\[\[artifacts\]\][\s\S]*?(?=\n\[|\n*$)/g, "\n");
|
|
12994
|
-
|
|
12995
|
-
|
|
12996
|
-
|
|
12997
|
-
|
|
12998
|
-
|
|
12999
|
-
|
|
13107
|
+
if (!workerExists) {
|
|
13108
|
+
const existingMigrations = toml.match(/\[\[migrations\]\]/);
|
|
13109
|
+
if (existingMigrations) {
|
|
13110
|
+
toml = toml.replace(
|
|
13111
|
+
/\[\[migrations\]\][\s\S]*?new_sqlite_classes\s*=\s*\[[^\]]*\]/,
|
|
13112
|
+
`[[migrations]]
|
|
13113
|
+
tag = "v1"
|
|
13000
13114
|
new_sqlite_classes = ["SessionDO", "WorkerDO", "Sandbox"]`
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13115
|
+
);
|
|
13116
|
+
} else {
|
|
13117
|
+
toml += `
|
|
13004
13118
|
# Auto-added by kimiflare /multi-agent \u2192 Set up (fresh deploy only)
|
|
13005
13119
|
[[migrations]]
|
|
13006
13120
|
tag = "v1"
|
|
13007
13121
|
new_sqlite_classes = ["SessionDO", "WorkerDO", "Sandbox"]
|
|
13008
13122
|
`;
|
|
13123
|
+
}
|
|
13009
13124
|
}
|
|
13010
13125
|
if (!/\[observability\.logs\]/.test(toml)) {
|
|
13011
13126
|
toml += `
|
|
@@ -13061,6 +13176,7 @@ invocation_logs = true
|
|
|
13061
13176
|
...cfg,
|
|
13062
13177
|
workerEndpoint: workerUrl,
|
|
13063
13178
|
workerApiKey,
|
|
13179
|
+
workerName,
|
|
13064
13180
|
multiAgentEnabled: true
|
|
13065
13181
|
};
|
|
13066
13182
|
await saveConfig(next);
|
|
@@ -13070,12 +13186,13 @@ invocation_logs = true
|
|
|
13070
13186
|
yield { message: "Setup complete \u2014 multi-agent is ready to use.", done: true };
|
|
13071
13187
|
return { workerEndpoint: workerUrl, workerApiKey };
|
|
13072
13188
|
}
|
|
13073
|
-
async function* teardownCommute() {
|
|
13189
|
+
async function* teardownCommute(opts2 = {}) {
|
|
13074
13190
|
const cfg = await loadConfig();
|
|
13075
13191
|
if (!cfg?.accountId || !cfg?.apiToken) {
|
|
13076
13192
|
yield { message: "Cloudflare credentials missing \u2014 nothing to tear down.", error: true };
|
|
13077
13193
|
throw new Error("missing CF creds");
|
|
13078
13194
|
}
|
|
13195
|
+
const workerName = opts2.workerName ?? cfg.workerName ?? WORKER_NAME;
|
|
13079
13196
|
const cfEnv = {
|
|
13080
13197
|
CLOUDFLARE_ACCOUNT_ID: cfg.accountId,
|
|
13081
13198
|
CLOUDFLARE_API_TOKEN: cfg.apiToken
|
|
@@ -13084,25 +13201,72 @@ async function* teardownCommute() {
|
|
|
13084
13201
|
yield { message: "wrangler not found. Install: npm install -g wrangler", error: true };
|
|
13085
13202
|
throw new Error("wrangler missing");
|
|
13086
13203
|
}
|
|
13087
|
-
yield { message: `Deleting Worker "${
|
|
13088
|
-
const del = await runCmd("wrangler", ["delete", "--name",
|
|
13204
|
+
yield { message: `Deleting Worker "${workerName}"\u2026` };
|
|
13205
|
+
const del = await runCmd("wrangler", ["delete", "--name", workerName], {
|
|
13089
13206
|
env: cfEnv,
|
|
13090
13207
|
input: "y\n",
|
|
13091
13208
|
timeoutMs: 6e4
|
|
13092
13209
|
});
|
|
13093
13210
|
if (del.code === 0) {
|
|
13094
|
-
yield { message: `Worker "${
|
|
13211
|
+
yield { message: `Worker "${workerName}" deleted`, ok: true };
|
|
13095
13212
|
} else {
|
|
13096
13213
|
const combined = (del.stdout + del.stderr).toLowerCase();
|
|
13097
13214
|
if (combined.includes("not found") || combined.includes("does not exist") || combined.includes("10007")) {
|
|
13098
13215
|
yield { message: "Worker not found (already deleted or never created)", ok: true };
|
|
13099
13216
|
} else {
|
|
13100
13217
|
yield {
|
|
13101
|
-
message: explainWranglerFailure(`wrangler delete --name ${
|
|
13218
|
+
message: explainWranglerFailure(`wrangler delete --name ${workerName}`, del.stdout, del.stderr),
|
|
13102
13219
|
error: true
|
|
13103
13220
|
};
|
|
13104
13221
|
}
|
|
13105
13222
|
}
|
|
13223
|
+
yield { message: `Looking up Durable Object namespaces for "${workerName}"\u2026` };
|
|
13224
|
+
try {
|
|
13225
|
+
const namespaces = await listDurableObjectNamespaces(cfg.accountId, cfg.apiToken);
|
|
13226
|
+
const targets = namespaces.filter(
|
|
13227
|
+
(ns) => ns.script === workerName || ns.name.startsWith(`${workerName}_`)
|
|
13228
|
+
);
|
|
13229
|
+
if (targets.length === 0) {
|
|
13230
|
+
yield { message: "No Durable Object namespaces found (nothing to delete)", ok: true };
|
|
13231
|
+
} else {
|
|
13232
|
+
for (const ns of targets) {
|
|
13233
|
+
try {
|
|
13234
|
+
await deleteDurableObjectNamespace(cfg.accountId, cfg.apiToken, ns.id);
|
|
13235
|
+
yield { message: `DO namespace ${ns.name} deleted (${ns.id.slice(0, 8)}\u2026)`, ok: true };
|
|
13236
|
+
} catch (err) {
|
|
13237
|
+
yield {
|
|
13238
|
+
message: `DO namespace ${ns.name} delete warning: ${err instanceof Error ? err.message : String(err)}`
|
|
13239
|
+
};
|
|
13240
|
+
}
|
|
13241
|
+
}
|
|
13242
|
+
}
|
|
13243
|
+
} catch (err) {
|
|
13244
|
+
yield {
|
|
13245
|
+
message: `DO namespace lookup warning: ${err instanceof Error ? err.message : String(err)}`
|
|
13246
|
+
};
|
|
13247
|
+
}
|
|
13248
|
+
yield { message: `Looking up container applications for "${workerName}"\u2026` };
|
|
13249
|
+
try {
|
|
13250
|
+
const apps = await listContainerApplications(cfg.accountId, cfg.apiToken);
|
|
13251
|
+
const appPrefix = `${workerName}-`.toLowerCase();
|
|
13252
|
+
const targets = apps.filter((app) => app.name.toLowerCase().startsWith(appPrefix));
|
|
13253
|
+
if (targets.length === 0) {
|
|
13254
|
+
yield { message: "No container applications found (nothing to delete)", ok: true };
|
|
13255
|
+
} else {
|
|
13256
|
+
for (const app of targets) {
|
|
13257
|
+
try {
|
|
13258
|
+
await deleteContainerApplication(cfg.accountId, cfg.apiToken, app.id);
|
|
13259
|
+
yield { message: `Container application ${app.name} deleted (${app.id.slice(0, 8)}\u2026)`, ok: true };
|
|
13260
|
+
} catch (err) {
|
|
13261
|
+
yield {
|
|
13262
|
+
message: `Container application ${app.name} delete warning: ${err instanceof Error ? err.message : String(err)}`
|
|
13263
|
+
};
|
|
13264
|
+
}
|
|
13265
|
+
}
|
|
13266
|
+
}
|
|
13267
|
+
} catch {
|
|
13268
|
+
yield { message: "(could not list container applications \u2014 skipping container cleanup)" };
|
|
13269
|
+
}
|
|
13106
13270
|
yield { message: "Listing KV namespaces to find OAUTH_KV\u2026" };
|
|
13107
13271
|
const kvList = await runCmd("wrangler", ["kv", "namespace", "list"], { env: cfEnv, timeoutMs: 3e4 });
|
|
13108
13272
|
if (kvList.code === 0) {
|
|
@@ -13136,6 +13300,7 @@ async function* teardownCommute() {
|
|
|
13136
13300
|
...cfg,
|
|
13137
13301
|
workerEndpoint: void 0,
|
|
13138
13302
|
workerApiKey: void 0,
|
|
13303
|
+
workerName: void 0,
|
|
13139
13304
|
multiAgentEnabled: false,
|
|
13140
13305
|
autoExecute: false
|
|
13141
13306
|
};
|
|
@@ -13143,15 +13308,17 @@ async function* teardownCommute() {
|
|
|
13143
13308
|
yield { message: "Local multi-agent config cleared", ok: true };
|
|
13144
13309
|
yield { message: "Tear-down complete \u2014 multi-agent is fully removed.", done: true };
|
|
13145
13310
|
}
|
|
13146
|
-
var COMMUTE_REPO, COMMUTE_BRANCH, WORKER_NAME, KV_TITLE, TOKEN_TEMPLATE_URL;
|
|
13311
|
+
var COMMUTE_REPO, COMMUTE_BRANCH, WORKER_NAME, KV_TITLE, CF_API, TOKEN_TEMPLATE_URL;
|
|
13147
13312
|
var init_deploy_commute = __esm({
|
|
13148
13313
|
"src/remote/deploy-commute.ts"() {
|
|
13149
13314
|
"use strict";
|
|
13150
13315
|
init_config();
|
|
13316
|
+
init_version();
|
|
13151
13317
|
COMMUTE_REPO = "https://github.com/sinameraji/kimiflare-commute.git";
|
|
13152
13318
|
COMMUTE_BRANCH = "main";
|
|
13153
13319
|
WORKER_NAME = "kimiflare-multi-agent";
|
|
13154
13320
|
KV_TITLE = "kimiflare-multi-agent-OAUTH_KV";
|
|
13321
|
+
CF_API = "https://api.cloudflare.com/client/v4";
|
|
13155
13322
|
TOKEN_TEMPLATE_URL = "https://dash.cloudflare.com/profile/api-tokens";
|
|
13156
13323
|
}
|
|
13157
13324
|
});
|
|
@@ -15588,7 +15755,7 @@ ${err instanceof Error ? err.message : err}`);
|
|
|
15588
15755
|
cam.send("AssistantStreamStarted", { stream_id: sid });
|
|
15589
15756
|
cam.send("AssistantTokenDelta", { stream_id: sid, token: "# Tearing down multi-agent\n\n" });
|
|
15590
15757
|
try {
|
|
15591
|
-
for await (const step of teardownCommute()) {
|
|
15758
|
+
for await (const step of teardownCommute({ workerName: cfg.workerName })) {
|
|
15592
15759
|
const prefix = step.error ? "\u2717 " : step.done || step.ok ? "\u2713 " : "\xB7 ";
|
|
15593
15760
|
cam.send("AssistantTokenDelta", { stream_id: sid, token: `${prefix}${step.message}
|
|
15594
15761
|
` });
|
|
@@ -20531,15 +20698,19 @@ import { useEffect as useEffect5, useState as useState9 } from "react";
|
|
|
20531
20698
|
import { Box as Box11, Text as Text12 } from "ink";
|
|
20532
20699
|
import Spinner5 from "ink-spinner";
|
|
20533
20700
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
20534
|
-
function WorkerList({ workers, isSynthesizing }) {
|
|
20701
|
+
function WorkerList({ workers, isSynthesizing, narration }) {
|
|
20535
20702
|
const theme = useTheme();
|
|
20536
|
-
if (workers.length === 0) return null;
|
|
20703
|
+
if (workers.length === 0 && !narration) return null;
|
|
20537
20704
|
const running = workers.filter((w) => w.status === "running").length;
|
|
20538
20705
|
const completed = workers.filter((w) => w.status === "completed").length;
|
|
20539
20706
|
const failed = workers.filter((w) => w.status === "failed").length;
|
|
20540
20707
|
const pending = workers.filter((w) => w.status === "pending").length;
|
|
20541
20708
|
const showSynthesis = isSynthesizing && running === 0;
|
|
20542
20709
|
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginBottom: 1, children: [
|
|
20710
|
+
narration && /* @__PURE__ */ jsx13(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, italic: true, children: narration.split("\n").map((line, i) => /* @__PURE__ */ jsxs11(Text12, { children: [
|
|
20711
|
+
line,
|
|
20712
|
+
"\n"
|
|
20713
|
+
] }, `narration-${i}`)) }) }),
|
|
20543
20714
|
/* @__PURE__ */ jsx13(Box11, { children: /* @__PURE__ */ jsxs11(Text12, { color: theme.accent, bold: true, children: [
|
|
20544
20715
|
"Workers: ",
|
|
20545
20716
|
pending > 0 ? `${pending} todo \xB7 ` : "",
|
|
@@ -20569,7 +20740,7 @@ function WorkerRow({ worker }) {
|
|
|
20569
20740
|
const statusIcon = worker.status === "pending" ? /* @__PURE__ */ jsx13(Text12, { color: theme.muted?.color ?? theme.info.color, children: "\u2610" }) : worker.status === "running" ? /* @__PURE__ */ jsx13(Text12, { color: theme.info.color, children: /* @__PURE__ */ jsx13(Spinner5, { type: "line" }) }) : worker.status === "completed" ? /* @__PURE__ */ jsx13(Text12, { color: theme.palette.success, children: "\u2611" }) : /* @__PURE__ */ jsx13(Text12, { color: theme.palette.error, children: "\u2612" });
|
|
20570
20741
|
const statusLabel = worker.status === "pending" ? "todo" : worker.status === "running" ? "ongoing" : worker.status === "completed" ? "done" : "failed";
|
|
20571
20742
|
const isDone = worker.status === "completed" || worker.status === "failed";
|
|
20572
|
-
const
|
|
20743
|
+
const hasSteps = worker.steps && worker.steps.length > 0;
|
|
20573
20744
|
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginLeft: 2, children: [
|
|
20574
20745
|
/* @__PURE__ */ jsx13(Box11, { children: /* @__PURE__ */ jsxs11(Text12, { children: [
|
|
20575
20746
|
statusIcon,
|
|
@@ -20602,7 +20773,37 @@ function WorkerRow({ worker }) {
|
|
|
20602
20773
|
worker.error.slice(0, 60)
|
|
20603
20774
|
] }) : null
|
|
20604
20775
|
] }) }),
|
|
20605
|
-
|
|
20776
|
+
hasSteps && /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", marginLeft: 4, children: worker.steps.map((step, i) => /* @__PURE__ */ jsx13(StepRow, { step, theme }, `${worker.id}-step-${i}`)) }),
|
|
20777
|
+
worker.logs.length > 0 && /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", marginLeft: 4, children: worker.logs.slice(-3).map((line, i) => /* @__PURE__ */ jsx13(Text12, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: line.slice(0, 120) }, `${worker.id}-log-${i}`)) })
|
|
20778
|
+
] });
|
|
20779
|
+
}
|
|
20780
|
+
function StepRow({ step, theme }) {
|
|
20781
|
+
if (step.status === "completed") {
|
|
20782
|
+
return /* @__PURE__ */ jsxs11(Text12, { color: theme.palette.success, children: [
|
|
20783
|
+
" ",
|
|
20784
|
+
"\u2713 ",
|
|
20785
|
+
/* @__PURE__ */ jsx13(Text12, { strikethrough: true, children: step.label })
|
|
20786
|
+
] });
|
|
20787
|
+
}
|
|
20788
|
+
if (step.status === "active") {
|
|
20789
|
+
return /* @__PURE__ */ jsxs11(Text12, { color: theme.accent, bold: true, children: [
|
|
20790
|
+
" ",
|
|
20791
|
+
/* @__PURE__ */ jsx13(Spinner5, { type: "line" }),
|
|
20792
|
+
" ",
|
|
20793
|
+
step.label
|
|
20794
|
+
] });
|
|
20795
|
+
}
|
|
20796
|
+
if (step.status === "failed") {
|
|
20797
|
+
return /* @__PURE__ */ jsxs11(Text12, { color: theme.palette.error, children: [
|
|
20798
|
+
" ",
|
|
20799
|
+
"\u2612 ",
|
|
20800
|
+
step.label
|
|
20801
|
+
] });
|
|
20802
|
+
}
|
|
20803
|
+
return /* @__PURE__ */ jsxs11(Text12, { color: theme.muted?.color ?? theme.info.color, dimColor: true, children: [
|
|
20804
|
+
" ",
|
|
20805
|
+
"\u2610 ",
|
|
20806
|
+
step.label
|
|
20606
20807
|
] });
|
|
20607
20808
|
}
|
|
20608
20809
|
function formatElapsed6(ms) {
|
|
@@ -21222,14 +21423,14 @@ async function cfFetch(url, init) {
|
|
|
21222
21423
|
}
|
|
21223
21424
|
async function ensureStore(accountId, apiToken) {
|
|
21224
21425
|
const listed = await cfFetch(
|
|
21225
|
-
`${
|
|
21426
|
+
`${CF_API2}/accounts/${encodeURIComponent(accountId)}/secrets_store/stores`,
|
|
21226
21427
|
{ method: "GET", apiToken }
|
|
21227
21428
|
);
|
|
21228
21429
|
if (!listed.ok) return listed;
|
|
21229
21430
|
const existing = listed.value.find((s) => s.name === STORE_NAME);
|
|
21230
21431
|
if (existing) return { ok: true, value: existing.id };
|
|
21231
21432
|
const created = await cfFetch(
|
|
21232
|
-
`${
|
|
21433
|
+
`${CF_API2}/accounts/${encodeURIComponent(accountId)}/secrets_store/stores`,
|
|
21233
21434
|
{ method: "POST", apiToken, body: { name: STORE_NAME } }
|
|
21234
21435
|
);
|
|
21235
21436
|
if (!created.ok) return created;
|
|
@@ -21237,7 +21438,7 @@ async function ensureStore(accountId, apiToken) {
|
|
|
21237
21438
|
}
|
|
21238
21439
|
async function pushProviderKey(accountId, apiToken, storeId, name, value, comment = "kimi-code BYOK") {
|
|
21239
21440
|
const res = await cfFetch(
|
|
21240
|
-
`${
|
|
21441
|
+
`${CF_API2}/accounts/${encodeURIComponent(accountId)}/secrets_store/stores/${encodeURIComponent(
|
|
21241
21442
|
storeId
|
|
21242
21443
|
)}/secrets`,
|
|
21243
21444
|
{
|
|
@@ -21256,12 +21457,12 @@ async function pushProviderKey(accountId, apiToken, storeId, name, value, commen
|
|
|
21256
21457
|
function aliasFor(provider) {
|
|
21257
21458
|
return `kimi-code-${provider}`;
|
|
21258
21459
|
}
|
|
21259
|
-
var
|
|
21460
|
+
var CF_API2, STORE_NAME;
|
|
21260
21461
|
var init_secrets_store = __esm({
|
|
21261
21462
|
"src/agent/secrets-store.ts"() {
|
|
21262
21463
|
"use strict";
|
|
21263
21464
|
init_version();
|
|
21264
|
-
|
|
21465
|
+
CF_API2 = "https://api.cloudflare.com/client/v4";
|
|
21265
21466
|
STORE_NAME = "kimi-code";
|
|
21266
21467
|
}
|
|
21267
21468
|
});
|
|
@@ -25241,13 +25442,14 @@ function MultiAgentModal({ initial, onSave, onDone, remoteWorkerUrl, remoteAuthS
|
|
|
25241
25442
|
setDeploying(true);
|
|
25242
25443
|
setDeployLog(["Starting tear-down\u2026"]);
|
|
25243
25444
|
try {
|
|
25244
|
-
for await (const step of teardownCommute()) {
|
|
25445
|
+
for await (const step of teardownCommute({ workerName: state.workerName })) {
|
|
25245
25446
|
const prefix = step.error ? "\u2717 " : step.done || step.ok ? "\u2713 " : "\xB7 ";
|
|
25246
25447
|
setDeployLog((l) => [...l, `${prefix}${step.message}`]);
|
|
25247
25448
|
if (step.done) {
|
|
25248
25449
|
persist({
|
|
25249
25450
|
workerEndpoint: void 0,
|
|
25250
25451
|
workerApiKey: void 0,
|
|
25452
|
+
workerName: void 0,
|
|
25251
25453
|
multiAgentEnabled: false,
|
|
25252
25454
|
autoExecute: false
|
|
25253
25455
|
});
|
|
@@ -25259,7 +25461,7 @@ function MultiAgentModal({ initial, onSave, onDone, remoteWorkerUrl, remoteAuthS
|
|
|
25259
25461
|
} finally {
|
|
25260
25462
|
setDeploying(false);
|
|
25261
25463
|
}
|
|
25262
|
-
}, [persist]);
|
|
25464
|
+
}, [persist, state.workerName]);
|
|
25263
25465
|
const beginEdit = useCallback7((f) => {
|
|
25264
25466
|
if (f === "deploy") {
|
|
25265
25467
|
void runDeploy2();
|
|
@@ -29772,6 +29974,7 @@ function App({
|
|
|
29772
29974
|
const [lastSessionTopic, setLastSessionTopic] = useState27(null);
|
|
29773
29975
|
const [activeWorkers, setActiveWorkers] = useState27([]);
|
|
29774
29976
|
const [isSynthesizing, setIsSynthesizing] = useState27(false);
|
|
29977
|
+
const [coordinatorNarration, setCoordinatorNarration] = useState27("");
|
|
29775
29978
|
useEffect11(() => {
|
|
29776
29979
|
setGitBranch(detectGitBranch());
|
|
29777
29980
|
}, []);
|
|
@@ -29851,6 +30054,7 @@ ${wcagWarnings.join("\n")}` }
|
|
|
29851
30054
|
const mcpInitRef = useRef7(false);
|
|
29852
30055
|
const submitRef = useRef7(() => {
|
|
29853
30056
|
});
|
|
30057
|
+
const multiAgentAbortRef = useRef7(null);
|
|
29854
30058
|
const lspManagerRef = useRef7(new LspManager());
|
|
29855
30059
|
const lspToolsRef = useRef7([]);
|
|
29856
30060
|
const lspInitRef = useRef7(false);
|
|
@@ -30234,6 +30438,11 @@ ${wcagWarnings.join("\n")}` }
|
|
|
30234
30438
|
hasPerm: hasPendingPermission(),
|
|
30235
30439
|
hasLimit: limitResolveRef.current !== null
|
|
30236
30440
|
});
|
|
30441
|
+
if (multiAgentAbortRef.current) {
|
|
30442
|
+
multiAgentAbortRef.current.abort();
|
|
30443
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "cancelling multi-agent workers\u2026" }]);
|
|
30444
|
+
return;
|
|
30445
|
+
}
|
|
30237
30446
|
const outcome = interruptOrExit(interruptDepsRef.current);
|
|
30238
30447
|
if (!outcome.didInterruptTurn && !outcome.hadPermission && !outcome.hadLimit && !outcome.hadLoop) {
|
|
30239
30448
|
logger.info("input:ctrl+c:exiting");
|
|
@@ -30243,10 +30452,18 @@ ${wcagWarnings.join("\n")}` }
|
|
|
30243
30452
|
if (key.escape) {
|
|
30244
30453
|
const now2 = Date.now();
|
|
30245
30454
|
const modalOpen = perm !== null || limitModal !== null || loopModal !== null || showLspWizard || showCommandList || commandWizard !== null || commandToDelete !== null || resumeSessions !== null || checkpointSession !== null || showThemePicker;
|
|
30246
|
-
if (!modalOpen &&
|
|
30247
|
-
|
|
30248
|
-
|
|
30249
|
-
|
|
30455
|
+
if (!modalOpen && !isAbortingRef.current && now2 - lastEscapeAtRef.current > 500) {
|
|
30456
|
+
if (multiAgentAbortRef.current) {
|
|
30457
|
+
lastEscapeAtRef.current = now2;
|
|
30458
|
+
multiAgentAbortRef.current.abort();
|
|
30459
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "cancelling multi-agent workers\u2026" }]);
|
|
30460
|
+
return;
|
|
30461
|
+
}
|
|
30462
|
+
if ((busyRef.current || supervisorRef.current.isRunning) && activeScopeRef.current) {
|
|
30463
|
+
lastEscapeAtRef.current = now2;
|
|
30464
|
+
interruptTurn(interruptDepsRef.current);
|
|
30465
|
+
return;
|
|
30466
|
+
}
|
|
30250
30467
|
}
|
|
30251
30468
|
}
|
|
30252
30469
|
if (key.ctrl && inputChar === "r") {
|
|
@@ -30277,6 +30494,11 @@ ${wcagWarnings.join("\n")}` }
|
|
|
30277
30494
|
hasLimit: limitResolveRef.current !== null,
|
|
30278
30495
|
hasLoop: loopResolveRef.current !== null
|
|
30279
30496
|
});
|
|
30497
|
+
if (multiAgentAbortRef.current) {
|
|
30498
|
+
multiAgentAbortRef.current.abort();
|
|
30499
|
+
setEvents((e) => [...e, { kind: "info", key: mkKey(), text: "cancelling multi-agent workers\u2026" }]);
|
|
30500
|
+
return;
|
|
30501
|
+
}
|
|
30280
30502
|
const outcome = interruptOrExit({
|
|
30281
30503
|
...interruptDepsRef.current,
|
|
30282
30504
|
skipPendingToolCleanup: true
|
|
@@ -30928,23 +31150,46 @@ ${wcagWarnings.join("\n")}` }
|
|
|
30928
31150
|
...e,
|
|
30929
31151
|
{ kind: "info", key: mkKey(), text: `multi-agent mode active, but task is ${classification.tier} \u2014 running locally` }
|
|
30930
31152
|
]);
|
|
31153
|
+
} else if (activeWorkers.length > 0) {
|
|
31154
|
+
setEvents((e) => [
|
|
31155
|
+
...e,
|
|
31156
|
+
{ kind: "info", key: mkKey(), text: `multi-agent workers already active (${activeWorkers.length}) \u2014 routing to coordinator` }
|
|
31157
|
+
]);
|
|
30931
31158
|
} else {
|
|
30932
31159
|
setEvents((e) => [
|
|
30933
31160
|
...e,
|
|
30934
31161
|
{ kind: "info", key: mkKey(), text: "multi-agent mode: spawning parallel research workers..." }
|
|
30935
31162
|
]);
|
|
31163
|
+
setCoordinatorNarration("");
|
|
31164
|
+
const controller = new AbortController();
|
|
31165
|
+
multiAgentAbortRef.current = controller;
|
|
30936
31166
|
try {
|
|
30937
31167
|
const { plan, conflicts, recommendations, prUrl, executor } = await supervisorRef.current.autoSpawnWorkers(
|
|
30938
31168
|
trimmed,
|
|
30939
31169
|
`Current project: ${process.cwd()}`,
|
|
30940
31170
|
(workers) => setActiveWorkers(workers),
|
|
30941
|
-
(phase) => setIsSynthesizing(phase === "synthesizing")
|
|
31171
|
+
(phase) => setIsSynthesizing(phase === "synthesizing"),
|
|
31172
|
+
controller.signal,
|
|
31173
|
+
(text2) => setCoordinatorNarration(text2)
|
|
30942
31174
|
);
|
|
31175
|
+
setCoordinatorNarration("");
|
|
30943
31176
|
setEvents((e) => [
|
|
30944
31177
|
...e,
|
|
30945
31178
|
{ kind: "info", key: mkKey(), text: "workers completed \u2014 synthesizing findings" }
|
|
30946
31179
|
]);
|
|
30947
|
-
|
|
31180
|
+
const asstId = mkAssistantId();
|
|
31181
|
+
setEvents((e) => [
|
|
31182
|
+
...e,
|
|
31183
|
+
{
|
|
31184
|
+
kind: "assistant",
|
|
31185
|
+
key: `asst_${asstId}`,
|
|
31186
|
+
id: asstId,
|
|
31187
|
+
text: plan,
|
|
31188
|
+
reasoning: "",
|
|
31189
|
+
streaming: false
|
|
31190
|
+
}
|
|
31191
|
+
]);
|
|
31192
|
+
messagesRef.current.push({ role: "assistant", content: plan });
|
|
30948
31193
|
if (conflicts.length > 0) {
|
|
30949
31194
|
setEvents((e) => [
|
|
30950
31195
|
...e,
|
|
@@ -30967,13 +31212,23 @@ ${conflicts.join("\n")}` }
|
|
|
30967
31212
|
return;
|
|
30968
31213
|
} catch (e) {
|
|
30969
31214
|
setIsSynthesizing(false);
|
|
31215
|
+
setCoordinatorNarration("");
|
|
30970
31216
|
const err = e;
|
|
30971
|
-
|
|
30972
|
-
|
|
30973
|
-
|
|
30974
|
-
|
|
31217
|
+
if (err.message === "Cancelled by user") {
|
|
31218
|
+
setEvents((e2) => [
|
|
31219
|
+
...e2,
|
|
31220
|
+
{ kind: "info", key: mkKey(), text: "multi-agent cancelled" }
|
|
31221
|
+
]);
|
|
31222
|
+
} else {
|
|
31223
|
+
setEvents((e2) => [
|
|
31224
|
+
...e2,
|
|
31225
|
+
{ kind: "error", key: mkKey(), text: `multi-agent spawn failed: ${err.message}` }
|
|
31226
|
+
]);
|
|
31227
|
+
}
|
|
30975
31228
|
endTurn();
|
|
30976
31229
|
return;
|
|
31230
|
+
} finally {
|
|
31231
|
+
multiAgentAbortRef.current = null;
|
|
30977
31232
|
}
|
|
30978
31233
|
}
|
|
30979
31234
|
}
|
|
@@ -31465,6 +31720,7 @@ ${conflicts.join("\n")}` }
|
|
|
31465
31720
|
multiAgentEnabled: cfg.multiAgentEnabled,
|
|
31466
31721
|
workerEndpoint: cfg.workerEndpoint,
|
|
31467
31722
|
workerApiKey: cfg.workerApiKey,
|
|
31723
|
+
workerName: cfg.workerName,
|
|
31468
31724
|
autoExecute: cfg.autoExecute
|
|
31469
31725
|
} : void 0,
|
|
31470
31726
|
onMultiAgentSave: async (patch) => {
|
|
@@ -31588,7 +31844,7 @@ ${conflicts.join("\n")}` }
|
|
|
31588
31844
|
}
|
|
31589
31845
|
}
|
|
31590
31846
|
) : /* @__PURE__ */ jsxs39(Box39, { flexDirection: "column", marginTop: 1, children: [
|
|
31591
|
-
activeWorkers.length > 0 && /* @__PURE__ */ jsx41(WorkerList, { workers: activeWorkers, isSynthesizing }),
|
|
31847
|
+
(activeWorkers.length > 0 || coordinatorNarration) && /* @__PURE__ */ jsx41(WorkerList, { workers: activeWorkers, isSynthesizing, narration: coordinatorNarration }),
|
|
31592
31848
|
tasks.length > 0 && /* @__PURE__ */ jsx41(
|
|
31593
31849
|
TaskList,
|
|
31594
31850
|
{
|