@averyyy/pi-coding-agent 0.80.3-piclient.9 → 0.80.6-piclient.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.
Files changed (207) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -3
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +4 -4
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/config-selector.d.ts +4 -2
  7. package/dist/cli/config-selector.d.ts.map +1 -1
  8. package/dist/cli/config-selector.js +1 -1
  9. package/dist/cli/config-selector.js.map +1 -1
  10. package/dist/core/agent-session-services.d.ts +1 -0
  11. package/dist/core/agent-session-services.d.ts.map +1 -1
  12. package/dist/core/agent-session-services.js +1 -0
  13. package/dist/core/agent-session-services.js.map +1 -1
  14. package/dist/core/agent-session.d.ts +24 -5
  15. package/dist/core/agent-session.d.ts.map +1 -1
  16. package/dist/core/agent-session.js +103 -31
  17. package/dist/core/agent-session.js.map +1 -1
  18. package/dist/core/auth-storage.d.ts.map +1 -1
  19. package/dist/core/auth-storage.js +13 -5
  20. package/dist/core/auth-storage.js.map +1 -1
  21. package/dist/core/cache-stats.d.ts +49 -0
  22. package/dist/core/cache-stats.d.ts.map +1 -0
  23. package/dist/core/cache-stats.js +101 -0
  24. package/dist/core/cache-stats.js.map +1 -0
  25. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  26. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  27. package/dist/core/compaction/branch-summarization.js.map +1 -1
  28. package/dist/core/compaction/compaction.d.ts +1 -2
  29. package/dist/core/compaction/compaction.d.ts.map +1 -1
  30. package/dist/core/compaction/compaction.js +56 -81
  31. package/dist/core/compaction/compaction.js.map +1 -1
  32. package/dist/core/extensions/index.d.ts +1 -1
  33. package/dist/core/extensions/index.d.ts.map +1 -1
  34. package/dist/core/extensions/index.js.map +1 -1
  35. package/dist/core/extensions/loader.d.ts.map +1 -1
  36. package/dist/core/extensions/loader.js +6 -0
  37. package/dist/core/extensions/loader.js.map +1 -1
  38. package/dist/core/extensions/runner.d.ts +6 -3
  39. package/dist/core/extensions/runner.d.ts.map +1 -1
  40. package/dist/core/extensions/runner.js +43 -0
  41. package/dist/core/extensions/runner.js.map +1 -1
  42. package/dist/core/extensions/types.d.ts +33 -11
  43. package/dist/core/extensions/types.d.ts.map +1 -1
  44. package/dist/core/extensions/types.js.map +1 -1
  45. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  46. package/dist/core/extensions/wrapper.js +22 -3
  47. package/dist/core/extensions/wrapper.js.map +1 -1
  48. package/dist/core/index.d.ts +1 -1
  49. package/dist/core/index.d.ts.map +1 -1
  50. package/dist/core/index.js.map +1 -1
  51. package/dist/core/keybindings.d.ts +8 -3
  52. package/dist/core/keybindings.d.ts.map +1 -1
  53. package/dist/core/keybindings.js +10 -9
  54. package/dist/core/keybindings.js.map +1 -1
  55. package/dist/core/model-registry.d.ts +4 -6
  56. package/dist/core/model-registry.d.ts.map +1 -1
  57. package/dist/core/model-registry.js +39 -9
  58. package/dist/core/model-registry.js.map +1 -1
  59. package/dist/core/model-resolver.d.ts +10 -0
  60. package/dist/core/model-resolver.d.ts.map +1 -1
  61. package/dist/core/model-resolver.js +14 -17
  62. package/dist/core/model-resolver.js.map +1 -1
  63. package/dist/core/package-manager.d.ts +4 -1
  64. package/dist/core/package-manager.d.ts.map +1 -1
  65. package/dist/core/package-manager.js +75 -28
  66. package/dist/core/package-manager.js.map +1 -1
  67. package/dist/core/pi-client-runtime-update.d.ts +14 -0
  68. package/dist/core/pi-client-runtime-update.d.ts.map +1 -0
  69. package/dist/core/pi-client-runtime-update.js +27 -0
  70. package/dist/core/pi-client-runtime-update.js.map +1 -0
  71. package/dist/core/pi-server-client.d.ts.map +1 -1
  72. package/dist/core/pi-server-client.js +122 -5
  73. package/dist/core/pi-server-client.js.map +1 -1
  74. package/dist/core/provider-attribution.d.ts.map +1 -1
  75. package/dist/core/provider-attribution.js +0 -10
  76. package/dist/core/provider-attribution.js.map +1 -1
  77. package/dist/core/resource-loader.d.ts +2 -2
  78. package/dist/core/resource-loader.d.ts.map +1 -1
  79. package/dist/core/resource-loader.js +6 -7
  80. package/dist/core/resource-loader.js.map +1 -1
  81. package/dist/core/sdk.d.ts +3 -1
  82. package/dist/core/sdk.d.ts.map +1 -1
  83. package/dist/core/sdk.js +9 -1
  84. package/dist/core/sdk.js.map +1 -1
  85. package/dist/core/session-manager.d.ts +20 -1
  86. package/dist/core/session-manager.d.ts.map +1 -1
  87. package/dist/core/session-manager.js +97 -68
  88. package/dist/core/session-manager.js.map +1 -1
  89. package/dist/core/settings-manager.d.ts +9 -3
  90. package/dist/core/settings-manager.d.ts.map +1 -1
  91. package/dist/core/settings-manager.js +10 -1
  92. package/dist/core/settings-manager.js.map +1 -1
  93. package/dist/core/slash-commands.d.ts +1 -0
  94. package/dist/core/slash-commands.d.ts.map +1 -1
  95. package/dist/core/slash-commands.js +3 -3
  96. package/dist/core/slash-commands.js.map +1 -1
  97. package/dist/core/tools/edit.d.ts.map +1 -1
  98. package/dist/core/tools/edit.js +2 -2
  99. package/dist/core/tools/edit.js.map +1 -1
  100. package/dist/index.d.ts +3 -2
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +2 -1
  103. package/dist/index.js.map +1 -1
  104. package/dist/main.d.ts +2 -2
  105. package/dist/main.d.ts.map +1 -1
  106. package/dist/main.js +1 -0
  107. package/dist/main.js.map +1 -1
  108. package/dist/modes/interactive/components/config-selector.d.ts +34 -3
  109. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  110. package/dist/modes/interactive/components/config-selector.js +280 -25
  111. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  112. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  113. package/dist/modes/interactive/components/custom-editor.js +1 -1
  114. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  115. package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  116. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
  117. package/dist/modes/interactive/components/custom-entry.js +52 -0
  118. package/dist/modes/interactive/components/custom-entry.js.map +1 -0
  119. package/dist/modes/interactive/components/footer.d.ts +4 -0
  120. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  121. package/dist/modes/interactive/components/footer.js +1 -1
  122. package/dist/modes/interactive/components/footer.js.map +1 -1
  123. package/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  124. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/login-dialog.js +9 -2
  126. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  127. package/dist/modes/interactive/components/oauth-selector.d.ts +3 -1
  128. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  129. package/dist/modes/interactive/components/oauth-selector.js +17 -6
  130. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  131. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  132. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  133. package/dist/modes/interactive/components/settings-selector.js +12 -1
  134. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  135. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  136. package/dist/modes/interactive/components/thinking-selector.js +2 -1
  137. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  138. package/dist/modes/interactive/components/tree-selector.d.ts +5 -0
  139. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  140. package/dist/modes/interactive/components/tree-selector.js +49 -12
  141. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  142. package/dist/modes/interactive/interactive-mode.d.ts +16 -5
  143. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  144. package/dist/modes/interactive/interactive-mode.js +368 -97
  145. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  146. package/dist/modes/interactive/theme/dark.json +1 -0
  147. package/dist/modes/interactive/theme/light.json +1 -0
  148. package/dist/modes/interactive/theme/theme-schema.json +6 -2
  149. package/dist/modes/interactive/theme/theme.d.ts +3 -2
  150. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  151. package/dist/modes/interactive/theme/theme.js +10 -3
  152. package/dist/modes/interactive/theme/theme.js.map +1 -1
  153. package/dist/modes/print-mode.d.ts.map +1 -1
  154. package/dist/modes/print-mode.js +1 -1
  155. package/dist/modes/print-mode.js.map +1 -1
  156. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  157. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  158. package/dist/modes/rpc/rpc-client.js +3 -3
  159. package/dist/modes/rpc/rpc-client.js.map +1 -1
  160. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  161. package/dist/modes/rpc/rpc-mode.js +4 -1
  162. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  163. package/dist/package-manager-cli.d.ts +2 -2
  164. package/dist/package-manager-cli.d.ts.map +1 -1
  165. package/dist/package-manager-cli.js +71 -17
  166. package/dist/package-manager-cli.js.map +1 -1
  167. package/dist/utils/clipboard-image.d.ts.map +1 -1
  168. package/dist/utils/clipboard-image.js +1 -1
  169. package/dist/utils/clipboard-image.js.map +1 -1
  170. package/dist/utils/clipboard-native.d.ts +1 -0
  171. package/dist/utils/clipboard-native.d.ts.map +1 -1
  172. package/dist/utils/clipboard-native.js.map +1 -1
  173. package/dist/utils/clipboard.d.ts +2 -0
  174. package/dist/utils/clipboard.d.ts.map +1 -1
  175. package/dist/utils/clipboard.js +13 -0
  176. package/dist/utils/clipboard.js.map +1 -1
  177. package/docs/custom-provider.md +6 -3
  178. package/docs/extensions.md +213 -18
  179. package/docs/keybindings.md +1 -0
  180. package/docs/models.md +51 -8
  181. package/docs/packages.md +2 -2
  182. package/docs/providers.md +3 -0
  183. package/docs/quickstart.md +1 -1
  184. package/docs/rpc.md +15 -5
  185. package/docs/sdk.md +51 -1
  186. package/docs/session-format.md +18 -8
  187. package/docs/settings.md +3 -2
  188. package/docs/themes.md +5 -3
  189. package/docs/tui.md +1 -1
  190. package/docs/usage.md +3 -2
  191. package/examples/extensions/README.md +1 -0
  192. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  193. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  194. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  195. package/examples/extensions/entry-renderer.ts +41 -0
  196. package/examples/extensions/gondolin/package-lock.json +2 -2
  197. package/examples/extensions/gondolin/package.json +1 -1
  198. package/examples/extensions/preset.ts +2 -2
  199. package/examples/extensions/question.ts +1 -0
  200. package/examples/extensions/reload-runtime.ts +2 -2
  201. package/examples/extensions/sandbox/package-lock.json +2 -2
  202. package/examples/extensions/sandbox/package.json +1 -1
  203. package/examples/extensions/with-deps/package-lock.json +2 -2
  204. package/examples/extensions/with-deps/package.json +1 -1
  205. package/examples/sdk/12-full-control.ts +1 -1
  206. package/examples/sdk/README.md +1 -1
  207. package/package.json +8 -4
@@ -151,6 +151,9 @@ export class AgentSession {
151
151
  // Event subscription state
152
152
  _unsubscribeAgent;
153
153
  _eventListeners = [];
154
+ _isAgentRunActive = false;
155
+ _idleWaitPromise;
156
+ _resolveIdleWait;
154
157
  /** Tracks pending steering messages for UI display. Removed when delivered. */
155
158
  _steeringMessages = [];
156
159
  /** Tracks pending follow-up messages for UI display. Removed when delivered. */
@@ -192,6 +195,7 @@ export class AgentSession {
192
195
  _extensionShutdownHandler;
193
196
  _extensionErrorListener;
194
197
  _extensionErrorUnsubscriber;
198
+ _autoSessionNameEnabled;
195
199
  _autoSessionNameAttempted = false;
196
200
  // Model registry for API key resolution
197
201
  _modelRegistry;
@@ -219,6 +223,7 @@ export class AgentSession {
219
223
  this._excludedToolNames = config.excludedToolNames ? new Set(config.excludedToolNames) : undefined;
220
224
  this._baseToolsOverride = config.baseToolsOverride;
221
225
  this._sessionStartEvent = config.sessionStartEvent ?? { type: "session_start", reason: "startup" };
226
+ this._autoSessionNameEnabled = config.autoSessionName ?? true;
222
227
  if (isPiServerMode()) {
223
228
  this._detachPiServerTerminalAssistantFailure();
224
229
  }
@@ -265,7 +270,7 @@ export class AgentSession {
265
270
  }
266
271
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
267
272
  }
268
- async _getCompactionRequestAuth(model) {
273
+ async _getSummarizationRequestAuth(model) {
269
274
  if (this.agent.streamFn === streamSimple) {
270
275
  return this._getRequiredRequestAuth(model);
271
276
  }
@@ -430,6 +435,33 @@ export class AgentSession {
430
435
  followUp: [...this._followUpMessages],
431
436
  });
432
437
  }
438
+ _getIdleWaitPromise() {
439
+ if (!this._idleWaitPromise) {
440
+ this._idleWaitPromise = new Promise((resolve) => {
441
+ this._resolveIdleWait = resolve;
442
+ });
443
+ }
444
+ return this._idleWaitPromise;
445
+ }
446
+ _resolveIdleWaitIfIdle() {
447
+ if (this._isAgentRunActive || !this._resolveIdleWait) {
448
+ return;
449
+ }
450
+ const resolve = this._resolveIdleWait;
451
+ this._idleWaitPromise = undefined;
452
+ this._resolveIdleWait = undefined;
453
+ resolve();
454
+ }
455
+ async _emitAgentSettled() {
456
+ this._isAgentRunActive = false;
457
+ try {
458
+ await this._extensionRunner.emit({ type: "agent_settled" });
459
+ this._emit({ type: "agent_settled" });
460
+ }
461
+ finally {
462
+ this._resolveIdleWaitIfIdle();
463
+ }
464
+ }
433
465
  // Track last assistant message for auto-compaction check
434
466
  _lastAssistantMessage = undefined;
435
467
  /** Internal handler for agent events - shared by subscribe and reconnect */
@@ -654,7 +686,16 @@ export class AgentSession {
654
686
  };
655
687
  const replacement = await this._extensionRunner.emitMessageEnd(extensionEvent);
656
688
  if (replacement) {
657
- this._replaceMessageInPlace(event.message, replacement);
689
+ // Untyped extension handlers can return messages with null/missing content;
690
+ // normalize so it never enters agent state or session history.
691
+ const normalized = (replacement.role === "user" ||
692
+ replacement.role === "assistant" ||
693
+ replacement.role === "toolResult" ||
694
+ replacement.role === "custom") &&
695
+ replacement.content == null
696
+ ? { ...replacement, content: [] }
697
+ : replacement;
698
+ this._replaceMessageInPlace(event.message, normalized);
658
699
  }
659
700
  }
660
701
  else if (event.type === "tool_execution_start") {
@@ -757,9 +798,13 @@ export class AgentSession {
757
798
  get thinkingLevel() {
758
799
  return this.agent.state.thinkingLevel;
759
800
  }
760
- /** Whether agent is currently streaming a response */
801
+ /** Whether the session is currently processing an agent run or post-run continuation. */
761
802
  get isStreaming() {
762
- return this.agent.state.isStreaming;
803
+ return this._isAgentRunActive;
804
+ }
805
+ /** Whether the session has no active agent run, retry, auto-compaction, or queued continuation. */
806
+ get isIdle() {
807
+ return !this._isAgentRunActive;
763
808
  }
764
809
  /** Current effective system prompt (includes any per-turn extension modifications) */
765
810
  get systemPrompt() {
@@ -912,6 +957,7 @@ export class AgentSession {
912
957
  // =========================================================================
913
958
  async _runAgentPrompt(messages) {
914
959
  this._resetValidationHintState();
960
+ this._isAgentRunActive = true;
915
961
  try {
916
962
  await this.agent.prompt(messages);
917
963
  while (await this._handlePostAgentRun()) {
@@ -937,6 +983,7 @@ export class AgentSession {
937
983
  finally {
938
984
  this._systemPromptOverride = undefined;
939
985
  this._flushPendingBashMessages();
986
+ await this._emitAgentSettled();
940
987
  }
941
988
  }
942
989
  _sessionHasInfoEntry() {
@@ -956,7 +1003,7 @@ export class AgentSession {
956
1003
  return transcript ? truncateForSessionNameInput(transcript) : undefined;
957
1004
  }
958
1005
  _shouldGenerateSessionName() {
959
- if (this._autoSessionNameAttempted || this._sessionHasInfoEntry())
1006
+ if (!this._autoSessionNameEnabled || this._autoSessionNameAttempted || this._sessionHasInfoEntry())
960
1007
  return false;
961
1008
  const userMessages = this.agent.state.messages.filter((message) => message.role === "user");
962
1009
  if (userMessages.length !== 1)
@@ -1140,7 +1187,8 @@ export class AgentSession {
1140
1187
  messages.push({
1141
1188
  role: "custom",
1142
1189
  customType: msg.customType,
1143
- content: msg.content,
1190
+ // Untyped extensions can pass null/missing content; normalize at ingestion.
1191
+ content: msg.content ?? [],
1144
1192
  display: msg.display,
1145
1193
  details: msg.details,
1146
1194
  timestamp: Date.now(),
@@ -1319,7 +1367,8 @@ export class AgentSession {
1319
1367
  const appMessage = {
1320
1368
  role: "custom",
1321
1369
  customType: message.customType,
1322
- content: message.content,
1370
+ // Untyped extensions can pass null/missing content; normalize at ingestion.
1371
+ content: message.content ?? [],
1323
1372
  display: message.display,
1324
1373
  details: message.details,
1325
1374
  timestamp: Date.now(),
@@ -1417,7 +1466,13 @@ export class AgentSession {
1417
1466
  async abort() {
1418
1467
  this.abortRetry();
1419
1468
  this.agent.abort();
1420
- await this.agent.waitForIdle();
1469
+ await this.waitForIdle();
1470
+ }
1471
+ async waitForIdle() {
1472
+ if (this.isIdle) {
1473
+ return;
1474
+ }
1475
+ await this._getIdleWaitPromise();
1421
1476
  }
1422
1477
  // =========================================================================
1423
1478
  // Model Management
@@ -1638,7 +1693,7 @@ export class AgentSession {
1638
1693
  if (!this.model) {
1639
1694
  throw new Error(formatNoModelSelectedMessage());
1640
1695
  }
1641
- const { apiKey, headers, env } = await this._getCompactionRequestAuth(this.model);
1696
+ const { apiKey, headers, env } = await this._getSummarizationRequestAuth(this.model);
1642
1697
  if (isPiServerMode()) {
1643
1698
  this._detachPiServerTerminalAssistantFailure();
1644
1699
  const piServerResult = await compactPiServer(this.model, {
@@ -1907,7 +1962,7 @@ export class AgentSession {
1907
1962
  env = authResult.env;
1908
1963
  }
1909
1964
  else {
1910
- ({ apiKey, headers, env } = await this._getCompactionRequestAuth(this.model));
1965
+ ({ apiKey, headers, env } = await this._getSummarizationRequestAuth(this.model));
1911
1966
  }
1912
1967
  if (isPiServerMode()) {
1913
1968
  this._emit({ type: "compaction_start", reason });
@@ -2072,10 +2127,7 @@ export class AgentSession {
2072
2127
  if (contextWindow <= 0)
2073
2128
  return false;
2074
2129
  const projectedTokens = estimateContextTokens(turn.context.messages).tokens;
2075
- if (projectedTokens >= contextWindow - settings.reserveTokens)
2076
- return true;
2077
- const toolResultTokens = estimateMessagesTokens(turn.toolResults);
2078
- return toolResultTokens >= settings.keepRecentTokens;
2130
+ return projectedTokens >= contextWindow - settings.reserveTokens;
2079
2131
  }
2080
2132
  _appendIntraTurnCompactionMarker() {
2081
2133
  const marker = {
@@ -2245,7 +2297,11 @@ export class AgentSession {
2245
2297
  });
2246
2298
  },
2247
2299
  appendEntry: (customType, data) => {
2248
- this.sessionManager.appendCustomEntry(customType, data);
2300
+ const entryId = this.sessionManager.appendCustomEntry(customType, data);
2301
+ const entry = this.sessionManager.getEntry(entryId);
2302
+ if (entry) {
2303
+ this._emit({ type: "entry_appended", entry });
2304
+ }
2249
2305
  },
2250
2306
  setSessionName: (name) => {
2251
2307
  this.setSessionName(name);
@@ -2271,7 +2327,7 @@ export class AgentSession {
2271
2327
  setThinkingLevel: (level) => this.setThinkingLevel(level),
2272
2328
  }, {
2273
2329
  getModel: () => this.model,
2274
- isIdle: () => !this.isStreaming,
2330
+ isIdle: () => this.isIdle,
2275
2331
  isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
2276
2332
  getSignal: () => this.agent.signal,
2277
2333
  abort: () => {
@@ -2732,7 +2788,7 @@ export class AgentSession {
2732
2788
  let summaryDetails;
2733
2789
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
2734
2790
  const model = this.model;
2735
- const { apiKey, headers, env } = await this._getRequiredRequestAuth(model);
2791
+ const { apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
2736
2792
  const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
2737
2793
  const result = await generateBranchSummary(entriesToSummarize, {
2738
2794
  model,
@@ -2863,28 +2919,44 @@ export class AgentSession {
2863
2919
  return "";
2864
2920
  }
2865
2921
  /**
2866
- * Get session statistics.
2922
+ * Get session statistics. Aggregates over ALL session entries (including
2923
+ * history that was compacted away), so token/cost totals reflect what was
2924
+ * actually billed across the session.
2867
2925
  */
2868
2926
  getSessionStats() {
2869
- const state = this.state;
2870
- const userMessages = state.messages.filter((m) => m.role === "user").length;
2871
- const assistantMessages = state.messages.filter((m) => m.role === "assistant").length;
2872
- const toolResults = state.messages.filter((m) => m.role === "toolResult").length;
2927
+ let userMessages = 0;
2928
+ let assistantMessages = 0;
2929
+ let toolResults = 0;
2930
+ let totalMessages = 0;
2873
2931
  let toolCalls = 0;
2874
2932
  let totalInput = 0;
2875
2933
  let totalOutput = 0;
2876
2934
  let totalCacheRead = 0;
2877
2935
  let totalCacheWrite = 0;
2878
2936
  let totalCost = 0;
2879
- for (const message of state.messages) {
2880
- if (message.role === "assistant") {
2937
+ for (const entry of this.sessionManager.getEntries()) {
2938
+ if (entry.type !== "message")
2939
+ continue;
2940
+ totalMessages++;
2941
+ const message = entry.message;
2942
+ if (message.role === "user") {
2943
+ userMessages++;
2944
+ }
2945
+ else if (message.role === "toolResult") {
2946
+ toolResults++;
2947
+ }
2948
+ else if (message.role === "assistant") {
2949
+ assistantMessages++;
2881
2950
  const assistantMsg = message;
2882
- toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
2883
- totalInput += assistantMsg.usage.input;
2884
- totalOutput += assistantMsg.usage.output;
2885
- totalCacheRead += assistantMsg.usage.cacheRead;
2886
- totalCacheWrite += assistantMsg.usage.cacheWrite;
2887
- totalCost += assistantMsg.usage.cost.total;
2951
+ if (Array.isArray(assistantMsg.content)) {
2952
+ toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
2953
+ }
2954
+ const usage = assistantMsg.usage;
2955
+ totalInput += usage.input;
2956
+ totalOutput += usage.output;
2957
+ totalCacheRead += usage.cacheRead;
2958
+ totalCacheWrite += usage.cacheWrite;
2959
+ totalCost += usage.cost.total;
2888
2960
  }
2889
2961
  }
2890
2962
  return {
@@ -2894,7 +2966,7 @@ export class AgentSession {
2894
2966
  assistantMessages,
2895
2967
  toolCalls,
2896
2968
  toolResults,
2897
- totalMessages: state.messages.length,
2969
+ totalMessages,
2898
2970
  tokens: {
2899
2971
  input: totalInput,
2900
2972
  output: totalOutput,