@jun133/athlete 0.0.2 → 0.0.4

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/README.md CHANGED
@@ -131,7 +131,7 @@ Athlete 想坚持的,不是“让模型显得更聪明”,而是让任务真
131
131
  | `athlete weixin serve` | 启动 Weixin 私聊服务 |
132
132
  | `athlete weixin logout` | 清理 Weixin 登录态 |
133
133
 
134
- 文档读取能力依赖 `MINERU_API_TOKEN`。Telegram 需要 `ATHLETE_TELEGRAM_TOKEN` 和 `ATHLETE_TELEGRAM_ALLOWED_USER_IDS`。Weixin 需要先执行 `athlete weixin login`,再配置 `ATHLETE_WEIXIN_ALLOWED_USER_IDS`。
134
+ 文档读取能力依赖 `MINERU_API_TOKEN`。Telegram 需要 `ATHLETE_TELEGRAM_TOKEN` 和 `ATHLETE_TELEGRAM_ALLOWED_USER_IDS`。Weixin 需要先执行 `athlete weixin login`,再配置 `ATHLETE_WEIXIN_ALLOWED_USER_IDS`。Telegram 和 Weixin 私聊里都支持 `/stop`,用于停止当前任务但不关闭服务。
135
135
 
136
136
  ### NPM 发布
137
137
 
package/dist/cli.js CHANGED
@@ -14707,6 +14707,9 @@ async function runAgentTurn(options) {
14707
14707
  emitAssistantFinalOutput(response, options);
14708
14708
  return completed.result;
14709
14709
  }
14710
+ if (response.content && !response.streamedAssistantContent) {
14711
+ options.callbacks?.onAssistantStage?.(response.content);
14712
+ }
14710
14713
  session = await options.sessionStore.appendMessages(session, [
14711
14714
  createMessage("assistant", response.content, {
14712
14715
  reasoningContent: response.reasoningContent,
@@ -16673,6 +16676,13 @@ function createStreamRenderer(config, options) {
16673
16676
  beginAssistant();
16674
16677
  writeStdout(delta);
16675
16678
  },
16679
+ onAssistantStage(text) {
16680
+ if (isAborted()) {
16681
+ return;
16682
+ }
16683
+ beginAssistant();
16684
+ writeStdout(text);
16685
+ },
16676
16686
  onAssistantText(text) {
16677
16687
  if (isAborted()) {
16678
16688
  return;
@@ -18891,6 +18901,7 @@ function normalizeCaption(value) {
18891
18901
  }
18892
18902
 
18893
18903
  // src/chat/visibleEvents.ts
18904
+ var TOOL_RESULT_PREVIEW_MAX_CHARS2 = 150;
18894
18905
  function createVisibleTurnCallbacks(options) {
18895
18906
  const assistantState = {
18896
18907
  bufferedDeltaText: "",
@@ -18900,6 +18911,22 @@ function createVisibleTurnCallbacks(options) {
18900
18911
  assistantState.bufferedDeltaText = "";
18901
18912
  assistantState.finalizedByTextEvent = false;
18902
18913
  };
18914
+ const flushBufferedAssistantStage = () => {
18915
+ if (assistantState.bufferedDeltaText.length === 0) {
18916
+ return;
18917
+ }
18918
+ emitAssistantStage(options, assistantState.bufferedDeltaText);
18919
+ resetAssistantStage();
18920
+ };
18921
+ const handleBufferedAssistantBeforeToolEvent = () => {
18922
+ if (options.flushBufferedAssistantBeforeToolEvents) {
18923
+ flushBufferedAssistantStage();
18924
+ return;
18925
+ }
18926
+ if (options.dropBufferedAssistantBeforeToolEvents) {
18927
+ resetAssistantStage();
18928
+ }
18929
+ };
18903
18930
  return {
18904
18931
  onModelWaitStart: () => {
18905
18932
  options.onActivity();
@@ -18920,6 +18947,14 @@ function createVisibleTurnCallbacks(options) {
18920
18947
  assistantState.bufferedDeltaText = "";
18921
18948
  assistantState.finalizedByTextEvent = true;
18922
18949
  },
18950
+ onAssistantStage: (text) => {
18951
+ options.onActivity();
18952
+ if (!options.enableAssistantStageEvents) {
18953
+ return;
18954
+ }
18955
+ emitAssistantStage(options, text);
18956
+ resetAssistantStage();
18957
+ },
18923
18958
  onAssistantDone: (text) => {
18924
18959
  options.onActivity();
18925
18960
  if (assistantState.bufferedDeltaText.length > 0) {
@@ -18943,11 +18978,14 @@ function createVisibleTurnCallbacks(options) {
18943
18978
  },
18944
18979
  onToolCall: (name) => {
18945
18980
  options.onActivity();
18981
+ handleBufferedAssistantBeforeToolEvent();
18946
18982
  emitNormalizedVisibleText(options, "tool_call", name);
18947
18983
  },
18948
18984
  onToolResult: (name, output) => {
18949
18985
  options.onActivity();
18986
+ handleBufferedAssistantBeforeToolEvent();
18950
18987
  if (name !== "todo_write") {
18988
+ emitNormalizedVisibleText(options, "tool_result_preview", extractToolResultPreview(output));
18951
18989
  return;
18952
18990
  }
18953
18991
  const preview = extractTodoPreview(output);
@@ -18955,6 +18993,7 @@ function createVisibleTurnCallbacks(options) {
18955
18993
  },
18956
18994
  onToolError: () => {
18957
18995
  options.onActivity();
18996
+ handleBufferedAssistantBeforeToolEvent();
18958
18997
  },
18959
18998
  onModelWaitStop: () => {
18960
18999
  return;
@@ -18972,6 +19011,11 @@ function extractTodoPreview(rawOutput) {
18972
19011
  }
18973
19012
  return null;
18974
19013
  }
19014
+ function extractToolResultPreview(rawOutput) {
19015
+ const parsed = tryParseVisibleObject(rawOutput);
19016
+ const preview = extractPrimaryPreview(parsed) ?? extractEntriesPreview(parsed) ?? extractMatchesPreview(parsed) ?? rawOutput;
19017
+ return truncateVisibleText(preview, TOOL_RESULT_PREVIEW_MAX_CHARS2);
19018
+ }
18975
19019
  function emitAssistantText(options, rawText) {
18976
19020
  emitExactVisibleText(options, "assistant", rawText);
18977
19021
  }
@@ -19011,6 +19055,76 @@ function normalizeVisibleText(value) {
19011
19055
  }
19012
19056
  return value.trim() ? value : "";
19013
19057
  }
19058
+ function truncateVisibleText(value, maxChars) {
19059
+ const normalized = normalizeVisibleText(
19060
+ typeof value === "string" ? value.replace(/\s+/g, " ").trim() : value
19061
+ );
19062
+ if (!normalized) {
19063
+ return null;
19064
+ }
19065
+ if (normalized.length <= maxChars) {
19066
+ return normalized;
19067
+ }
19068
+ return `${normalized.slice(0, maxChars)}...`;
19069
+ }
19070
+ function tryParseVisibleObject(rawOutput) {
19071
+ try {
19072
+ const parsed = JSON.parse(rawOutput);
19073
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
19074
+ return null;
19075
+ }
19076
+ return parsed;
19077
+ } catch {
19078
+ return null;
19079
+ }
19080
+ }
19081
+ function extractPrimaryPreview(payload) {
19082
+ if (!payload) {
19083
+ return null;
19084
+ }
19085
+ for (const key of ["preview", "content", "output", "markdownPreview", "error", "reason", "hint"]) {
19086
+ const value = payload[key];
19087
+ if (typeof value === "string" && value.trim().length > 0) {
19088
+ return value;
19089
+ }
19090
+ }
19091
+ return null;
19092
+ }
19093
+ function extractEntriesPreview(payload) {
19094
+ const entries = payload?.entries;
19095
+ if (!Array.isArray(entries) || entries.length === 0) {
19096
+ return null;
19097
+ }
19098
+ const fragments = entries.slice(0, 2).map((entry) => {
19099
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
19100
+ return null;
19101
+ }
19102
+ const record = entry;
19103
+ const type = record.type === "directory" ? "dir" : "file";
19104
+ const path59 = typeof record.path === "string" ? record.path : "";
19105
+ return path59 ? `${type} ${path59}` : null;
19106
+ }).filter((value) => Boolean(value));
19107
+ return fragments.length > 0 ? fragments.join(" ") : null;
19108
+ }
19109
+ function extractMatchesPreview(payload) {
19110
+ const matches = payload?.matches;
19111
+ if (!Array.isArray(matches) || matches.length === 0) {
19112
+ return null;
19113
+ }
19114
+ const first = matches[0];
19115
+ if (!first || typeof first !== "object" || Array.isArray(first)) {
19116
+ return null;
19117
+ }
19118
+ const record = first;
19119
+ const path59 = typeof record.path === "string" ? record.path : "";
19120
+ const text = typeof record.text === "string" ? record.text : "";
19121
+ const line = typeof record.line === "number" ? record.line : void 0;
19122
+ const prefix = path59 ? `${path59}${line ? `:${line}` : ""}` : "";
19123
+ if (prefix && text) {
19124
+ return `${prefix} ${text}`;
19125
+ }
19126
+ return prefix || text || null;
19127
+ }
19014
19128
 
19015
19129
  // src/chat/durableTurnDisplay.ts
19016
19130
  var DurableTurnDisplay = class {
@@ -19023,7 +19137,10 @@ var DurableTurnDisplay = class {
19023
19137
  onVisibleEvent: (event) => {
19024
19138
  this.enqueueVisibleText(event.text);
19025
19139
  },
19026
- shouldEmitEvent: options.shouldEmitEvent
19140
+ shouldEmitEvent: options.shouldEmitEvent,
19141
+ flushBufferedAssistantBeforeToolEvents: options.flushBufferedAssistantBeforeToolEvents,
19142
+ dropBufferedAssistantBeforeToolEvents: options.dropBufferedAssistantBeforeToolEvents,
19143
+ enableAssistantStageEvents: options.enableAssistantStageEvents
19027
19144
  });
19028
19145
  }
19029
19146
  callbacks;
@@ -19111,6 +19228,9 @@ var TelegramTurnDisplay = class extends DurableTurnDisplay {
19111
19228
  },
19112
19229
  sendTyping: async (target) => options.sendTyping(target.chatId),
19113
19230
  enqueueVisibleMessage: options.enqueueVisibleMessage,
19231
+ shouldEmitEvent: (event) => event.kind !== "tool_call",
19232
+ flushBufferedAssistantBeforeToolEvents: true,
19233
+ enableAssistantStageEvents: true,
19114
19234
  typingIntervalMs: options.typingIntervalMs,
19115
19235
  scheduleTypingTick: options.scheduleTypingTick
19116
19236
  });
@@ -20200,6 +20320,10 @@ function wrapCallbacksWithSpinnerStop(callbacks, stopSpinner) {
20200
20320
  stopSpinner();
20201
20321
  callbacks.onAssistantDelta?.(delta);
20202
20322
  },
20323
+ onAssistantStage(text) {
20324
+ stopSpinner();
20325
+ callbacks.onAssistantStage?.(text);
20326
+ },
20203
20327
  onAssistantDone(fullText) {
20204
20328
  stopSpinner();
20205
20329
  callbacks.onAssistantDone?.(fullText);
@@ -21667,7 +21791,8 @@ var WeixinTurnDisplay = class extends DurableTurnDisplay {
21667
21791
  },
21668
21792
  sendTyping: async (target) => options.sendTyping(target.userId),
21669
21793
  enqueueVisibleMessage: options.enqueueVisibleMessage,
21670
- shouldEmitEvent: (event) => event.kind !== "tool_call",
21794
+ shouldEmitEvent: (event) => event.kind === "assistant",
21795
+ dropBufferedAssistantBeforeToolEvents: true,
21671
21796
  typingIntervalMs: options.typingIntervalMs,
21672
21797
  scheduleTypingTick: options.scheduleTypingTick
21673
21798
  });