@suwujs/king-ai 0.2.10 → 0.2.11

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,5 @@
1
1
  import { execFileSync, spawn } from "node:child_process";
2
- import { access, mkdir, writeFile } from "node:fs/promises";
2
+ import { access, mkdir, readFile, writeFile } from "node:fs/promises";
3
3
  import { existsSync, writeFileSync } from "node:fs";
4
4
  import { join, delimiter as PATH_DELIMITER } from "node:path";
5
5
  import { cleanLine, stripLoneSurrogates } from "./text.js";
@@ -202,6 +202,17 @@ Privacy boundary:
202
202
  Use the \`king-ai\` command on PATH to interact with the remote runtime.
203
203
  `;
204
204
  }
205
+ async function seedPersonaFile(path, persona) {
206
+ const next = personaHeader(persona);
207
+ if (!(await exists(path))) {
208
+ await writeFile(path, next, "utf8");
209
+ return;
210
+ }
211
+ const current = await readFile(path, "utf8").catch(() => "");
212
+ if (!current.includes("You are ") || !current.includes("a teammate running from this local agent home."))
213
+ return;
214
+ await writeFile(path, next, "utf8");
215
+ }
205
216
  function failurePreview(exitCode, signalName, stderr, stdout) {
206
217
  const detail = [...stderr, ...stdout].join("\n").trim();
207
218
  const prefix = signalName ? `process terminated by ${signalName}` : `process exited with code ${exitCode}`;
@@ -807,9 +818,7 @@ class ClaudeAdapter {
807
818
  async seedHome(home, persona) {
808
819
  await ensureCommonHome(home);
809
820
  await mkdir(join(home, ".claude", "skills"), { recursive: true });
810
- const claudeMd = join(home, "CLAUDE.md");
811
- if (!(await exists(claudeMd)))
812
- await writeFile(claudeMd, personaHeader(persona), "utf8");
821
+ await seedPersonaFile(join(home, "CLAUDE.md"), persona);
813
822
  }
814
823
  async classify(args) {
815
824
  const extra = envExtraArgs("KING_AI_TRIAGE_ARGS");
@@ -907,9 +916,7 @@ class CodexAdapter {
907
916
  bin = "codex";
908
917
  async seedHome(home, persona) {
909
918
  await ensureCommonHome(home);
910
- const agentsMd = join(home, "AGENTS.md");
911
- if (!(await exists(agentsMd)))
912
- await writeFile(agentsMd, personaHeader(persona), "utf8");
919
+ await seedPersonaFile(join(home, "AGENTS.md"), persona);
913
920
  }
914
921
  classify(args) {
915
922
  const extra = envExtraArgs("KING_AI_TRIAGE_ARGS");
@@ -15,5 +15,5 @@ export declare const HEARTBEAT_PATH: string;
15
15
  export declare const HOST_EVENTS_PATH: string;
16
16
  export declare const HOST_RUNS_PATH: string;
17
17
  export declare const SERVICE_LABEL = "dev.king-ai";
18
- export declare const CURRENT_VERSION = "0.2.10";
18
+ export declare const CURRENT_VERSION = "0.2.11";
19
19
  export declare const DEFAULT_SERVER: string;
package/dist/src/paths.js CHANGED
@@ -22,5 +22,5 @@ export const HEARTBEAT_PATH = join(CONFIG_DIR, "heartbeat.json");
22
22
  export const HOST_EVENTS_PATH = join(CONFIG_DIR, "host-events.ndjson");
23
23
  export const HOST_RUNS_PATH = join(CONFIG_DIR, "host-runs.ndjson");
24
24
  export const SERVICE_LABEL = "dev.king-ai";
25
- export const CURRENT_VERSION = "0.2.10";
25
+ export const CURRENT_VERSION = "0.2.11";
26
26
  export const DEFAULT_SERVER = process.env.KING_AI_SERVER_URL || "https://api.king-ai.ai";
@@ -21,6 +21,7 @@ export interface WakeEventInfo {
21
21
  agentId: string | null;
22
22
  sentAt: number | null;
23
23
  deliveryLatencyMs: number | null;
24
+ resetState: boolean;
24
25
  }
25
26
  export declare class Semaphore {
26
27
  private readonly max;
@@ -77,6 +78,7 @@ export declare class AgentRunner {
77
78
  private lastAgendaCheckAt;
78
79
  private sideSteering;
79
80
  private lastSteeredMsgId;
81
+ private resetInProgress;
80
82
  private runStats;
81
83
  private lastBudgetEventState;
82
84
  private sharedSkillSnapshot;
@@ -93,6 +95,8 @@ export declare class AgentRunner {
93
95
  start(): Promise<void>;
94
96
  beginStop(): void;
95
97
  stop(): void;
98
+ private resetLocalState;
99
+ private handleResetLocalState;
96
100
  scheduleWake(reason: string, conversationId?: string | null): void;
97
101
  private kickTurn;
98
102
  private steerRunningTurn;
@@ -253,7 +253,7 @@ export function agentSessionFile(agentId, engine) {
253
253
  }
254
254
  export function parseWakeEventInfo(rawData, now = Date.now()) {
255
255
  if (!rawData)
256
- return { conversationId: null, agentId: null, sentAt: null, deliveryLatencyMs: null };
256
+ return { conversationId: null, agentId: null, sentAt: null, deliveryLatencyMs: null, resetState: false };
257
257
  try {
258
258
  const data = JSON.parse(rawData);
259
259
  const conversationId = typeof data.conversationId === "string" ? data.conversationId : null;
@@ -263,11 +263,12 @@ export function parseWakeEventInfo(rawData, now = Date.now()) {
263
263
  conversationId,
264
264
  agentId,
265
265
  sentAt,
266
- deliveryLatencyMs: sentAt == null ? null : Math.max(0, now - sentAt)
266
+ deliveryLatencyMs: sentAt == null ? null : Math.max(0, now - sentAt),
267
+ resetState: data.resetState === true
267
268
  };
268
269
  }
269
270
  catch {
270
- return { conversationId: null, agentId: null, sentAt: null, deliveryLatencyMs: null };
271
+ return { conversationId: null, agentId: null, sentAt: null, deliveryLatencyMs: null, resetState: false };
271
272
  }
272
273
  }
273
274
  export function shouldHandleWakeEvent(info, agentId) {
@@ -300,6 +301,7 @@ export class AgentRunner {
300
301
  lastAgendaCheckAt = 0;
301
302
  sideSteering = false;
302
303
  lastSteeredMsgId = null;
304
+ resetInProgress = false;
303
305
  runStats = emptyAgentRunStats();
304
306
  lastBudgetEventState = null;
305
307
  sharedSkillSnapshot;
@@ -426,6 +428,38 @@ export class AgentRunner {
426
428
  this.engineSession?.stop();
427
429
  this.engineSession = null;
428
430
  }
431
+ async resetLocalState() {
432
+ this.engineSession?.stop();
433
+ this.engineSession = null;
434
+ this.sessionId = null;
435
+ this.token = "";
436
+ this.tokenExpiresAt = 0;
437
+ this.pendingRerun = false;
438
+ this.lastWakeConvo = null;
439
+ this.lastSteeredMsgId = null;
440
+ this.remediation = null;
441
+ await rm(this.sessionFile, { force: true });
442
+ await rm(this.home, { recursive: true, force: true });
443
+ this.stopped = false;
444
+ try {
445
+ await this.start();
446
+ }
447
+ finally {
448
+ this.resetInProgress = false;
449
+ }
450
+ }
451
+ handleResetLocalState() {
452
+ if (this.resetInProgress)
453
+ return;
454
+ this.resetInProgress = true;
455
+ this.beginStop();
456
+ setTimeout(() => {
457
+ swallowTurnRejection(this.resetLocalState(), (message) => {
458
+ this.resetInProgress = false;
459
+ console.error(`[${this.agent.id}/${this.adapter.id}] resetLocalState rejected (swallowed): ${message}`);
460
+ });
461
+ }, 0);
462
+ }
429
463
  scheduleWake(reason, conversationId) {
430
464
  if (this.stopped)
431
465
  return;
@@ -1113,6 +1147,11 @@ ${delta}`;
1113
1147
  const info = parseWakeEventInfo(evt.data);
1114
1148
  if (!shouldHandleWakeEvent(info, this.agent.id))
1115
1149
  continue;
1150
+ if (info.resetState) {
1151
+ console.log(`[${this.agent.id}/${this.adapter.id}] reset-state wake received; clearing local agent home and engine session`);
1152
+ this.handleResetLocalState();
1153
+ break;
1154
+ }
1116
1155
  const conversationId = info.conversationId;
1117
1156
  if (evt.event === "steer") {
1118
1157
  if (conversationId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suwujs/king-ai",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "King AI, a local BYOA agent daemon that bridges remote runtime events to Claude or Codex CLI.",
5
5
  "type": "module",
6
6
  "bin": {