kimiflare 0.76.1 → 0.78.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.
@@ -1,5 +1,7 @@
1
1
  import { Readable, Writable } from 'node:stream';
2
2
 
3
+ type Mode = "edit" | "plan" | "auto" | "multi-agent-experimental";
4
+
3
5
  type Role = "system" | "user" | "assistant" | "tool";
4
6
  interface ToolCall {
5
7
  id: string;
@@ -335,6 +337,23 @@ interface KimiConfig {
335
337
  };
336
338
  /** Id of the Cloudflare Secrets Store kimi-code uses for provider-key BYOK aliases. */
337
339
  secretsStoreId?: string;
340
+ /** Worker endpoint URL for spawning standalone research/executor workers. */
341
+ workerEndpoint?: string;
342
+ /** Max cost per worker in USD (default: 1.0). */
343
+ workerBudgetUsd?: number;
344
+ /** Max workers to spawn in parallel (default: 3). */
345
+ workerMaxParallel?: number;
346
+ /** Timeout per worker in milliseconds (default: 300000 = 5 min). */
347
+ workerTimeoutMs?: number;
348
+ /** Enable multi-agent-experimental mode in the mode cycle. Default: false. */
349
+ multiAgentEnabled?: boolean;
350
+ /** Bearer/secret for the worker endpoint (sent as X-Worker-Api-Key). */
351
+ workerApiKey?: string;
352
+ /** Name of the deployed multi-agent Worker. Used for tear-down. */
353
+ workerName?: string;
354
+ /** When true, after plan workers synthesize, spawn one executor worker
355
+ * to implement the synthesized plan and open a PR. Off by default. */
356
+ autoExecute?: boolean;
338
357
  }
339
358
  declare const DEFAULT_MODEL = "@cf/moonshotai/kimi-k2.6";
340
359
  declare const DEFAULT_REASONING_EFFORT: ReasoningEffort;
@@ -506,7 +525,7 @@ interface SessionStatus {
506
525
  isCompacting: boolean;
507
526
  pendingSteer: string[];
508
527
  pendingFollowUp: string[];
509
- currentMode: "plan" | "edit" | "auto";
528
+ currentMode: Mode;
510
529
  }
511
530
  type PermissionHandler = (req: PermissionRequest) => Promise<PermissionDecision>;
512
531
  interface KimiFlareSession {
@@ -534,7 +553,7 @@ declare function createAgentSession(opts: CreateSessionOptions): Promise<{
534
553
  }>;
535
554
 
536
555
  declare function createDefaultPermissionHandler(options: {
537
- mode: "plan" | "edit" | "auto";
556
+ mode: Mode;
538
557
  onRequest?: (req: PermissionRequest) => void;
539
558
  }): PermissionHandler;
540
559
 
package/dist/sdk/index.js CHANGED
@@ -505,6 +505,8 @@ function modeDescription(m) {
505
505
  return "plan \u2014 read-only research; blocks writes/edits/mutating bash until you exit plan mode";
506
506
  case "auto":
507
507
  return "auto \u2014 autonomous; auto-approves every tool call (use with care)";
508
+ case "multi-agent-experimental":
509
+ return "multi-agent \u2014 experimental; for heavy tasks, spawns parallel research workers automatically";
508
510
  }
509
511
  }
510
512
  function isBlockedInPlanMode(toolName) {
@@ -607,13 +609,16 @@ function systemPromptForMode(m) {
607
609
  if (m === "auto") {
608
610
  return "\n\nAUTO MODE is active. The user has opted into autonomous execution \u2014 every tool call will be auto-approved. Work efficiently, but do not take irreversible destructive actions (rm -rf, git push --force, dropping tables, etc.) without pausing to describe them in chat first. Prefer smaller reversible steps.";
609
611
  }
612
+ if (m === "multi-agent-experimental") {
613
+ return "\n\nMULTI-AGENT EXPERIMENTAL MODE is active. For heavy tasks, the coordinator will automatically spawn parallel research workers instead of handling everything locally. Do not manually call spawn_worker \u2014 the coordinator handles worker orchestration. For light or medium tasks, the turn runs locally with normal edit-mode permissions. When workers complete, their findings are synthesized into a coherent plan for your review.";
614
+ }
610
615
  return "";
611
616
  }
612
617
  var MODES, MUTATING_TOOLS, DANGEROUS_PATTERNS, GIT_READONLY_SUBCOMMANDS, READONLY_COMMANDS;
613
618
  var init_mode = __esm({
614
619
  "src/mode.ts"() {
615
620
  "use strict";
616
- MODES = ["edit", "plan", "auto"];
621
+ MODES = ["edit", "plan", "auto", "multi-agent-experimental"];
617
622
  MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "bash"]);
618
623
  DANGEROUS_PATTERNS = /[<>;`$]|\$\(|\$\{|\|\||\b&\s*$/;
619
624
  GIT_READONLY_SUBCOMMANDS = {
@@ -5415,6 +5420,182 @@ var memoryForgetTool = {
5415
5420
  }
5416
5421
  };
5417
5422
 
5423
+ // src/tools/spawn-worker.ts
5424
+ init_logger();
5425
+ var DEFAULT_WORKER_TIMEOUT_MS = 3e5;
5426
+ var DEFAULT_WORKER_BUDGET_USD = 1;
5427
+ async function callWorkerEndpoint(endpoint, apiKey, payload, signal, timeoutMs = DEFAULT_WORKER_TIMEOUT_MS) {
5428
+ const controller = new AbortController();
5429
+ const timer2 = setTimeout(() => controller.abort(), timeoutMs);
5430
+ const url = `${endpoint}/worker`;
5431
+ const headers = {
5432
+ "Content-Type": "application/json",
5433
+ ...apiKey ? { "X-Worker-Api-Key": apiKey } : {}
5434
+ };
5435
+ const body = JSON.stringify(payload);
5436
+ const fetchSignal = signal ?? controller.signal;
5437
+ try {
5438
+ const res = await fetch(url, { method: "POST", headers, body, signal: fetchSignal });
5439
+ if (res.ok) {
5440
+ return await res.json();
5441
+ }
5442
+ if (res.status >= 500 && res.status < 600) {
5443
+ logger.warn("spawn_worker:retrying", { status: res.status, endpoint });
5444
+ const retryRes = await fetch(url, { method: "POST", headers, body, signal: fetchSignal });
5445
+ if (retryRes.ok) {
5446
+ return await retryRes.json();
5447
+ }
5448
+ const text2 = await retryRes.text().catch(() => "");
5449
+ throw new Error(`Worker endpoint returned ${retryRes.status}: ${text2.slice(0, 200)}`);
5450
+ }
5451
+ const text = await res.text().catch(() => "");
5452
+ throw new Error(`Worker endpoint returned ${res.status}: ${text.slice(0, 200)}`);
5453
+ } finally {
5454
+ clearTimeout(timer2);
5455
+ }
5456
+ }
5457
+ var spawnWorkerTool = {
5458
+ name: "spawn_worker",
5459
+ description: [
5460
+ "Spawn a standalone remote worker agent to perform research or execute a plan.",
5461
+ "Workers run independently with their own full context window and tool access.",
5462
+ "Mode 'plan': read-only research worker that returns structured findings.",
5463
+ "Mode 'execute': write-enabled worker that creates a branch, implements changes, and opens a PR.",
5464
+ "Use for heavy tasks that benefit from parallel research (e.g. 'research OAuth2, testing, and migration')."
5465
+ ].join(" "),
5466
+ parameters: {
5467
+ type: "object",
5468
+ properties: {
5469
+ mode: {
5470
+ type: "string",
5471
+ enum: ["plan", "execute"],
5472
+ description: "Worker mode: 'plan' for read-only research, 'execute' for write + PR."
5473
+ },
5474
+ task: {
5475
+ type: "string",
5476
+ description: "The mission brief for the worker. Be specific about what to research or implement."
5477
+ },
5478
+ context: {
5479
+ type: "string",
5480
+ description: "Additional context about the current project state or goals."
5481
+ },
5482
+ budget: {
5483
+ type: "object",
5484
+ properties: {
5485
+ maxCostUsd: { type: "number", description: "Max cost in USD for this worker. Default 1.0." }
5486
+ }
5487
+ },
5488
+ outputFormat: {
5489
+ type: "string",
5490
+ enum: ["structured", "text"],
5491
+ description: "Output format. Default 'structured'."
5492
+ },
5493
+ tools: {
5494
+ type: "string",
5495
+ enum: ["all", "read-only"],
5496
+ description: "Tool set available to the worker. Default 'all' for plan mode, ignored for execute."
5497
+ },
5498
+ model: {
5499
+ type: "string",
5500
+ description: "Model to use for the worker. Defaults to @cf/moonshotai/kimi-k2.6."
5501
+ },
5502
+ branchName: {
5503
+ type: "string",
5504
+ description: "For execute mode: feature branch name to create."
5505
+ },
5506
+ baseBranch: {
5507
+ type: "string",
5508
+ description: "For execute mode: base branch to fork from. Default 'main'."
5509
+ },
5510
+ prTitle: {
5511
+ type: "string",
5512
+ description: "For execute mode: PR title."
5513
+ },
5514
+ prBody: {
5515
+ type: "string",
5516
+ description: "For execute mode: PR body markdown."
5517
+ }
5518
+ },
5519
+ required: ["mode", "task"],
5520
+ additionalProperties: false
5521
+ },
5522
+ needsPermission: true,
5523
+ render: (args) => ({
5524
+ title: `spawn_worker (${args.mode})`,
5525
+ body: args.task.slice(0, 200)
5526
+ }),
5527
+ async run(args, ctx) {
5528
+ const endpoint = process.env.KIMIFLARE_WORKER_ENDPOINT;
5529
+ if (!endpoint) {
5530
+ const msg = "Worker endpoint not configured. Set KIMIFLARE_WORKER_ENDPOINT or workerEndpoint in config.";
5531
+ const bytes = Buffer.byteLength(msg, "utf8");
5532
+ return { content: msg, rawBytes: bytes, reducedBytes: bytes };
5533
+ }
5534
+ const apiKey = process.env.KIMIFLARE_WORKER_API_KEY;
5535
+ const timeoutMs = readNumberEnv("KIMIFLARE_WORKER_TIMEOUT_MS") ?? DEFAULT_WORKER_TIMEOUT_MS;
5536
+ const budgetUsd = args.budget?.maxCostUsd ?? readNumberEnv("KIMIFLARE_WORKER_BUDGET_USD") ?? DEFAULT_WORKER_BUDGET_USD;
5537
+ const payload = {
5538
+ mode: args.mode,
5539
+ task: args.task,
5540
+ context: args.context ?? "",
5541
+ budget: { maxCostUsd: budgetUsd },
5542
+ outputFormat: args.outputFormat ?? "structured",
5543
+ tools: args.tools ?? (args.mode === "plan" ? "read-only" : "all"),
5544
+ model: args.model ?? "@cf/moonshotai/kimi-k2.6",
5545
+ ...args.mode === "execute" ? {
5546
+ branchName: args.branchName,
5547
+ baseBranch: args.baseBranch ?? "main",
5548
+ prTitle: args.prTitle,
5549
+ prBody: args.prBody
5550
+ } : {}
5551
+ };
5552
+ logger.info("spawn_worker:starting", { mode: args.mode, endpoint, taskPreview: args.task.slice(0, 100) });
5553
+ try {
5554
+ const result = await callWorkerEndpoint(endpoint, apiKey, payload, ctx.signal, timeoutMs);
5555
+ if (result.status !== "completed") {
5556
+ const msg = `Worker ${result.workerId} ${result.status}: ${result.error ?? "unknown error"}`;
5557
+ const bytes2 = Buffer.byteLength(msg, "utf8");
5558
+ return { content: msg, rawBytes: bytes2, reducedBytes: bytes2 };
5559
+ }
5560
+ const lines = [
5561
+ `Worker ${result.workerId} completed.`,
5562
+ `Cost: $${result.costUsd.toFixed(2)} \xB7 Tokens: ${result.tokensUsed.toLocaleString()}`,
5563
+ "",
5564
+ "## Findings",
5565
+ ...result.findings.map(
5566
+ (f) => `- **${f.topic}** (${f.confidence}): ${f.summary} [relevance: ${f.relevance}]`
5567
+ ),
5568
+ "",
5569
+ "## Recommendations",
5570
+ ...result.recommendations.map((r) => `- ${r}`)
5571
+ ];
5572
+ if (result.filesRead.length > 0) {
5573
+ lines.push("", "## Files Read", ...result.filesRead.map((f) => `- ${f}`));
5574
+ }
5575
+ if (result.webSources.length > 0) {
5576
+ lines.push("", "## Web Sources", ...result.webSources.map((u) => `- ${u}`));
5577
+ }
5578
+ const content = lines.join("\n");
5579
+ const bytes = Buffer.byteLength(content, "utf8");
5580
+ return { content, rawBytes: bytes, reducedBytes: bytes };
5581
+ } catch (e) {
5582
+ const err = e;
5583
+ const cause = err.cause;
5584
+ const diagnostic = cause ? `${err.message} (${cause.message})` : err.message;
5585
+ const msg = `Failed to spawn worker: ${diagnostic}`;
5586
+ logger.error("spawn_worker:failed", { error: diagnostic });
5587
+ const bytes = Buffer.byteLength(msg, "utf8");
5588
+ return { content: msg, rawBytes: bytes, reducedBytes: bytes };
5589
+ }
5590
+ }
5591
+ };
5592
+ function readNumberEnv(name) {
5593
+ const raw = process.env[name];
5594
+ if (!raw) return void 0;
5595
+ const parsed = parseInt(raw, 10);
5596
+ return Number.isNaN(parsed) ? void 0 : parsed;
5597
+ }
5598
+
5418
5599
  // src/tools/artifact-store.ts
5419
5600
  var ToolArtifactStore = class {
5420
5601
  artifacts = /* @__PURE__ */ new Map();
@@ -5982,7 +6163,8 @@ var ALL_TOOLS = [
5982
6163
  tasksSetTool,
5983
6164
  memoryRememberTool,
5984
6165
  memoryRecallTool,
5985
- memoryForgetTool
6166
+ memoryForgetTool,
6167
+ spawnWorkerTool
5986
6168
  ];
5987
6169
  function toPermissionResult(d) {
5988
6170
  if (typeof d === "string") {
@@ -8052,7 +8234,7 @@ function readBooleanEnv(name) {
8052
8234
  if (normalized === "0" || normalized === "false") return false;
8053
8235
  return void 0;
8054
8236
  }
8055
- function readNumberEnv(name) {
8237
+ function readNumberEnv2(name) {
8056
8238
  const raw = process.env[name];
8057
8239
  if (!raw) return void 0;
8058
8240
  const parsed = parseInt(raw, 10);
@@ -8110,7 +8292,7 @@ async function loadConfig() {
8110
8292
  const envCoauthor = readCoauthorEnv();
8111
8293
  const envAiGatewayId = process.env.KIMIFLARE_AI_GATEWAY_ID;
8112
8294
  warnIfBlankGatewayId(envAiGatewayId, "env");
8113
- const envAiGatewayCacheTtl = readNumberEnv("KIMIFLARE_AI_GATEWAY_CACHE_TTL");
8295
+ const envAiGatewayCacheTtl = readNumberEnv2("KIMIFLARE_AI_GATEWAY_CACHE_TTL");
8114
8296
  const envAiGatewaySkipCache = readBooleanEnv("KIMIFLARE_AI_GATEWAY_SKIP_CACHE");
8115
8297
  const envAiGatewayCollectLogPayload = readBooleanEnv(
8116
8298
  "KIMIFLARE_AI_GATEWAY_COLLECT_LOG_PAYLOAD"
@@ -8124,8 +8306,8 @@ async function loadConfig() {
8124
8306
  const imageHistoryTurns = envImageTurns ? parseInt(envImageTurns, 10) : void 0;
8125
8307
  const envMemoryEnabled = readBooleanEnv("KIMIFLARE_MEMORY_ENABLED");
8126
8308
  const envMemoryDbPath = process.env.KIMIFLARE_MEMORY_DB_PATH;
8127
- const envMemoryMaxAgeDays = readNumberEnv("KIMIFLARE_MEMORY_MAX_AGE_DAYS");
8128
- const envMemoryMaxEntries = readNumberEnv("KIMIFLARE_MEMORY_MAX_ENTRIES");
8309
+ const envMemoryMaxAgeDays = readNumberEnv2("KIMIFLARE_MEMORY_MAX_AGE_DAYS");
8310
+ const envMemoryMaxEntries = readNumberEnv2("KIMIFLARE_MEMORY_MAX_ENTRIES");
8129
8311
  const envMemoryEmbeddingModel = process.env.KIMIFLARE_MEMORY_EMBEDDING_MODEL;
8130
8312
  const envPlumbingModel = process.env.KIMIFLARE_PLUMBING_MODEL;
8131
8313
  const envMemoryExtractionModel = process.env.KIMIFLARE_MEMORY_EXTRACTION_MODEL;
@@ -8135,6 +8317,7 @@ async function loadConfig() {
8135
8317
  const envShell = process.env.KIMIFLARE_SHELL;
8136
8318
  const envProviderKeys = readProviderKeysEnv();
8137
8319
  const envUnifiedBilling = readBooleanEnv("KIMIFLARE_UNIFIED_BILLING");
8320
+ const envMultiAgentEnabled = readBooleanEnv("KIMIFLARE_MULTI_AGENT_ENABLED");
8138
8321
  if (envAccount && envToken) {
8139
8322
  return {
8140
8323
  accountId: envAccount,
@@ -8171,7 +8354,14 @@ async function loadConfig() {
8171
8354
  providerKeys: envProviderKeys ?? persisted?.providerKeys,
8172
8355
  providerKeyAliases: persisted?.providerKeyAliases,
8173
8356
  secretsStoreId: persisted?.secretsStoreId,
8174
- unifiedBilling: envUnifiedBilling ?? persisted?.unifiedBilling
8357
+ unifiedBilling: envUnifiedBilling ?? persisted?.unifiedBilling,
8358
+ workerEndpoint: process.env.KIMIFLARE_WORKER_ENDPOINT,
8359
+ workerBudgetUsd: readNumberEnv2("KIMIFLARE_WORKER_BUDGET_USD"),
8360
+ workerMaxParallel: readNumberEnv2("KIMIFLARE_WORKER_MAX_PARALLEL"),
8361
+ workerTimeoutMs: readNumberEnv2("KIMIFLARE_WORKER_TIMEOUT_MS"),
8362
+ multiAgentEnabled: envMultiAgentEnabled,
8363
+ workerApiKey: process.env.KIMIFLARE_WORKER_API_KEY,
8364
+ autoExecute: readBooleanEnv("KIMIFLARE_AUTO_EXECUTE")
8175
8365
  };
8176
8366
  }
8177
8367
  if (persisted) {
@@ -8211,7 +8401,14 @@ async function loadConfig() {
8211
8401
  providerKeys: envProviderKeys ?? parsed.providerKeys,
8212
8402
  providerKeyAliases: parsed.providerKeyAliases,
8213
8403
  secretsStoreId: parsed.secretsStoreId,
8214
- unifiedBilling: envUnifiedBilling ?? parsed.unifiedBilling
8404
+ unifiedBilling: envUnifiedBilling ?? parsed.unifiedBilling,
8405
+ workerEndpoint: process.env.KIMIFLARE_WORKER_ENDPOINT ?? parsed.workerEndpoint,
8406
+ workerBudgetUsd: parsed.workerBudgetUsd,
8407
+ workerMaxParallel: parsed.workerMaxParallel,
8408
+ workerTimeoutMs: parsed.workerTimeoutMs,
8409
+ multiAgentEnabled: envMultiAgentEnabled ?? parsed.multiAgentEnabled,
8410
+ workerApiKey: process.env.KIMIFLARE_WORKER_API_KEY ?? parsed.workerApiKey,
8411
+ autoExecute: parsed.autoExecute
8215
8412
  };
8216
8413
  }
8217
8414
  }