@codex-infinity/pi-infinity 0.63.3 → 0.64.1

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 (71) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +2 -2
  3. package/dist/core/agent-session.d.ts +5 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +48 -34
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/extensions/runner.d.ts.map +1 -1
  8. package/dist/core/extensions/runner.js +1 -0
  9. package/dist/core/extensions/runner.js.map +1 -1
  10. package/dist/core/extensions/types.d.ts +4 -0
  11. package/dist/core/extensions/types.d.ts.map +1 -1
  12. package/dist/core/extensions/types.js.map +1 -1
  13. package/dist/core/keybindings.d.ts +10 -0
  14. package/dist/core/keybindings.d.ts.map +1 -1
  15. package/dist/core/keybindings.js +10 -0
  16. package/dist/core/keybindings.js.map +1 -1
  17. package/dist/core/model-registry.d.ts +3 -1
  18. package/dist/core/model-registry.d.ts.map +1 -1
  19. package/dist/core/model-registry.js +7 -1
  20. package/dist/core/model-registry.js.map +1 -1
  21. package/dist/core/sdk.d.ts +1 -1
  22. package/dist/core/sdk.d.ts.map +1 -1
  23. package/dist/core/sdk.js +2 -2
  24. package/dist/core/sdk.js.map +1 -1
  25. package/dist/core/session-manager.d.ts +3 -0
  26. package/dist/core/session-manager.d.ts.map +1 -1
  27. package/dist/core/session-manager.js +13 -6
  28. package/dist/core/session-manager.js.map +1 -1
  29. package/dist/core/tools/edit.d.ts.map +1 -1
  30. package/dist/core/tools/edit.js +15 -4
  31. package/dist/core/tools/edit.js.map +1 -1
  32. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  33. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  34. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  35. package/dist/main.d.ts.map +1 -1
  36. package/dist/main.js +1 -1
  37. package/dist/main.js.map +1 -1
  38. package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  39. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  40. package/dist/modes/interactive/components/assistant-message.js +13 -3
  41. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  42. package/dist/modes/interactive/components/tree-selector.d.ts +4 -2
  43. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  44. package/dist/modes/interactive/components/tree-selector.js +48 -15
  45. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  46. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  47. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  48. package/dist/modes/interactive/interactive-mode.js +23 -3
  49. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  50. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  51. package/dist/modes/rpc/rpc-mode.js +3 -0
  52. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  53. package/docs/extensions.md +61 -0
  54. package/docs/json.md +5 -2
  55. package/docs/keybindings.md +2 -0
  56. package/docs/rpc.md +21 -7
  57. package/docs/sdk.md +20 -12
  58. package/docs/tree.md +5 -2
  59. package/examples/extensions/README.md +1 -0
  60. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  61. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  62. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  63. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  64. package/examples/extensions/hidden-thinking-label.ts +57 -0
  65. package/examples/extensions/with-deps/package-lock.json +2 -2
  66. package/examples/extensions/with-deps/package.json +1 -1
  67. package/examples/sdk/02-custom-model.ts +1 -1
  68. package/examples/sdk/09-api-keys-and-oauth.ts +3 -3
  69. package/examples/sdk/12-full-control.ts +1 -1
  70. package/examples/sdk/README.md +3 -3
  71. package/package.json +4 -4
@@ -160,7 +160,7 @@ export class AgentSession {
160
160
  * happens here instead of in wrappers.
161
161
  */
162
162
  _installAgentToolHooks() {
163
- this.agent.setBeforeToolCall(async ({ toolCall, args }) => {
163
+ this.agent.beforeToolCall = async ({ toolCall, args }) => {
164
164
  const runner = this._extensionRunner;
165
165
  if (!runner?.hasHandlers("tool_call")) {
166
166
  return undefined;
@@ -180,8 +180,8 @@ export class AgentSession {
180
180
  }
181
181
  throw new Error(`Extension failed, blocking execution: ${String(err)}`);
182
182
  }
183
- });
184
- this.agent.setAfterToolCall(async ({ toolCall, args, result, isError }) => {
183
+ };
184
+ this.agent.afterToolCall = async ({ toolCall, args, result, isError }) => {
185
185
  const runner = this._extensionRunner;
186
186
  if (!runner?.hasHandlers("tool_result")) {
187
187
  return undefined;
@@ -202,7 +202,7 @@ export class AgentSession {
202
202
  content: hookResult.content,
203
203
  details: hookResult.details,
204
204
  };
205
- });
205
+ };
206
206
  }
207
207
  // =========================================================================
208
208
  // Event Subscription
@@ -213,6 +213,13 @@ export class AgentSession {
213
213
  l(event);
214
214
  }
215
215
  }
216
+ _emitQueueUpdate() {
217
+ this._emit({
218
+ type: "queue_update",
219
+ steering: [...this._steeringMessages],
220
+ followUp: [...this._followUpMessages],
221
+ });
222
+ }
216
223
  _createRetryPromiseForAgentEnd(event) {
217
224
  if (event.type !== "agent_end" || this._retryPromise) {
218
225
  return;
@@ -249,12 +256,14 @@ export class AgentSession {
249
256
  const steeringIndex = this._steeringMessages.indexOf(messageText);
250
257
  if (steeringIndex !== -1) {
251
258
  this._steeringMessages.splice(steeringIndex, 1);
259
+ this._emitQueueUpdate();
252
260
  }
253
261
  else {
254
262
  // Check follow-up queue
255
263
  const followUpIndex = this._followUpMessages.indexOf(messageText);
256
264
  if (followUpIndex !== -1) {
257
265
  this._followUpMessages.splice(followUpIndex, 1);
266
+ this._emitQueueUpdate();
258
267
  }
259
268
  }
260
269
  }
@@ -529,10 +538,10 @@ export class AgentSession {
529
538
  validToolNames.push(name);
530
539
  }
531
540
  }
532
- this.agent.setTools(tools);
541
+ this.agent.state.tools = tools;
533
542
  // Rebuild base system prompt with new tool set
534
543
  this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
535
- this.agent.setSystemPrompt(this._baseSystemPrompt);
544
+ this.agent.state.systemPrompt = this._baseSystemPrompt;
536
545
  }
537
546
  /** Whether compaction or branch summarization is currently running */
538
547
  get isCompacting() {
@@ -546,11 +555,11 @@ export class AgentSession {
546
555
  }
547
556
  /** Current steering mode */
548
557
  get steeringMode() {
549
- return this.agent.getSteeringMode();
558
+ return this.agent.steeringMode;
550
559
  }
551
560
  /** Current follow-up mode */
552
561
  get followUpMode() {
553
- return this.agent.getFollowUpMode();
562
+ return this.agent.followUpMode;
554
563
  }
555
564
  /** Current session file path, or undefined if sessions are disabled */
556
565
  get sessionFile() {
@@ -741,11 +750,11 @@ export class AgentSession {
741
750
  }
742
751
  // Apply extension-modified system prompt, or reset to base
743
752
  if (result?.systemPrompt) {
744
- this.agent.setSystemPrompt(result.systemPrompt);
753
+ this.agent.state.systemPrompt = result.systemPrompt;
745
754
  }
746
755
  else {
747
756
  // Ensure we're using the base prompt (in case previous turn had modifications)
748
- this.agent.setSystemPrompt(this._baseSystemPrompt);
757
+ this.agent.state.systemPrompt = this._baseSystemPrompt;
749
758
  }
750
759
  }
751
760
  await this.agent.prompt(messages);
@@ -850,6 +859,7 @@ export class AgentSession {
850
859
  */
851
860
  async _queueSteer(text, images) {
852
861
  this._steeringMessages.push(text);
862
+ this._emitQueueUpdate();
853
863
  const content = [{ type: "text", text }];
854
864
  if (images) {
855
865
  content.push(...images);
@@ -865,6 +875,7 @@ export class AgentSession {
865
875
  */
866
876
  async _queueFollowUp(text, images) {
867
877
  this._followUpMessages.push(text);
878
+ this._emitQueueUpdate();
868
879
  const content = [{ type: "text", text }];
869
880
  if (images) {
870
881
  content.push(...images);
@@ -924,7 +935,7 @@ export class AgentSession {
924
935
  await this.agent.prompt(appMessage);
925
936
  }
926
937
  else {
927
- this.agent.appendMessage(appMessage);
938
+ this.agent.state.messages.push(appMessage);
928
939
  this.sessionManager.appendCustomMessageEntry(message.customType, message.content, message.display, message.details);
929
940
  this._emit({ type: "message_start", message: appMessage });
930
941
  this._emit({ type: "message_end", message: appMessage });
@@ -978,6 +989,7 @@ export class AgentSession {
978
989
  this._steeringMessages = [];
979
990
  this._followUpMessages = [];
980
991
  this.agent.clearAllQueues();
992
+ this._emitQueueUpdate();
981
993
  return { steering, followUp };
982
994
  }
983
995
  /** Number of pending messages (includes both steering and follow-up) */
@@ -1037,7 +1049,7 @@ export class AgentSession {
1037
1049
  await options.setup(this.sessionManager);
1038
1050
  // Sync agent state with session manager after setup
1039
1051
  const sessionContext = this.sessionManager.buildSessionContext();
1040
- this.agent.replaceMessages(sessionContext.messages);
1052
+ this.agent.state.messages = sessionContext.messages;
1041
1053
  }
1042
1054
  this._reconnectToAgent();
1043
1055
  // Emit session_switch event with reason "new" to extensions
@@ -1077,7 +1089,7 @@ export class AgentSession {
1077
1089
  }
1078
1090
  const previousModel = this.model;
1079
1091
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1080
- this.agent.setModel(model);
1092
+ this.agent.state.model = model;
1081
1093
  this.sessionManager.appendModelChange(model.provider, model.id);
1082
1094
  this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
1083
1095
  // Re-clamp thinking level for new model's capabilities
@@ -1112,7 +1124,7 @@ export class AgentSession {
1112
1124
  const next = scopedModels[nextIndex];
1113
1125
  const thinkingLevel = this._getThinkingLevelForModelSwitch(next.thinkingLevel);
1114
1126
  // Apply model
1115
- this.agent.setModel(next.model);
1127
+ this.agent.state.model = next.model;
1116
1128
  this.sessionManager.appendModelChange(next.model.provider, next.model.id);
1117
1129
  this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
1118
1130
  // Apply thinking level.
@@ -1135,7 +1147,7 @@ export class AgentSession {
1135
1147
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1136
1148
  const nextModel = availableModels[nextIndex];
1137
1149
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1138
- this.agent.setModel(nextModel);
1150
+ this.agent.state.model = nextModel;
1139
1151
  this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
1140
1152
  this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
1141
1153
  // Re-clamp thinking level for new model's capabilities
@@ -1156,7 +1168,7 @@ export class AgentSession {
1156
1168
  const effectiveLevel = availableLevels.includes(level) ? level : this._clampThinkingLevel(level, availableLevels);
1157
1169
  // Only persist if actually changing
1158
1170
  const isChanging = effectiveLevel !== this.agent.state.thinkingLevel;
1159
- this.agent.setThinkingLevel(effectiveLevel);
1171
+ this.agent.state.thinkingLevel = effectiveLevel;
1160
1172
  if (isChanging) {
1161
1173
  this.sessionManager.appendThinkingLevelChange(effectiveLevel);
1162
1174
  if (this.supportsThinking() || effectiveLevel !== "off") {
@@ -1235,7 +1247,7 @@ export class AgentSession {
1235
1247
  * Saves to settings.
1236
1248
  */
1237
1249
  setSteeringMode(mode) {
1238
- this.agent.setSteeringMode(mode);
1250
+ this.agent.steeringMode = mode;
1239
1251
  this.settingsManager.setSteeringMode(mode);
1240
1252
  }
1241
1253
  /**
@@ -1243,7 +1255,7 @@ export class AgentSession {
1243
1255
  * Saves to settings.
1244
1256
  */
1245
1257
  setFollowUpMode(mode) {
1246
- this.agent.setFollowUpMode(mode);
1258
+ this.agent.followUpMode = mode;
1247
1259
  this.settingsManager.setFollowUpMode(mode);
1248
1260
  }
1249
1261
  // =========================================================================
@@ -1318,7 +1330,7 @@ export class AgentSession {
1318
1330
  this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
1319
1331
  const newEntries = this.sessionManager.getEntries();
1320
1332
  const sessionContext = this.sessionManager.buildSessionContext();
1321
- this.agent.replaceMessages(sessionContext.messages);
1333
+ this.agent.state.messages = sessionContext.messages;
1322
1334
  // Get the saved compaction entry for the extension event
1323
1335
  const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
1324
1336
  if (this._extensionRunner && savedCompactionEntry) {
@@ -1424,7 +1436,7 @@ export class AgentSession {
1424
1436
  // but we don't want it in context for the retry)
1425
1437
  const messages = this.agent.state.messages;
1426
1438
  if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
1427
- this.agent.replaceMessages(messages.slice(0, -1));
1439
+ this.agent.state.messages = messages.slice(0, -1);
1428
1440
  }
1429
1441
  await this._runAutoCompaction("overflow", true);
1430
1442
  return;
@@ -1555,7 +1567,7 @@ export class AgentSession {
1555
1567
  this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
1556
1568
  const newEntries = this.sessionManager.getEntries();
1557
1569
  const sessionContext = this.sessionManager.buildSessionContext();
1558
- this.agent.replaceMessages(sessionContext.messages);
1570
+ this.agent.state.messages = sessionContext.messages;
1559
1571
  // Get the saved compaction entry for the extension event
1560
1572
  const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
1561
1573
  if (this._extensionRunner && savedCompactionEntry) {
@@ -1576,7 +1588,7 @@ export class AgentSession {
1576
1588
  const messages = this.agent.state.messages;
1577
1589
  const lastMsg = messages[messages.length - 1];
1578
1590
  if (lastMsg?.role === "assistant" && lastMsg.stopReason === "error") {
1579
- this.agent.replaceMessages(messages.slice(0, -1));
1591
+ this.agent.state.messages = messages.slice(0, -1);
1580
1592
  }
1581
1593
  setTimeout(() => {
1582
1594
  this.agent.continue().catch(() => { });
@@ -1651,7 +1663,7 @@ export class AgentSession {
1651
1663
  };
1652
1664
  this._resourceLoader.extendResources(extensionPaths);
1653
1665
  this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
1654
- this.agent.setSystemPrompt(this._baseSystemPrompt);
1666
+ this.agent.state.systemPrompt = this._baseSystemPrompt;
1655
1667
  }
1656
1668
  buildExtensionResourcePaths(entries) {
1657
1669
  return entries.map((entry) => {
@@ -1693,7 +1705,7 @@ export class AgentSession {
1693
1705
  if (!refreshedModel || refreshedModel === currentModel) {
1694
1706
  return;
1695
1707
  }
1696
- this.agent.setModel(refreshedModel);
1708
+ this.agent.state.model = refreshedModel;
1697
1709
  }
1698
1710
  _bindExtensionCore(runner) {
1699
1711
  const getCommands = () => {
@@ -2018,7 +2030,7 @@ export class AgentSession {
2018
2030
  // Remove error message from agent state (keep in session for history)
2019
2031
  const messages = this.agent.state.messages;
2020
2032
  if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
2021
- this.agent.replaceMessages(messages.slice(0, -1));
2033
+ this.agent.state.messages = messages.slice(0, -1);
2022
2034
  }
2023
2035
  // Wait with exponential backoff (abortable)
2024
2036
  this._retryAbortController = new AbortController();
@@ -2061,9 +2073,11 @@ export class AgentSession {
2061
2073
  * Returns immediately if no retry is in progress.
2062
2074
  */
2063
2075
  async waitForRetry() {
2064
- if (this._retryPromise) {
2065
- await this._retryPromise;
2076
+ if (!this._retryPromise) {
2077
+ return;
2066
2078
  }
2079
+ await this._retryPromise;
2080
+ await this.agent.waitForIdle();
2067
2081
  }
2068
2082
  /** Whether auto-retry is currently in progress */
2069
2083
  get isRetrying() {
@@ -2135,7 +2149,7 @@ export class AgentSession {
2135
2149
  }
2136
2150
  else {
2137
2151
  // Add to agent state immediately
2138
- this.agent.appendMessage(bashMessage);
2152
+ this.agent.state.messages.push(bashMessage);
2139
2153
  // Save to session
2140
2154
  this.sessionManager.appendMessage(bashMessage);
2141
2155
  }
@@ -2163,7 +2177,7 @@ export class AgentSession {
2163
2177
  return;
2164
2178
  for (const bashMessage of this._pendingBashMessages) {
2165
2179
  // Add to agent state
2166
- this.agent.appendMessage(bashMessage);
2180
+ this.agent.state.messages.push(bashMessage);
2167
2181
  // Save to session
2168
2182
  this.sessionManager.appendMessage(bashMessage);
2169
2183
  }
@@ -2210,14 +2224,14 @@ export class AgentSession {
2210
2224
  });
2211
2225
  }
2212
2226
  // Emit session event to custom tools
2213
- this.agent.replaceMessages(sessionContext.messages);
2227
+ this.agent.state.messages = sessionContext.messages;
2214
2228
  // Restore model if saved
2215
2229
  if (sessionContext.model) {
2216
2230
  const previousModel = this.model;
2217
2231
  const availableModels = await this._modelRegistry.getAvailable();
2218
2232
  const match = availableModels.find((m) => m.provider === sessionContext.model.provider && m.id === sessionContext.model.modelId);
2219
2233
  if (match) {
2220
- this.agent.setModel(match);
2234
+ this.agent.state.model = match;
2221
2235
  await this._emitModelSelect(match, previousModel, "restore");
2222
2236
  }
2223
2237
  }
@@ -2232,7 +2246,7 @@ export class AgentSession {
2232
2246
  const effectiveLevel = availableLevels.includes(defaultThinkingLevel)
2233
2247
  ? defaultThinkingLevel
2234
2248
  : this._clampThinkingLevel(defaultThinkingLevel, availableLevels);
2235
- this.agent.setThinkingLevel(effectiveLevel);
2249
+ this.agent.state.thinkingLevel = effectiveLevel;
2236
2250
  this.sessionManager.appendThinkingLevelChange(effectiveLevel);
2237
2251
  }
2238
2252
  this._reconnectToAgent();
@@ -2292,7 +2306,7 @@ export class AgentSession {
2292
2306
  }
2293
2307
  // Emit session event to custom tools (with reason "fork")
2294
2308
  if (!skipConversationRestore) {
2295
- this.agent.replaceMessages(sessionContext.messages);
2309
+ this.agent.state.messages = sessionContext.messages;
2296
2310
  }
2297
2311
  return { selectedText, cancelled: false };
2298
2312
  }
@@ -2451,7 +2465,7 @@ export class AgentSession {
2451
2465
  }
2452
2466
  // Update agent state
2453
2467
  const sessionContext = this.sessionManager.buildSessionContext();
2454
- this.agent.replaceMessages(sessionContext.messages);
2468
+ this.agent.state.messages = sessionContext.messages;
2455
2469
  // Emit session_tree event
2456
2470
  if (this._extensionRunner) {
2457
2471
  await this._extensionRunner.emit({