zencode-cli 0.2.2 → 0.2.3

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.
@@ -56,6 +56,7 @@ var init_client = __esm({
56
56
  params.tools = tools;
57
57
  params.tool_choice = "auto";
58
58
  }
59
+ params.stream_options = { include_usage: true };
59
60
  const abortController = new AbortController();
60
61
  this.activeAbortController = abortController;
61
62
  try {
@@ -67,7 +68,16 @@ var init_client = __esm({
67
68
  let reasoningStarted = false;
68
69
  let reasoningEnded = false;
69
70
  const toolCallMap = /* @__PURE__ */ new Map();
71
+ let usageInfo = null;
70
72
  for await (const chunk of stream) {
73
+ const chunkUsage = chunk.usage;
74
+ if (chunkUsage && chunkUsage.total_tokens) {
75
+ usageInfo = {
76
+ prompt_tokens: chunkUsage.prompt_tokens ?? 0,
77
+ completion_tokens: chunkUsage.completion_tokens ?? 0,
78
+ total_tokens: chunkUsage.total_tokens
79
+ };
80
+ }
71
81
  const choice = chunk.choices[0];
72
82
  if (!choice) continue;
73
83
  const delta = choice.delta;
@@ -140,6 +150,9 @@ var init_client = __esm({
140
150
  if (toolCalls.length > 0) {
141
151
  assistantMessage.tool_calls = toolCalls;
142
152
  }
153
+ if (usageInfo) {
154
+ assistantMessage.usage = usageInfo;
155
+ }
143
156
  callbacks.onFinish?.(assistantMessage);
144
157
  return assistantMessage;
145
158
  } catch (error) {
@@ -193,6 +206,13 @@ var init_client = __esm({
193
206
  }
194
207
  }));
195
208
  }
209
+ if (response.usage) {
210
+ result.usage = {
211
+ prompt_tokens: response.usage.prompt_tokens,
212
+ completion_tokens: response.usage.completion_tokens,
213
+ total_tokens: response.usage.total_tokens
214
+ };
215
+ }
196
216
  return result;
197
217
  }
198
218
  get modelName() {
@@ -1600,7 +1620,8 @@ var init_sub_agent = __esm({
1600
1620
  allowedTools;
1601
1621
  maxTurns;
1602
1622
  timeoutMs;
1603
- constructor(client, registry, config, task, allowedTools = ["read-file", "glob", "grep"], maxTurns = 10, timeoutMs = DEFAULT_TIMEOUT_MS) {
1623
+ tracker;
1624
+ constructor(client, registry, config, task, allowedTools = ["read-file", "glob", "grep"], maxTurns = 10, timeoutMs = DEFAULT_TIMEOUT_MS, tracker) {
1604
1625
  this.client = client;
1605
1626
  this.registry = registry;
1606
1627
  this.config = config;
@@ -1608,6 +1629,7 @@ var init_sub_agent = __esm({
1608
1629
  this.allowedTools = allowedTools.filter((t) => t !== "spawn-agents" && t !== "todo");
1609
1630
  this.maxTurns = Math.min(maxTurns, 15);
1610
1631
  this.timeoutMs = timeoutMs;
1632
+ this.tracker = tracker;
1611
1633
  }
1612
1634
  async run() {
1613
1635
  return Promise.race([
@@ -1637,6 +1659,9 @@ var init_sub_agent = __esm({
1637
1659
  conversation.getMessages(),
1638
1660
  tools.length > 0 ? tools : void 0
1639
1661
  );
1662
+ if (assistantMsg.usage && this.tracker) {
1663
+ this.tracker.addTokens(assistantMsg.usage.total_tokens);
1664
+ }
1640
1665
  conversation.addAssistantMessage(assistantMsg);
1641
1666
  if (!assistantMsg.tool_calls || assistantMsg.tool_calls.length === 0) {
1642
1667
  lastContent = assistantMsg.content || "";
@@ -1760,7 +1785,7 @@ function createSpawnAgentsTool(client, registry, config, tracker) {
1760
1785
  if (tools.length === 0) {
1761
1786
  tools = DEFAULT_TOOLS.filter((t) => autoTools.includes(t));
1762
1787
  }
1763
- return new SubAgent(client, registry, config, task.description, tools, maxTurns);
1788
+ return new SubAgent(client, registry, config, task.description, tools, maxTurns, void 0, tracker);
1764
1789
  });
1765
1790
  const wrappedRuns = agents.map(
1766
1791
  (agent) => agent.run().then(
@@ -1929,11 +1954,13 @@ var init_runner = __esm({
1929
1954
  registry;
1930
1955
  config;
1931
1956
  agentConfig;
1932
- constructor(client, registry, config, agentConfig) {
1957
+ tracker;
1958
+ constructor(client, registry, config, agentConfig, tracker) {
1933
1959
  this.client = client;
1934
1960
  this.registry = registry;
1935
1961
  this.config = config;
1936
1962
  this.agentConfig = agentConfig;
1963
+ this.tracker = tracker;
1937
1964
  }
1938
1965
  /**
1939
1966
  * 执行子 Agent 任务
@@ -1974,6 +2001,9 @@ ${context}`;
1974
2001
  tools.length > 0 ? tools : void 0,
1975
2002
  callbacks
1976
2003
  );
2004
+ if (assistantMsg.usage && this.tracker) {
2005
+ this.tracker.addTokens(assistantMsg.usage.total_tokens);
2006
+ }
1977
2007
  conversation.addAssistantMessage(assistantMsg);
1978
2008
  if (!assistantMsg.tool_calls || assistantMsg.tool_calls.length === 0) {
1979
2009
  lastContent = assistantMsg.content || "";
@@ -2058,7 +2088,7 @@ ${context}`;
2058
2088
  });
2059
2089
 
2060
2090
  // src/tools/dispatch.ts
2061
- function createDispatchTool(defaultClient, toolRegistry, config, agentRegistry, callbacks) {
2091
+ function createDispatchTool(defaultClient, toolRegistry, config, agentRegistry, tracker, callbacks) {
2062
2092
  return {
2063
2093
  name: "dispatch",
2064
2094
  description: "\u8C03\u5EA6\u5B50 Agent \u6267\u884C\u4E13\u95E8\u4EFB\u52A1\u3002\u5B50 Agent \u6709\u72EC\u7ACB\u5BF9\u8BDD\u548C\u4E13\u5C5E\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF0C\u9002\u7528\u4E8E\u9700\u8981\u4E13\u4E1A\u89D2\u8272\u7684\u573A\u666F\u3002",
@@ -2100,11 +2130,14 @@ function createDispatchTool(defaultClient, toolRegistry, config, agentRegistry,
2100
2130
  maxTokens: config.max_tokens
2101
2131
  });
2102
2132
  }
2103
- const runner = new SubAgentRunner(client, toolRegistry, config, agentConfig);
2133
+ const runner = new SubAgentRunner(client, toolRegistry, config, agentConfig, tracker);
2134
+ tracker?.start([`${agentName}: ${task.slice(0, 60)}`]);
2104
2135
  try {
2105
2136
  const result = await runner.execute(task, context, callbacks?.() ?? {});
2137
+ tracker?.finish();
2106
2138
  return { content: result || "\uFF08\u5B50 Agent \u6267\u884C\u5B8C\u6210\uFF0C\u65E0\u8F93\u51FA\uFF09" };
2107
2139
  } catch (err) {
2140
+ tracker?.finish();
2108
2141
  const msg = err instanceof Error ? err.message : String(err);
2109
2142
  return { content: `\u5B50 Agent \u6267\u884C\u9519\u8BEF\uFF1A${msg}` };
2110
2143
  }
@@ -2407,7 +2440,8 @@ var init_sub_agent_tracker = __esm({
2407
2440
  total: descriptions.length,
2408
2441
  completed: 0,
2409
2442
  failed: 0,
2410
- descriptions
2443
+ descriptions,
2444
+ tokens: 0
2411
2445
  };
2412
2446
  this.notify();
2413
2447
  }
@@ -2421,6 +2455,11 @@ var init_sub_agent_tracker = __esm({
2421
2455
  this.progress = { ...this.progress, failed: this.progress.failed + 1 };
2422
2456
  this.notify();
2423
2457
  }
2458
+ addTokens(count) {
2459
+ if (!this.progress) return;
2460
+ this.progress = { ...this.progress, tokens: this.progress.tokens + count };
2461
+ this.notify();
2462
+ }
2424
2463
  finish() {
2425
2464
  this.progress = null;
2426
2465
  this.notify();
@@ -2712,9 +2751,21 @@ function getToolParamSummary(name, params) {
2712
2751
  case "glob":
2713
2752
  case "grep":
2714
2753
  return String(params["pattern"] || "");
2754
+ case "spawn-agents": {
2755
+ const tasks = params["tasks"];
2756
+ if (!tasks || tasks.length === 0) return "";
2757
+ return `${tasks.length} tasks: ${tasks.map((t) => t.description || "?").join(" | ").slice(0, 100)}`;
2758
+ }
2759
+ case "dispatch":
2760
+ return `${params["agent"] || "?"}: ${String(params["task"] || "").slice(0, 80)}`;
2715
2761
  default:
2716
2762
  const keys = Object.keys(params);
2717
- return keys.length > 0 ? String(params[keys[0]] || "").slice(0, 60) : "";
2763
+ if (keys.length === 0) return "";
2764
+ const val = params[keys[0]];
2765
+ if (val === null || val === void 0) return "";
2766
+ if (typeof val === "string") return val.slice(0, 60);
2767
+ if (typeof val === "number" || typeof val === "boolean") return String(val);
2768
+ return JSON.stringify(val).slice(0, 60);
2718
2769
  }
2719
2770
  }
2720
2771
  function truncateContent(text, maxLines) {
@@ -2972,6 +3023,11 @@ var init_InputArea = __esm({
2972
3023
  // src/cli/tui/components/StatusBar.tsx
2973
3024
  import { Box as Box5, Text as Text4 } from "ink";
2974
3025
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
3026
+ function formatTokens(n) {
3027
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
3028
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
3029
+ return String(n);
3030
+ }
2975
3031
  function StatusBar({ isRunning, modelName, todoPlan, subAgentProgress }) {
2976
3032
  const todoProgress = todoPlan ? `${todoPlan.items.filter((i) => i.status === "completed").length}/${todoPlan.items.length}` : null;
2977
3033
  return /* @__PURE__ */ jsxs4(Box5, { marginTop: 1, children: [
@@ -2985,16 +3041,21 @@ function StatusBar({ isRunning, modelName, todoPlan, subAgentProgress }) {
2985
3041
  subAgentProgress && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2986
3042
  /* @__PURE__ */ jsx5(Text4, { color: "#ebdbb2", children: " \u2502 " }),
2987
3043
  /* @__PURE__ */ jsxs4(Text4, { color: "#b8bb26", children: [
2988
- "\u{1F916} Agents: ",
3044
+ "Agents: ",
2989
3045
  subAgentProgress.completed + subAgentProgress.failed,
2990
3046
  "/",
2991
3047
  subAgentProgress.total
3048
+ ] }),
3049
+ /* @__PURE__ */ jsx5(Text4, { color: "#ebdbb2", children: " \u2502 " }),
3050
+ /* @__PURE__ */ jsxs4(Text4, { color: "#83a598", children: [
3051
+ "tokens: ",
3052
+ formatTokens(subAgentProgress.tokens)
2992
3053
  ] })
2993
3054
  ] }),
2994
3055
  todoProgress && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2995
3056
  /* @__PURE__ */ jsx5(Text4, { color: "#ebdbb2", children: " \u2502 " }),
2996
3057
  /* @__PURE__ */ jsxs4(Text4, { color: "#fabd2f", children: [
2997
- "\u{1F4CB} Plan: ",
3058
+ "Plan: ",
2998
3059
  todoProgress
2999
3060
  ] })
3000
3061
  ] })
@@ -3687,7 +3748,7 @@ async function startTui(options) {
3687
3748
  if (config.features.todo === "on") {
3688
3749
  registry.register(createTodoTool(todoStore));
3689
3750
  }
3690
- registry.register(createDispatchTool(client, registry, config, agentRegistry));
3751
+ registry.register(createDispatchTool(client, registry, config, agentRegistry, subAgentTracker));
3691
3752
  const agent = new Agent(client, registry, config, systemPrompt);
3692
3753
  const { waitUntilExit } = render(
3693
3754
  /* @__PURE__ */ jsx10(
@@ -4234,7 +4295,7 @@ async function runOnce(prompt, config) {
4234
4295
  }
4235
4296
  function createCli() {
4236
4297
  const program2 = new Command();
4237
- program2.name("zencode").description("\u6781\u7B80 CLI AI \u7F16\u7A0B\u5DE5\u5177").version("0.2.1").option("-m, --model <model>", "\u6307\u5B9A\u6A21\u578B\u540D\u79F0").option("-k, --api-key <key>", "API \u5BC6\u94A5").option("-u, --base-url <url>", "API \u57FA\u7840 URL").option("--simple", "\u4F7F\u7528\u7B80\u5355 REPL \u6A21\u5F0F\uFF08\u975E\u5168\u5C4F TUI\uFF09").argument("[prompt...]", "\u76F4\u63A5\u6267\u884C\u7684\u63D0\u793A\u8BCD\uFF08\u975E\u4EA4\u4E92\u5F0F\uFF09").action(async (promptParts, opts) => {
4298
+ program2.name("zencode").description("\u6781\u7B80 CLI AI \u7F16\u7A0B\u5DE5\u5177").version("0.2.3").option("-m, --model <model>", "\u6307\u5B9A\u6A21\u578B\u540D\u79F0").option("-k, --api-key <key>", "API \u5BC6\u94A5").option("-u, --base-url <url>", "API \u57FA\u7840 URL").option("--simple", "\u4F7F\u7528\u7B80\u5355 REPL \u6A21\u5F0F\uFF08\u975E\u5168\u5C4F TUI\uFF09").argument("[prompt...]", "\u76F4\u63A5\u6267\u884C\u7684\u63D0\u793A\u8BCD\uFF08\u975E\u4EA4\u4E92\u5F0F\uFF09").action(async (promptParts, opts) => {
4238
4299
  const config = loadConfig(opts);
4239
4300
  if (!config.api_key) {
4240
4301
  printError("\u672A\u8BBE\u7F6E API \u5BC6\u94A5\u3002\u8BF7\u901A\u8FC7\u4EE5\u4E0B\u65B9\u5F0F\u4E4B\u4E00\u8BBE\u7F6E\uFF1A");