@wagemule/daemon 0.1.8 → 0.1.10

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/main.cjs CHANGED
@@ -1837,7 +1837,11 @@ var KimiAdapter = class {
1837
1837
  });
1838
1838
  this.lines = import_node_readline4.default.createInterface({ input: this.child.stdout });
1839
1839
  this.lines.on("line", (line) => this.handleLine(line));
1840
- this.writeWire("initialize", { clientInfo: { name: "wm-daemon", version: "0.0.1" } });
1840
+ this.writeWire("initialize", {
1841
+ protocol_version: "1.10",
1842
+ client: { name: "wm-daemon", version: "0.0.1" },
1843
+ capabilities: { supports_question: false, supports_plan_mode: false }
1844
+ });
1841
1845
  }
1842
1846
  async prompt(input) {
1843
1847
  const startInput = this.startInput;
@@ -1878,8 +1882,17 @@ var KimiAdapter = class {
1878
1882
  if (input.abortSignal?.aborted) throw new Error("Runtime aborted");
1879
1883
  input.abortSignal?.addEventListener("abort", abortHandler, { once: true });
1880
1884
  events.push({ type: "task_delivered", content: input.prompt });
1881
- this.writeWire("prompt", { prompt: input.prompt, sessionId: this.sessionId });
1885
+ this.active.promptRequestId = this.writeWire("prompt", { user_input: input.prompt });
1882
1886
  await withTimeout(turnFinished, input.timeoutMs ?? 18e4, "Kimi wire turn timeout");
1887
+ if (this.active.errorMessage) {
1888
+ return {
1889
+ status: this.active.status ?? "runtime_error",
1890
+ finalMessage,
1891
+ runtimeSessionId: this.sessionId,
1892
+ events,
1893
+ errorMessage: this.active.errorMessage
1894
+ };
1895
+ }
1883
1896
  return { status: "ok", finalMessage, runtimeSessionId: this.sessionId, events };
1884
1897
  } catch (error) {
1885
1898
  return {
@@ -1908,20 +1921,34 @@ var KimiAdapter = class {
1908
1921
  this.child = null;
1909
1922
  }
1910
1923
  writeWire(method, params) {
1911
- this.child?.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id: this.nextId++, method, params })}
1924
+ const id = String(this.nextId++);
1925
+ this.child?.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
1912
1926
  `);
1927
+ return id;
1913
1928
  }
1914
1929
  handleLine(line) {
1915
- const parsed = parseStreamJsonLine("kimi", line);
1930
+ const parsed = parseKimiWireLine(line);
1916
1931
  if (!parsed) return;
1917
- if (parsed.sessionId) this.sessionId = parsed.sessionId;
1918
1932
  const active = this.active;
1919
1933
  const runInput = active?.runInput ?? (this.startInput ? { ...this.startInput, prompt: "" } : void 0);
1920
1934
  if (!runInput) return;
1935
+ if (parsed.errorMessage && active && parsed.id === active.promptRequestId) {
1936
+ active.errorMessage = parsed.errorMessage;
1937
+ active.status = "runtime_error";
1938
+ active.events.push({ type: "runtime_error", content: parsed.errorMessage, data: parsed.data });
1939
+ runInput.onEvent?.({ type: "runtime_error", content: parsed.errorMessage, data: parsed.data });
1940
+ active.finish();
1941
+ return;
1942
+ }
1921
1943
  if (active) {
1944
+ if (parsed.retry) active.lastRetry = parsed.retry;
1945
+ if (parsed.interrupted) {
1946
+ active.status = "runtime_error";
1947
+ active.errorMessage = kimiInterruptedMessage(active.lastRetry);
1948
+ }
1922
1949
  if (parsed.appendFinalMessage) active.append(parsed.appendFinalMessage);
1923
1950
  if (parsed.finalMessage) active.set(parsed.finalMessage);
1924
- if (parsed.events.some((event) => event.type === "turn_finished")) active.finish();
1951
+ if (parsed.finished || parsed.events.some((event) => event.type === "turn_finished")) active.finish();
1925
1952
  for (const event of parsed.events) {
1926
1953
  active.events.push(event);
1927
1954
  runInput.onEvent?.(event);
@@ -1929,6 +1956,103 @@ var KimiAdapter = class {
1929
1956
  }
1930
1957
  }
1931
1958
  };
1959
+ function parseKimiWireLine(line) {
1960
+ if (!line.trim()) return void 0;
1961
+ let value;
1962
+ try {
1963
+ value = JSON.parse(line);
1964
+ } catch {
1965
+ return {
1966
+ appendFinalMessage: `${line}
1967
+ `,
1968
+ events: [{ type: "runtime_stdout", content: line }]
1969
+ };
1970
+ }
1971
+ const msg = value;
1972
+ const id = typeof msg.id === "string" ? msg.id : void 0;
1973
+ if (msg.error && typeof msg.error === "object") {
1974
+ const error = msg.error;
1975
+ return {
1976
+ id,
1977
+ errorMessage: typeof error.message === "string" ? error.message : "Kimi wire request failed",
1978
+ data: msg,
1979
+ events: []
1980
+ };
1981
+ }
1982
+ if (msg.result && typeof msg.result === "object") {
1983
+ const result = msg.result;
1984
+ const status = typeof result.status === "string" ? result.status : void 0;
1985
+ return {
1986
+ id,
1987
+ finished: status === "finished" || status === "cancelled" || status === "max_steps_reached",
1988
+ data: msg,
1989
+ events: status ? [{ type: "turn_finished", data: { runtime: "kimi", status, result } }] : [{ type: "runtime_started", data: { runtime: "kimi", result } }]
1990
+ };
1991
+ }
1992
+ if (msg.method !== "event" || !msg.params || typeof msg.params !== "object") {
1993
+ return { id, events: [{ type: "runtime_event", data: msg }] };
1994
+ }
1995
+ const params = msg.params;
1996
+ const eventType = typeof params.type === "string" ? params.type : "runtime_event";
1997
+ const payload = params.payload && typeof params.payload === "object" ? params.payload : {};
1998
+ const text = stringValue5(payload.text) ?? stringValue5(payload.content) ?? stringValue5(payload.message) ?? stringValue5(payload.delta?.text);
1999
+ if ((eventType === "TextPart" || eventType === "ContentPart") && text) {
2000
+ return {
2001
+ appendFinalMessage: text,
2002
+ events: [{ type: "assistant_delta", content: text, data: msg }]
2003
+ };
2004
+ }
2005
+ if (eventType === "TurnEnd") {
2006
+ return { finished: true, events: [{ type: "turn_finished", data: msg }] };
2007
+ }
2008
+ if (eventType === "ToolCallPart") {
2009
+ return { events: [] };
2010
+ }
2011
+ if (eventType === "ToolCall") {
2012
+ return {
2013
+ events: [{ type: "tool_start", content: text ?? stringValue5(payload.name), data: msg }]
2014
+ };
2015
+ }
2016
+ if (eventType === "ToolResult") {
2017
+ return {
2018
+ events: [{ type: "tool_result", content: text, data: msg }]
2019
+ };
2020
+ }
2021
+ if (eventType === "StepRetry") {
2022
+ return {
2023
+ retry: kimiRetryInfo(payload),
2024
+ events: [{ type: "runtime_event", content: text, data: msg }]
2025
+ };
2026
+ }
2027
+ if (eventType === "StepInterrupted") {
2028
+ return {
2029
+ interrupted: true,
2030
+ events: [{ type: "runtime_error", content: "Kimi step interrupted", data: msg }]
2031
+ };
2032
+ }
2033
+ return {
2034
+ events: [{ type: kimiEventName(eventType), content: text, data: msg }]
2035
+ };
2036
+ }
2037
+ function kimiEventName(eventType) {
2038
+ if (/begin|status|loading|retry|compaction|hook|notification/i.test(eventType)) return "runtime_event";
2039
+ return eventType;
2040
+ }
2041
+ function kimiRetryInfo(payload) {
2042
+ const statusCode = typeof payload.status_code === "number" ? payload.status_code : void 0;
2043
+ const errorType = typeof payload.error_type === "string" ? payload.error_type : void 0;
2044
+ return { errorType, statusCode };
2045
+ }
2046
+ function kimiInterruptedMessage(retry) {
2047
+ if (retry?.statusCode) {
2048
+ const type = retry.errorType ? `${retry.errorType} ` : "";
2049
+ return `Kimi step interrupted after ${type}${retry.statusCode}`;
2050
+ }
2051
+ return "Kimi step interrupted";
2052
+ }
2053
+ function stringValue5(value) {
2054
+ return typeof value === "string" ? value : void 0;
2055
+ }
1932
2056
  function kimiAgentYaml() {
1933
2057
  return [
1934
2058
  "version: 1",
@@ -3853,21 +3977,21 @@ function renderRuntimeLine(context, line) {
3853
3977
  function extractTextFromRuntimeJsonLine(line) {
3854
3978
  try {
3855
3979
  const record = JSON.parse(line);
3856
- const direct = stringValue5(record.result ?? record.text ?? record.content);
3980
+ const direct = stringValue6(record.result ?? record.text ?? record.content);
3857
3981
  if (direct) return direct;
3858
3982
  const message = record.message;
3859
- const messageText = message ? stringValue5(message.text ?? message.content) : void 0;
3983
+ const messageText = message ? stringValue6(message.text ?? message.content) : void 0;
3860
3984
  if (messageText) return messageText;
3861
3985
  const content = Array.isArray(message?.content) ? message?.content : [];
3862
3986
  const parts = content.map(
3863
- (part) => typeof part === "object" && part ? stringValue5(part.text) : void 0
3987
+ (part) => typeof part === "object" && part ? stringValue6(part.text) : void 0
3864
3988
  ).filter(Boolean);
3865
3989
  return parts.length > 0 ? parts.join("") : void 0;
3866
3990
  } catch {
3867
3991
  return line;
3868
3992
  }
3869
3993
  }
3870
- function stringValue5(value) {
3994
+ function stringValue6(value) {
3871
3995
  return typeof value === "string" && value.length > 0 ? value : void 0;
3872
3996
  }
3873
3997
  function writeLine(context, line) {
@@ -3891,7 +4015,7 @@ var import_ws = __toESM(require("ws"));
3891
4015
  // package.json
3892
4016
  var package_default = {
3893
4017
  name: "@wagemule/daemon",
3894
- version: "0.1.8",
4018
+ version: "0.1.10",
3895
4019
  private: false,
3896
4020
  description: "Wage Mule local daemon for connecting local agent runtimes to Workspace Server.",
3897
4021
  main: "./dist/main.cjs",
@@ -3915,7 +4039,7 @@ var package_default = {
3915
4039
  start: "node dist/main.cjs",
3916
4040
  prepack: "npm run build",
3917
4041
  "pack:check": "node scripts/pack-check.mjs",
3918
- test: "node --import tsx src/workspace/agent-workspace.test.ts && node --import tsx src/workspace/feishu-token-writer.test.ts && node --import tsx src/agent-manager/workspace-browser.test.ts && node --import tsx src/agent-manager/agent-process-manager.memory.test.ts && node --import tsx src/agent-manager/agent-process-manager.delivery.test.ts && node --import tsx src/agent-manager/agent-process-manager.model-validation.test.ts && node --import tsx src/agent-manager/skill-scanner.test.ts && node --import tsx src/runtime/capabilities.test.ts && node --import tsx src/runtime/model-detector.test.ts && node --import tsx src/runtime/persistent-adapter.test.ts && node --import tsx src/runtime/json-rpc-stdio-client.test.ts && node --import tsx src/runtime/acp-adapter.test.ts && node --import tsx src/runtime/codex-adapter.test.ts && node --import tsx src/runtime/claude-adapter.test.ts && node --import tsx src/testing/smoke-harness.test.ts && node --import tsx src/lab/lab-store.test.ts && node --import tsx src/lab/lab-ui.test.ts && node --import tsx src/lab/interactive-lab.test.ts && node --import tsx src/main.test.ts && node --import tsx src/testing/integration.test.ts",
4042
+ test: "node --import tsx src/workspace/agent-workspace.test.ts && node --import tsx src/workspace/feishu-token-writer.test.ts && node --import tsx src/agent-manager/workspace-browser.test.ts && node --import tsx src/agent-manager/agent-process-manager.memory.test.ts && node --import tsx src/agent-manager/agent-process-manager.delivery.test.ts && node --import tsx src/agent-manager/agent-process-manager.model-validation.test.ts && node --import tsx src/agent-manager/skill-scanner.test.ts && node --import tsx src/runtime/capabilities.test.ts && node --import tsx src/runtime/model-detector.test.ts && node --import tsx src/runtime/persistent-adapter.test.ts && node --import tsx src/runtime/json-rpc-stdio-client.test.ts && node --import tsx src/runtime/acp-adapter.test.ts && node --import tsx src/runtime/codex-adapter.test.ts && node --import tsx src/runtime/claude-adapter.test.ts && node --import tsx src/runtime/kimi-adapter.test.ts && node --import tsx src/testing/smoke-harness.test.ts && node --import tsx src/lab/lab-store.test.ts && node --import tsx src/lab/lab-ui.test.ts && node --import tsx src/lab/interactive-lab.test.ts && node --import tsx src/main.test.ts && node --import tsx src/testing/integration.test.ts",
3919
4043
  "test:real": "node --import tsx src/testing/integration-real.test.ts",
3920
4044
  typecheck: "tsc --noEmit"
3921
4045
  },
@@ -4075,7 +4199,7 @@ function summarizeDaemonMessage(msg) {
4075
4199
  return base;
4076
4200
  }
4077
4201
  function shouldLogDaemonMessage(msg) {
4078
- return !(msg.type === "agent:activity" && msg.detail === "assistant_delta");
4202
+ return !(msg.type === "agent:activity" && (msg.detail === "assistant_delta" || msg.detail === "tool_progress"));
4079
4203
  }
4080
4204
  function summarizeServerMessage(msg) {
4081
4205
  const base = `type=${msg.type}`;
@@ -4311,20 +4435,24 @@ ${stderr}`);
4311
4435
  };
4312
4436
  function parseKimiModelConfig(configText) {
4313
4437
  const ids = [];
4438
+ const labels = /* @__PURE__ */ new Map();
4314
4439
  let defaultModel;
4315
4440
  let section;
4441
+ let currentModelKey;
4316
4442
  for (const rawLine of configText.split(/\r?\n/)) {
4317
4443
  const line = stripYamlComment(rawLine).trim();
4318
4444
  if (!line) continue;
4319
4445
  const table = line.match(/^\[models\.([^\]]+)]$/);
4320
4446
  if (table) {
4321
- section = `models.${unquote(table[1].trim())}`;
4322
- pushUnique(ids, section.slice("models.".length));
4447
+ currentModelKey = unquote(table[1].trim());
4448
+ section = `models.${currentModelKey}`;
4449
+ pushUnique(ids, currentModelKey);
4323
4450
  continue;
4324
4451
  }
4325
4452
  const anyTable = line.match(/^\[([^\]]+)]$/);
4326
4453
  if (anyTable) {
4327
4454
  section = anyTable[1]?.trim();
4455
+ currentModelKey = void 0;
4328
4456
  continue;
4329
4457
  }
4330
4458
  const defaultModelLine = line.match(/^default_model\s*=\s*["']?([^"']+)["']?\s*$/);
@@ -4333,7 +4461,11 @@ function parseKimiModelConfig(configText) {
4333
4461
  pushUnique(ids, defaultModel);
4334
4462
  continue;
4335
4463
  }
4336
- if (section?.startsWith("models.")) continue;
4464
+ if (section?.startsWith("models.")) {
4465
+ const model2 = line.match(/^model\s*=\s*["']?([^"']+)["']?\s*$/);
4466
+ if (model2 && currentModelKey) labels.set(currentModelKey, model2[1].trim());
4467
+ continue;
4468
+ }
4337
4469
  const model = line.match(/^model\s*=\s*["']?([^"']+)["']?\s*$/);
4338
4470
  if (model) {
4339
4471
  const value = model[1]?.trim();
@@ -4348,6 +4480,7 @@ function parseKimiModelConfig(configText) {
4348
4480
  }
4349
4481
  const models = ids.map((id) => ({
4350
4482
  ...defaultReasoningModel(id, id === defaultModel),
4483
+ label: labels.get(id) ?? id,
4351
4484
  default: id === defaultModel ? true : void 0
4352
4485
  }));
4353
4486
  return { models: normalizeDefault(models, defaultModel), defaultModel };
@@ -4861,6 +4994,7 @@ function shellQuote(value) {
4861
4994
  // src/agent-manager/activity-tracker.ts
4862
4995
  var ActivityTracker = class {
4863
4996
  clientSeq = 0;
4997
+ lastProgressAt = /* @__PURE__ */ new Map();
4864
4998
  toEntries(events) {
4865
4999
  return events.flatMap((event) => this.toEntry(event));
4866
5000
  }
@@ -4868,6 +5002,13 @@ var ActivityTracker = class {
4868
5002
  this.clientSeq += 1;
4869
5003
  return this.clientSeq;
4870
5004
  }
5005
+ shouldPublishProgress(key, intervalMs) {
5006
+ const now = Date.now();
5007
+ const last = this.lastProgressAt.get(key) ?? 0;
5008
+ if (now - last < intervalMs) return false;
5009
+ this.lastProgressAt.set(key, now);
5010
+ return true;
5011
+ }
4871
5012
  toEntry(event) {
4872
5013
  const timestamp = Date.now();
4873
5014
  if (event.type.includes("tool")) {
@@ -5136,11 +5277,13 @@ var AgentProcessManager = class {
5136
5277
  "Feishu delegation tick.",
5137
5278
  `Human ID: ${delegation.human_id}`,
5138
5279
  `Delegation ID: ${delegation.id}`,
5139
- `Read Feishu messages from the last ${lookbackMinutes} minutes only. Never send, reply, react, or mutate Feishu during this tick.`,
5140
- "For each new inbound Feishu message that needs a reply, draft a concise reply and create exactly one inbox item with:",
5280
+ `Read Feishu messages from the last ${lookbackMinutes} minutes only by using the injected .wm/lark-cli wrapper and the lark-im skill. Do not use runtime TaskList or background task tools for Feishu messages.`,
5281
+ "For each new inbound Feishu message that needs a reply, first create exactly one inbox item as the dedupe/process record:",
5141
5282
  "wm inbox feishu-draft create --delegation-id <delegation_id> --human-id <human_id> --feishu-message-id <message_id> --chat-id <chat_id> --sender-name <name> --sender-open-id <open_id> --original-text <summary> --draft-text <draft>",
5142
- "Deduplicate by Feishu message_id. If there are no new relevant messages, do nothing.",
5143
- "Do not call lark-cli im +messages-send or any other Feishu send command unless a later approved inbox task explicitly asks you to send."
5283
+ "If the reply is low-risk and routine, send exactly that draft once with lark-cli im +messages-reply or lark-cli im +messages-send, then run: wm inbox feishu-draft sent --id <Inbox ID> --message-id <sent message_id>",
5284
+ "If the reply is uncertain, sensitive, or high-risk, do not send it; leave the inbox item open for human approval.",
5285
+ "If sending fails, run: wm inbox feishu-draft failed --id <Inbox ID> --error <short error>.",
5286
+ "Deduplicate by Feishu message_id. If there are no new relevant messages, do nothing."
5144
5287
  ].join("\n")
5145
5288
  };
5146
5289
  void this.enqueueStart({
@@ -5536,7 +5679,9 @@ var AgentProcessManager = class {
5536
5679
  deltaLogCount += 1;
5537
5680
  } else {
5538
5681
  flushDeltaLog();
5539
- this.log(`runtime event agent=${agentId} type=${event.type}${event.content ? ` text=${compact(event.content)}` : ""}`);
5682
+ if (event.type !== "tool_progress") {
5683
+ this.log(`runtime event agent=${agentId} type=${event.type}${event.content ? ` text=${compact(event.content)}` : ""}`);
5684
+ }
5540
5685
  }
5541
5686
  const running = this.running.get(agentId);
5542
5687
  if (running) {
@@ -5569,6 +5714,7 @@ var AgentProcessManager = class {
5569
5714
  }
5570
5715
  }
5571
5716
  const entries = tracker.toEntries([event]);
5717
+ if (event.type === "tool_progress" && !tracker.shouldPublishProgress("tool_progress", 1e3)) return;
5572
5718
  this.sendActivity({
5573
5719
  agentId,
5574
5720
  activity: "working",