@kody-ade/kody-engine 0.4.403 → 0.4.405

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.
Files changed (2) hide show
  1. package/dist/bin/kody.js +63 -64
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "package.json"() {
16
16
  package_default = {
17
17
  name: "@kody-ade/kody-engine",
18
- version: "0.4.403",
18
+ version: "0.4.405",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -21933,6 +21933,19 @@ async function runCodexChatTurn(args) {
21933
21933
  import * as fs13 from "fs";
21934
21934
  import * as path14 from "path";
21935
21935
  import posixPath2 from "path/posix";
21936
+ var BackendEventSink = class {
21937
+ constructor(append, tenantId2, sessionId) {
21938
+ this.append = append;
21939
+ this.tenantId = tenantId2;
21940
+ this.sessionId = sessionId;
21941
+ }
21942
+ append;
21943
+ tenantId;
21944
+ sessionId;
21945
+ async emit(event) {
21946
+ await this.append(this.tenantId, this.sessionId, event);
21947
+ }
21948
+ };
21936
21949
  function eventsFilePath(cwd, sessionId) {
21937
21950
  return path14.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
21938
21951
  }
@@ -22042,6 +22055,7 @@ function createSessionStore(opts) {
22042
22055
  };
22043
22056
  return {
22044
22057
  backend: "convex",
22058
+ readMode: async () => (await read()).conversation.runtime?.kind === "live" ? "interactive" : "one-shot",
22045
22059
  readActiveAgent: async () => (await read()).conversation.activeAgent,
22046
22060
  readTurns: async () => currentEpochTurns(await read()),
22047
22061
  appendTurn: async (turn) => {
@@ -22586,20 +22600,6 @@ import posixPath3 from "path/posix";
22586
22600
  function sessionFilePath(cwd, sessionId) {
22587
22601
  return path16.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
22588
22602
  }
22589
- function readMeta(file) {
22590
- if (!fs15.existsSync(file)) return null;
22591
- const raw = fs15.readFileSync(file, "utf-8");
22592
- const firstLine2 = raw.split("\n", 1)[0]?.trim();
22593
- if (!firstLine2) return null;
22594
- try {
22595
- const parsed = JSON.parse(firstLine2);
22596
- if (parsed.type !== "meta") return null;
22597
- if (parsed.mode !== "one-shot" && parsed.mode !== "interactive") return null;
22598
- return parsed;
22599
- } catch {
22600
- return null;
22601
- }
22602
- }
22603
22603
  function readSession(file) {
22604
22604
  if (!fs15.existsSync(file)) return [];
22605
22605
  const raw = fs15.readFileSync(file, "utf-8").trim();
@@ -22617,29 +22617,6 @@ function readSession(file) {
22617
22617
  }
22618
22618
  return turns;
22619
22619
  }
22620
- function appendTurn(file, turn) {
22621
- fs15.mkdirSync(path16.dirname(file), { recursive: true });
22622
- const line = JSON.stringify({
22623
- role: turn.role,
22624
- content: turn.content,
22625
- timestamp: turn.timestamp,
22626
- toolCalls: turn.toolCalls ?? []
22627
- });
22628
- fs15.appendFileSync(file, `${line}
22629
- `);
22630
- }
22631
- function seedInitialMessage(file, message) {
22632
- if (!message.trim()) return false;
22633
- const turns = readSession(file);
22634
- const lastUser = [...turns].reverse().find((t) => t.role === "user");
22635
- if (lastUser && lastUser.content === message) return false;
22636
- appendTurn(file, {
22637
- role: "user",
22638
- content: message,
22639
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
22640
- });
22641
- return true;
22642
- }
22643
22620
 
22644
22621
  // src/servers/brain-serve.ts
22645
22622
  init_config();
@@ -25066,7 +25043,6 @@ async function loadConfigSafe() {
25066
25043
  }
25067
25044
 
25068
25045
  // src/chat-cli.ts
25069
- import * as fs49 from "fs";
25070
25046
  import * as path49 from "path";
25071
25047
 
25072
25048
  // src/chat/inbox.ts
@@ -25258,6 +25234,7 @@ async function emit2(sink, type, sessionId, suffix, payload) {
25258
25234
  // src/chat-cli.ts
25259
25235
  init_config();
25260
25236
  init_litellm();
25237
+ init_state_backend();
25261
25238
  init_stateWorkspace();
25262
25239
  var DEFAULT_MODEL2 = "claude/claude-haiku-4-5-20251001";
25263
25240
  var CHAT_HELP = `kody chat \u2014 dashboard-driven chat session
@@ -25322,7 +25299,15 @@ function tryLoadConfig(cwd) {
25322
25299
  }
25323
25300
  }
25324
25301
  function buildSink(cwd, sessionId, dashboardUrl) {
25325
- const sinks = [new FileSink(eventsFilePath(cwd, sessionId))];
25302
+ const backend = createStateBackendFromEnv();
25303
+ const sinks = [
25304
+ new BackendEventSink(
25305
+ (tenantId2, targetSessionId, event) => backend.appendChatEvent(tenantId2, targetSessionId, event),
25306
+ "global",
25307
+ sessionId
25308
+ ),
25309
+ new FileSink(eventsFilePath(cwd, sessionId))
25310
+ ];
25326
25311
  if (dashboardUrl) sinks.push(new HttpSink(dashboardUrl, sessionId));
25327
25312
  return new TeeSink(sinks);
25328
25313
  }
@@ -25396,15 +25381,27 @@ ${CHAT_HELP}`);
25396
25381
  process.stdout.write(`\u2192 kody:chat: litellm proxy ready (url=${litellm?.url ?? "skipped"})
25397
25382
  `);
25398
25383
  const sessionFile = sessionFilePath(cwd, sessionId);
25399
- if (args.initMessage) seedInitialMessage(sessionFile, args.initMessage);
25384
+ const store = createSessionStore({ sessionId, sessionFile });
25385
+ if (args.initMessage) {
25386
+ await store.appendTurn({
25387
+ role: "user",
25388
+ content: args.initMessage,
25389
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
25390
+ });
25391
+ }
25400
25392
  const sink = buildSink(cwd, sessionId, args.dashboardUrl);
25401
- const meta = readMeta(sessionFile);
25402
- process.stdout.write(
25403
- `\u2192 kody:chat: session file=${sessionFile} exists=${fs49.existsSync(sessionFile)} meta=${meta ? meta.mode : "none"}
25404
- `
25405
- );
25393
+ const mode = await store.readMode();
25394
+ const meta = {
25395
+ type: "meta",
25396
+ mode,
25397
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
25398
+ ...process.env.KODY_IDLE_EXIT_MS ? { idleExitMs: Number(process.env.KODY_IDLE_EXIT_MS) } : {},
25399
+ ...process.env.KODY_HARD_CAP_MS ? { hardCapMs: Number(process.env.KODY_HARD_CAP_MS) } : {}
25400
+ };
25401
+ process.stdout.write(`\u2192 kody:chat: canonical conversation mode=${mode}
25402
+ `);
25406
25403
  try {
25407
- if (meta?.mode === "interactive") {
25404
+ if (mode === "interactive") {
25408
25405
  const result2 = await runInteractiveMode({
25409
25406
  sessionId,
25410
25407
  cwd,
@@ -25415,6 +25412,7 @@ ${CHAT_HELP}`);
25415
25412
  verbose: args.verbose,
25416
25413
  quiet: args.quiet,
25417
25414
  config,
25415
+ store,
25418
25416
  ...reasoningEffort ? { reasoningEffort } : {}
25419
25417
  });
25420
25418
  return result2.exitCode;
@@ -25429,6 +25427,7 @@ ${CHAT_HELP}`);
25429
25427
  verbose: args.verbose,
25430
25428
  quiet: args.quiet,
25431
25429
  config,
25430
+ store,
25432
25431
  ...reasoningEffort ? { reasoningEffort } : {}
25433
25432
  });
25434
25433
  return result.exitCode;
@@ -25446,7 +25445,7 @@ init_config();
25446
25445
  // src/definition-hydration.ts
25447
25446
  init_state_backend();
25448
25447
  import { createHash as createHash5 } from "crypto";
25449
- import * as fs50 from "fs";
25448
+ import * as fs49 from "fs";
25450
25449
  import * as path50 from "path";
25451
25450
  var SLUG_RE2 = /^[a-z0-9][a-z0-9_-]{0,63}$/;
25452
25451
  function assertSafeDefinitionPath(filePath) {
@@ -25481,32 +25480,32 @@ function writeDefinition(root, kind, definition) {
25481
25480
  if (kind === "agent") {
25482
25481
  const raw = bundle.files["agent.md"];
25483
25482
  if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
25484
- fs50.writeFileSync(path50.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
25483
+ fs49.writeFileSync(path50.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
25485
25484
  return;
25486
25485
  }
25487
25486
  if (kind === "goal") {
25488
25487
  const goalRoot = path50.join(root, "goals", definition.slug);
25489
25488
  for (const [filePath, contents] of Object.entries(bundle.files)) {
25490
25489
  const target = path50.join(goalRoot, filePath);
25491
- fs50.mkdirSync(path50.dirname(target), { recursive: true });
25492
- fs50.writeFileSync(target, contents, "utf8");
25490
+ fs49.mkdirSync(path50.dirname(target), { recursive: true });
25491
+ fs49.writeFileSync(target, contents, "utf8");
25493
25492
  }
25494
25493
  return;
25495
25494
  }
25496
25495
  const capabilityRoot = path50.join(root, "capabilities", definition.slug);
25497
25496
  for (const [filePath, contents] of Object.entries(bundle.files)) {
25498
25497
  const target = path50.join(capabilityRoot, filePath);
25499
- fs50.mkdirSync(path50.dirname(target), { recursive: true });
25500
- fs50.writeFileSync(target, contents, "utf8");
25498
+ fs49.mkdirSync(path50.dirname(target), { recursive: true });
25499
+ fs49.writeFileSync(target, contents, "utf8");
25501
25500
  }
25502
25501
  }
25503
25502
  async function hydrateDefinitions(options) {
25504
25503
  const root = path50.join(options.cwd, ".kody-engine", "definitions");
25505
25504
  const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
25506
- fs50.rmSync(staging, { recursive: true, force: true });
25507
- fs50.mkdirSync(path50.join(staging, "agents"), { recursive: true });
25508
- fs50.mkdirSync(path50.join(staging, "capabilities"), { recursive: true });
25509
- fs50.mkdirSync(path50.join(staging, "goals"), { recursive: true });
25505
+ fs49.rmSync(staging, { recursive: true, force: true });
25506
+ fs49.mkdirSync(path50.join(staging, "agents"), { recursive: true });
25507
+ fs49.mkdirSync(path50.join(staging, "capabilities"), { recursive: true });
25508
+ fs49.mkdirSync(path50.join(staging, "goals"), { recursive: true });
25510
25509
  try {
25511
25510
  const [capabilities, agents, goals] = await Promise.all([
25512
25511
  options.backend.listDefinitions(options.tenantId, "capability"),
@@ -25532,13 +25531,13 @@ async function hydrateDefinitions(options) {
25532
25531
  hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
25533
25532
  versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
25534
25533
  };
25535
- fs50.writeFileSync(path50.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
25534
+ fs49.writeFileSync(path50.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
25536
25535
  `, "utf8");
25537
- fs50.rmSync(root, { recursive: true, force: true });
25538
- fs50.renameSync(staging, root);
25536
+ fs49.rmSync(root, { recursive: true, force: true });
25537
+ fs49.renameSync(staging, root);
25539
25538
  return { root, tenantId: options.tenantId, versions: manifest.versions };
25540
25539
  } catch (error) {
25541
- fs50.rmSync(staging, { recursive: true, force: true });
25540
+ fs49.rmSync(staging, { recursive: true, force: true });
25542
25541
  throw error;
25543
25542
  }
25544
25543
  }
@@ -26397,7 +26396,7 @@ async function poolServe() {
26397
26396
 
26398
26397
  // src/servers/runner-serve.ts
26399
26398
  import { spawn as spawn9 } from "child_process";
26400
- import * as fs51 from "fs";
26399
+ import * as fs50 from "fs";
26401
26400
  import { createServer as createServer6 } from "http";
26402
26401
  var DEFAULT_PORT2 = 8080;
26403
26402
  var DEFAULT_WORKDIR = "/workspace/repo";
@@ -26532,8 +26531,8 @@ async function defaultRunJob(job) {
26532
26531
  const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
26533
26532
  const branch = job.ref ?? "main";
26534
26533
  const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
26535
- fs51.rmSync(workdir, { recursive: true, force: true });
26536
- fs51.mkdirSync(workdir, { recursive: true });
26534
+ fs50.rmSync(workdir, { recursive: true, force: true });
26535
+ fs50.mkdirSync(workdir, { recursive: true });
26537
26536
  const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
26538
26537
  const target = job.runRequest.target;
26539
26538
  const interactive = target.type === "chat";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.403",
3
+ "version": "0.4.405",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",