@apolloyh/apollo-agent 0.1.9 → 0.1.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.
@@ -0,0 +1,5 @@
1
+ {
2
+ "log": true,
3
+ "denyTools": [],
4
+ "denyMessage": "Blocked by project hooks (.apollo/hooks.json)."
5
+ }
package/README.md CHANGED
@@ -23,7 +23,7 @@ Terminal text wordmark (no icon / no triangle):
23
23
  - Built-in `simplify`, `verify`, and `debug` workflows; workspace skills can override them
24
24
  - Waiting UI: blinking `◆`
25
25
 
26
- ## Run
26
+ ## Install
27
27
 
28
28
  ```bash
29
29
  npm install -g @apolloyh/apollo-agent
@@ -40,7 +40,7 @@ Apollo creates global defaults at `~/.apollo/config.json` and copies the complet
40
40
  reference to `~/.apollo/config.example.json`. Project overrides live at
41
41
  `.apollo/config.json`; Apollo also reads the legacy `agent.config.json` during migration.
42
42
  Configuration layers as built-in defaults → user config → project config → `--config`.
43
- Set `systemPrompt` in either config to append stable custom system instructions; restart Apollo to reload them.
43
+ Set `systemPrompt` in either config to place stable custom instructions at the front of the system prompt; restart Apollo to reload them.
44
44
 
45
45
  Apollo also loads `~/.apollo/APOLLO.md` followed by the project `APOLLO.md` (lowercase
46
46
  `apollo.md` is accepted). If no project Apollo file exists, the standard `AGENTS.md` and
@@ -49,7 +49,14 @@ Apollo also loads `~/.apollo/APOLLO.md` followed by the project `APOLLO.md` (low
49
49
  While Apollo is working, type and press Enter to queue another user message. Queued messages
50
50
  run in FIFO order after the current turn; press Esc to interrupt the current turn safely.
51
51
 
52
- Commands: `/help` · `/skills` · `/simplify` · `/verify` · `/debug` · `/agents` · `/sessions` · `/resume` · `/verbose` · `/stream` · `/clear` · `/exit`
52
+ Commands: `/help` · `/skill` · `/simplify` · `/verify` · `/debug` · `/agents` · `/status` · `/sessions` · `/resume` · `/plan` · `/goal` · `/workflow` · `/verbose` · `/stream` · `/clear` · `/exit`
53
+
54
+ ## Documentation
55
+
56
+ - [完整使用指南](docs/guide.md)
57
+ - [SDK 接入指南](docs/sdk.md)
58
+ - [npm 打包与发布手册](docs/npm-release.md)
59
+ - [高级功能与恢复机制](docs/features-cc.md)
53
60
 
54
61
  ## SDK
55
62
 
@@ -69,4 +76,4 @@ try {
69
76
  }
70
77
  ```
71
78
 
72
- See the [SDK integration guide](docs/sdk.md) and [requirements](docs/requirements.md).
79
+ See the [full usage guide](docs/guide.md) and [SDK integration guide](docs/sdk.md).
package/dist/brand.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** Product identity — single source of truth for display strings. */
2
2
  export declare const PRODUCT: {
3
3
  readonly name: "Apollo";
4
- readonly version: "0.1.9";
4
+ readonly version: "0.1.11";
5
5
  readonly tagline: "Your personal agent — answer first, act when needed.";
6
6
  readonly packageName: "@apolloyh/apollo-agent";
7
7
  readonly userAgent: "ApolloAgent/0.1";
package/dist/brand.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /** Product identity — single source of truth for display strings. */
2
2
  export const PRODUCT = {
3
3
  name: "Apollo",
4
- version: "0.1.9",
4
+ version: "0.1.11",
5
5
  tagline: "Your personal agent — answer first, act when needed.",
6
6
  packageName: "@apolloyh/apollo-agent",
7
7
  userAgent: "ApolloAgent/0.1",
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ let liveStatus;
21
21
  let runningTaskCount = 0;
22
22
  let activeVerb = "Thinking";
23
23
  let assistantResponseStarted = false;
24
+ let liveThinkingPreview = "";
24
25
  /** Prevent double green/red outcome lines in one user turn */
25
26
  let outcomePrintedThisTurn = false;
26
27
  let pastedTextSequence = 0;
@@ -97,31 +98,19 @@ async function main() {
97
98
  // never reaches the interactive `runtime` binding). Also lets SIGINT close whichever is active.
98
99
  let activeRuntime;
99
100
  const traceSink = (event) => {
100
- // Collect process into collapsible Thought (always, even when quiet)
101
+ let completedThought = null;
102
+ // Collect only model thinking tokens into the collapsible Thought.
101
103
  if (event.type === "llm_request") {
102
104
  thoughtFold.beginTurn();
103
- thoughtFold.note(`turn ${event.turn} · ${event.toolCount} tools available`);
104
105
  }
105
- else if (event.type === "llm_retry") {
106
- thoughtFold.note(`retry ${event.attempt} · ${event.mode} · ${event.reason}`);
107
- }
108
- else if (event.type === "tool_call") {
109
- thoughtFold.noteTool(event.tool);
110
- }
111
- else if (event.type === "tool_result") {
112
- thoughtFold.note(`${event.tool} ${event.isError ? "failed" : "ok"}`);
113
- }
114
- else if (event.type === "task_start") {
115
- thoughtFold.note(`Task(${event.subagentType}): ${event.description}`);
116
- }
117
- else if (event.type === "task_finish") {
118
- thoughtFold.note(`Task(${event.subagentType}) finished`);
106
+ else if (event.type === "thinking_delta") {
107
+ thoughtFold.appendThinking(event.text);
119
108
  }
120
109
  else if (event.type === "assistant_delta") {
121
- thoughtFold.finalizeAndPrint();
110
+ completedThought = thoughtFold.finalizeAndPrint();
122
111
  }
123
112
  else if (event.type === "llm_response" && event.stopReason !== "tool_use") {
124
- thoughtFold.finalizeAndPrint();
113
+ completedThought = thoughtFold.finalizeAndPrint();
125
114
  }
126
115
  if (event.type === "workflow_status") {
127
116
  const bar = workflowStatusBar({
@@ -166,6 +155,8 @@ async function main() {
166
155
  if (renderBeforeStatus)
167
156
  rendererSink(event);
168
157
  updateLiveStatus(event, interactiveMode);
158
+ if (interactiveMode && completedThought)
159
+ thoughtFold.printPreview(completedThought);
169
160
  taskActivity.record(event);
170
161
  if (!renderBeforeStatus)
171
162
  rendererSink(event);
@@ -513,10 +504,6 @@ async function main() {
513
504
  stdout.write(notes.map((n) => `- ${n.id} ${n.title}\n ${n.content.slice(0, 120).replace(/\n/g, " ")}`).join("\n") + "\n");
514
505
  continue;
515
506
  }
516
- if (text === "/thought" || text === "/think" || text === "/t") {
517
- thoughtFold.toggle();
518
- continue;
519
- }
520
507
  if (text.startsWith("/verbose")) {
521
508
  const value = text.split(/\s+/)[1];
522
509
  traceOptions.verbose = value === "on" ? true : value === "off" ? false : !traceOptions.verbose;
@@ -756,8 +743,19 @@ function updateLiveStatus(event, enabled) {
756
743
  switch (event.type) {
757
744
  case "llm_request":
758
745
  assistantResponseStarted = false;
746
+ liveThinkingPreview = "";
759
747
  startLiveStatus(runningTaskCount > 0 ? formatRunningTasks() : activeVerb);
760
748
  break;
749
+ case "thinking_delta": {
750
+ liveThinkingPreview = stripTerminalEscapes(`${liveThinkingPreview}${event.text}`)
751
+ .replace(/\s+/g, " ")
752
+ .trimStart()
753
+ .slice(0, 1000);
754
+ if (liveStatus)
755
+ liveStatus.text = "Thinking";
756
+ paintLiveStatus();
757
+ break;
758
+ }
761
759
  case "llm_retry":
762
760
  startLiveStatus(event.mode === "after-compaction"
763
761
  ? "Retrying after compaction"
@@ -1038,6 +1036,9 @@ async function readCliLine(options) {
1038
1036
  const liveStatusLine = renderLiveStatusLine(options.color);
1039
1037
  if (liveStatusLine)
1040
1038
  lines.push(liveStatusLine);
1039
+ if (liveStatus?.text === "Thinking" && liveThinkingPreview) {
1040
+ lines.push(...renderLiveThinkingLines(liveThinkingPreview, options.color));
1041
+ }
1041
1042
  lines.push(renderInputBorder("top", options.color));
1042
1043
  const view = renderInputView(buffer, cursor, inputContentWidth(), pastedTextBlocks);
1043
1044
  const idleQueue = options.queueMode && !buffer;
@@ -1614,6 +1615,37 @@ function renderLiveStatusLine(useColor) {
1614
1615
  : `${liveStatus.text}...`;
1615
1616
  return formatWaitLine({ frame: liveStatus.frame, label, elapsed, useColor });
1616
1617
  }
1618
+ function renderLiveThinkingLines(value, useColor) {
1619
+ const prefixWidth = 4;
1620
+ const width = Math.max(24, Math.min((stdout.columns ?? 100) - prefixWidth, 96));
1621
+ const lines = [];
1622
+ let current = "";
1623
+ let currentWidth = 0;
1624
+ let consumed = 0;
1625
+ const characters = Array.from(value);
1626
+ for (const char of characters) {
1627
+ const charWidth = displayLength(char);
1628
+ if (current && currentWidth + charWidth > width) {
1629
+ lines.push(current);
1630
+ if (lines.length === 3)
1631
+ break;
1632
+ current = "";
1633
+ currentWidth = 0;
1634
+ }
1635
+ current += char;
1636
+ currentWidth += charWidth;
1637
+ consumed += 1;
1638
+ }
1639
+ if (lines.length < 3 && current)
1640
+ lines.push(current);
1641
+ if (consumed < characters.length && lines.length) {
1642
+ const last = truncateDisplay(lines[lines.length - 1], Math.max(1, width - 1)).replace(/…$/, "");
1643
+ lines[lines.length - 1] = `${last}…`;
1644
+ }
1645
+ const dim = useColor ? "\x1b[90m" : "";
1646
+ const reset = useColor ? "\x1b[0m" : "";
1647
+ return lines.map((line, index) => `${dim}${index === 0 ? " └ " : " "}${line}${reset}`);
1648
+ }
1617
1649
  function renderInputBorder(position, useColor) {
1618
1650
  const terminalWidth = Math.max(48, Math.min(stdout.columns ?? 100, 100));
1619
1651
  const left = position === "top" ? "╭" : "╰";
@@ -1641,7 +1673,7 @@ function renderWelcomeBanner(options) {
1641
1673
  `${dim}trace${reset} ${options.quiet ? "quiet" : "verbose"}`,
1642
1674
  `${dim}approval${reset} ${options.yolo ? `${green}yolo${reset}` : "ask"}`,
1643
1675
  "",
1644
- `${dim}Type / to search · /thought expands Thought · /help${reset}`,
1676
+ `${dim}Type / to search · /help${reset}`,
1645
1677
  "",
1646
1678
  "",
1647
1679
  ].join("\n");
@@ -18,6 +18,9 @@ export type ToolInputDelta = {
18
18
  tool?: string;
19
19
  detail?: string;
20
20
  };
21
+ export type ThinkingDelta = {
22
+ text: string;
23
+ };
21
24
  export declare class MalformedStreamError extends Error {
22
25
  constructor(message: string, cause?: unknown);
23
26
  }
@@ -40,6 +43,7 @@ export declare class AnthropicClient {
40
43
  stream?: boolean;
41
44
  signal?: AbortSignal;
42
45
  onTextDelta?: (text: string) => void;
46
+ onThinkingDelta?: (event: ThinkingDelta) => void;
43
47
  onToolInputDelta?: (event: ToolInputDelta) => void;
44
48
  }): Promise<AnthropicResponse>;
45
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/llm/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEnF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,2BAA2B,EAAE,MAAM,CAAC;IACpC,uBAAuB,EAAE,MAAM,CAAC;CACjC,CAAC;AAMF,MAAM,MAAM,cAAc,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAI7C;AAED,qBAAa,uBAAwB,SAAQ,oBAAoB;gBACnD,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAIxD;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,MAAM,EAAE,MAAM;aACd,YAAY,EAAE,MAAM;aACpB,eAAe,EAAE,OAAO;gBAFxB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,OAAO;CAK3C;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAExC,aAAa,CAAC,KAAK,EAAE;QACzB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,KAAK,EAAE,aAAa,EAAE,CAAC;QACvB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QACrC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;KACpD,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAqC/B"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/llm/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEnF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,2BAA2B,EAAE,MAAM,CAAC;IACpC,uBAAuB,EAAE,MAAM,CAAC;CACjC,CAAC;AAOF,MAAM,MAAM,cAAc,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC/E,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAI7C;AAED,qBAAa,uBAAwB,SAAQ,oBAAoB;gBACnD,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAIxD;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,MAAM,EAAE,MAAM;aACd,YAAY,EAAE,MAAM;aACpB,eAAe,EAAE,OAAO;gBAFxB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,OAAO;CAK3C;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAExC,aAAa,CAAC,KAAK,EAAE;QACzB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,KAAK,EAAE,aAAa,EAAE,CAAC;QACvB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QACrC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;QACjD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;KACpD,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAsC/B"}
@@ -48,6 +48,7 @@ export class AnthropicClient {
48
48
  cache_control: this.config.cacheTtl === "1h"
49
49
  ? { type: "ephemeral", ttl: "1h" }
50
50
  : { type: "ephemeral" },
51
+ ...(supportsThinking(this.config) ? { thinking: { type: "enabled" } } : {}),
51
52
  stream: input.stream ?? false,
52
53
  }),
53
54
  signal: input.signal
@@ -59,12 +60,12 @@ export class AnthropicClient {
59
60
  throw new AnthropicApiError(response.status, errorText, response.headers);
60
61
  }
61
62
  if (input.stream) {
62
- return readStreamingResponse(response, input.onTextDelta, input.onToolInputDelta);
63
+ return readStreamingResponse(response, input.onTextDelta, input.onToolInputDelta, input.onThinkingDelta);
63
64
  }
64
65
  return (await response.json());
65
66
  }
66
67
  }
67
- async function readStreamingResponse(response, onTextDelta, onToolInputDelta) {
68
+ async function readStreamingResponse(response, onTextDelta, onToolInputDelta, onThinkingDelta) {
68
69
  if (!response.body)
69
70
  throw new Error("Anthropic API returned an empty stream body.");
70
71
  const reader = response.body.getReader();
@@ -100,7 +101,7 @@ async function readStreamingResponse(response, onTextDelta, onToolInputDelta) {
100
101
  stopReason = reason;
101
102
  }, (part) => {
102
103
  usage = mergeUsage(usage, part);
103
- }, onTextDelta, onToolInputDelta);
104
+ }, onTextDelta, onToolInputDelta, onThinkingDelta);
104
105
  }
105
106
  separator = buffer.match(/\r?\n\r?\n/);
106
107
  }
@@ -119,7 +120,7 @@ async function readStreamingResponse(response, onTextDelta, onToolInputDelta) {
119
120
  stopReason = reason;
120
121
  }, (part) => {
121
122
  usage = mergeUsage(usage, part);
122
- }, onTextDelta, onToolInputDelta);
123
+ }, onTextDelta, onToolInputDelta, onThinkingDelta);
123
124
  }
124
125
  }
125
126
  if (blocks.size === 0) {
@@ -161,7 +162,7 @@ function parseStreamEvent(data) {
161
162
  throw new MalformedStreamError("Model returned malformed JSON in the event stream.", error);
162
163
  }
163
164
  }
164
- function applyStreamEvent(event, blocks, setResponseId, setStopReason, setUsage, onTextDelta, onToolInputDelta) {
165
+ function applyStreamEvent(event, blocks, setResponseId, setStopReason, setUsage, onTextDelta, onToolInputDelta, onThinkingDelta) {
165
166
  if (event.type === "message_start") {
166
167
  const message = event.message;
167
168
  if (message?.id)
@@ -186,6 +187,13 @@ function applyStreamEvent(event, blocks, setResponseId, setStopReason, setUsage,
186
187
  if (contentBlock.type === "text") {
187
188
  blocks.set(index, { type: "text", text: contentBlock.text ?? "" });
188
189
  }
190
+ else if (contentBlock.type === "thinking") {
191
+ blocks.set(index, {
192
+ type: "thinking",
193
+ thinking: contentBlock.thinking ?? "",
194
+ signature: contentBlock.signature,
195
+ });
196
+ }
189
197
  else if (contentBlock.type === "tool_use") {
190
198
  const block = {
191
199
  type: "tool_use",
@@ -203,12 +211,26 @@ function applyStreamEvent(event, blocks, setResponseId, setStopReason, setUsage,
203
211
  const index = Number(event.index);
204
212
  const block = blocks.get(index);
205
213
  const delta = event.delta;
206
- if (!block || !delta)
214
+ if (!delta)
215
+ return;
216
+ const publicThinking = delta.type === "summary_delta"
217
+ ? delta.summary
218
+ : delta.type === "reasoning_delta" || delta.type === "reasoning_summary_delta"
219
+ ? (delta.reasoning_summary ?? delta.reasoning)
220
+ : delta.type === "thinking_delta"
221
+ ? delta.thinking
222
+ : undefined;
223
+ if (publicThinking)
224
+ onThinkingDelta?.({ text: publicThinking });
225
+ if (!block)
207
226
  return;
208
227
  if (block.type === "text" && delta.type === "text_delta" && delta.text) {
209
228
  block.text += delta.text;
210
229
  onTextDelta?.(delta.text);
211
230
  }
231
+ else if (block.type === "thinking" && delta.type === "thinking_delta" && delta.thinking) {
232
+ block.thinking += delta.thinking;
233
+ }
212
234
  else if (block.type === "tool_use" && delta.type === "input_json_delta" && delta.partial_json) {
213
235
  block.inputJson += delta.partial_json;
214
236
  block.detail ??= partialToolDetail(block.inputJson);
@@ -258,7 +280,7 @@ function mergeUsage(current, part) {
258
280
  }, { ...next });
259
281
  }
260
282
  function finalizeStreamBlock(block) {
261
- if (block.type === "text")
283
+ if (block.type === "text" || block.type === "thinking")
262
284
  return block;
263
285
  let input = {};
264
286
  if (block.inputJson.trim()) {
@@ -276,3 +298,6 @@ function finalizeStreamBlock(block) {
276
298
  input,
277
299
  };
278
300
  }
301
+ function supportsThinking(config) {
302
+ return /(?:^glm-|bigmodel\.cn)/i.test(`${config.model} ${config.baseUrl}`);
303
+ }
@@ -79,6 +79,13 @@ export declare class QueryEngine {
79
79
  conversationSize(): number;
80
80
  getUsageStats(): UsageStats;
81
81
  getCacheMode(): string;
82
+ getRuntimeInfo(): {
83
+ model: string;
84
+ baseUrl: string;
85
+ maxTokens: number;
86
+ contextMaxChars: number;
87
+ workspaceRoot: string;
88
+ };
82
89
  close(): Promise<void>;
83
90
  ensureSession(title?: string): Promise<SessionSnapshot>;
84
91
  saveCurrentSession(): Promise<string | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"query-engine.d.ts","sourceRoot":"","sources":["../../src/runtime/query-engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query-engine.d.ts","sourceRoot":"","sources":["../../src/runtime/query-engine.ts"],"names":[],"mappings":"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"}
@@ -133,6 +133,15 @@ export class QueryEngine {
133
133
  }
134
134
  return `Anthropic-compatible (${this.options.llmConfig.cacheTtl ?? "5m"} requested)`;
135
135
  }
136
+ getRuntimeInfo() {
137
+ return {
138
+ model: this.options.llmConfig.model,
139
+ baseUrl: this.options.llmConfig.baseUrl,
140
+ maxTokens: this.options.llmConfig.maxTokens,
141
+ contextMaxChars: this.options.agentConfig.context.maxChars,
142
+ workspaceRoot: this.options.agentConfig.workspaceRoot,
143
+ };
144
+ }
136
145
  async close() {
137
146
  await this.mcpManager.closeAll();
138
147
  }
@@ -526,12 +535,18 @@ export class QueryEngine {
526
535
  streamedText += text;
527
536
  this.options.emit({ type: "assistant_delta", text });
528
537
  };
538
+ const onThinkingDelta = isSubagent
539
+ ? undefined
540
+ : (event) => {
541
+ this.options.emit({ type: "thinking_delta", text: event.text });
542
+ };
529
543
  const buildRequest = (useStream) => ({
530
544
  system: prompt,
531
545
  messages: this.messages,
532
546
  tools: toolDefinitions,
533
547
  stream: useStream,
534
548
  onTextDelta: useStream ? onTextDelta : undefined,
549
+ onThinkingDelta: useStream ? onThinkingDelta : undefined,
535
550
  onToolInputDelta: useStream && !isSubagent
536
551
  ? (event) => {
537
552
  const now = Date.now();
@@ -1,19 +1,10 @@
1
1
  /**
2
- * Terminal collapsible Thought blocks (like web ProcessTimeline).
3
- * Default: one line “◆ Thought for 0.5s ▸”
4
- * Expand: /thought or key `t` → show detail lines under it.
2
+ * Bounded terminal preview for model thinking tokens.
5
3
  */
6
4
  export type ThoughtBlock = {
7
- id: string;
8
5
  startedAt: number;
9
6
  endedAt?: number;
10
- /** Short lines shown when expanded */
11
- lines: string[];
12
- tools: string[];
13
- expanded: boolean;
14
- /** Printed to terminal already (collapsed header) */
15
- printed: boolean;
16
- /** true if turn failed */
7
+ thinking: string;
17
8
  failed?: boolean;
18
9
  };
19
10
  export type ThoughtFoldOptions = {
@@ -21,28 +12,22 @@ export type ThoughtFoldOptions = {
21
12
  out: (text: string) => void;
22
13
  };
23
14
  export declare class ThoughtFoldManager {
24
- private blocks;
25
15
  private current;
26
16
  private options;
27
17
  constructor(options: ThoughtFoldOptions);
28
18
  setColor(color: boolean): void;
29
19
  /** Start a new thought window for this user turn. */
30
20
  beginTurn(): void;
31
- note(line: string): void;
32
- noteTool(tool: string): void;
21
+ appendThinking(text: string): void;
22
+ printPreview(block: ThoughtBlock, maxChars?: number): void;
33
23
  /**
34
- * Finalize current thought and print collapsed header (once).
24
+ * Finalize current thought and optionally print a failure header.
35
25
  * Call before streaming the final answer, or at end of turn.
36
26
  */
37
- finalizeAndPrint(defaultDetail?: string, failed?: boolean, printHeader?: boolean): ThoughtBlock | null;
38
- /** Toggle expand/collapse of the last thought (or by id). */
39
- toggle(id?: string): void;
40
- expandLast(): void;
41
- lastSummary(): string | null;
27
+ finalizeAndPrint(_defaultDetail?: string, failed?: boolean, printHeader?: boolean): ThoughtBlock | null;
42
28
  clear(): void;
43
29
  private duration;
44
30
  private printHeader;
45
- private printExpanded;
46
31
  private dim;
47
32
  }
48
33
  //# sourceMappingURL=thought-fold.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"thought-fold.d.ts","sourceRoot":"","sources":["../src/thought-fold.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AAQF,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAqB;gBAExB,OAAO,EAAE,kBAAkB;IAIvC,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9B,qDAAqD;IACrD,SAAS,IAAI,IAAI;IAWjB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IASxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B;;;OAGG;IACH,gBAAgB,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,UAAQ,EAAE,WAAW,UAAQ,GAAG,YAAY,GAAG,IAAI;IA0BlG,6DAA6D;IAC7D,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI;IAgBzB,UAAU,IAAI,IAAI;IAclB,WAAW,IAAI,MAAM,GAAG,IAAI;IAO5B,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,GAAG;CAIZ"}
1
+ {"version":3,"file":"thought-fold.d.ts","sourceRoot":"","sources":["../src/thought-fold.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AAOF,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAqB;gBAExB,OAAO,EAAE,kBAAkB;IAIvC,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9B,qDAAqD;IACrD,SAAS,IAAI,IAAI;IAQjB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKlC,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,SAAM,GAAG,IAAI;IAevD;;;OAGG;IACH,gBAAgB,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,UAAQ,EAAE,WAAW,UAAQ,GAAG,YAAY,GAAG,IAAI;IAWnG,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,GAAG;CAIZ"}
@@ -1,15 +1,12 @@
1
1
  /**
2
- * Terminal collapsible Thought blocks (like web ProcessTimeline).
3
- * Default: one line “◆ Thought for 0.5s ▸”
4
- * Expand: /thought or key `t` → show detail lines under it.
2
+ * Bounded terminal preview for model thinking tokens.
5
3
  */
4
+ import { stripTerminalEscapes } from "./trace.js";
6
5
  const DIM = "\x1b[90m";
7
6
  const RESET = "\x1b[0m";
8
- const AMBER = "\x1b[38;2;251;191;36m";
9
7
  const GREEN = "\x1b[32m";
10
8
  const RED = "\x1b[31m";
11
9
  export class ThoughtFoldManager {
12
- blocks = [];
13
10
  current = null;
14
11
  options;
15
12
  constructor(options) {
@@ -20,103 +17,47 @@ export class ThoughtFoldManager {
20
17
  }
21
18
  /** Start a new thought window for this user turn. */
22
19
  beginTurn() {
20
+ if (this.current)
21
+ return;
23
22
  this.current = {
24
- id: `th-${Date.now()}`,
25
23
  startedAt: Date.now(),
26
- lines: [],
27
- tools: [],
28
- expanded: false,
29
- printed: false,
24
+ thinking: "",
30
25
  };
31
26
  }
32
- note(line) {
33
- if (!this.current)
34
- return;
35
- const t = line.trim();
36
- if (!t)
37
- return;
38
- // de-dupe consecutive
39
- if (this.current.lines[this.current.lines.length - 1] === t)
27
+ appendThinking(text) {
28
+ if (!this.current || !text)
40
29
  return;
41
- this.current.lines.push(t);
30
+ this.current.thinking = `${this.current.thinking}${text}`.slice(-6000);
42
31
  }
43
- noteTool(tool) {
44
- if (!this.current)
32
+ printPreview(block, maxChars = 300) {
33
+ const characters = Array.from(stripTerminalEscapes(block.thinking).replace(/\s+/g, " ").trim());
34
+ if (!characters.length)
45
35
  return;
46
- if (!this.current.tools.includes(tool))
47
- this.current.tools.push(tool);
48
- this.note(`used ${tool}`);
36
+ const visible = characters.slice(0, maxChars);
37
+ for (let index = 0; index < visible.length; index += 100) {
38
+ const line = visible.slice(index, index + 100).join("");
39
+ this.options.out(this.dim(`${index === 0 ? " └ " : " "}${line}\n`));
40
+ }
41
+ if (characters.length > maxChars) {
42
+ this.options.out(this.dim(" … more hidden\n"));
43
+ }
49
44
  }
50
45
  /**
51
- * Finalize current thought and print collapsed header (once).
46
+ * Finalize current thought and optionally print a failure header.
52
47
  * Call before streaming the final answer, or at end of turn.
53
48
  */
54
- finalizeAndPrint(defaultDetail, failed = false, printHeader = false) {
49
+ finalizeAndPrint(_defaultDetail, failed = false, printHeader = false) {
55
50
  if (!this.current)
56
51
  return null;
57
- if (this.current.printed)
58
- return this.current;
59
52
  this.current.endedAt = Date.now();
60
53
  this.current.failed = failed;
61
- if (this.current.lines.length === 0 && defaultDetail) {
62
- this.current.lines.push(defaultDetail);
63
- }
64
- if (this.current.lines.length === 0) {
65
- this.current.lines.push("Processed the request and prepared a reply.");
66
- }
67
- this.blocks.push(this.current);
68
- // Only the most recent block is ever toggled/expanded; cap history so a long-lived
69
- // interactive session doesn't grow this array (and its retained lines) without bound.
70
- if (this.blocks.length > 50)
71
- this.blocks.splice(0, this.blocks.length - 50);
72
- if (printHeader) {
54
+ if (printHeader)
73
55
  this.printHeader(this.current);
74
- this.current.printed = true;
75
- }
76
56
  const done = this.current;
77
57
  this.current = null;
78
58
  return done;
79
59
  }
80
- /** Toggle expand/collapse of the last thought (or by id). */
81
- toggle(id) {
82
- const block = id
83
- ? this.blocks.find((b) => b.id === id)
84
- : this.blocks[this.blocks.length - 1];
85
- if (!block) {
86
- this.options.out(this.dim("(no thought to expand yet)\n"));
87
- return;
88
- }
89
- block.expanded = !block.expanded;
90
- if (block.expanded) {
91
- this.printExpanded(block);
92
- }
93
- else {
94
- this.options.out(this.dim(" (thought collapsed — /thought to expand again)\n"));
95
- }
96
- }
97
- expandLast() {
98
- const block = this.blocks[this.blocks.length - 1];
99
- if (!block) {
100
- this.options.out(this.dim("(no thought to expand yet)\n"));
101
- return;
102
- }
103
- if (!block.expanded) {
104
- block.expanded = true;
105
- this.printExpanded(block);
106
- }
107
- else {
108
- this.printExpanded(block); // re-print
109
- }
110
- }
111
- lastSummary() {
112
- const b = this.blocks[this.blocks.length - 1];
113
- if (!b)
114
- return null;
115
- const sec = ((b.endedAt ?? Date.now()) - b.startedAt) / 1000;
116
- return `Thought for ${sec.toFixed(1)}s · ${b.tools.length} tools · ${b.expanded ? "expanded" : "collapsed"}`;
117
- }
118
60
  clear() {
119
- this.blocks = [];
120
61
  this.current = null;
121
62
  }
122
63
  duration(block) {
@@ -124,29 +65,13 @@ export class ThoughtFoldManager {
124
65
  return `${(ms / 1000).toFixed(1)}s`;
125
66
  }
126
67
  printHeader(block) {
127
- const arrow = block.expanded ? "▾" : "▸";
128
- // CC style: green ● success, red ● failure (not amber while done)
129
68
  const color = block.failed ? RED : GREEN;
130
69
  const dot = this.options.color ? `${color}●${RESET}` : "●";
131
70
  const label = block.failed
132
71
  ? `Failed · ${this.duration(block)}`
133
72
  : `Thought for ${this.duration(block)}`;
134
73
  const labelPainted = this.options.color ? `${color}${label}${RESET}` : label;
135
- const hint = this.dim(` ${arrow} /thought to expand`);
136
- this.options.out(`\n${dot} ${labelPainted}${hint}\n`);
137
- }
138
- printExpanded(block) {
139
- const color = block.failed ? RED : GREEN;
140
- const dot = this.options.color ? `${color}●${RESET}` : "●";
141
- const head = block.failed ? `Failed · ${this.duration(block)}` : `Thought for ${this.duration(block)}`;
142
- this.options.out(`\n${dot} ${head} ▾\n`);
143
- if (block.tools.length) {
144
- this.options.out(this.dim(` tools: ${block.tools.join(", ")}\n`));
145
- }
146
- for (const line of block.lines) {
147
- this.options.out(this.dim(` │ ${line}\n`));
148
- }
149
- this.options.out(this.dim(" └ /thought to collapse\n\n"));
74
+ this.options.out(`\n${dot} ${labelPainted}\n`);
150
75
  }
151
76
  dim(text) {
152
77
  if (!this.options.color)