pi-namespace-patch 1.1.0-namespace.3 → 1.2.0-namespace.1

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 (237) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +4 -7
  3. package/dist/bundle/chunks/anthropic-messages-Q7SXESRX.js +6 -0
  4. package/dist/bundle/chunks/{azure-openai-responses-6A4PNZTH.js → azure-openai-responses-LM52U7CK.js} +1 -1
  5. package/dist/bundle/chunks/chunk-3ZATHNCK.js +9 -0
  6. package/dist/bundle/chunks/chunk-5GTPJSRI.js +7 -0
  7. package/dist/bundle/chunks/chunk-6MWTY2OB.js +130 -0
  8. package/dist/bundle/chunks/chunk-6QGV3IWD.js +6 -0
  9. package/dist/bundle/chunks/{chunk-SYCGMWFH.js → chunk-AKJ3ZOR3.js} +1 -1
  10. package/dist/bundle/chunks/chunk-C2AEIDJZ.js +2 -0
  11. package/dist/bundle/chunks/{chunk-LTSARG5Q.js → chunk-CQ3XTLTY.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-UH5J7I7X.js → chunk-D7PHKNBM.js} +26 -92
  13. package/dist/bundle/chunks/chunk-DOST5PQW.js +82 -0
  14. package/dist/bundle/chunks/{chunk-GXLAGZ3Z.js → chunk-GDR5JFDJ.js} +1 -1
  15. package/dist/bundle/chunks/{chunk-Q7ROD45H.js → chunk-H7S5Z6OB.js} +77 -71
  16. package/dist/bundle/chunks/{chunk-CH4ZBH45.js → chunk-HACVPRBJ.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-O7YIWAPD.js → chunk-ITZNWD4K.js} +1 -1
  18. package/dist/bundle/chunks/chunk-RDZVAGPR.js +2 -0
  19. package/dist/bundle/chunks/{chunk-VLRCF7MR.js → chunk-TN4NLWHF.js} +1 -1
  20. package/dist/bundle/chunks/{chunk-Y4NYF362.js → chunk-WBQBCFWG.js} +1 -1
  21. package/dist/bundle/chunks/chunk-WJUNYZC5.js +2 -0
  22. package/dist/bundle/chunks/{chunk-33CRHCAK.js → chunk-XIX7LUWI.js} +1 -1
  23. package/dist/bundle/chunks/{cli-OQYLWLA3.js → cli-SWM4FQ6V.js} +3 -3
  24. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-U3AH4ODQ.js → cloudflare-workers-ai-system-one-UTBL2KOF.js} +1 -1
  25. package/dist/bundle/chunks/codemode-worker.js +17 -9
  26. package/dist/bundle/chunks/easter-egg-3d-OX6RUCIS.js +2 -0
  27. package/dist/bundle/chunks/execute-3CFUPDLS.js +499 -0
  28. package/dist/bundle/chunks/github-copilot.js +1 -1
  29. package/dist/bundle/chunks/{google-generative-ai-X2VFFS4I.js → google-generative-ai-DXKP72HC.js} +1 -1
  30. package/dist/bundle/chunks/{google-vertex-KMGHFTSP.js → google-vertex-W6SIDOVV.js} +1 -1
  31. package/dist/bundle/chunks/{mistral-conversations-PRZLM26U.js → mistral-conversations-GBMHTSYF.js} +1 -1
  32. package/dist/bundle/chunks/openai-codex-responses-RN6B5UPP.js +10 -0
  33. package/dist/bundle/chunks/{openai-completions-WWQW7S3V.js → openai-completions-QW2B4SML.js} +1 -1
  34. package/dist/bundle/chunks/{openai-decisions-QLZKZLAK.js → openai-decisions-WVPMQ4JD.js} +1 -1
  35. package/dist/bundle/chunks/{openai-responses-KV7QHJY6.js → openai-responses-KDJUSIU7.js} +1 -1
  36. package/dist/bundle/chunks/runtime-366HE7CW.js +2 -0
  37. package/dist/bundle/chunks/{typesafe-system-one-B4NNEG67.js → typesafe-system-one-ZSK3RN4B.js} +1 -1
  38. package/dist/bundle/chunks/virtual-modules-KHZAOPVZ.js +2 -0
  39. package/dist/bundle/cli-runtime.js +1 -1
  40. package/dist/bundle/index.js +1 -1
  41. package/dist/bundle/rpc-entry.js +1 -1
  42. package/dist/core/agent-session.d.ts +14 -1
  43. package/dist/core/agent-session.d.ts.map +1 -1
  44. package/dist/core/agent-session.js +89 -57
  45. package/dist/core/agent-session.js.map +1 -1
  46. package/dist/core/auth-storage.d.ts.map +1 -1
  47. package/dist/core/auth-storage.js +20 -13
  48. package/dist/core/auth-storage.js.map +1 -1
  49. package/dist/core/bug-report.d.ts +9 -1
  50. package/dist/core/bug-report.d.ts.map +1 -1
  51. package/dist/core/compaction/utils.d.ts +6 -0
  52. package/dist/core/compaction/utils.d.ts.map +1 -1
  53. package/dist/core/compaction/utils.js +7 -8
  54. package/dist/core/compaction/utils.js.map +1 -1
  55. package/dist/core/extensions/index.d.ts +1 -1
  56. package/dist/core/extensions/index.d.ts.map +1 -1
  57. package/dist/core/extensions/index.js.map +1 -1
  58. package/dist/core/extensions/runner.d.ts +4 -2
  59. package/dist/core/extensions/runner.d.ts.map +1 -1
  60. package/dist/core/extensions/runner.js +2 -3
  61. package/dist/core/extensions/runner.js.map +1 -1
  62. package/dist/core/extensions/types.d.ts +31 -7
  63. package/dist/core/extensions/types.d.ts.map +1 -1
  64. package/dist/core/extensions/types.js.map +1 -1
  65. package/dist/core/key-id-schema.d.ts +6 -0
  66. package/dist/core/key-id-schema.d.ts.map +1 -0
  67. package/dist/core/key-id-schema.js +16 -0
  68. package/dist/core/key-id-schema.js.map +1 -0
  69. package/dist/core/keybindings-schema.d.ts +4 -0
  70. package/dist/core/keybindings-schema.d.ts.map +1 -0
  71. package/dist/core/keybindings-schema.js +16 -0
  72. package/dist/core/keybindings-schema.js.map +1 -0
  73. package/dist/core/keybindings.d.ts +194 -62
  74. package/dist/core/keybindings.d.ts.map +1 -1
  75. package/dist/core/keybindings.js +26 -23
  76. package/dist/core/keybindings.js.map +1 -1
  77. package/dist/core/model-config.d.ts +695 -74
  78. package/dist/core/model-config.d.ts.map +1 -1
  79. package/dist/core/model-config.js +16 -166
  80. package/dist/core/model-config.js.map +1 -1
  81. package/dist/core/model-runtime.d.ts.map +1 -1
  82. package/dist/core/model-runtime.js +11 -6
  83. package/dist/core/model-runtime.js.map +1 -1
  84. package/dist/core/package-manager.d.ts.map +1 -1
  85. package/dist/core/package-manager.js +3 -3
  86. package/dist/core/package-manager.js.map +1 -1
  87. package/dist/core/project-trust.d.ts.map +1 -1
  88. package/dist/core/project-trust.js +2 -1
  89. package/dist/core/project-trust.js.map +1 -1
  90. package/dist/core/remote-catalog-provider.d.ts +12 -1
  91. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  92. package/dist/core/remote-catalog-provider.js +82 -24
  93. package/dist/core/remote-catalog-provider.js.map +1 -1
  94. package/dist/core/resource-loader.d.ts.map +1 -1
  95. package/dist/core/resource-loader.js +5 -1
  96. package/dist/core/resource-loader.js.map +1 -1
  97. package/dist/core/settings-defaults.d.ts +65 -0
  98. package/dist/core/settings-defaults.d.ts.map +1 -0
  99. package/dist/core/settings-defaults.js +66 -0
  100. package/dist/core/settings-defaults.js.map +1 -0
  101. package/dist/core/settings-manager.d.ts +4 -147
  102. package/dist/core/settings-manager.d.ts.map +1 -1
  103. package/dist/core/settings-manager.js +48 -44
  104. package/dist/core/settings-manager.js.map +1 -1
  105. package/dist/core/settings-schema.d.ts +228 -0
  106. package/dist/core/settings-schema.d.ts.map +1 -0
  107. package/dist/core/settings-schema.js +287 -0
  108. package/dist/core/settings-schema.js.map +1 -0
  109. package/dist/core/tools/render-utils.d.ts +18 -0
  110. package/dist/core/tools/render-utils.d.ts.map +1 -1
  111. package/dist/core/tools/render-utils.js +46 -0
  112. package/dist/core/tools/render-utils.js.map +1 -1
  113. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  114. package/dist/core/tools/renderers/bash.js +7 -40
  115. package/dist/core/tools/renderers/bash.js.map +1 -1
  116. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  117. package/dist/extensions/codemode/execute.js +64 -45
  118. package/dist/extensions/codemode/execute.js.map +1 -1
  119. package/dist/extensions/codemode/index.d.ts.map +1 -1
  120. package/dist/extensions/codemode/index.js +2 -1
  121. package/dist/extensions/codemode/index.js.map +1 -1
  122. package/dist/extensions/codemode/renderer.d.ts +2 -2
  123. package/dist/extensions/codemode/renderer.d.ts.map +1 -1
  124. package/dist/extensions/codemode/renderer.js +9 -3
  125. package/dist/extensions/codemode/renderer.js.map +1 -1
  126. package/dist/extensions/codemode/tool.d.ts +6 -12
  127. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  128. package/dist/extensions/codemode/tool.js +44 -32
  129. package/dist/extensions/codemode/tool.js.map +1 -1
  130. package/dist/extensions/mcp/cli.js +5 -8
  131. package/dist/extensions/mcp/cli.js.map +1 -1
  132. package/dist/extensions/mcp/index.d.ts.map +1 -1
  133. package/dist/extensions/mcp/index.js +26 -23
  134. package/dist/extensions/mcp/index.js.map +1 -1
  135. package/dist/extensions/mcp/resources.d.ts +0 -6
  136. package/dist/extensions/mcp/resources.d.ts.map +1 -1
  137. package/dist/extensions/mcp/resources.js +1 -1
  138. package/dist/extensions/mcp/resources.js.map +1 -1
  139. package/dist/extensions/mcp/runtime.d.ts +3 -6
  140. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  141. package/dist/extensions/mcp/runtime.js +4 -39
  142. package/dist/extensions/mcp/runtime.js.map +1 -1
  143. package/dist/extensions/mcp/tools.d.ts +2 -3
  144. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  145. package/dist/extensions/mcp/tools.js +62 -6
  146. package/dist/extensions/mcp/tools.js.map +1 -1
  147. package/dist/extensions/tool-search/tool.d.ts +0 -2
  148. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  149. package/dist/extensions/tool-search/tool.js +2 -4
  150. package/dist/extensions/tool-search/tool.js.map +1 -1
  151. package/dist/index.d.ts +1 -1
  152. package/dist/index.d.ts.map +1 -1
  153. package/dist/index.js.map +1 -1
  154. package/dist/main.js +3 -3
  155. package/dist/main.js.map +1 -1
  156. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  157. package/dist/modes/interactive/components/settings-selector.js +3 -2
  158. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  159. package/dist/modes/interactive/components/status-indicator.d.ts +1 -1
  160. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  161. package/dist/modes/interactive/components/status-indicator.js +2 -2
  162. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  163. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  164. package/dist/modes/interactive/interactive-mode.js +11 -5
  165. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  166. package/dist/modes/interactive/theme/dark.json +1 -1
  167. package/dist/modes/interactive/theme/light.json +1 -1
  168. package/dist/modes/interactive/theme/theme-schema.d.ts +28 -0
  169. package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -0
  170. package/dist/modes/interactive/theme/theme-schema.js +105 -0
  171. package/dist/modes/interactive/theme/theme-schema.js.map +1 -0
  172. package/dist/modes/interactive/theme/theme-tokens.d.ts +257 -0
  173. package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -0
  174. package/dist/modes/interactive/theme/theme-tokens.js +94 -0
  175. package/dist/modes/interactive/theme/theme-tokens.js.map +1 -0
  176. package/dist/modes/interactive/theme/theme.d.ts +13 -16
  177. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  178. package/dist/modes/interactive/theme/theme.js +21 -29
  179. package/dist/modes/interactive/theme/theme.js.map +1 -1
  180. package/dist/modes/print-mode.d.ts.map +1 -1
  181. package/dist/modes/print-mode.js +4 -0
  182. package/dist/modes/print-mode.js.map +1 -1
  183. package/dist/utils/clipboard.d.ts.map +1 -1
  184. package/dist/utils/clipboard.js +6 -1
  185. package/dist/utils/clipboard.js.map +1 -1
  186. package/docs/cli-integration.md +1 -1
  187. package/docs/cli.md +1 -1
  188. package/docs/codemode.md +1 -1
  189. package/docs/compaction.md +2 -2
  190. package/docs/environment-variables.md +2 -1
  191. package/docs/extensions.md +7 -4
  192. package/docs/keybindings.md +1 -0
  193. package/docs/mcp.md +1 -1
  194. package/docs/models.md +1 -0
  195. package/docs/providers.md +20 -0
  196. package/docs/settings.md +3 -1
  197. package/docs/themes.md +4 -2
  198. package/docs/tui.md +1 -1
  199. package/examples/README.md +0 -3
  200. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  201. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  202. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  203. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  204. package/examples/extensions/gondolin/package-lock.json +2 -2
  205. package/examples/extensions/gondolin/package.json +1 -1
  206. package/examples/extensions/overlay-test.ts +2 -2
  207. package/examples/extensions/plan-mode/index.ts +6 -2
  208. package/examples/extensions/sandbox/package-lock.json +2 -2
  209. package/examples/extensions/sandbox/package.json +1 -1
  210. package/examples/extensions/with-deps/package-lock.json +2 -2
  211. package/examples/extensions/with-deps/package.json +1 -1
  212. package/package.json +9 -20
  213. package/schemas/keybindings.schema.json +393 -0
  214. package/schemas/models.schema.json +1157 -0
  215. package/schemas/settings.schema.json +765 -0
  216. package/schemas/theme.schema.json +365 -0
  217. package/dist/bundle/chunks/anthropic-messages-KT2ID7DZ.js +0 -6
  218. package/dist/bundle/chunks/chunk-BK6FEHYX.js +0 -20
  219. package/dist/bundle/chunks/chunk-J757S5U3.js +0 -2
  220. package/dist/bundle/chunks/chunk-MXTZIDYW.js +0 -15
  221. package/dist/bundle/chunks/chunk-OTL6MGLJ.js +0 -134
  222. package/dist/bundle/chunks/chunk-W5MPVSHA.js +0 -82
  223. package/dist/bundle/chunks/easter-egg-3d-TQFQS342.js +0 -2
  224. package/dist/bundle/chunks/execute-7IRB5TUX.js +0 -490
  225. package/dist/bundle/chunks/openai-codex-responses-ZSLJZYOE.js +0 -10
  226. package/dist/bundle/chunks/runtime-ROGZ2EXI.js +0 -2
  227. package/dist/bundle/chunks/virtual-modules-4Y4G76EB.js +0 -2
  228. package/dist/modes/interactive/theme/theme-json.d.ts +0 -85
  229. package/dist/modes/interactive/theme/theme-json.d.ts.map +0 -1
  230. package/dist/modes/interactive/theme/theme-json.js +0 -132
  231. package/dist/modes/interactive/theme/theme-json.js.map +0 -1
  232. package/dist/modes/interactive/theme/theme-schema.json +0 -361
  233. package/examples/plugins/pi-example-plugin/README.md +0 -38
  234. package/examples/plugins/pi-example-plugin/package.json +0 -10
  235. package/examples/plugins/pi-example-plugin/src/contract.ts +0 -13
  236. package/examples/plugins/pi-example-plugin/src/session.ts +0 -24
  237. package/examples/plugins/pi-example-plugin/src/tui.ts +0 -31
@@ -1 +1 @@
1
- {"version":3,"file":"project-trust.d.ts","sourceRoot":"","sources":["../../src/core/project-trust.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAIN,KAAK,iBAAiB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAE/D,MAAM,WAAW,4BAA4B;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,OAAO,CAAC,CAkDnG"}
1
+ {"version":3,"file":"project-trust.d.ts","sourceRoot":"","sources":["../../src/core/project-trust.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAIN,KAAK,iBAAiB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAE/D,MAAM,WAAW,4BAA4B;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,OAAO,CAAC,CAkDnG"}
@@ -1,5 +1,6 @@
1
1
  import { APP_NAME, CONFIG_DIR_NAME } from "../config.js";
2
2
  import { emitProjectTrustEvent } from "./extensions/runner.js";
3
+ import { SETTINGS_DEFAULTS } from "./settings-defaults.js";
3
4
  import { getProjectTrustOptions, hasTrustRequiringProjectResources, } from "./trust-manager.js";
4
5
  function formatProjectTrustPrompt(cwd) {
5
6
  return `Trust project folder?\n${cwd}\n\nThis allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`;
@@ -38,7 +39,7 @@ export async function resolveProjectTrusted(options) {
38
39
  if (decision !== null) {
39
40
  return decision;
40
41
  }
41
- switch (options.defaultProjectTrust ?? "ask") {
42
+ switch (options.defaultProjectTrust ?? SETTINGS_DEFAULTS.defaultProjectTrust) {
42
43
  case "always":
43
44
  return true;
44
45
  case "never":
@@ -1 +1 @@
1
- {"version":3,"file":"project-trust.js","sourceRoot":"","sources":["../../src/core/project-trust.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_NAME, CONFIG_DIR_NAME } from \"../config.ts\";\nimport { emitProjectTrustEvent } from \"./extensions/runner.ts\";\nimport type { LoadExtensionsResult, ProjectTrustContext } from \"./extensions/types.ts\";\nimport type { DefaultProjectTrust } from \"./settings-manager.ts\";\nimport {\n\tgetProjectTrustOptions,\n\thasTrustRequiringProjectResources,\n\ttype ProjectTrustOption,\n\ttype ProjectTrustStore,\n} from \"./trust-manager.ts\";\n\nexport type AppMode = \"interactive\" | \"print\" | \"json\" | \"rpc\";\n\nexport interface ResolveProjectTrustedOptions {\n\tcwd: string;\n\ttrustStore: ProjectTrustStore;\n\ttrustOverride?: boolean;\n\tdefaultProjectTrust?: DefaultProjectTrust;\n\textensionsResult?: LoadExtensionsResult;\n\tprojectTrustContext: ProjectTrustContext;\n\tonExtensionError?: (message: string) => void;\n}\n\nfunction formatProjectTrustPrompt(cwd: string): string {\n\treturn `Trust project folder?\\n${cwd}\\n\\nThis allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`;\n}\n\nasync function selectProjectTrustOption(\n\tcwd: string,\n\tctx: ProjectTrustContext,\n): Promise<ProjectTrustOption | undefined> {\n\tconst options = getProjectTrustOptions(cwd, { includeSessionOnly: true });\n\tconst selected = await ctx.ui.select(\n\t\tformatProjectTrustPrompt(cwd),\n\t\toptions.map((option) => option.label),\n\t);\n\treturn options.find((option) => option.label === selected);\n}\n\nfunction saveProjectTrustPromptResult(trustStore: ProjectTrustStore, result: ProjectTrustOption): void {\n\tif (result.updates.length > 0) {\n\t\ttrustStore.setMany(result.updates);\n\t}\n}\n\nexport async function resolveProjectTrusted(options: ResolveProjectTrustedOptions): Promise<boolean> {\n\tif (options.trustOverride !== undefined) {\n\t\treturn options.trustOverride;\n\t}\n\tif (!hasTrustRequiringProjectResources(options.cwd)) {\n\t\treturn true;\n\t}\n\n\tif (options.extensionsResult) {\n\t\tconst { result, errors } = await emitProjectTrustEvent(\n\t\t\toptions.extensionsResult,\n\t\t\t{ type: \"project_trust\", cwd: options.cwd },\n\t\t\toptions.projectTrustContext,\n\t\t);\n\t\tfor (const error of errors) {\n\t\t\toptions.onExtensionError?.(`Extension \"${error.extensionPath}\" project_trust error: ${error.error}`);\n\t\t}\n\t\tif (result) {\n\t\t\tconst trusted = result.trusted === \"yes\";\n\t\t\tif (result.remember === true) {\n\t\t\t\toptions.trustStore.set(options.cwd, trusted);\n\t\t\t}\n\t\t\treturn trusted;\n\t\t}\n\t}\n\n\tconst decision = options.trustStore.get(options.cwd);\n\tif (decision !== null) {\n\t\treturn decision;\n\t}\n\n\tswitch (options.defaultProjectTrust ?? \"ask\") {\n\t\tcase \"always\":\n\t\t\treturn true;\n\t\tcase \"never\":\n\t\t\treturn false;\n\t\tcase \"ask\":\n\t\t\tbreak;\n\t}\n\n\tif (!options.projectTrustContext.hasUI) {\n\t\treturn false;\n\t}\n\n\tconst selected = await selectProjectTrustOption(options.cwd, options.projectTrustContext);\n\tif (selected !== undefined) {\n\t\tsaveProjectTrustPromptResult(options.trustStore, selected);\n\t\treturn selected.trusted;\n\t}\n\treturn false;\n}\n"]}
1
+ {"version":3,"file":"project-trust.js","sourceRoot":"","sources":["../../src/core/project-trust.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_NAME, CONFIG_DIR_NAME } from \"../config.ts\";\nimport { emitProjectTrustEvent } from \"./extensions/runner.ts\";\nimport type { LoadExtensionsResult, ProjectTrustContext } from \"./extensions/types.ts\";\nimport { SETTINGS_DEFAULTS } from \"./settings-defaults.ts\";\nimport type { DefaultProjectTrust } from \"./settings-manager.ts\";\nimport {\n\tgetProjectTrustOptions,\n\thasTrustRequiringProjectResources,\n\ttype ProjectTrustOption,\n\ttype ProjectTrustStore,\n} from \"./trust-manager.ts\";\n\nexport type AppMode = \"interactive\" | \"print\" | \"json\" | \"rpc\";\n\nexport interface ResolveProjectTrustedOptions {\n\tcwd: string;\n\ttrustStore: ProjectTrustStore;\n\ttrustOverride?: boolean;\n\tdefaultProjectTrust?: DefaultProjectTrust;\n\textensionsResult?: LoadExtensionsResult;\n\tprojectTrustContext: ProjectTrustContext;\n\tonExtensionError?: (message: string) => void;\n}\n\nfunction formatProjectTrustPrompt(cwd: string): string {\n\treturn `Trust project folder?\\n${cwd}\\n\\nThis allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`;\n}\n\nasync function selectProjectTrustOption(\n\tcwd: string,\n\tctx: ProjectTrustContext,\n): Promise<ProjectTrustOption | undefined> {\n\tconst options = getProjectTrustOptions(cwd, { includeSessionOnly: true });\n\tconst selected = await ctx.ui.select(\n\t\tformatProjectTrustPrompt(cwd),\n\t\toptions.map((option) => option.label),\n\t);\n\treturn options.find((option) => option.label === selected);\n}\n\nfunction saveProjectTrustPromptResult(trustStore: ProjectTrustStore, result: ProjectTrustOption): void {\n\tif (result.updates.length > 0) {\n\t\ttrustStore.setMany(result.updates);\n\t}\n}\n\nexport async function resolveProjectTrusted(options: ResolveProjectTrustedOptions): Promise<boolean> {\n\tif (options.trustOverride !== undefined) {\n\t\treturn options.trustOverride;\n\t}\n\tif (!hasTrustRequiringProjectResources(options.cwd)) {\n\t\treturn true;\n\t}\n\n\tif (options.extensionsResult) {\n\t\tconst { result, errors } = await emitProjectTrustEvent(\n\t\t\toptions.extensionsResult,\n\t\t\t{ type: \"project_trust\", cwd: options.cwd },\n\t\t\toptions.projectTrustContext,\n\t\t);\n\t\tfor (const error of errors) {\n\t\t\toptions.onExtensionError?.(`Extension \"${error.extensionPath}\" project_trust error: ${error.error}`);\n\t\t}\n\t\tif (result) {\n\t\t\tconst trusted = result.trusted === \"yes\";\n\t\t\tif (result.remember === true) {\n\t\t\t\toptions.trustStore.set(options.cwd, trusted);\n\t\t\t}\n\t\t\treturn trusted;\n\t\t}\n\t}\n\n\tconst decision = options.trustStore.get(options.cwd);\n\tif (decision !== null) {\n\t\treturn decision;\n\t}\n\n\tswitch (options.defaultProjectTrust ?? SETTINGS_DEFAULTS.defaultProjectTrust) {\n\t\tcase \"always\":\n\t\t\treturn true;\n\t\tcase \"never\":\n\t\t\treturn false;\n\t\tcase \"ask\":\n\t\t\tbreak;\n\t}\n\n\tif (!options.projectTrustContext.hasUI) {\n\t\treturn false;\n\t}\n\n\tconst selected = await selectProjectTrustOption(options.cwd, options.projectTrustContext);\n\tif (selected !== undefined) {\n\t\tsaveProjectTrustPromptResult(options.trustStore, selected);\n\t\treturn selected.trusted;\n\t}\n\treturn false;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type ModelType, type Provider } from "@earendil-works/pi-ai";
1
+ import { type AnyModel, type ModelType, type Provider, type RefreshModelsContext } from "@earendil-works/pi-ai";
2
2
  export declare const REMOTE_CATALOG_REFRESH_INTERVAL_MS: number;
3
3
  /**
4
4
  * Model types this client can consume. Sent as `?types=` so the catalog server
@@ -7,6 +7,17 @@ export declare const REMOTE_CATALOG_REFRESH_INTERVAL_MS: number;
7
7
  * the chat-only shard, which this client handles unchanged.
8
8
  */
9
9
  export declare const REMOTE_CATALOG_MODEL_TYPES: readonly ModelType[];
10
+ /** Replaces the catalog with a credential-specific model list. */
11
+ export type PersonalizeCatalog = (catalog: readonly AnyModel[], context: RefreshModelsContext) => Promise<readonly AnyModel[]>;
10
12
  /** Add a persisted pi.dev catalog overlay to a static built-in provider. */
11
13
  export declare function withRemoteCatalog(provider: Provider, catalogBaseUrl?: string, localGeneratedAt?: number): Provider;
14
+ /**
15
+ * Like `withRemoteCatalog`, but on each network refresh the catalog (built-in models plus a newer
16
+ * pi.dev catalog) is passed through `personalize` and the result is saved. The saved entry holds
17
+ * the personalized list, not the pi.dev catalog, and replaces the catalog, including offline.
18
+ * The refresh interval and etag revalidation are skipped. An empty list (nothing saved yet, or an
19
+ * empty catalog saved by an older pi after a failed or missing pi.dev catalog) falls back to the
20
+ * built-in models.
21
+ */
22
+ export declare function withPersonalizedCatalog(provider: Provider, personalize: PersonalizeCatalog, catalogBaseUrl?: string, localGeneratedAt?: number): Provider;
12
23
  //# sourceMappingURL=remote-catalog-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remote-catalog-provider.d.ts","sourceRoot":"","sources":["../../src/core/remote-catalog-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,MAAM,uBAAuB,CAAC;AAO/B,eAAO,MAAM,kCAAkC,QAAqB,CAAC;AACrE;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,SAAS,EAAoC,CAAC;AAsChG,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE,MAAiC,EACjD,gBAAgB,CAAC,EAAE,MAAM,GACvB,QAAQ,CA6FV"}
1
+ {"version":3,"file":"remote-catalog-provider.d.ts","sourceRoot":"","sources":["../../src/core/remote-catalog-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,QAAQ,EAIb,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,MAAM,uBAAuB,CAAC;AAO/B,eAAO,MAAM,kCAAkC,QAAqB,CAAC;AACrE;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,SAAS,EAAoC,CAAC;AA0EhG,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAAG,CAChC,OAAO,EAAE,SAAS,QAAQ,EAAE,EAC5B,OAAO,EAAE,oBAAoB,KACzB,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;AAElC,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,QAAQ,EAClB,cAAc,GAAE,MAAiC,EACjD,gBAAgB,CAAC,EAAE,MAAM,GACvB,QAAQ,CA6EV;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,kBAAkB,EAC/B,cAAc,GAAE,MAAiC,EACjD,gBAAgB,CAAC,EAAE,MAAM,GACvB,QAAQ,CAwCV"}
@@ -37,13 +37,33 @@ function parseCatalog(providerId, value) {
37
37
  .filter(isSupportedModelType)
38
38
  .map((model) => ({ ...model, provider: providerId }));
39
39
  }
40
+ /** Read a successful pi.dev catalog response. A missing or invalid Last-Modified header is 0. */
41
+ async function readCatalog(providerId, response) {
42
+ const lastModified = Date.parse(response.headers.get("last-modified") ?? "");
43
+ return {
44
+ models: parseCatalog(providerId, await response.json()),
45
+ lastModified: Number.isNaN(lastModified) ? 0 : lastModified,
46
+ etag: response.headers.get("etag") ?? undefined,
47
+ };
48
+ }
49
+ /** Whether a pi.dev catalog is newer than the model data shipped with pi. */
50
+ function isNewer(lastModified, localGeneratedAt) {
51
+ return localGeneratedAt === undefined || (lastModified !== undefined && lastModified > localGeneratedAt);
52
+ }
40
53
  function remoteModels(entry, localGeneratedAt) {
41
- if (!entry)
42
- return [];
43
- if (localGeneratedAt !== undefined && (entry.lastModified === undefined || entry.lastModified <= localGeneratedAt)) {
44
- return [];
45
- }
46
- return entry.models;
54
+ return entry && isNewer(entry.lastModified, localGeneratedAt) ? entry.models : [];
55
+ }
56
+ function requestCatalog(providerId, catalogBaseUrl, signal, validator) {
57
+ const url = new URL(`/api/models/providers/${encodeURIComponent(providerId)}`, catalogBaseUrl);
58
+ url.searchParams.set("types", REMOTE_CATALOG_MODEL_TYPES.join(","));
59
+ return fetchWithRetry(url, {
60
+ headers: {
61
+ accept: "application/json",
62
+ "User-Agent": getPiUserAgent(VERSION),
63
+ ...(validator ? { "if-none-match": validator } : {}),
64
+ },
65
+ signal,
66
+ }, { attemptTimeoutMs: REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS });
47
67
  }
48
68
  /** Add a persisted pi.dev catalog overlay to a static built-in provider. */
49
69
  export function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BASE_URL, localGeneratedAt) {
@@ -64,6 +84,9 @@ export function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BAS
64
84
  }
65
85
  if (!context.allowNetwork || context.signal.aborted)
66
86
  return;
87
+ // Skip the request if pi.dev was checked less than REMOTE_CATALOG_REFRESH_INTERVAL_MS ago.
88
+ // An entry without lastModified (saved by an older pi, or after a failed first request) is
89
+ // always refetched: remoteModels() ignores it, so waiting would leave the overlay empty.
67
90
  if (!context.force &&
68
91
  stored?.checkedAt !== undefined &&
69
92
  stored.lastModified !== undefined &&
@@ -73,16 +96,7 @@ export function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BAS
73
96
  // Only revalidate when a cached body backs the validator, so a 304 can never
74
97
  // leave the overlay empty.
75
98
  const validator = stored && stored.models.length > 0 ? stored.etag : undefined;
76
- const url = new URL(`/api/models/providers/${encodeURIComponent(provider.id)}`, catalogBaseUrl);
77
- url.searchParams.set("types", REMOTE_CATALOG_MODEL_TYPES.join(","));
78
- const response = await fetchWithRetry(url, {
79
- headers: {
80
- accept: "application/json",
81
- "User-Agent": getPiUserAgent(VERSION),
82
- ...(validator ? { "if-none-match": validator } : {}),
83
- },
84
- signal: context.signal,
85
- }, { attemptTimeoutMs: REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS });
99
+ const response = await requestCatalog(provider.id, catalogBaseUrl, context.signal, validator);
86
100
  if (context.signal.aborted)
87
101
  return;
88
102
  const checkedAt = Date.now();
@@ -109,16 +123,10 @@ export function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BAS
109
123
  await context.publish({ persist: { ...(stored ?? { models: [] }), checkedAt } });
110
124
  throw new Error(`Model catalog request failed for ${provider.id}: ${response.status}`);
111
125
  }
112
- const refreshed = parseCatalog(provider.id, await response.json());
113
- const lastModified = Date.parse(response.headers.get("last-modified") ?? "");
126
+ const catalog = await readCatalog(provider.id, response);
114
127
  if (context.signal.aborted)
115
128
  return;
116
- const entry = {
117
- models: refreshed,
118
- checkedAt,
119
- lastModified: Number.isNaN(lastModified) ? 0 : lastModified,
120
- etag: response.headers.get("etag") ?? undefined,
121
- };
129
+ const entry = { ...catalog, checkedAt };
122
130
  const published = remoteModels(entry, localGeneratedAt);
123
131
  await context.publish({
124
132
  persist: entry,
@@ -129,4 +137,54 @@ export function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BAS
129
137
  },
130
138
  };
131
139
  }
140
+ /**
141
+ * Like `withRemoteCatalog`, but on each network refresh the catalog (built-in models plus a newer
142
+ * pi.dev catalog) is passed through `personalize` and the result is saved. The saved entry holds
143
+ * the personalized list, not the pi.dev catalog, and replaces the catalog, including offline.
144
+ * The refresh interval and etag revalidation are skipped. An empty list (nothing saved yet, or an
145
+ * empty catalog saved by an older pi after a failed or missing pi.dev catalog) falls back to the
146
+ * built-in models.
147
+ */
148
+ export function withPersonalizedCatalog(provider, personalize, catalogBaseUrl = DEFAULT_CATALOG_BASE_URL, localGeneratedAt) {
149
+ let personalModels = [];
150
+ const builtinModels = () => provider.getAllModels?.() ?? provider.getModels();
151
+ const getAllModels = () => (personalModels.length > 0 ? personalModels : builtinModels());
152
+ return {
153
+ ...provider,
154
+ getModels: () => getAllModels().filter((model) => isModelType(model, "chat")),
155
+ getAllModels,
156
+ refreshModels: async (context) => {
157
+ const restored = (context.stored?.models ?? []).filter((model) => model.provider === provider.id);
158
+ if (!(await context.publish({
159
+ update: () => {
160
+ personalModels = restored;
161
+ },
162
+ }))) {
163
+ return;
164
+ }
165
+ if (!context.allowNetwork || context.signal.aborted)
166
+ return;
167
+ const response = await requestCatalog(provider.id, catalogBaseUrl, context.signal);
168
+ if (context.signal.aborted)
169
+ return;
170
+ let remote = [];
171
+ if (response.status !== 404 && response.status !== 501) {
172
+ if (!response.ok)
173
+ throw new Error(`Model catalog request failed for ${provider.id}: ${response.status}`);
174
+ const catalog = await readCatalog(provider.id, response);
175
+ if (isNewer(catalog.lastModified, localGeneratedAt))
176
+ remote = catalog.models;
177
+ }
178
+ const personalized = await personalize(mergeModels(builtinModels(), remote), context);
179
+ if (context.signal.aborted)
180
+ return;
181
+ await context.publish({
182
+ persist: { models: personalized, checkedAt: Date.now() },
183
+ update: () => {
184
+ personalModels = personalized;
185
+ },
186
+ });
187
+ },
188
+ };
189
+ }
132
190
  //# sourceMappingURL=remote-catalog-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"remote-catalog-provider.js","sourceRoot":"","sources":["../../src/core/remote-catalog-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AnyModel,\n\tgetModelType,\n\tisModelType,\n\ttype ModelsStoreEntry,\n\ttype ModelType,\n\ttype Provider,\n} from \"@earendil-works/pi-ai\";\nimport { VERSION } from \"../config.ts\";\nimport { fetchWithRetry } from \"../utils/management-http.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\n\nconst DEFAULT_CATALOG_BASE_URL = \"https://pi.dev\";\nconst REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS = 4_000;\nexport const REMOTE_CATALOG_REFRESH_INTERVAL_MS = 4 * 60 * 60 * 1000;\n/**\n * Model types this client can consume. Sent as `?types=` so the catalog server\n * returns the full-type shard instead of the chat-only one served to clients\n * that predate model types. A server that ignores the parameter still returns\n * the chat-only shard, which this client handles unchanged.\n */\nexport const REMOTE_CATALOG_MODEL_TYPES: readonly ModelType[] = [\"chat\", \"image\", \"classifier\"];\n\nfunction isSupportedModelType(model: { type?: unknown }): boolean {\n\treturn (\n\t\tmodel.type === undefined ||\n\t\t(typeof model.type === \"string\" && REMOTE_CATALOG_MODEL_TYPES.includes(model.type as ModelType))\n\t);\n}\n\nfunction mergeModels<TModel extends AnyModel>(baseline: readonly TModel[], dynamic: readonly TModel[]): TModel[] {\n\tconst merged = new Map<string, TModel>();\n\tfor (const model of [...baseline, ...dynamic]) merged.set(`${getModelType(model)}\\0${model.id}`, model);\n\treturn [...merged.values()];\n}\n\nfunction parseCatalog(providerId: string, value: unknown): AnyModel[] {\n\tconst entries = Array.isArray(value)\n\t\t? value\n\t\t: typeof value === \"object\" && value !== null && \"models\" in value && Array.isArray(value.models)\n\t\t\t? value.models\n\t\t\t: typeof value === \"object\" && value !== null\n\t\t\t\t? Object.values(value)\n\t\t\t\t: undefined;\n\tif (!entries) throw new Error(`Invalid model catalog for provider \"${providerId}\"`);\n\treturn entries\n\t\t.filter((entry): entry is Record<string, unknown> => typeof entry === \"object\" && entry !== null && \"id\" in entry)\n\t\t.filter(isSupportedModelType)\n\t\t.map((model) => ({ ...model, provider: providerId }) as AnyModel);\n}\n\nfunction remoteModels(entry: ModelsStoreEntry | undefined, localGeneratedAt: number | undefined): readonly AnyModel[] {\n\tif (!entry) return [];\n\tif (localGeneratedAt !== undefined && (entry.lastModified === undefined || entry.lastModified <= localGeneratedAt)) {\n\t\treturn [];\n\t}\n\treturn entry.models;\n}\n\n/** Add a persisted pi.dev catalog overlay to a static built-in provider. */\nexport function withRemoteCatalog(\n\tprovider: Provider,\n\tcatalogBaseUrl: string = DEFAULT_CATALOG_BASE_URL,\n\tlocalGeneratedAt?: number,\n): Provider {\n\tlet dynamicModels: readonly AnyModel[] = [];\n\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeModels(\n\t\t\t\tprovider.getModels(),\n\t\t\t\tdynamicModels.filter((model) => isModelType(model, \"chat\")),\n\t\t\t),\n\t\tgetAllModels: () => mergeModels(provider.getAllModels?.() ?? provider.getModels(), dynamicModels),\n\t\trefreshModels: async (context) => {\n\t\t\tconst stored = context.stored;\n\t\t\tconst restored = remoteModels(stored, localGeneratedAt).filter((model) => model.provider === provider.id);\n\t\t\tif (\n\t\t\t\t!(await context.publish({\n\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\tdynamicModels = restored;\n\t\t\t\t\t},\n\t\t\t\t}))\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!context.allowNetwork || context.signal.aborted) return;\n\t\t\tif (\n\t\t\t\t!context.force &&\n\t\t\t\tstored?.checkedAt !== undefined &&\n\t\t\t\tstored.lastModified !== undefined &&\n\t\t\t\tDate.now() - stored.checkedAt < REMOTE_CATALOG_REFRESH_INTERVAL_MS\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only revalidate when a cached body backs the validator, so a 304 can never\n\t\t\t// leave the overlay empty.\n\t\t\tconst validator = stored && stored.models.length > 0 ? stored.etag : undefined;\n\t\t\tconst url = new URL(`/api/models/providers/${encodeURIComponent(provider.id)}`, catalogBaseUrl);\n\t\t\turl.searchParams.set(\"types\", REMOTE_CATALOG_MODEL_TYPES.join(\",\"));\n\t\t\tconst response = await fetchWithRetry(\n\t\t\t\turl,\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\taccept: \"application/json\",\n\t\t\t\t\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t\t\t\t\t\t...(validator ? { \"if-none-match\": validator } : {}),\n\t\t\t\t\t},\n\t\t\t\t\tsignal: context.signal,\n\t\t\t\t},\n\t\t\t\t{ attemptTimeoutMs: REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS },\n\t\t\t);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst checkedAt = Date.now();\n\t\t\t// Unchanged: dynamicModels already holds the stored overlay, so only the\n\t\t\t// freshness window moves.\n\t\t\tif (response.status === 304 && stored) {\n\t\t\t\tawait context.publish({ persist: { ...stored, checkedAt } });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (response.status === 404 || response.status === 501) {\n\t\t\t\tawait context.publish({\n\t\t\t\t\tpersist: {\n\t\t\t\t\t\t...(stored ?? { models: [] }),\n\t\t\t\t\t\tcheckedAt,\n\t\t\t\t\t\tlastModified: 0,\n\t\t\t\t\t\tetag: undefined,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\t// Transient failure: the cached body and its validator stay valid, so keep the\n\t\t\t\t// etag and let the next refresh revalidate instead of downloading the catalog.\n\t\t\t\tawait context.publish({ persist: { ...(stored ?? { models: [] }), checkedAt } });\n\t\t\t\tthrow new Error(`Model catalog request failed for ${provider.id}: ${response.status}`);\n\t\t\t}\n\t\t\tconst refreshed = parseCatalog(provider.id, await response.json());\n\t\t\tconst lastModified = Date.parse(response.headers.get(\"last-modified\") ?? \"\");\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst entry: ModelsStoreEntry = {\n\t\t\t\tmodels: refreshed,\n\t\t\t\tcheckedAt,\n\t\t\t\tlastModified: Number.isNaN(lastModified) ? 0 : lastModified,\n\t\t\t\tetag: response.headers.get(\"etag\") ?? undefined,\n\t\t\t};\n\t\t\tconst published = remoteModels(entry, localGeneratedAt);\n\t\t\tawait context.publish({\n\t\t\t\tpersist: entry,\n\t\t\t\tupdate: () => {\n\t\t\t\t\tdynamicModels = published;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"remote-catalog-provider.js","sourceRoot":"","sources":["../../src/core/remote-catalog-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AnyModel,\n\tgetModelType,\n\tisModelType,\n\ttype ModelsStoreEntry,\n\ttype ModelType,\n\ttype Provider,\n\ttype RefreshModelsContext,\n} from \"@earendil-works/pi-ai\";\nimport { VERSION } from \"../config.ts\";\nimport { fetchWithRetry } from \"../utils/management-http.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\n\nconst DEFAULT_CATALOG_BASE_URL = \"https://pi.dev\";\nconst REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS = 4_000;\nexport const REMOTE_CATALOG_REFRESH_INTERVAL_MS = 4 * 60 * 60 * 1000;\n/**\n * Model types this client can consume. Sent as `?types=` so the catalog server\n * returns the full-type shard instead of the chat-only one served to clients\n * that predate model types. A server that ignores the parameter still returns\n * the chat-only shard, which this client handles unchanged.\n */\nexport const REMOTE_CATALOG_MODEL_TYPES: readonly ModelType[] = [\"chat\", \"image\", \"classifier\"];\n\nfunction isSupportedModelType(model: { type?: unknown }): boolean {\n\treturn (\n\t\tmodel.type === undefined ||\n\t\t(typeof model.type === \"string\" && REMOTE_CATALOG_MODEL_TYPES.includes(model.type as ModelType))\n\t);\n}\n\nfunction mergeModels<TModel extends AnyModel>(baseline: readonly TModel[], dynamic: readonly TModel[]): TModel[] {\n\tconst merged = new Map<string, TModel>();\n\tfor (const model of [...baseline, ...dynamic]) merged.set(`${getModelType(model)}\\0${model.id}`, model);\n\treturn [...merged.values()];\n}\n\nfunction parseCatalog(providerId: string, value: unknown): AnyModel[] {\n\tconst entries = Array.isArray(value)\n\t\t? value\n\t\t: typeof value === \"object\" && value !== null && \"models\" in value && Array.isArray(value.models)\n\t\t\t? value.models\n\t\t\t: typeof value === \"object\" && value !== null\n\t\t\t\t? Object.values(value)\n\t\t\t\t: undefined;\n\tif (!entries) throw new Error(`Invalid model catalog for provider \"${providerId}\"`);\n\treturn entries\n\t\t.filter((entry): entry is Record<string, unknown> => typeof entry === \"object\" && entry !== null && \"id\" in entry)\n\t\t.filter(isSupportedModelType)\n\t\t.map((model) => ({ ...model, provider: providerId }) as AnyModel);\n}\n\n/** Read a successful pi.dev catalog response. A missing or invalid Last-Modified header is 0. */\nasync function readCatalog(\n\tproviderId: string,\n\tresponse: Response,\n): Promise<{ models: AnyModel[]; lastModified: number; etag: string | undefined }> {\n\tconst lastModified = Date.parse(response.headers.get(\"last-modified\") ?? \"\");\n\treturn {\n\t\tmodels: parseCatalog(providerId, await response.json()),\n\t\tlastModified: Number.isNaN(lastModified) ? 0 : lastModified,\n\t\tetag: response.headers.get(\"etag\") ?? undefined,\n\t};\n}\n\n/** Whether a pi.dev catalog is newer than the model data shipped with pi. */\nfunction isNewer(lastModified: number | undefined, localGeneratedAt: number | undefined): boolean {\n\treturn localGeneratedAt === undefined || (lastModified !== undefined && lastModified > localGeneratedAt);\n}\n\nfunction remoteModels(entry: ModelsStoreEntry | undefined, localGeneratedAt: number | undefined): readonly AnyModel[] {\n\treturn entry && isNewer(entry.lastModified, localGeneratedAt) ? entry.models : [];\n}\n\nfunction requestCatalog(\n\tproviderId: string,\n\tcatalogBaseUrl: string,\n\tsignal: AbortSignal,\n\tvalidator?: string,\n): Promise<Response> {\n\tconst url = new URL(`/api/models/providers/${encodeURIComponent(providerId)}`, catalogBaseUrl);\n\turl.searchParams.set(\"types\", REMOTE_CATALOG_MODEL_TYPES.join(\",\"));\n\treturn fetchWithRetry(\n\t\turl,\n\t\t{\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t\t\t\t...(validator ? { \"if-none-match\": validator } : {}),\n\t\t\t},\n\t\t\tsignal,\n\t\t},\n\t\t{ attemptTimeoutMs: REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS },\n\t);\n}\n\n/** Replaces the catalog with a credential-specific model list. */\nexport type PersonalizeCatalog = (\n\tcatalog: readonly AnyModel[],\n\tcontext: RefreshModelsContext,\n) => Promise<readonly AnyModel[]>;\n\n/** Add a persisted pi.dev catalog overlay to a static built-in provider. */\nexport function withRemoteCatalog(\n\tprovider: Provider,\n\tcatalogBaseUrl: string = DEFAULT_CATALOG_BASE_URL,\n\tlocalGeneratedAt?: number,\n): Provider {\n\tlet dynamicModels: readonly AnyModel[] = [];\n\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeModels(\n\t\t\t\tprovider.getModels(),\n\t\t\t\tdynamicModels.filter((model) => isModelType(model, \"chat\")),\n\t\t\t),\n\t\tgetAllModels: () => mergeModels(provider.getAllModels?.() ?? provider.getModels(), dynamicModels),\n\t\trefreshModels: async (context) => {\n\t\t\tconst stored = context.stored;\n\t\t\tconst restored = remoteModels(stored, localGeneratedAt).filter((model) => model.provider === provider.id);\n\t\t\tif (\n\t\t\t\t!(await context.publish({\n\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\tdynamicModels = restored;\n\t\t\t\t\t},\n\t\t\t\t}))\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!context.allowNetwork || context.signal.aborted) return;\n\t\t\t// Skip the request if pi.dev was checked less than REMOTE_CATALOG_REFRESH_INTERVAL_MS ago.\n\t\t\t// An entry without lastModified (saved by an older pi, or after a failed first request) is\n\t\t\t// always refetched: remoteModels() ignores it, so waiting would leave the overlay empty.\n\t\t\tif (\n\t\t\t\t!context.force &&\n\t\t\t\tstored?.checkedAt !== undefined &&\n\t\t\t\tstored.lastModified !== undefined &&\n\t\t\t\tDate.now() - stored.checkedAt < REMOTE_CATALOG_REFRESH_INTERVAL_MS\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only revalidate when a cached body backs the validator, so a 304 can never\n\t\t\t// leave the overlay empty.\n\t\t\tconst validator = stored && stored.models.length > 0 ? stored.etag : undefined;\n\t\t\tconst response = await requestCatalog(provider.id, catalogBaseUrl, context.signal, validator);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst checkedAt = Date.now();\n\t\t\t// Unchanged: dynamicModels already holds the stored overlay, so only the\n\t\t\t// freshness window moves.\n\t\t\tif (response.status === 304 && stored) {\n\t\t\t\tawait context.publish({ persist: { ...stored, checkedAt } });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (response.status === 404 || response.status === 501) {\n\t\t\t\tawait context.publish({\n\t\t\t\t\tpersist: {\n\t\t\t\t\t\t...(stored ?? { models: [] }),\n\t\t\t\t\t\tcheckedAt,\n\t\t\t\t\t\tlastModified: 0,\n\t\t\t\t\t\tetag: undefined,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\t// Transient failure: the cached body and its validator stay valid, so keep the\n\t\t\t\t// etag and let the next refresh revalidate instead of downloading the catalog.\n\t\t\t\tawait context.publish({ persist: { ...(stored ?? { models: [] }), checkedAt } });\n\t\t\t\tthrow new Error(`Model catalog request failed for ${provider.id}: ${response.status}`);\n\t\t\t}\n\t\t\tconst catalog = await readCatalog(provider.id, response);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst entry: ModelsStoreEntry = { ...catalog, checkedAt };\n\t\t\tconst published = remoteModels(entry, localGeneratedAt);\n\t\t\tawait context.publish({\n\t\t\t\tpersist: entry,\n\t\t\t\tupdate: () => {\n\t\t\t\t\tdynamicModels = published;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n}\n\n/**\n * Like `withRemoteCatalog`, but on each network refresh the catalog (built-in models plus a newer\n * pi.dev catalog) is passed through `personalize` and the result is saved. The saved entry holds\n * the personalized list, not the pi.dev catalog, and replaces the catalog, including offline.\n * The refresh interval and etag revalidation are skipped. An empty list (nothing saved yet, or an\n * empty catalog saved by an older pi after a failed or missing pi.dev catalog) falls back to the\n * built-in models.\n */\nexport function withPersonalizedCatalog(\n\tprovider: Provider,\n\tpersonalize: PersonalizeCatalog,\n\tcatalogBaseUrl: string = DEFAULT_CATALOG_BASE_URL,\n\tlocalGeneratedAt?: number,\n): Provider {\n\tlet personalModels: readonly AnyModel[] = [];\n\tconst builtinModels = (): readonly AnyModel[] => provider.getAllModels?.() ?? provider.getModels();\n\tconst getAllModels = (): readonly AnyModel[] => (personalModels.length > 0 ? personalModels : builtinModels());\n\n\treturn {\n\t\t...provider,\n\t\tgetModels: () => getAllModels().filter((model) => isModelType(model, \"chat\")),\n\t\tgetAllModels,\n\t\trefreshModels: async (context) => {\n\t\t\tconst restored = (context.stored?.models ?? []).filter((model) => model.provider === provider.id);\n\t\t\tif (\n\t\t\t\t!(await context.publish({\n\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\tpersonalModels = restored;\n\t\t\t\t\t},\n\t\t\t\t}))\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!context.allowNetwork || context.signal.aborted) return;\n\n\t\t\tconst response = await requestCatalog(provider.id, catalogBaseUrl, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tlet remote: readonly AnyModel[] = [];\n\t\t\tif (response.status !== 404 && response.status !== 501) {\n\t\t\t\tif (!response.ok) throw new Error(`Model catalog request failed for ${provider.id}: ${response.status}`);\n\t\t\t\tconst catalog = await readCatalog(provider.id, response);\n\t\t\t\tif (isNewer(catalog.lastModified, localGeneratedAt)) remote = catalog.models;\n\t\t\t}\n\t\t\tconst personalized = await personalize(mergeModels(builtinModels(), remote), context);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tawait context.publish({\n\t\t\t\tpersist: { models: personalized, checkedAt: Date.now() },\n\t\t\t\tupdate: () => {\n\t\t\t\t\tpersonalModels = personalized;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"resource-loader.d.ts","sourceRoot":"","sources":["../../src/core/resource-loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,KAAK,EAAE,MAAM,qCAAqC,CAAC;AACpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAI9E,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAO/D,OAAO,KAAK,EAEX,gBAAgB,EAEhB,eAAe,EACf,oBAAoB,EACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAyB,KAAK,YAAY,EAAyB,MAAM,sBAAsB,CAAC;AACvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAWzC,MAAM,WAAW,sBAAsB;IACtC,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC,CAAC;IAC7D,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC,CAAC;IAC9D,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,2BAA2B;IAC3C,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,gBAAgB,EAAE,oBAAoB,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9F;AAyDD,KAAK,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;AAEnE,uGAAuG;AACvG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,KAAK,IAAI,gBAAgB,CAEpF;AAwCD,MAAM,WAAW,cAAc;IAC9B,aAAa,IAAI,oBAAoB,CAAC;IACtC,SAAS,IAAI;QAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAAC;IACpE,UAAU,IAAI;QAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAAC;IAC/E,SAAS,IAAI;QAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAAC;IACpE,cAAc,IAAI;QAAE,WAAW,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;IAC5E,eAAe,IAAI,MAAM,GAAG,SAAS,CAAC;IACtC,qBAAqB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACtD,qBAAqB,IAAI,MAAM,EAAE,CAAC;IAClC,4BAA4B,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,eAAe,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACrD,MAAM,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAmED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CACjB,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAmC3C;AAED,MAAM,WAAW,4BAA4B;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,6BAA6B,CAAC,EAAE,MAAM,EAAE,CAAC;IACzC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,kBAAkB,CAAC,EAAE,eAAe,EAAE,CAAC;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wGAAwG;IACxG,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,oBAAoB,CAAC;IAC1E,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,KAAK;QAClF,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,WAAW,EAAE,kBAAkB,EAAE,CAAC;KAClC,CAAC;IACF,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,KAAK;QAC7F,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,WAAW,EAAE,kBAAkB,EAAE,CAAC;KAClC,CAAC;IACF,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,KAAK;QAClF,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,WAAW,EAAE,kBAAkB,EAAE,CAAC;KAClC,CAAC;IACF,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAAK;QAC1F,WAAW,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACtD,CAAC;IACF,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,0BAA0B,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;CAC1D;AAED,qBAAa,qBAAsB,YAAW,cAAc;IAC3D,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,wBAAwB,CAAW;IAC3C,OAAO,CAAC,oBAAoB,CAAW;IACvC,OAAO,CAAC,6BAA6B,CAAW;IAChD,OAAO,CAAC,oBAAoB,CAAW;IACvC,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,iBAAiB,CAAgC;IACzD,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,yBAAyB,CAAc;IAC/C,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,kBAAkB,CAAC,CAAS;IACpC,OAAO,CAAC,wBAAwB,CAAC,CAAW;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAuD;IAClF,OAAO,CAAC,cAAc,CAAC,CAGrB;IACF,OAAO,CAAC,eAAe,CAAC,CAGtB;IACF,OAAO,CAAC,cAAc,CAAC,CAGrB;IACF,OAAO,CAAC,mBAAmB,CAAC,CAE1B;IACF,OAAO,CAAC,oBAAoB,CAAC,CAAmD;IAChF,OAAO,CAAC,0BAA0B,CAAC,CAA+B;IAElE,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,sBAAsB,CAAC,CAAS;IACxC,OAAO,CAAC,kBAAkB,CAAW;IACrC,OAAO,CAAC,6BAA6B,CAAW;IAChD,OAAO,CAAC,cAAc,CAAW;IACjC,OAAO,CAAC,yBAAyB,CAA0B;IAC3D,OAAO,CAAC,0BAA0B,CAA0B;IAC5D,OAAO,CAAC,yBAAyB,CAA0B;IAC3D,OAAO,CAAC,sBAAsB,CAA4B;IAC1D,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,cAAc,CAAW;IACjC,OAAO,CAAC,MAAM,CAAU;IAExB,YAAY,OAAO,EAAE,4BAA4B,EAoDhD;IAED,aAAa,IAAI,oBAAoB,CAEpC;IAED,SAAS,IAAI;QAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAElE;IAED,UAAU,IAAI;QAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAE7E;IAED,SAAS,IAAI;QAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;KAAE,CAElE;IAED,cAAc,IAAI;QAAE,WAAW,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAE1E;IAED,eAAe,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED,qBAAqB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAEpD;IAED,qBAAqB,IAAI,MAAM,EAAE,CAEhC;IAED,4BAA4B,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAEtD;IAED,eAAe,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAsCnD;IAEK,0BAA0B,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAMhE;IAEK,MAAM,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAqKjE;YAEa,uBAAuB;IAkCrC,OAAO,CAAC,wBAAwB;IAIhC,qGAAqG;YACvF,kBAAkB;YAgClB,qBAAqB;IA4CnC,OAAO,CAAC,+BAA+B;IASvC,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,uBAAuB;IAc/B;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;IA0BlC,OAAO,CAAC,qBAAqB;IA0B7B,OAAO,CAAC,sBAAsB;IA8B9B,OAAO,CAAC,qBAAqB;IA2B7B,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,qBAAqB;IA8C7B,OAAO,CAAC,2BAA2B;IA8CnC,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,UAAU;IA2ClB,OAAO,CAAC,iBAAiB;IAmCzB,OAAO,CAAC,iBAAiB;YAcX,sBAAsB;IAyBpC,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,8BAA8B;IActC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,wBAAwB;CAqChC"}
1
+ {"version":3,"file":"resource-loader.d.ts","sourceRoot":"","sources":["../../src/core/resource-loader.ts"],"names":[],"mappings":"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"}
@@ -177,7 +177,11 @@ export function loadProjectContextFiles(options) {
177
177
  let currentDir = resolvedCwd;
178
178
  while (true) {
179
179
  const contextFile = loadContextFileFromDir(currentDir);
180
- const isShadowed = shadowedContextFile !== undefined && canonicalizePath(contextFile?.path ?? "") === shadowedContextFile;
180
+ // Compare the directory's real path, not the file's: a worktree AGENTS.md that
181
+ // symlinks to the main repo's file resolves to the shadowed path itself.
182
+ const isShadowed = shadowedContextFile !== undefined &&
183
+ contextFile !== null &&
184
+ join(canonicalizePath(currentDir), basename(contextFile.path)) === shadowedContextFile;
181
185
  if (contextFile && !isShadowed && !seenPaths.has(contextFile.path)) {
182
186
  ancestorContextFiles.unshift(contextFile);
183
187
  seenPaths.add(contextFile.path);