@vaclav-synacek/pi-coding-agent-termux 0.50.7-1 → 0.51.1-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 (168) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/dist/cli/args.d.ts.map +1 -1
  3. package/dist/cli/args.js +2 -0
  4. package/dist/cli/args.js.map +1 -1
  5. package/dist/cli/session-picker.d.ts.map +1 -1
  6. package/dist/cli/session-picker.js +3 -1
  7. package/dist/cli/session-picker.js.map +1 -1
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +9 -0
  10. package/dist/config.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +5 -1
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +76 -15
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/extensions/index.d.ts +3 -3
  16. package/dist/core/extensions/index.d.ts.map +1 -1
  17. package/dist/core/extensions/index.js +1 -1
  18. package/dist/core/extensions/index.js.map +1 -1
  19. package/dist/core/extensions/runner.d.ts +19 -1
  20. package/dist/core/extensions/runner.d.ts.map +1 -1
  21. package/dist/core/extensions/runner.js +42 -0
  22. package/dist/core/extensions/runner.js.map +1 -1
  23. package/dist/core/extensions/types.d.ts +88 -6
  24. package/dist/core/extensions/types.d.ts.map +1 -1
  25. package/dist/core/extensions/types.js +4 -1
  26. package/dist/core/extensions/types.js.map +1 -1
  27. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  28. package/dist/core/extensions/wrapper.js +1 -1
  29. package/dist/core/extensions/wrapper.js.map +1 -1
  30. package/dist/core/keybindings.d.ts +1 -1
  31. package/dist/core/keybindings.d.ts.map +1 -1
  32. package/dist/core/keybindings.js +8 -0
  33. package/dist/core/keybindings.js.map +1 -1
  34. package/dist/core/model-registry.d.ts.map +1 -1
  35. package/dist/core/model-registry.js +27 -18
  36. package/dist/core/model-registry.js.map +1 -1
  37. package/dist/core/package-manager.d.ts.map +1 -1
  38. package/dist/core/package-manager.js +11 -9
  39. package/dist/core/package-manager.js.map +1 -1
  40. package/dist/core/resource-loader.d.ts +24 -0
  41. package/dist/core/resource-loader.d.ts.map +1 -1
  42. package/dist/core/resource-loader.js +88 -19
  43. package/dist/core/resource-loader.js.map +1 -1
  44. package/dist/core/sdk.d.ts.map +1 -1
  45. package/dist/core/sdk.js +1 -0
  46. package/dist/core/sdk.js.map +1 -1
  47. package/dist/core/session-manager.d.ts +2 -0
  48. package/dist/core/session-manager.d.ts.map +1 -1
  49. package/dist/core/session-manager.js +2 -0
  50. package/dist/core/session-manager.js.map +1 -1
  51. package/dist/core/settings-manager.d.ts +5 -0
  52. package/dist/core/settings-manager.d.ts.map +1 -1
  53. package/dist/core/settings-manager.js +16 -0
  54. package/dist/core/settings-manager.js.map +1 -1
  55. package/dist/core/skills.d.ts.map +1 -1
  56. package/dist/core/skills.js +1 -0
  57. package/dist/core/skills.js.map +1 -1
  58. package/dist/core/tools/bash.d.ts +11 -0
  59. package/dist/core/tools/bash.d.ts.map +1 -1
  60. package/dist/core/tools/bash.js +18 -3
  61. package/dist/core/tools/bash.js.map +1 -1
  62. package/dist/core/tools/edit.d.ts +2 -0
  63. package/dist/core/tools/edit.d.ts.map +1 -1
  64. package/dist/core/tools/edit.js.map +1 -1
  65. package/dist/core/tools/find.d.ts +2 -0
  66. package/dist/core/tools/find.d.ts.map +1 -1
  67. package/dist/core/tools/find.js.map +1 -1
  68. package/dist/core/tools/grep.d.ts +2 -0
  69. package/dist/core/tools/grep.d.ts.map +1 -1
  70. package/dist/core/tools/grep.js.map +1 -1
  71. package/dist/core/tools/index.d.ts +7 -7
  72. package/dist/core/tools/index.d.ts.map +1 -1
  73. package/dist/core/tools/index.js +5 -5
  74. package/dist/core/tools/index.js.map +1 -1
  75. package/dist/core/tools/ls.d.ts +2 -0
  76. package/dist/core/tools/ls.d.ts.map +1 -1
  77. package/dist/core/tools/ls.js.map +1 -1
  78. package/dist/core/tools/read.d.ts +2 -0
  79. package/dist/core/tools/read.d.ts.map +1 -1
  80. package/dist/core/tools/read.js.map +1 -1
  81. package/dist/core/tools/write.d.ts +2 -0
  82. package/dist/core/tools/write.d.ts.map +1 -1
  83. package/dist/core/tools/write.js.map +1 -1
  84. package/dist/index.d.ts +3 -3
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +1 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  89. package/dist/modes/interactive/components/custom-message.js +0 -7
  90. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  91. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  92. package/dist/modes/interactive/components/daxnuts.js +1 -1
  93. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  94. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  95. package/dist/modes/interactive/components/scoped-models-selector.js +4 -1
  96. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  97. package/dist/modes/interactive/components/session-selector-search.d.ts +4 -2
  98. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  99. package/dist/modes/interactive/components/session-selector-search.js +13 -4
  100. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  101. package/dist/modes/interactive/components/session-selector.d.ts +12 -2
  102. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  103. package/dist/modes/interactive/components/session-selector.js +188 -57
  104. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  105. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  106. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  107. package/dist/modes/interactive/components/settings-selector.js +12 -0
  108. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  109. package/dist/modes/interactive/components/tree-selector.d.ts +6 -0
  110. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  111. package/dist/modes/interactive/components/tree-selector.js +43 -16
  112. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  113. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  114. package/dist/modes/interactive/interactive-mode.js +24 -15
  115. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  116. package/dist/modes/print-mode.d.ts.map +1 -1
  117. package/dist/modes/print-mode.js +4 -0
  118. package/dist/modes/print-mode.js.map +1 -1
  119. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  120. package/dist/modes/rpc/rpc-mode.js +4 -0
  121. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  122. package/dist/utils/clipboard-image.d.ts.map +1 -1
  123. package/dist/utils/clipboard-image.js +52 -10
  124. package/dist/utils/clipboard-image.js.map +1 -1
  125. package/dist/utils/clipboard-native.d.ts +7 -0
  126. package/dist/utils/clipboard-native.d.ts.map +1 -0
  127. package/dist/utils/clipboard-native.js +14 -0
  128. package/dist/utils/clipboard-native.js.map +1 -0
  129. package/dist/utils/tools-manager.d.ts.map +1 -1
  130. package/dist/utils/tools-manager.js +14 -0
  131. package/dist/utils/tools-manager.js.map +1 -1
  132. package/docs/custom-provider.md +2 -1
  133. package/docs/extensions.md +57 -9
  134. package/docs/keybindings.md +9 -0
  135. package/docs/models.md +43 -14
  136. package/docs/rpc.md +188 -1
  137. package/docs/settings.md +5 -1
  138. package/docs/termux.md +127 -0
  139. package/examples/extensions/README.md +9 -0
  140. package/examples/extensions/antigravity-image-gen.ts +1 -1
  141. package/examples/extensions/bash-spawn-hook.ts +30 -0
  142. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  143. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  144. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  145. package/examples/extensions/custom-provider-qwen-cli/index.ts +345 -0
  146. package/examples/extensions/custom-provider-qwen-cli/package.json +16 -0
  147. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  148. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  149. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  150. package/examples/extensions/dynamic-resources/index.ts +15 -0
  151. package/examples/extensions/hello.ts +1 -1
  152. package/examples/extensions/question.ts +1 -1
  153. package/examples/extensions/questionnaire.ts +1 -1
  154. package/examples/extensions/rpc-demo.ts +124 -0
  155. package/examples/extensions/sandbox/index.ts +1 -1
  156. package/examples/extensions/shutdown-command.ts +2 -2
  157. package/examples/extensions/ssh.ts +4 -4
  158. package/examples/extensions/subagent/index.ts +1 -1
  159. package/examples/extensions/titlebar-spinner.ts +58 -0
  160. package/examples/extensions/todo.ts +1 -1
  161. package/examples/extensions/tool-override.ts +1 -1
  162. package/examples/extensions/truncated-tool.ts +1 -1
  163. package/examples/extensions/with-deps/package-lock.json +2 -2
  164. package/examples/extensions/with-deps/package.json +1 -1
  165. package/examples/rpc-extension-ui.ts +632 -0
  166. package/examples/sdk/06-extensions.ts +1 -1
  167. package/examples/sdk/12-full-control.ts +1 -0
  168. package/package.json +6 -5
@@ -13,7 +13,7 @@
13
13
  * Modes use this class and add their own I/O layer on top.
14
14
  */
15
15
  import { readFileSync } from "node:fs";
16
- import { join } from "node:path";
16
+ import { basename, dirname, join } from "node:path";
17
17
  import { isContextOverflow, modelsAreEqual, resetApiProviders, supportsXhigh } from "@mariozechner/pi-ai";
18
18
  import { getDocsPath } from "../config.js";
19
19
  import { theme } from "../modes/interactive/theme/theme.js";
@@ -884,21 +884,36 @@ export class AgentSession {
884
884
  }
885
885
  return this._cycleAvailableModel(direction);
886
886
  }
887
+ async _getScopedModelsWithApiKey() {
888
+ const apiKeysByProvider = new Map();
889
+ const result = [];
890
+ for (const scoped of this._scopedModels) {
891
+ const provider = scoped.model.provider;
892
+ let apiKey;
893
+ if (apiKeysByProvider.has(provider)) {
894
+ apiKey = apiKeysByProvider.get(provider);
895
+ }
896
+ else {
897
+ apiKey = await this._modelRegistry.getApiKeyForProvider(provider);
898
+ apiKeysByProvider.set(provider, apiKey);
899
+ }
900
+ if (apiKey) {
901
+ result.push(scoped);
902
+ }
903
+ }
904
+ return result;
905
+ }
887
906
  async _cycleScopedModel(direction) {
888
- if (this._scopedModels.length <= 1)
907
+ const scopedModels = await this._getScopedModelsWithApiKey();
908
+ if (scopedModels.length <= 1)
889
909
  return undefined;
890
910
  const currentModel = this.model;
891
- let currentIndex = this._scopedModels.findIndex((sm) => modelsAreEqual(sm.model, currentModel));
911
+ let currentIndex = scopedModels.findIndex((sm) => modelsAreEqual(sm.model, currentModel));
892
912
  if (currentIndex === -1)
893
913
  currentIndex = 0;
894
- const len = this._scopedModels.length;
914
+ const len = scopedModels.length;
895
915
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
896
- const next = this._scopedModels[nextIndex];
897
- // Validate API key
898
- const apiKey = await this._modelRegistry.getApiKey(next.model);
899
- if (!apiKey) {
900
- throw new Error(`No API key for ${next.model.provider}/${next.model.id}`);
901
- }
916
+ const next = scopedModels[nextIndex];
902
917
  // Apply model
903
918
  this.agent.setModel(next.model);
904
919
  this.sessionManager.appendModelChange(next.model.provider, next.model.id);
@@ -937,14 +952,18 @@ export class AgentSession {
937
952
  /**
938
953
  * Set thinking level.
939
954
  * Clamps to model capabilities based on available thinking levels.
940
- * Saves to session and settings.
955
+ * Saves to session and settings only if the level actually changes.
941
956
  */
942
957
  setThinkingLevel(level) {
943
958
  const availableLevels = this.getAvailableThinkingLevels();
944
959
  const effectiveLevel = availableLevels.includes(level) ? level : this._clampThinkingLevel(level, availableLevels);
960
+ // Only persist if actually changing
961
+ const isChanging = effectiveLevel !== this.agent.state.thinkingLevel;
945
962
  this.agent.setThinkingLevel(effectiveLevel);
946
- this.sessionManager.appendThinkingLevelChange(effectiveLevel);
947
- this.settingsManager.setDefaultThinkingLevel(effectiveLevel);
963
+ if (isChanging) {
964
+ this.sessionManager.appendThinkingLevelChange(effectiveLevel);
965
+ this.settingsManager.setDefaultThinkingLevel(effectiveLevel);
966
+ }
948
967
  }
949
968
  /**
950
969
  * Cycle to next thinking level.
@@ -1317,7 +1336,48 @@ export class AgentSession {
1317
1336
  if (this._extensionRunner) {
1318
1337
  this._applyExtensionBindings(this._extensionRunner);
1319
1338
  await this._extensionRunner.emit({ type: "session_start" });
1339
+ await this.extendResourcesFromExtensions("startup");
1340
+ }
1341
+ }
1342
+ async extendResourcesFromExtensions(reason) {
1343
+ if (!this._extensionRunner?.hasHandlers("resources_discover")) {
1344
+ return;
1345
+ }
1346
+ const { skillPaths, promptPaths, themePaths } = await this._extensionRunner.emitResourcesDiscover(this._cwd, reason);
1347
+ if (skillPaths.length === 0 && promptPaths.length === 0 && themePaths.length === 0) {
1348
+ return;
1349
+ }
1350
+ const extensionPaths = {
1351
+ skillPaths: this.buildExtensionResourcePaths(skillPaths),
1352
+ promptPaths: this.buildExtensionResourcePaths(promptPaths),
1353
+ themePaths: this.buildExtensionResourcePaths(themePaths),
1354
+ };
1355
+ this._resourceLoader.extendResources(extensionPaths);
1356
+ this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
1357
+ this.agent.setSystemPrompt(this._baseSystemPrompt);
1358
+ }
1359
+ buildExtensionResourcePaths(entries) {
1360
+ return entries.map((entry) => {
1361
+ const source = this.getExtensionSourceLabel(entry.extensionPath);
1362
+ const baseDir = entry.extensionPath.startsWith("<") ? undefined : dirname(entry.extensionPath);
1363
+ return {
1364
+ path: entry.path,
1365
+ metadata: {
1366
+ source,
1367
+ scope: "temporary",
1368
+ origin: "top-level",
1369
+ baseDir,
1370
+ },
1371
+ };
1372
+ });
1373
+ }
1374
+ getExtensionSourceLabel(extensionPath) {
1375
+ if (extensionPath.startsWith("<")) {
1376
+ return `extension:${extensionPath.replace(/[<>]/g, "")}`;
1320
1377
  }
1378
+ const base = basename(extensionPath);
1379
+ const name = base.replace(/\.(ts|js)$/, "");
1380
+ return `extension:${name}`;
1321
1381
  }
1322
1382
  _applyExtensionBindings(runner) {
1323
1383
  runner.setUIContext(this._extensionUIContext);
@@ -1482,6 +1542,7 @@ export class AgentSession {
1482
1542
  this._extensionErrorListener;
1483
1543
  if (this._extensionRunner && hasBindings) {
1484
1544
  await this._extensionRunner.emit({ type: "session_start" });
1545
+ await this.extendResourcesFromExtensions("reload");
1485
1546
  }
1486
1547
  }
1487
1548
  // =========================================================================
@@ -1499,8 +1560,8 @@ export class AgentSession {
1499
1560
  if (isContextOverflow(message, contextWindow))
1500
1561
  return false;
1501
1562
  const err = message.errorMessage;
1502
- // Match: overloaded_error, rate limit, 429, 500, 502, 503, 504, service unavailable, connection errors, fetch failed, terminated
1503
- 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/i.test(err);
1563
+ // Match: overloaded_error, rate limit, 429, 500, 502, 503, 504, service unavailable, connection errors, fetch failed, terminated, retry delay exceeded
1564
+ 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);
1504
1565
  }
1505
1566
  /**
1506
1567
  * Handle retryable errors with exponential backoff.