@earendil-works/pi-coding-agent 0.80.7 → 0.80.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 (140) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +6 -6
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js +2 -0
  5. package/dist/bun/cli.js.map +1 -1
  6. package/dist/cli/args.d.ts.map +1 -1
  7. package/dist/cli/args.js +1 -1
  8. package/dist/cli/args.js.map +1 -1
  9. package/dist/cli/list-models.d.ts +2 -2
  10. package/dist/cli/list-models.d.ts.map +1 -1
  11. package/dist/cli/list-models.js +3 -3
  12. package/dist/cli/list-models.js.map +1 -1
  13. package/dist/core/agent-session-services.d.ts +3 -6
  14. package/dist/core/agent-session-services.d.ts.map +1 -1
  15. package/dist/core/agent-session-services.js +10 -9
  16. package/dist/core/agent-session-services.js.map +1 -1
  17. package/dist/core/agent-session.d.ts +5 -6
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +57 -30
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/auth-storage.d.ts +15 -99
  22. package/dist/core/auth-storage.d.ts.map +1 -1
  23. package/dist/core/auth-storage.js +46 -259
  24. package/dist/core/auth-storage.js.map +1 -1
  25. package/dist/core/cache-stats.d.ts +2 -2
  26. package/dist/core/cache-stats.d.ts.map +1 -1
  27. package/dist/core/cache-stats.js +1 -1
  28. package/dist/core/cache-stats.js.map +1 -1
  29. package/dist/core/extensions/loader.d.ts.map +1 -1
  30. package/dist/core/extensions/loader.js +8 -2
  31. package/dist/core/extensions/loader.js.map +1 -1
  32. package/dist/core/extensions/runner.d.ts +1 -0
  33. package/dist/core/extensions/runner.d.ts.map +1 -1
  34. package/dist/core/extensions/runner.js +3 -0
  35. package/dist/core/extensions/runner.js.map +1 -1
  36. package/dist/core/extensions/types.d.ts +9 -2
  37. package/dist/core/extensions/types.d.ts.map +1 -1
  38. package/dist/core/extensions/types.js.map +1 -1
  39. package/dist/core/model-config.d.ts +507 -0
  40. package/dist/core/model-config.d.ts.map +1 -0
  41. package/dist/core/model-config.js +242 -0
  42. package/dist/core/model-config.js.map +1 -0
  43. package/dist/core/model-registry.d.ts +13 -123
  44. package/dist/core/model-registry.d.ts.map +1 -1
  45. package/dist/core/model-registry.js +44 -747
  46. package/dist/core/model-registry.js.map +1 -1
  47. package/dist/core/model-resolver.d.ts +6 -6
  48. package/dist/core/model-resolver.d.ts.map +1 -1
  49. package/dist/core/model-resolver.js +17 -17
  50. package/dist/core/model-resolver.js.map +1 -1
  51. package/dist/core/model-runtime.d.ts +77 -0
  52. package/dist/core/model-runtime.d.ts.map +1 -0
  53. package/dist/core/model-runtime.js +418 -0
  54. package/dist/core/model-runtime.js.map +1 -0
  55. package/dist/core/models-store.d.ts +17 -0
  56. package/dist/core/models-store.d.ts.map +1 -0
  57. package/dist/core/models-store.js +45 -0
  58. package/dist/core/models-store.js.map +1 -0
  59. package/dist/core/provider-composer.d.ts +55 -0
  60. package/dist/core/provider-composer.d.ts.map +1 -0
  61. package/dist/core/provider-composer.js +375 -0
  62. package/dist/core/provider-composer.js.map +1 -0
  63. package/dist/core/radius.d.ts +0 -19
  64. package/dist/core/radius.d.ts.map +1 -1
  65. package/dist/core/radius.js +0 -28
  66. package/dist/core/radius.js.map +1 -1
  67. package/dist/core/remote-catalog-provider.d.ts +5 -0
  68. package/dist/core/remote-catalog-provider.d.ts.map +1 -0
  69. package/dist/core/remote-catalog-provider.js +83 -0
  70. package/dist/core/remote-catalog-provider.js.map +1 -0
  71. package/dist/core/runtime-credentials.d.ts +15 -0
  72. package/dist/core/runtime-credentials.d.ts.map +1 -0
  73. package/dist/core/runtime-credentials.js +36 -0
  74. package/dist/core/runtime-credentials.js.map +1 -0
  75. package/dist/core/sdk.d.ts +3 -6
  76. package/dist/core/sdk.d.ts.map +1 -1
  77. package/dist/core/sdk.js +14 -25
  78. package/dist/core/sdk.js.map +1 -1
  79. package/dist/index.d.ts +2 -1
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +2 -2
  82. package/dist/index.js.map +1 -1
  83. package/dist/main.d.ts.map +1 -1
  84. package/dist/main.js +11 -13
  85. package/dist/main.js.map +1 -1
  86. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  87. package/dist/modes/interactive/components/assistant-message.js +22 -10
  88. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  89. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  90. package/dist/modes/interactive/components/footer.js +1 -1
  91. package/dist/modes/interactive/components/footer.js.map +1 -1
  92. package/dist/modes/interactive/components/login-dialog.d.ts +4 -8
  93. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  94. package/dist/modes/interactive/components/login-dialog.js +14 -12
  95. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  96. package/dist/modes/interactive/components/model-selector.d.ts +11 -4
  97. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  98. package/dist/modes/interactive/components/model-selector.js +72 -41
  99. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  100. package/dist/modes/interactive/components/oauth-selector.d.ts +4 -4
  101. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  102. package/dist/modes/interactive/components/oauth-selector.js +14 -27
  103. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  104. package/dist/modes/interactive/interactive-mode.d.ts +6 -3
  105. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  106. package/dist/modes/interactive/interactive-mode.js +154 -142
  107. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  108. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  109. package/dist/modes/rpc/rpc-mode.js +2 -2
  110. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  111. package/dist/package-manager-cli.d.ts.map +1 -1
  112. package/dist/package-manager-cli.js +67 -5
  113. package/dist/package-manager-cli.js.map +1 -1
  114. package/docs/custom-provider.md +6 -11
  115. package/docs/extensions.md +22 -1
  116. package/docs/models.md +1 -0
  117. package/docs/packages.md +1 -0
  118. package/docs/providers.md +13 -1
  119. package/docs/sdk.md +40 -50
  120. package/docs/usage.md +1 -0
  121. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  122. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  123. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  124. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  125. package/examples/extensions/gondolin/package-lock.json +2 -2
  126. package/examples/extensions/gondolin/package.json +1 -1
  127. package/examples/extensions/sandbox/package-lock.json +2 -2
  128. package/examples/extensions/sandbox/package.json +1 -1
  129. package/examples/extensions/with-deps/package-lock.json +2 -2
  130. package/examples/extensions/with-deps/package.json +1 -1
  131. package/examples/sdk/02-custom-model.ts +5 -8
  132. package/examples/sdk/09-api-keys-and-oauth.ts +13 -31
  133. package/examples/sdk/12-full-control.ts +7 -12
  134. package/examples/sdk/README.md +14 -18
  135. package/npm-shrinkwrap.json +12 -12
  136. package/package.json +4 -4
  137. package/dist/core/provider-display-names.d.ts +0 -2
  138. package/dist/core/provider-display-names.d.ts.map +0 -1
  139. package/dist/core/provider-display-names.js +0 -37
  140. package/dist/core/provider-display-names.js.map +0 -1
@@ -27,6 +27,7 @@ import { exportSessionToHtml } from "./export-html/index.js";
27
27
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
28
28
  import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
29
29
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
30
+ import { ModelRegistry } from "./model-registry.js";
30
31
  import { expandPromptTemplate } from "./prompt-templates.js";
31
32
  import { CURRENT_SESSION_VERSION, getLatestCompactionEntry } from "./session-manager.js";
32
33
  import { createSyntheticSourceInfo } from "./source-info.js";
@@ -49,6 +50,14 @@ export function parseSkillBlock(text) {
49
50
  userMessage: match[4]?.trim() || undefined,
50
51
  };
51
52
  }
53
+ // ============================================================================
54
+ // Types
55
+ // ============================================================================
56
+ function withoutDeletedHeaders(headers) {
57
+ return headers
58
+ ? Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] !== null))
59
+ : undefined;
60
+ }
52
61
  function estimateMessagesTokens(messages) {
53
62
  let tokens = 0;
54
63
  for (const message of messages) {
@@ -113,8 +122,7 @@ export class AgentSession {
113
122
  _extensionShutdownHandler;
114
123
  _extensionErrorListener;
115
124
  _extensionErrorUnsubscriber;
116
- // Model registry for API key resolution
117
- _modelRegistry;
125
+ _modelRuntime;
118
126
  // Tool registry for extension getTools/setTools
119
127
  _toolRegistry = new Map();
120
128
  _toolDefinitions = new Map();
@@ -132,7 +140,7 @@ export class AgentSession {
132
140
  this._resourceLoader = config.resourceLoader;
133
141
  this._customTools = config.customTools ?? [];
134
142
  this._cwd = config.cwd;
135
- this._modelRegistry = config.modelRegistry;
143
+ this._modelRuntime = config.modelRuntime;
136
144
  this._extensionRunnerRef = config.extensionRunnerRef;
137
145
  this._initialActiveToolNames = config.initialActiveToolNames;
138
146
  this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
@@ -149,22 +157,29 @@ export class AgentSession {
149
157
  includeAllExtensionTools: true,
150
158
  });
151
159
  }
152
- /** Model registry for API key resolution and model discovery */
153
- get modelRegistry() {
154
- return this._modelRegistry;
160
+ get modelRuntime() {
161
+ return this._modelRuntime;
155
162
  }
156
163
  async _getRequiredRequestAuth(model) {
157
- const result = await this._modelRegistry.getApiKeyAndHeaders(model);
158
- if (!result.ok) {
159
- if (result.error.startsWith("No API key found")) {
164
+ let result;
165
+ try {
166
+ result = await this._modelRuntime.getAuth(model);
167
+ }
168
+ catch (error) {
169
+ const cause = error instanceof Error ? error.cause : undefined;
170
+ if (cause instanceof Error && cause.message === "authHeader requires a resolved API key") {
160
171
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
161
172
  }
162
- throw new Error(result.error);
173
+ throw error;
163
174
  }
164
- if (result.apiKey) {
165
- return { apiKey: result.apiKey, headers: result.headers, env: result.env };
175
+ if (result?.auth.apiKey) {
176
+ return {
177
+ apiKey: result.auth.apiKey,
178
+ headers: withoutDeletedHeaders(result.auth.headers),
179
+ env: result.env,
180
+ };
166
181
  }
167
- const isOAuth = this._modelRegistry.isUsingOAuth(model);
182
+ const isOAuth = this._modelRuntime.isUsingOAuth(model.provider);
168
183
  if (isOAuth) {
169
184
  throw new Error(`Authentication failed for "${model.provider}". ` +
170
185
  `Credentials may have expired or network is unavailable. ` +
@@ -176,8 +191,15 @@ export class AgentSession {
176
191
  if (this.agent.streamFn === streamSimple) {
177
192
  return this._getRequiredRequestAuth(model);
178
193
  }
179
- const result = await this._modelRegistry.getApiKeyAndHeaders(model);
180
- return result.ok ? { apiKey: result.apiKey, headers: result.headers, env: result.env } : {};
194
+ try {
195
+ const result = await this._modelRuntime.getAuth(model);
196
+ return result
197
+ ? { apiKey: result.auth.apiKey, headers: withoutDeletedHeaders(result.auth.headers), env: result.env }
198
+ : {};
199
+ }
200
+ catch {
201
+ return {};
202
+ }
181
203
  }
182
204
  /**
183
205
  * Install tool hooks once on the Agent instance.
@@ -828,8 +850,10 @@ export class AgentSession {
828
850
  if (!this.model) {
829
851
  throw new Error(formatNoModelSelectedMessage());
830
852
  }
831
- if (!this._modelRegistry.hasConfiguredAuth(this.model)) {
832
- const isOAuth = this._modelRegistry.isUsingOAuth(this.model);
853
+ const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
854
+ (await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
855
+ if (!hasConfiguredAuth) {
856
+ const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
833
857
  if (isOAuth) {
834
858
  throw new Error(`Authentication failed for "${this.model.provider}". ` +
835
859
  `Credentials may have expired or network is unavailable. ` +
@@ -1174,7 +1198,7 @@ export class AgentSession {
1174
1198
  * @throws Error if no auth is configured for the model
1175
1199
  */
1176
1200
  async setModel(model) {
1177
- if (!this._modelRegistry.hasConfiguredAuth(model)) {
1201
+ if (!(await this._modelRuntime.checkAuth(model.provider))) {
1178
1202
  throw new Error(`No API key for ${model.provider}/${model.id}`);
1179
1203
  }
1180
1204
  const previousModel = this.model;
@@ -1199,7 +1223,11 @@ export class AgentSession {
1199
1223
  return this._cycleAvailableModel(direction);
1200
1224
  }
1201
1225
  async _cycleScopedModel(direction) {
1202
- const scopedModels = this._scopedModels.filter((scoped) => this._modelRegistry.hasConfiguredAuth(scoped.model));
1226
+ const checks = await Promise.all(this._scopedModels.map(async (scoped) => ({
1227
+ scoped,
1228
+ auth: await this._modelRuntime.checkAuth(scoped.model.provider),
1229
+ })));
1230
+ const scopedModels = checks.filter(({ auth }) => auth !== undefined).map(({ scoped }) => scoped);
1203
1231
  if (scopedModels.length <= 1)
1204
1232
  return undefined;
1205
1233
  const currentModel = this.model;
@@ -1223,7 +1251,7 @@ export class AgentSession {
1223
1251
  return { model: next.model, thinkingLevel: this.thinkingLevel, isScoped: true };
1224
1252
  }
1225
1253
  async _cycleAvailableModel(direction) {
1226
- const availableModels = await this._modelRegistry.getAvailable();
1254
+ const availableModels = await this._modelRuntime.getAvailable();
1227
1255
  if (availableModels.length <= 1)
1228
1256
  return undefined;
1229
1257
  const currentModel = this.model;
@@ -1573,12 +1601,11 @@ export class AgentSession {
1573
1601
  let headers;
1574
1602
  let env;
1575
1603
  if (this.agent.streamFn === streamSimple) {
1576
- const authResult = await this._modelRegistry.getApiKeyAndHeaders(this.model);
1577
- if (!authResult.ok || !authResult.apiKey) {
1604
+ const authResult = await this._modelRuntime.getAuth(this.model);
1605
+ if (!authResult?.auth.apiKey)
1578
1606
  return false;
1579
- }
1580
- apiKey = authResult.apiKey;
1581
- headers = authResult.headers;
1607
+ apiKey = authResult.auth.apiKey;
1608
+ headers = withoutDeletedHeaders(authResult.auth.headers);
1582
1609
  env = authResult.env;
1583
1610
  }
1584
1611
  else {
@@ -1790,7 +1817,7 @@ export class AgentSession {
1790
1817
  if (!currentModel) {
1791
1818
  return;
1792
1819
  }
1793
- const refreshedModel = this._modelRegistry.find(currentModel.provider, currentModel.id);
1820
+ const refreshedModel = this._modelRuntime.getModel(currentModel.provider, currentModel.id);
1794
1821
  if (!refreshedModel || refreshedModel === currentModel) {
1795
1822
  return;
1796
1823
  }
@@ -1859,7 +1886,7 @@ export class AgentSession {
1859
1886
  refreshTools: () => this._refreshToolRegistry(),
1860
1887
  getCommands,
1861
1888
  setModel: async (model) => {
1862
- if (!this.modelRegistry.hasConfiguredAuth(model))
1889
+ if (!this._modelRuntime.hasConfiguredAuth(model.provider))
1863
1890
  return false;
1864
1891
  await this.setModel(model);
1865
1892
  return true;
@@ -1899,11 +1926,11 @@ export class AgentSession {
1899
1926
  getSystemPromptOptions: () => this._baseSystemPromptOptions,
1900
1927
  }, {
1901
1928
  registerProvider: (name, config) => {
1902
- this._modelRegistry.registerProvider(name, config);
1929
+ this._modelRuntime.registerProvider(name, config);
1903
1930
  this._refreshCurrentModelFromRegistry();
1904
1931
  },
1905
1932
  unregisterProvider: (name) => {
1906
- this._modelRegistry.unregisterProvider(name);
1933
+ this._modelRuntime.unregisterProvider(name);
1907
1934
  this._refreshCurrentModelFromRegistry();
1908
1935
  },
1909
1936
  });
@@ -2005,7 +2032,7 @@ export class AgentSession {
2005
2032
  extensionsResult.runtime.flagValues.set(name, value);
2006
2033
  }
2007
2034
  }
2008
- this._extensionRunner = new ExtensionRunner(extensionsResult.extensions, extensionsResult.runtime, this._cwd, this.sessionManager, this._modelRegistry);
2035
+ this._extensionRunner = new ExtensionRunner(extensionsResult.extensions, extensionsResult.runtime, this._cwd, this.sessionManager, new ModelRegistry(this._modelRuntime));
2009
2036
  if (this._extensionRunnerRef) {
2010
2037
  this._extensionRunnerRef.current = this._extensionRunner;
2011
2038
  }