@mariozechner/pi-coding-agent 0.62.0 → 0.63.0

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 (89) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/core/agent-session.d.ts +5 -3
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +34 -44
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/auth-storage.d.ts +3 -1
  7. package/dist/core/auth-storage.d.ts.map +1 -1
  8. package/dist/core/auth-storage.js +5 -2
  9. package/dist/core/auth-storage.js.map +1 -1
  10. package/dist/core/compaction/branch-summarization.d.ts +2 -0
  11. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  12. package/dist/core/compaction/branch-summarization.js +2 -2
  13. package/dist/core/compaction/branch-summarization.js.map +1 -1
  14. package/dist/core/compaction/compaction.d.ts +2 -2
  15. package/dist/core/compaction/compaction.d.ts.map +1 -1
  16. package/dist/core/compaction/compaction.js +9 -9
  17. package/dist/core/compaction/compaction.js.map +1 -1
  18. package/dist/core/export-html/index.d.ts.map +1 -1
  19. package/dist/core/export-html/index.js +5 -4
  20. package/dist/core/export-html/index.js.map +1 -1
  21. package/dist/core/model-registry.d.ts +18 -2
  22. package/dist/core/model-registry.d.ts.map +1 -1
  23. package/dist/core/model-registry.js +83 -69
  24. package/dist/core/model-registry.js.map +1 -1
  25. package/dist/core/model-resolver.d.ts.map +1 -1
  26. package/dist/core/model-resolver.js +4 -4
  27. package/dist/core/model-resolver.js.map +1 -1
  28. package/dist/core/package-manager.d.ts.map +1 -1
  29. package/dist/core/package-manager.js +54 -6
  30. package/dist/core/package-manager.js.map +1 -1
  31. package/dist/core/resolve-config-value.d.ts +6 -0
  32. package/dist/core/resolve-config-value.d.ts.map +1 -1
  33. package/dist/core/resolve-config-value.js +37 -5
  34. package/dist/core/resolve-config-value.js.map +1 -1
  35. package/dist/core/sdk.d.ts +1 -1
  36. package/dist/core/sdk.d.ts.map +1 -1
  37. package/dist/core/sdk.js +13 -22
  38. package/dist/core/sdk.js.map +1 -1
  39. package/dist/core/settings-manager.d.ts +2 -0
  40. package/dist/core/settings-manager.d.ts.map +1 -1
  41. package/dist/core/settings-manager.js +3 -0
  42. package/dist/core/settings-manager.js.map +1 -1
  43. package/dist/core/timings.d.ts +1 -0
  44. package/dist/core/timings.d.ts.map +1 -1
  45. package/dist/core/timings.js +6 -0
  46. package/dist/core/timings.js.map +1 -1
  47. package/dist/core/tools/edit-diff.d.ts +23 -1
  48. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  49. package/dist/core/tools/edit-diff.js +100 -32
  50. package/dist/core/tools/edit-diff.js.map +1 -1
  51. package/dist/core/tools/edit.d.ts +18 -6
  52. package/dist/core/tools/edit.d.ts.map +1 -1
  53. package/dist/core/tools/edit.js +100 -58
  54. package/dist/core/tools/edit.js.map +1 -1
  55. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  56. package/dist/core/tools/file-mutation-queue.js +4 -4
  57. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  58. package/dist/core/tools/index.d.ts +12 -4
  59. package/dist/core/tools/index.d.ts.map +1 -1
  60. package/dist/main.d.ts.map +1 -1
  61. package/dist/main.js +28 -10
  62. package/dist/main.js.map +1 -1
  63. package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
  64. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  65. package/dist/modes/interactive/components/bash-execution.js +18 -5
  66. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  67. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  68. package/dist/modes/interactive/interactive-mode.js +2 -1
  69. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  70. package/dist/modes/print-mode.d.ts +1 -1
  71. package/dist/modes/print-mode.d.ts.map +1 -1
  72. package/dist/modes/print-mode.js +83 -71
  73. package/dist/modes/print-mode.js.map +1 -1
  74. package/docs/development.md +3 -1
  75. package/docs/extensions.md +2 -1
  76. package/docs/models.md +6 -0
  77. package/docs/rpc.md +11 -2
  78. package/docs/settings.md +12 -0
  79. package/examples/extensions/custom-compaction.ts +17 -4
  80. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  81. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  82. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  83. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  84. package/examples/extensions/handoff.ts +5 -2
  85. package/examples/extensions/qna.ts +5 -2
  86. package/examples/extensions/summarize.ts +15 -4
  87. package/examples/extensions/with-deps/package-lock.json +2 -2
  88. package/examples/extensions/with-deps/package.json +1 -1
  89. package/package.json +5 -4
@@ -134,6 +134,23 @@ export class AgentSession {
134
134
  get modelRegistry() {
135
135
  return this._modelRegistry;
136
136
  }
137
+ async _getRequiredRequestAuth(model) {
138
+ const result = await this._modelRegistry.getApiKeyAndHeaders(model);
139
+ if (!result.ok) {
140
+ throw new Error(result.error);
141
+ }
142
+ if (result.apiKey) {
143
+ return { apiKey: result.apiKey, headers: result.headers };
144
+ }
145
+ const isOAuth = this._modelRegistry.isUsingOAuth(model);
146
+ if (isOAuth) {
147
+ throw new Error(`Authentication failed for "${model.provider}". ` +
148
+ `Credentials may have expired or network is unavailable. ` +
149
+ `Run '/login ${model.provider}' to re-authenticate.`);
150
+ }
151
+ throw new Error(`No API key found for ${model.provider}.\n\n` +
152
+ `Use /login or set an API key environment variable. See ${join(getDocsPath(), "providers.md")}`);
153
+ }
137
154
  /**
138
155
  * Install tool hooks once on the Agent instance.
139
156
  *
@@ -686,9 +703,7 @@ export class AgentSession {
686
703
  `Use /login or set an API key environment variable. See ${join(getDocsPath(), "providers.md")}\n\n` +
687
704
  "Then use /model to select a model.");
688
705
  }
689
- // Validate API key
690
- const apiKey = await this._modelRegistry.getApiKey(this.model);
691
- if (!apiKey) {
706
+ if (!this._modelRegistry.hasConfiguredAuth(this.model)) {
692
707
  const isOAuth = this._modelRegistry.isUsingOAuth(this.model);
693
708
  if (isOAuth) {
694
709
  throw new Error(`Authentication failed for "${this.model.provider}". ` +
@@ -1065,12 +1080,11 @@ export class AgentSession {
1065
1080
  }
1066
1081
  /**
1067
1082
  * Set model directly.
1068
- * Validates API key, saves to session and settings.
1069
- * @throws Error if no API key available for the model
1083
+ * Validates that auth is configured, saves to session and settings.
1084
+ * @throws Error if no auth is configured for the model
1070
1085
  */
1071
1086
  async setModel(model) {
1072
- const apiKey = await this._modelRegistry.getApiKey(model);
1073
- if (!apiKey) {
1087
+ if (!this._modelRegistry.hasConfiguredAuth(model)) {
1074
1088
  throw new Error(`No API key for ${model.provider}/${model.id}`);
1075
1089
  }
1076
1090
  const previousModel = this.model;
@@ -1094,27 +1108,11 @@ export class AgentSession {
1094
1108
  }
1095
1109
  return this._cycleAvailableModel(direction);
1096
1110
  }
1097
- async _getScopedModelsWithApiKey() {
1098
- const apiKeysByProvider = new Map();
1099
- const result = [];
1100
- for (const scoped of this._scopedModels) {
1101
- const provider = scoped.model.provider;
1102
- let apiKey;
1103
- if (apiKeysByProvider.has(provider)) {
1104
- apiKey = apiKeysByProvider.get(provider);
1105
- }
1106
- else {
1107
- apiKey = await this._modelRegistry.getApiKeyForProvider(provider);
1108
- apiKeysByProvider.set(provider, apiKey);
1109
- }
1110
- if (apiKey) {
1111
- result.push(scoped);
1112
- }
1113
- }
1114
- return result;
1111
+ _getScopedModelsWithAuth() {
1112
+ return this._scopedModels.filter((scoped) => this._modelRegistry.hasConfiguredAuth(scoped.model));
1115
1113
  }
1116
1114
  async _cycleScopedModel(direction) {
1117
- const scopedModels = await this._getScopedModelsWithApiKey();
1115
+ const scopedModels = this._getScopedModelsWithAuth();
1118
1116
  if (scopedModels.length <= 1)
1119
1117
  return undefined;
1120
1118
  const currentModel = this.model;
@@ -1148,10 +1146,6 @@ export class AgentSession {
1148
1146
  const len = availableModels.length;
1149
1147
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1150
1148
  const nextModel = availableModels[nextIndex];
1151
- const apiKey = await this._modelRegistry.getApiKey(nextModel);
1152
- if (!apiKey) {
1153
- throw new Error(`No API key for ${nextModel.provider}/${nextModel.id}`);
1154
- }
1155
1149
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1156
1150
  this.agent.setModel(nextModel);
1157
1151
  this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
@@ -1280,10 +1274,7 @@ export class AgentSession {
1280
1274
  if (!this.model) {
1281
1275
  throw new Error("No model selected");
1282
1276
  }
1283
- const apiKey = await this._modelRegistry.getApiKey(this.model);
1284
- if (!apiKey) {
1285
- throw new Error(`No API key for ${this.model.provider}`);
1286
- }
1277
+ const { apiKey, headers } = await this._getRequiredRequestAuth(this.model);
1287
1278
  const pathEntries = this.sessionManager.getBranch();
1288
1279
  const settings = this.settingsManager.getCompactionSettings();
1289
1280
  const preparation = prepareCompaction(pathEntries, settings);
@@ -1326,7 +1317,7 @@ export class AgentSession {
1326
1317
  }
1327
1318
  else {
1328
1319
  // Generate compaction result
1329
- const result = await compact(preparation, this.model, apiKey, customInstructions, this._compactionAbortController.signal);
1320
+ const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal);
1330
1321
  summary = result.summary;
1331
1322
  firstKeptEntryId = result.firstKeptEntryId;
1332
1323
  tokensBefore = result.tokensBefore;
@@ -1466,11 +1457,12 @@ export class AgentSession {
1466
1457
  this._emit({ type: "auto_compaction_end", result: undefined, aborted: false, willRetry: false });
1467
1458
  return;
1468
1459
  }
1469
- const apiKey = await this._modelRegistry.getApiKey(this.model);
1470
- if (!apiKey) {
1460
+ const authResult = await this._modelRegistry.getApiKeyAndHeaders(this.model);
1461
+ if (!authResult.ok || !authResult.apiKey) {
1471
1462
  this._emit({ type: "auto_compaction_end", result: undefined, aborted: false, willRetry: false });
1472
1463
  return;
1473
1464
  }
1465
+ const { apiKey, headers } = authResult;
1474
1466
  const pathEntries = this.sessionManager.getBranch();
1475
1467
  const preparation = prepareCompaction(pathEntries, settings);
1476
1468
  if (!preparation) {
@@ -1509,7 +1501,7 @@ export class AgentSession {
1509
1501
  }
1510
1502
  else {
1511
1503
  // Generate compaction result
1512
- const compactResult = await compact(preparation, this.model, apiKey, undefined, this._autoCompactionAbortController.signal);
1504
+ const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal);
1513
1505
  summary = compactResult.summary;
1514
1506
  firstKeptEntryId = compactResult.firstKeptEntryId;
1515
1507
  tokensBefore = compactResult.tokensBefore;
@@ -1720,8 +1712,7 @@ export class AgentSession {
1720
1712
  refreshTools: () => this._refreshToolRegistry(),
1721
1713
  getCommands,
1722
1714
  setModel: async (model) => {
1723
- const key = await this.modelRegistry.getApiKey(model);
1724
- if (!key)
1715
+ if (!this.modelRegistry.hasConfiguredAuth(model))
1725
1716
  return false;
1726
1717
  await this.setModel(model);
1727
1718
  return true;
@@ -2302,14 +2293,12 @@ export class AgentSession {
2302
2293
  let summaryDetails;
2303
2294
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
2304
2295
  const model = this.model;
2305
- const apiKey = await this._modelRegistry.getApiKey(model);
2306
- if (!apiKey) {
2307
- throw new Error(`No API key for ${model.provider}`);
2308
- }
2296
+ const { apiKey, headers } = await this._getRequiredRequestAuth(model);
2309
2297
  const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
2310
2298
  const result = await generateBranchSummary(entriesToSummarize, {
2311
2299
  model,
2312
2300
  apiKey,
2301
+ headers,
2313
2302
  signal: this._branchSummaryAbortController.signal,
2314
2303
  customInstructions,
2315
2304
  replaceInstructions,
@@ -2466,6 +2455,7 @@ export class AgentSession {
2466
2455
  total: totalInput + totalOutput + totalCacheRead + totalCacheWrite,
2467
2456
  },
2468
2457
  cost: totalCost,
2458
+ contextUsage: this.getContextUsage(),
2469
2459
  };
2470
2460
  }
2471
2461
  getContextUsage() {