@fleetagent/pi-coding-agent 0.0.6 → 0.0.8

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 (157) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +3 -3
  3. package/dist/cli/file-processor.d.ts.map +1 -1
  4. package/dist/cli/file-processor.js +2 -3
  5. package/dist/cli/file-processor.js.map +1 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +15 -2
  8. package/dist/config.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +12 -0
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +123 -18
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/export-html/template.js +6 -3
  14. package/dist/core/extensions/runner.d.ts +1 -1
  15. package/dist/core/extensions/runner.d.ts.map +1 -1
  16. package/dist/core/extensions/runner.js +8 -2
  17. package/dist/core/extensions/runner.js.map +1 -1
  18. package/dist/core/extensions/types.d.ts +4 -2
  19. package/dist/core/extensions/types.d.ts.map +1 -1
  20. package/dist/core/extensions/types.js.map +1 -1
  21. package/dist/core/model-registry.d.ts.map +1 -1
  22. package/dist/core/model-registry.js +65 -13
  23. package/dist/core/model-registry.js.map +1 -1
  24. package/dist/core/output-guard.d.ts +1 -0
  25. package/dist/core/output-guard.d.ts.map +1 -1
  26. package/dist/core/output-guard.js +52 -22
  27. package/dist/core/output-guard.js.map +1 -1
  28. package/dist/core/package-manager.d.ts.map +1 -1
  29. package/dist/core/package-manager.js +31 -12
  30. package/dist/core/package-manager.js.map +1 -1
  31. package/dist/core/pi-agent.d.ts.map +1 -1
  32. package/dist/core/pi-agent.js +12 -3
  33. package/dist/core/pi-agent.js.map +1 -1
  34. package/dist/core/resolve-config-value.d.ts +9 -1
  35. package/dist/core/resolve-config-value.d.ts.map +1 -1
  36. package/dist/core/resolve-config-value.js +134 -11
  37. package/dist/core/resolve-config-value.js.map +1 -1
  38. package/dist/core/session/jsonl-helpers.d.ts +2 -1
  39. package/dist/core/session/jsonl-helpers.d.ts.map +1 -1
  40. package/dist/core/session/jsonl-helpers.js +6 -3
  41. package/dist/core/session/jsonl-helpers.js.map +1 -1
  42. package/dist/core/session/local-session-manager.d.ts +1 -0
  43. package/dist/core/session/local-session-manager.d.ts.map +1 -1
  44. package/dist/core/session/local-session-manager.js +12 -4
  45. package/dist/core/session/local-session-manager.js.map +1 -1
  46. package/dist/core/session/session-manager.d.ts +1 -0
  47. package/dist/core/session/session-manager.d.ts.map +1 -1
  48. package/dist/core/session/session-manager.js.map +1 -1
  49. package/dist/core/session/stores/jsonl-session-store.d.ts +2 -1
  50. package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -1
  51. package/dist/core/session/stores/jsonl-session-store.js +105 -78
  52. package/dist/core/session/stores/jsonl-session-store.js.map +1 -1
  53. package/dist/core/settings-manager.d.ts +2 -0
  54. package/dist/core/settings-manager.d.ts.map +1 -1
  55. package/dist/core/settings-manager.js +14 -9
  56. package/dist/core/settings-manager.js.map +1 -1
  57. package/dist/core/tools/bash.d.ts.map +1 -1
  58. package/dist/core/tools/bash.js +73 -63
  59. package/dist/core/tools/bash.js.map +1 -1
  60. package/dist/core/tools/edit.d.ts.map +1 -1
  61. package/dist/core/tools/edit.js +45 -76
  62. package/dist/core/tools/edit.js.map +1 -1
  63. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  64. package/dist/core/tools/file-mutation-queue.js +27 -12
  65. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  66. package/dist/core/tools/find.d.ts.map +1 -1
  67. package/dist/core/tools/find.js +11 -2
  68. package/dist/core/tools/find.js.map +1 -1
  69. package/dist/core/tools/grep.d.ts.map +1 -1
  70. package/dist/core/tools/grep.js +3 -3
  71. package/dist/core/tools/grep.js.map +1 -1
  72. package/dist/core/tools/ls.d.ts.map +1 -1
  73. package/dist/core/tools/ls.js +13 -4
  74. package/dist/core/tools/ls.js.map +1 -1
  75. package/dist/core/tools/path-utils.d.ts +1 -0
  76. package/dist/core/tools/path-utils.d.ts.map +1 -1
  77. package/dist/core/tools/path-utils.js +37 -0
  78. package/dist/core/tools/path-utils.js.map +1 -1
  79. package/dist/core/tools/read.d.ts.map +1 -1
  80. package/dist/core/tools/read.js +7 -6
  81. package/dist/core/tools/read.js.map +1 -1
  82. package/dist/core/tools/write.d.ts.map +1 -1
  83. package/dist/core/tools/write.js +24 -32
  84. package/dist/core/tools/write.js.map +1 -1
  85. package/dist/main.d.ts.map +1 -1
  86. package/dist/main.js +3 -2
  87. package/dist/main.js.map +1 -1
  88. package/dist/migrations.d.ts.map +1 -1
  89. package/dist/migrations.js +118 -1
  90. package/dist/migrations.js.map +1 -1
  91. package/dist/modes/interactive/components/footer.d.ts +1 -0
  92. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  93. package/dist/modes/interactive/components/footer.js +14 -5
  94. package/dist/modes/interactive/components/footer.js.map +1 -1
  95. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  96. package/dist/modes/interactive/components/user-message.js +1 -1
  97. package/dist/modes/interactive/components/user-message.js.map +1 -1
  98. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  99. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  100. package/dist/modes/interactive/interactive-mode.js +34 -8
  101. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  102. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  103. package/dist/modes/interactive/theme/theme.js +10 -0
  104. package/dist/modes/interactive/theme/theme.js.map +1 -1
  105. package/dist/modes/rpc/rpc-client.d.ts +3 -0
  106. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  107. package/dist/modes/rpc/rpc-client.js +64 -7
  108. package/dist/modes/rpc/rpc-client.js.map +1 -1
  109. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  110. package/dist/modes/rpc/rpc-mode.js +15 -3
  111. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  112. package/dist/utils/clipboard-native.d.ts +3 -1
  113. package/dist/utils/clipboard-native.d.ts.map +1 -1
  114. package/dist/utils/clipboard-native.js +14 -8
  115. package/dist/utils/clipboard-native.js.map +1 -1
  116. package/dist/utils/deprecation.d.ts +4 -0
  117. package/dist/utils/deprecation.d.ts.map +1 -0
  118. package/dist/utils/deprecation.js +13 -0
  119. package/dist/utils/deprecation.js.map +1 -0
  120. package/dist/utils/image-resize-core.d.ts +30 -0
  121. package/dist/utils/image-resize-core.d.ts.map +1 -0
  122. package/dist/utils/image-resize-core.js +124 -0
  123. package/dist/utils/image-resize-core.js.map +1 -0
  124. package/dist/utils/image-resize-worker.d.ts +2 -0
  125. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  126. package/dist/utils/image-resize-worker.js +31 -0
  127. package/dist/utils/image-resize-worker.js.map +1 -0
  128. package/dist/utils/image-resize.d.ts +6 -27
  129. package/dist/utils/image-resize.d.ts.map +1 -1
  130. package/dist/utils/image-resize.js +60 -116
  131. package/dist/utils/image-resize.js.map +1 -1
  132. package/dist/utils/json.d.ts +3 -0
  133. package/dist/utils/json.d.ts.map +1 -0
  134. package/dist/utils/json.js +7 -0
  135. package/dist/utils/json.js.map +1 -0
  136. package/dist/utils/version-check.d.ts.map +1 -1
  137. package/dist/utils/version-check.js +10 -4
  138. package/dist/utils/version-check.js.map +1 -1
  139. package/docs/custom-provider.md +22 -9
  140. package/docs/extensions.md +4 -3
  141. package/docs/models.md +34 -12
  142. package/docs/packages.md +5 -4
  143. package/docs/providers.md +13 -5
  144. package/docs/sdk.md +56 -0
  145. package/docs/settings.md +4 -2
  146. package/docs/terminal-setup.md +6 -0
  147. package/docs/usage.md +3 -3
  148. package/examples/extensions/README.md +1 -0
  149. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  150. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  151. package/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
  152. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  153. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  154. package/examples/extensions/sandbox/package.json +1 -1
  155. package/examples/extensions/with-deps/package.json +1 -1
  156. package/npm-shrinkwrap.json +13 -12
  157. package/package.json +5 -5
@@ -110,6 +110,9 @@ export class AgentSession {
110
110
  // Compaction state
111
111
  _compactionAbortController = undefined;
112
112
  _autoCompactionAbortController = undefined;
113
+ _extensionCompactionQueue = [];
114
+ _extensionCompactionTimer = undefined;
115
+ _extensionCompactionRunning = false;
113
116
  _overflowRecoveryAttempted = false;
114
117
  // Branch summarization state
115
118
  _branchSummaryAbortController = undefined;
@@ -165,6 +168,7 @@ export class AgentSession {
165
168
  // (session persistence, extensions, auto-compaction, retry logic)
166
169
  this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
167
170
  this._installAgentToolHooks();
171
+ this._installAgentTurnPreparation();
168
172
  this._buildRuntime({
169
173
  activeToolNames: this._initialActiveToolNames,
170
174
  includeAllExtensionTools: true,
@@ -253,6 +257,27 @@ export class AgentSession {
253
257
  };
254
258
  };
255
259
  }
260
+ _installAgentTurnPreparation() {
261
+ const previousPrepareNextTurn = this.agent.prepareNextTurn;
262
+ this.agent.prepareNextTurn = async (signal) => {
263
+ const previousUpdate = await previousPrepareNextTurn?.(signal);
264
+ const compacted = await this._drainExtensionCompactionQueue("between-turns");
265
+ if (!compacted) {
266
+ return previousUpdate;
267
+ }
268
+ return {
269
+ ...previousUpdate,
270
+ context: this._buildCurrentAgentContext(previousUpdate?.context),
271
+ };
272
+ };
273
+ }
274
+ _buildCurrentAgentContext(previousContext) {
275
+ return {
276
+ systemPrompt: previousContext?.systemPrompt ?? this.agent.state.systemPrompt,
277
+ messages: this.agent.state.messages.slice(),
278
+ tools: previousContext?.tools ?? this.agent.state.tools.slice(),
279
+ };
280
+ }
256
281
  // =========================================================================
257
282
  // Event Subscription
258
283
  // =========================================================================
@@ -299,6 +324,9 @@ export class AgentSession {
299
324
  await this._emitExtensionEvent(event);
300
325
  // Notify all listeners
301
326
  this._emit(event.type === "agent_end" ? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } : event);
327
+ if (event.type === "agent_end") {
328
+ this._scheduleExtensionCompactions();
329
+ }
302
330
  // Handle session persistence
303
331
  if (event.type === "message_end") {
304
332
  // Check if this is a custom message from extensions
@@ -503,6 +531,21 @@ export class AgentSession {
503
531
  * Call this when completely done with the session.
504
532
  */
505
533
  dispose() {
534
+ try {
535
+ this.abortRetry();
536
+ this.abortCompaction();
537
+ this.abortBranchSummary();
538
+ this.abortBash();
539
+ this.agent.abort();
540
+ }
541
+ catch {
542
+ // Dispose must succeed even if an abort hook throws.
543
+ }
544
+ if (this._extensionCompactionTimer !== undefined) {
545
+ clearTimeout(this._extensionCompactionTimer);
546
+ this._extensionCompactionTimer = undefined;
547
+ }
548
+ this._extensionCompactionQueue = [];
506
549
  this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().");
507
550
  this._disconnectFromAgent();
508
551
  this._eventListeners = [];
@@ -710,7 +753,12 @@ export class AgentSession {
710
753
  });
711
754
  this._retryAttempt = 0;
712
755
  }
713
- return await this._checkCompaction(msg);
756
+ if (await this._checkCompaction(msg)) {
757
+ return true;
758
+ }
759
+ // The agent loop drains both queues before emitting agent_end. Any messages
760
+ // here were queued by agent_end extension handlers and need a continuation.
761
+ return this.agent.hasQueuedMessages();
714
762
  }
715
763
  async getStructuredResponse(options) {
716
764
  if (this.isStreaming) {
@@ -920,7 +968,7 @@ export class AgentSession {
920
968
  let currentText = text;
921
969
  let currentImages = options?.images;
922
970
  if (this._extensionRunner.hasHandlers("input")) {
923
- const inputResult = await this._extensionRunner.emitInput(currentText, currentImages, options?.source ?? "interactive");
971
+ const inputResult = await this._extensionRunner.emitInput(currentText, currentImages, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
924
972
  if (inputResult.action === "handled") {
925
973
  preflightResult?.(true);
926
974
  return;
@@ -1229,8 +1277,8 @@ export class AgentSession {
1229
1277
  else {
1230
1278
  this.agent.state.messages.push(appMessage);
1231
1279
  this.session.appendCustomMessageEntry(message.customType, message.content, message.display, message.details);
1232
- this._emit({ type: "message_start", message: appMessage });
1233
- this._emit({ type: "message_end", message: appMessage });
1280
+ await this._emit({ type: "message_start", message: appMessage });
1281
+ await this._emit({ type: "message_end", message: appMessage });
1234
1282
  }
1235
1283
  }
1236
1284
  /**
@@ -1485,14 +1533,73 @@ export class AgentSession {
1485
1533
  // =========================================================================
1486
1534
  // Compaction
1487
1535
  // =========================================================================
1536
+ /** Queue extension-triggered compaction outside the currently active agent turn. */
1537
+ _requestExtensionCompaction(options) {
1538
+ this._extensionCompactionQueue.push(options ?? {});
1539
+ if (this.isStreaming) {
1540
+ return;
1541
+ }
1542
+ this._scheduleExtensionCompactions();
1543
+ }
1544
+ _scheduleExtensionCompactions() {
1545
+ const alreadyScheduled = this._extensionCompactionTimer !== undefined;
1546
+ if (this._extensionCompactionRunning || alreadyScheduled || this._extensionCompactionQueue.length === 0) {
1547
+ return;
1548
+ }
1549
+ this._extensionCompactionTimer = setTimeout(() => {
1550
+ this._extensionCompactionTimer = undefined;
1551
+ void this._drainExtensionCompactionQueue();
1552
+ }, 0);
1553
+ }
1554
+ async _drainExtensionCompactionQueue(mode = "idle") {
1555
+ if (this._extensionCompactionRunning) {
1556
+ return false;
1557
+ }
1558
+ this._extensionCompactionRunning = true;
1559
+ let compacted = false;
1560
+ try {
1561
+ while (mode === "between-turns" || !this.isStreaming) {
1562
+ const options = this._extensionCompactionQueue.shift();
1563
+ if (!options) {
1564
+ break;
1565
+ }
1566
+ compacted = true;
1567
+ await this._runRequestedExtensionCompaction(options, mode === "idle");
1568
+ }
1569
+ }
1570
+ finally {
1571
+ this._extensionCompactionRunning = false;
1572
+ }
1573
+ if (mode === "idle" && !this.isStreaming) {
1574
+ this._scheduleExtensionCompactions();
1575
+ }
1576
+ return compacted;
1577
+ }
1578
+ async _runRequestedExtensionCompaction(options, abortActiveRun) {
1579
+ try {
1580
+ const result = await this._compactSession(options.customInstructions, { abortActiveRun });
1581
+ options.onComplete?.(result);
1582
+ }
1583
+ catch (error) {
1584
+ const err = error instanceof Error ? error : new Error(String(error));
1585
+ options.onError?.(err);
1586
+ }
1587
+ }
1488
1588
  /**
1489
1589
  * Manually compact the session context.
1490
1590
  * Aborts current agent operation first.
1491
1591
  * @param customInstructions Optional instructions for the compaction summary
1492
1592
  */
1493
1593
  async compact(customInstructions) {
1494
- this._disconnectFromAgent();
1495
- await this.abort();
1594
+ return this._compactSession(customInstructions, { abortActiveRun: true });
1595
+ }
1596
+ async _compactSession(customInstructions, options) {
1597
+ let disconnected = false;
1598
+ if (options.abortActiveRun) {
1599
+ this._disconnectFromAgent();
1600
+ disconnected = true;
1601
+ await this.abort();
1602
+ }
1496
1603
  this._compactionAbortController = new AbortController();
1497
1604
  this._emit({ type: "compaction_start", reason: "manual" });
1498
1605
  try {
@@ -1594,7 +1701,9 @@ export class AgentSession {
1594
1701
  }
1595
1702
  finally {
1596
1703
  this._compactionAbortController = undefined;
1597
- this._reconnectToAgent();
1704
+ if (disconnected) {
1705
+ this._reconnectToAgent();
1706
+ }
1598
1707
  }
1599
1708
  }
1600
1709
  /**
@@ -2025,16 +2134,7 @@ export class AgentSession {
2025
2134
  },
2026
2135
  getContextUsage: () => this.getContextUsage(),
2027
2136
  compact: (options) => {
2028
- void (async () => {
2029
- try {
2030
- const result = await this.compact(options?.customInstructions);
2031
- options?.onComplete?.(result);
2032
- }
2033
- catch (error) {
2034
- const err = error instanceof Error ? error : new Error(String(error));
2035
- options?.onError?.(err);
2036
- }
2037
- })();
2137
+ this._requestExtensionCompaction(options);
2038
2138
  },
2039
2139
  getSystemPrompt: () => this.systemPrompt,
2040
2140
  }, {
@@ -2182,6 +2282,9 @@ export class AgentSession {
2182
2282
  // =========================================================================
2183
2283
  // Auto-Retry
2184
2284
  // =========================================================================
2285
+ _isNonRetryableProviderLimitError(errorMessage) {
2286
+ return /GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorMessage);
2287
+ }
2185
2288
  /**
2186
2289
  * Check if an error is retryable (overloaded, rate limit, server errors).
2187
2290
  * Context overflow errors are NOT retryable (handled by compaction instead).
@@ -2194,6 +2297,8 @@ export class AgentSession {
2194
2297
  if (isContextOverflow(message, contextWindow))
2195
2298
  return false;
2196
2299
  const err = message.errorMessage;
2300
+ if (this._isNonRetryableProviderLimitError(err))
2301
+ return false;
2197
2302
  // Match: overloaded_error, provider returned error, rate limit, 429, 500, 502, 503, 504, service unavailable, network/connection errors (including connection lost), WebSocket transport closes/errors, fetch failed, premature stream endings, HTTP/2 closed before response, terminated, retry delay exceeded
2198
2303
  return /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i.test(err);
2199
2304
  }
@@ -2361,7 +2466,7 @@ export class AgentSession {
2361
2466
  */
2362
2467
  setSessionName(name) {
2363
2468
  this.session.appendSessionInfo(name);
2364
- this._emit({ type: "session_info_changed", name: this.session.getSessionName() });
2469
+ void this._emit({ type: "session_info_changed", name: this.session.getSessionName() });
2365
2470
  }
2366
2471
  // =========================================================================
2367
2472
  // Tree Navigation