gsd-pi 2.10.2 → 2.10.5

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 (136) hide show
  1. package/README.md +2 -0
  2. package/dist/cli.js +7 -0
  3. package/dist/loader.js +1 -0
  4. package/dist/onboarding.js +104 -59
  5. package/dist/update-cmd.d.ts +1 -0
  6. package/dist/update-cmd.js +40 -0
  7. package/node_modules/@gsd/native/dist/hasher/index.d.ts +32 -0
  8. package/node_modules/@gsd/native/dist/hasher/index.js +37 -0
  9. package/node_modules/@gsd/native/dist/native.d.ts +4 -1
  10. package/node_modules/@gsd/native/dist/native.js +39 -9
  11. package/node_modules/@gsd/native/dist/xxhash/index.d.ts +14 -0
  12. package/node_modules/@gsd/native/dist/xxhash/index.js +17 -0
  13. package/node_modules/@gsd/pi-coding-agent/dist/core/agent-session.d.ts +6 -0
  14. package/node_modules/@gsd/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  15. package/node_modules/@gsd/pi-coding-agent/dist/core/agent-session.js +58 -9
  16. package/node_modules/@gsd/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  17. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.d.ts +72 -12
  18. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  19. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.js +254 -43
  20. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  21. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.test.d.ts +2 -0
  22. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.test.d.ts.map +1 -0
  23. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.test.js +159 -0
  24. package/node_modules/@gsd/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -0
  25. package/node_modules/@gsd/pi-coding-agent/dist/core/model-registry.d.ts +4 -2
  26. package/node_modules/@gsd/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  27. package/node_modules/@gsd/pi-coding-agent/dist/core/model-registry.js +6 -4
  28. package/node_modules/@gsd/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  29. package/node_modules/@gsd/pi-coding-agent/dist/core/settings-manager.d.ts +15 -0
  30. package/node_modules/@gsd/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  31. package/node_modules/@gsd/pi-coding-agent/dist/core/settings-manager.js +12 -0
  32. package/node_modules/@gsd/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  33. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.d.ts +40 -0
  34. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.d.ts.map +1 -0
  35. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.js +92 -0
  36. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.js.map +1 -0
  37. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.test.d.ts +2 -0
  38. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.test.d.ts.map +1 -0
  39. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.test.js +156 -0
  40. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash-interceptor.test.js.map +1 -0
  41. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash.d.ts +8 -0
  42. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  43. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash.js +18 -0
  44. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  45. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/index.d.ts +1 -0
  46. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  47. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/index.js +1 -0
  48. package/node_modules/@gsd/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  49. package/node_modules/@gsd/pi-coding-agent/dist/index.d.ts +2 -2
  50. package/node_modules/@gsd/pi-coding-agent/dist/index.d.ts.map +1 -1
  51. package/node_modules/@gsd/pi-coding-agent/dist/index.js +1 -1
  52. package/node_modules/@gsd/pi-coding-agent/dist/index.js.map +1 -1
  53. package/node_modules/@gsd/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  54. package/node_modules/@gsd/pi-coding-agent/dist/modes/interactive/interactive-mode.js +1 -1
  55. package/node_modules/@gsd/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  56. package/node_modules/@gsd/pi-coding-agent/src/core/agent-session.ts +65 -9
  57. package/node_modules/@gsd/pi-coding-agent/src/core/auth-storage.test.ts +194 -0
  58. package/node_modules/@gsd/pi-coding-agent/src/core/auth-storage.ts +283 -53
  59. package/node_modules/@gsd/pi-coding-agent/src/core/model-registry.ts +6 -4
  60. package/node_modules/@gsd/pi-coding-agent/src/core/settings-manager.ts +29 -0
  61. package/node_modules/@gsd/pi-coding-agent/src/core/tools/bash-interceptor.test.ts +198 -0
  62. package/node_modules/@gsd/pi-coding-agent/src/core/tools/bash-interceptor.ts +115 -0
  63. package/node_modules/@gsd/pi-coding-agent/src/core/tools/bash.ts +29 -0
  64. package/node_modules/@gsd/pi-coding-agent/src/core/tools/index.ts +8 -0
  65. package/node_modules/@gsd/pi-coding-agent/src/index.ts +6 -0
  66. package/node_modules/@gsd/pi-coding-agent/src/modes/interactive/interactive-mode.ts +1 -1
  67. package/package.json +8 -2
  68. package/packages/native/dist/hasher/index.d.ts +32 -0
  69. package/packages/native/dist/hasher/index.js +37 -0
  70. package/packages/native/dist/native.d.ts +4 -1
  71. package/packages/native/dist/native.js +39 -9
  72. package/packages/native/dist/xxhash/index.d.ts +14 -0
  73. package/packages/native/dist/xxhash/index.js +17 -0
  74. package/packages/native/src/native.ts +39 -9
  75. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +6 -0
  76. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  77. package/packages/pi-coding-agent/dist/core/agent-session.js +58 -9
  78. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  79. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +72 -12
  80. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  81. package/packages/pi-coding-agent/dist/core/auth-storage.js +254 -43
  82. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  83. package/packages/pi-coding-agent/dist/core/auth-storage.test.d.ts +2 -0
  84. package/packages/pi-coding-agent/dist/core/auth-storage.test.d.ts.map +1 -0
  85. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +159 -0
  86. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -0
  87. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +4 -2
  88. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  89. package/packages/pi-coding-agent/dist/core/model-registry.js +6 -4
  90. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  91. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +15 -0
  92. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  93. package/packages/pi-coding-agent/dist/core/settings-manager.js +12 -0
  94. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  95. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.d.ts +40 -0
  96. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.d.ts.map +1 -0
  97. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.js +92 -0
  98. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.js.map +1 -0
  99. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.test.d.ts +2 -0
  100. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.test.d.ts.map +1 -0
  101. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.test.js +156 -0
  102. package/packages/pi-coding-agent/dist/core/tools/bash-interceptor.test.js.map +1 -0
  103. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +8 -0
  104. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  105. package/packages/pi-coding-agent/dist/core/tools/bash.js +18 -0
  106. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  107. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +1 -0
  108. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  109. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
  110. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  111. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  112. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  113. package/packages/pi-coding-agent/dist/index.js +1 -1
  114. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +1 -1
  117. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  118. package/packages/pi-coding-agent/src/core/agent-session.ts +65 -9
  119. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +194 -0
  120. package/packages/pi-coding-agent/src/core/auth-storage.ts +283 -53
  121. package/packages/pi-coding-agent/src/core/model-registry.ts +6 -4
  122. package/packages/pi-coding-agent/src/core/settings-manager.ts +29 -0
  123. package/packages/pi-coding-agent/src/core/tools/bash-interceptor.test.ts +198 -0
  124. package/packages/pi-coding-agent/src/core/tools/bash-interceptor.ts +115 -0
  125. package/packages/pi-coding-agent/src/core/tools/bash.ts +29 -0
  126. package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
  127. package/packages/pi-coding-agent/src/index.ts +6 -0
  128. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +1 -1
  129. package/src/resources/extensions/async-jobs/async-bash-tool.ts +211 -0
  130. package/src/resources/extensions/async-jobs/await-tool.ts +101 -0
  131. package/src/resources/extensions/async-jobs/cancel-job-tool.ts +34 -0
  132. package/src/resources/extensions/async-jobs/index.ts +133 -0
  133. package/src/resources/extensions/async-jobs/job-manager.ts +250 -0
  134. package/src/resources/extensions/gsd/git-service.ts +13 -3
  135. package/src/resources/extensions/gsd/prompts/system.md +5 -2
  136. package/src/resources/extensions/gsd/tests/git-service.test.ts +36 -0
@@ -608,7 +608,7 @@ export class AgentSession {
608
608
  "Then use /model to select a model.");
609
609
  }
610
610
  // Validate API key
611
- const apiKey = await this._modelRegistry.getApiKey(this.model);
611
+ const apiKey = await this._modelRegistry.getApiKey(this.model, this.sessionId);
612
612
  if (!apiKey) {
613
613
  const isOAuth = this._modelRegistry.isUsingOAuth(this.model);
614
614
  if (isOAuth) {
@@ -989,7 +989,7 @@ export class AgentSession {
989
989
  * @throws Error if no API key available for the model
990
990
  */
991
991
  async setModel(model, options) {
992
- const apiKey = await this._modelRegistry.getApiKey(model);
992
+ const apiKey = await this._modelRegistry.getApiKey(model, this.sessionId);
993
993
  if (!apiKey) {
994
994
  throw new Error(`No API key for ${model.provider}/${model.id}`);
995
995
  }
@@ -1026,7 +1026,7 @@ export class AgentSession {
1026
1026
  apiKey = apiKeysByProvider.get(provider);
1027
1027
  }
1028
1028
  else {
1029
- apiKey = await this._modelRegistry.getApiKeyForProvider(provider);
1029
+ apiKey = await this._modelRegistry.getApiKeyForProvider(provider, this.sessionId);
1030
1030
  apiKeysByProvider.set(provider, apiKey);
1031
1031
  }
1032
1032
  if (apiKey) {
@@ -1072,7 +1072,7 @@ export class AgentSession {
1072
1072
  const len = availableModels.length;
1073
1073
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1074
1074
  const nextModel = availableModels[nextIndex];
1075
- const apiKey = await this._modelRegistry.getApiKey(nextModel);
1075
+ const apiKey = await this._modelRegistry.getApiKey(nextModel, this.sessionId);
1076
1076
  if (!apiKey) {
1077
1077
  throw new Error(`No API key for ${nextModel.provider}/${nextModel.id}`);
1078
1078
  }
@@ -1206,7 +1206,7 @@ export class AgentSession {
1206
1206
  if (!this.model) {
1207
1207
  throw new Error("No model selected");
1208
1208
  }
1209
- const apiKey = await this._modelRegistry.getApiKey(this.model);
1209
+ const apiKey = await this._modelRegistry.getApiKey(this.model, this.sessionId);
1210
1210
  if (!apiKey) {
1211
1211
  throw new Error(`No API key for ${this.model.provider}`);
1212
1212
  }
@@ -1392,7 +1392,7 @@ export class AgentSession {
1392
1392
  this._emit({ type: "auto_compaction_end", result: undefined, aborted: false, willRetry: false });
1393
1393
  return;
1394
1394
  }
1395
- const apiKey = await this._modelRegistry.getApiKey(this.model);
1395
+ const apiKey = await this._modelRegistry.getApiKey(this.model, this.sessionId);
1396
1396
  if (!apiKey) {
1397
1397
  this._emit({ type: "auto_compaction_end", result: undefined, aborted: false, willRetry: false });
1398
1398
  return;
@@ -1647,7 +1647,7 @@ export class AgentSession {
1647
1647
  refreshTools: () => this._refreshToolRegistry(),
1648
1648
  getCommands,
1649
1649
  setModel: async (model, options) => {
1650
- const key = await this.modelRegistry.getApiKey(model);
1650
+ const key = await this.modelRegistry.getApiKey(model, this.sessionId);
1651
1651
  if (!key)
1652
1652
  return false;
1653
1653
  await this.setModel(model, options);
@@ -1737,7 +1737,14 @@ export class AgentSession {
1737
1737
  ? this._baseToolsOverride
1738
1738
  : createAllTools(this._cwd, {
1739
1739
  read: { autoResizeImages },
1740
- bash: { commandPrefix: shellCommandPrefix },
1740
+ bash: {
1741
+ commandPrefix: shellCommandPrefix,
1742
+ interceptor: {
1743
+ enabled: this.settingsManager.getBashInterceptorEnabled(),
1744
+ rules: this.settingsManager.getBashInterceptorRules(),
1745
+ },
1746
+ availableToolNames: () => this.getActiveToolNames(),
1747
+ },
1741
1748
  });
1742
1749
  this._baseToolRegistry = new Map(Object.entries(baseTools).map(([name, tool]) => [name, tool]));
1743
1750
  const extensionsResult = this._resourceLoader.getExtensions();
@@ -1806,8 +1813,23 @@ export class AgentSession {
1806
1813
  // Match: overloaded_error, rate limit, 429, 500, 502, 503, 504, service unavailable, connection errors, fetch failed, terminated, retry delay exceeded
1807
1814
  return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay/i.test(err);
1808
1815
  }
1816
+ /**
1817
+ * Classify an error message into a usage-limit error type for credential backoff.
1818
+ */
1819
+ _classifyErrorType(errorMessage) {
1820
+ const err = errorMessage.toLowerCase();
1821
+ if (/quota|billing|exceeded.*limit|usage.*limit/i.test(err))
1822
+ return "quota_exhausted";
1823
+ if (/rate.?limit|too many requests|429/i.test(err))
1824
+ return "rate_limit";
1825
+ if (/500|502|503|504|server.?error|internal.?error|service.?unavailable/i.test(err))
1826
+ return "server_error";
1827
+ return "unknown";
1828
+ }
1809
1829
  /**
1810
1830
  * Handle retryable errors with exponential backoff.
1831
+ * When multiple credentials are available, marks the failing credential
1832
+ * as backed off and retries immediately with the next one.
1811
1833
  * @returns true if retry was initiated, false if max retries exceeded or disabled
1812
1834
  */
1813
1835
  async _handleRetryableError(message) {
@@ -1823,6 +1845,33 @@ export class AgentSession {
1823
1845
  this._retryResolve = resolve;
1824
1846
  });
1825
1847
  }
1848
+ // Try credential fallback before counting against retry budget.
1849
+ // If another credential is available, switch to it and retry immediately.
1850
+ if (this.model && message.errorMessage) {
1851
+ const errorType = this._classifyErrorType(message.errorMessage);
1852
+ const hasAlternate = this._modelRegistry.authStorage.markUsageLimitReached(this.model.provider, this.sessionId, { errorType });
1853
+ if (hasAlternate) {
1854
+ // Remove error message from agent state
1855
+ const messages = this.agent.state.messages;
1856
+ if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
1857
+ this.agent.replaceMessages(messages.slice(0, -1));
1858
+ }
1859
+ this._emit({
1860
+ type: "auto_retry_start",
1861
+ attempt: this._retryAttempt + 1,
1862
+ maxAttempts: settings.maxRetries,
1863
+ delayMs: 0,
1864
+ errorMessage: `${message.errorMessage} (switching credential)`,
1865
+ });
1866
+ // Retry immediately with the next credential - don't increment _retryAttempt
1867
+ setTimeout(() => {
1868
+ this.agent.continue().catch(() => {
1869
+ // Retry failed - will be caught by next agent_end
1870
+ });
1871
+ }, 0);
1872
+ return true;
1873
+ }
1874
+ }
1826
1875
  this._retryAttempt++;
1827
1876
  if (this._retryAttempt > settings.maxRetries) {
1828
1877
  // Max retries exceeded, emit final failure and reset
@@ -2203,7 +2252,7 @@ export class AgentSession {
2203
2252
  let summaryDetails;
2204
2253
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
2205
2254
  const model = this.model;
2206
- const apiKey = await this._modelRegistry.getApiKey(model);
2255
+ const apiKey = await this._modelRegistry.getApiKey(model, this.sessionId);
2207
2256
  if (!apiKey) {
2208
2257
  throw new Error(`No API key for ${model.provider}`);
2209
2258
  }