@astralyn/pi 1.4.6 → 1.4.7

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 (242) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/bundle/chunks/{chunk-KDO6L76C.js → chunk-FODCTZXW.js} +4 -4
  3. package/dist/bundle/chunks/{chunk-EYKC6ESU.js → chunk-FYKNSJG6.js} +1 -1
  4. package/dist/bundle/chunks/{chunk-AXFWZIHH.js → chunk-MG5XDTXV.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-ALHAFUHP.js → chunk-PU2IWWXV.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-5M3YJ54Z.js → chunk-RO2VH6UZ.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-RBTJBQWX.js → chunk-YJTSOLP2.js} +73 -74
  8. package/dist/bundle/chunks/{cli-FH77R7JR.js → cli-MEL7SGJD.js} +1 -1
  9. package/dist/bundle/chunks/{execute-5ZQUS52M.js → execute-4CWRNHPO.js} +1 -1
  10. package/dist/bundle/chunks/{runtime-R5CMHJ5P.js → runtime-R3X67XMR.js} +1 -1
  11. package/dist/bundle/chunks/{virtual-modules-KCQU7LOC.js → virtual-modules-PKEOKGYI.js} +1 -1
  12. package/dist/bundle/cli.js +1 -1
  13. package/dist/bundle/index.js +1 -1
  14. package/dist/bundle/rpc-entry.js +1 -1
  15. package/dist/core/agent-session.d.ts +0 -3
  16. package/dist/core/agent-session.d.ts.map +1 -1
  17. package/dist/core/agent-session.js +0 -4
  18. package/dist/core/agent-session.js.map +1 -1
  19. package/dist/core/extensions/index.d.ts +1 -1
  20. package/dist/core/extensions/index.d.ts.map +1 -1
  21. package/dist/core/extensions/index.js.map +1 -1
  22. package/dist/core/package-manager.d.ts +7 -1
  23. package/dist/core/package-manager.d.ts.map +1 -1
  24. package/dist/core/package-manager.js +72 -1
  25. package/dist/core/package-manager.js.map +1 -1
  26. package/dist/core/resource-loader.d.ts +1 -0
  27. package/dist/core/resource-loader.d.ts.map +1 -1
  28. package/dist/core/resource-loader.js +23 -7
  29. package/dist/core/resource-loader.js.map +1 -1
  30. package/dist/core/settings-manager.d.ts +4 -2
  31. package/dist/core/settings-manager.d.ts.map +1 -1
  32. package/dist/core/settings-manager.js +11 -0
  33. package/dist/core/settings-manager.js.map +1 -1
  34. package/dist/core/settings-schema.d.ts +7 -0
  35. package/dist/core/settings-schema.d.ts.map +1 -1
  36. package/dist/core/settings-schema.js +6 -0
  37. package/dist/core/settings-schema.js.map +1 -1
  38. package/dist/core/skills.d.ts +10 -0
  39. package/dist/core/skills.d.ts.map +1 -1
  40. package/dist/core/skills.js +23 -0
  41. package/dist/core/skills.js.map +1 -1
  42. package/dist/core/tasks/delivery.d.ts +11 -4
  43. package/dist/core/tasks/delivery.d.ts.map +1 -1
  44. package/dist/core/tasks/delivery.js +9 -9
  45. package/dist/core/tasks/delivery.js.map +1 -1
  46. package/dist/core/tasks/execution.d.ts +10 -3
  47. package/dist/core/tasks/execution.d.ts.map +1 -1
  48. package/dist/core/tasks/execution.js +72 -52
  49. package/dist/core/tasks/execution.js.map +1 -1
  50. package/dist/core/tasks/format.d.ts +0 -2
  51. package/dist/core/tasks/format.d.ts.map +1 -1
  52. package/dist/core/tasks/format.js +1 -16
  53. package/dist/core/tasks/format.js.map +1 -1
  54. package/dist/core/tasks/limits.d.ts +12 -1
  55. package/dist/core/tasks/limits.d.ts.map +1 -1
  56. package/dist/core/tasks/limits.js +20 -1
  57. package/dist/core/tasks/limits.js.map +1 -1
  58. package/dist/core/tasks/output.d.ts +6 -12
  59. package/dist/core/tasks/output.d.ts.map +1 -1
  60. package/dist/core/tasks/output.js +35 -32
  61. package/dist/core/tasks/output.js.map +1 -1
  62. package/dist/core/tasks/record.d.ts +45 -0
  63. package/dist/core/tasks/record.d.ts.map +1 -0
  64. package/dist/core/tasks/record.js +80 -0
  65. package/dist/core/tasks/record.js.map +1 -0
  66. package/dist/core/tasks/runtime.d.ts +14 -14
  67. package/dist/core/tasks/runtime.d.ts.map +1 -1
  68. package/dist/core/tasks/runtime.js +111 -93
  69. package/dist/core/tasks/runtime.js.map +1 -1
  70. package/dist/core/tasks/session.d.ts +0 -1
  71. package/dist/core/tasks/session.d.ts.map +1 -1
  72. package/dist/core/tasks/session.js +7 -8
  73. package/dist/core/tasks/session.js.map +1 -1
  74. package/dist/core/tasks/store.d.ts +18 -25
  75. package/dist/core/tasks/store.d.ts.map +1 -1
  76. package/dist/core/tasks/store.js +42 -40
  77. package/dist/core/tasks/store.js.map +1 -1
  78. package/dist/core/tasks/types.d.ts +96 -17
  79. package/dist/core/tasks/types.d.ts.map +1 -1
  80. package/dist/core/tasks/types.js.map +1 -1
  81. package/dist/core/tools/shell-execution.d.ts +8 -7
  82. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  83. package/dist/core/tools/shell-execution.js +18 -26
  84. package/dist/core/tools/shell-execution.js.map +1 -1
  85. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  86. package/dist/core/tools/shell-tool.js +31 -29
  87. package/dist/core/tools/shell-tool.js.map +1 -1
  88. package/dist/core/usage-totals.d.ts +3 -0
  89. package/dist/core/usage-totals.d.ts.map +1 -1
  90. package/dist/core/usage-totals.js +15 -0
  91. package/dist/core/usage-totals.js.map +1 -1
  92. package/dist/extensions/agent/progress.d.ts.map +1 -1
  93. package/dist/extensions/agent/progress.js +1 -11
  94. package/dist/extensions/agent/progress.js.map +1 -1
  95. package/dist/extensions/agent/tool.d.ts.map +1 -1
  96. package/dist/extensions/agent/tool.js +9 -5
  97. package/dist/extensions/agent/tool.js.map +1 -1
  98. package/dist/extensions/agent/worker.d.ts.map +1 -1
  99. package/dist/extensions/agent/worker.js +3 -5
  100. package/dist/extensions/agent/worker.js.map +1 -1
  101. package/dist/extensions/btw/agent.d.ts +1 -1
  102. package/dist/extensions/btw/agent.d.ts.map +1 -1
  103. package/dist/extensions/btw/agent.js +3 -20
  104. package/dist/extensions/btw/agent.js.map +1 -1
  105. package/dist/extensions/cached-compaction/index.d.ts.map +1 -1
  106. package/dist/extensions/cached-compaction/index.js +3 -22
  107. package/dist/extensions/cached-compaction/index.js.map +1 -1
  108. package/dist/extensions/cached-compaction/render.d.ts +1 -0
  109. package/dist/extensions/cached-compaction/render.d.ts.map +1 -1
  110. package/dist/extensions/cached-compaction/render.js +42 -14
  111. package/dist/extensions/cached-compaction/render.js.map +1 -1
  112. package/dist/extensions/deepwiki/client.d.ts.map +1 -1
  113. package/dist/extensions/deepwiki/client.js +6 -78
  114. package/dist/extensions/deepwiki/client.js.map +1 -1
  115. package/dist/extensions/deepwiki/transport.d.ts +3 -0
  116. package/dist/extensions/deepwiki/transport.d.ts.map +1 -0
  117. package/dist/extensions/deepwiki/transport.js +96 -0
  118. package/dist/extensions/deepwiki/transport.js.map +1 -0
  119. package/dist/extensions/provider/ui/builtin-data.d.ts +3 -3
  120. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  121. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  122. package/dist/extensions/provider/ui/compat.d.ts +3 -3
  123. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  124. package/dist/extensions/provider/ui/compat.js.map +1 -1
  125. package/dist/extensions/provider/ui/controls.d.ts +2 -2
  126. package/dist/extensions/provider/ui/controls.d.ts.map +1 -1
  127. package/dist/extensions/provider/ui/controls.js.map +1 -1
  128. package/dist/extensions/provider/ui/dialogs.d.ts +3 -3
  129. package/dist/extensions/provider/ui/dialogs.d.ts.map +1 -1
  130. package/dist/extensions/provider/ui/dialogs.js.map +1 -1
  131. package/dist/extensions/provider/ui/dictionary.d.ts +2 -2
  132. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  133. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  134. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  135. package/dist/extensions/provider/ui/editor.js +1 -3
  136. package/dist/extensions/provider/ui/editor.js.map +1 -1
  137. package/dist/extensions/provider/ui/fetch-models.d.ts +2 -2
  138. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  139. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  140. package/dist/extensions/provider/ui/model-fields.d.ts +2 -2
  141. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  142. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  143. package/dist/extensions/provider/ui/model-options.d.ts +6 -6
  144. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  145. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  146. package/dist/extensions/provider/ui/pane.d.ts +21 -12
  147. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  148. package/dist/extensions/provider/ui/pane.js.map +1 -1
  149. package/dist/extensions/provider/ui/provider-fields.d.ts +3 -3
  150. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  151. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  152. package/dist/extensions/provider/ui/thinking-map.d.ts +2 -2
  153. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  154. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  155. package/dist/extensions/run-summary/format.js +1 -1
  156. package/dist/extensions/run-summary/format.js.map +1 -1
  157. package/dist/extensions/statusline/usage.d.ts.map +1 -1
  158. package/dist/extensions/statusline/usage.js +2 -6
  159. package/dist/extensions/statusline/usage.js.map +1 -1
  160. package/dist/extensions/tasks/tool/actions.d.ts +1 -1
  161. package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
  162. package/dist/extensions/tasks/tool/actions.js +49 -106
  163. package/dist/extensions/tasks/tool/actions.js.map +1 -1
  164. package/dist/extensions/tasks/tool/constants.d.ts +1 -6
  165. package/dist/extensions/tasks/tool/constants.d.ts.map +1 -1
  166. package/dist/extensions/tasks/tool/constants.js +1 -6
  167. package/dist/extensions/tasks/tool/constants.js.map +1 -1
  168. package/dist/extensions/tasks/tool/schema.d.ts +0 -3
  169. package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
  170. package/dist/extensions/tasks/tool/schema.js +4 -13
  171. package/dist/extensions/tasks/tool/schema.js.map +1 -1
  172. package/dist/extensions/tasks/tool.d.ts.map +1 -1
  173. package/dist/extensions/tasks/tool.js +2 -2
  174. package/dist/extensions/tasks/tool.js.map +1 -1
  175. package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
  176. package/dist/extensions/tasks/ui/completion-render.js +31 -33
  177. package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
  178. package/dist/extensions/tasks/ui/layout.d.ts +7 -7
  179. package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
  180. package/dist/extensions/tasks/ui/layout.js +17 -19
  181. package/dist/extensions/tasks/ui/layout.js.map +1 -1
  182. package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
  183. package/dist/extensions/tasks/ui/list.js +2 -3
  184. package/dist/extensions/tasks/ui/list.js.map +1 -1
  185. package/dist/extensions/tasks/ui/manager.d.ts +16 -7
  186. package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
  187. package/dist/extensions/tasks/ui/manager.js +163 -131
  188. package/dist/extensions/tasks/ui/manager.js.map +1 -1
  189. package/dist/extensions/tasks/ui/model.d.ts +25 -0
  190. package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
  191. package/dist/extensions/tasks/ui/model.js +4 -0
  192. package/dist/extensions/tasks/ui/model.js.map +1 -1
  193. package/dist/extensions/tasks/ui/render.d.ts +1 -1
  194. package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
  195. package/dist/extensions/tasks/ui/render.js +11 -7
  196. package/dist/extensions/tasks/ui/render.js.map +1 -1
  197. package/dist/extensions/tasks/ui/status.d.ts +15 -0
  198. package/dist/extensions/tasks/ui/status.d.ts.map +1 -0
  199. package/dist/extensions/tasks/ui/status.js +16 -0
  200. package/dist/extensions/tasks/ui/status.js.map +1 -0
  201. package/dist/index.d.ts +1 -1
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js.map +1 -1
  204. package/dist/modes/interactive/components/config-selector.d.ts +14 -1
  205. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  206. package/dist/modes/interactive/components/config-selector.js +258 -7
  207. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  208. package/dist/modes/interactive/components/status-marker.d.ts +2 -1
  209. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  210. package/dist/modes/interactive/components/status-marker.js +0 -1
  211. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  212. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  213. package/dist/modes/interactive/interactive-mode.js +7 -1
  214. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  215. package/dist/utils/duration.d.ts +3 -0
  216. package/dist/utils/duration.d.ts.map +1 -0
  217. package/dist/utils/duration.js +17 -0
  218. package/dist/utils/duration.js.map +1 -0
  219. package/dist/utils/number.d.ts +3 -0
  220. package/dist/utils/number.d.ts.map +1 -0
  221. package/dist/utils/number.js +5 -0
  222. package/dist/utils/number.js.map +1 -0
  223. package/docs/bundled/extensions/agent.md +3 -3
  224. package/docs/bundled/extensions/cached-compaction.md +13 -4
  225. package/docs/bundled/extensions/deepwiki.md +3 -1
  226. package/docs/extensions.md +5 -5
  227. package/docs/packages.md +5 -3
  228. package/docs/sdk.md +1 -1
  229. package/docs/session-format.md +1 -1
  230. package/docs/settings.md +11 -0
  231. package/docs/skills.md +23 -0
  232. package/npm-shrinkwrap.json +2 -2
  233. package/package.json +1 -1
  234. package/schemas/settings.schema.json +36 -0
  235. package/dist/extensions/deepwiki/http.d.ts +0 -13
  236. package/dist/extensions/deepwiki/http.d.ts.map +0 -1
  237. package/dist/extensions/deepwiki/http.js +0 -88
  238. package/dist/extensions/deepwiki/http.js.map +0 -1
  239. package/dist/extensions/tasks/ui/task-view.d.ts +0 -8
  240. package/dist/extensions/tasks/ui/task-view.d.ts.map +0 -1
  241. package/dist/extensions/tasks/ui/task-view.js +0 -13
  242. package/dist/extensions/tasks/ui/task-view.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAMnE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoF/D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAMnE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkE/D"}
@@ -3,8 +3,8 @@ import { renderCachedCompactionEntry } from "./render.js";
3
3
  import { checkpointSummary, keptStart, summaryInstruction } from "./summary.js";
4
4
  const CARD_TYPE = "cached-compaction";
5
5
  export default function cachedCompaction(pi) {
6
+ /** Card for the summary returned to the current compaction; every compaction starts by clearing it. */
6
7
  let completed;
7
- let pendingCard;
8
8
  pi.registerEntryRenderer(CARD_TYPE, renderCachedCompactionEntry);
9
9
  pi.on("session_before_compact", async (event, ctx) => {
10
10
  completed = undefined;
@@ -63,29 +63,10 @@ export default function cachedCompaction(pi) {
63
63
  }
64
64
  });
65
65
  pi.on("session_compact", (event) => {
66
- if (!event.fromExtension || !completed)
67
- return;
68
66
  const card = completed;
69
67
  completed = undefined;
70
- pendingCard = card;
71
- setTimeout(() => {
72
- if (pendingCard !== card)
73
- return;
74
- pendingCard = undefined;
75
- try {
76
- pi.appendEntry(CARD_TYPE, card);
77
- }
78
- catch {
79
- // The session may be disposed before the deferred card is appended.
80
- }
81
- }, 0);
82
- });
83
- pi.on("session_compact_failed", () => {
84
- completed = undefined;
85
- });
86
- pi.on("session_shutdown", () => {
87
- completed = undefined;
88
- pendingCard = undefined;
68
+ if (event.fromExtension && card)
69
+ pi.appendEntry(CARD_TYPE, card);
89
70
  });
90
71
  }
91
72
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { contentText } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { type CachedCompactionCard, renderCachedCompactionEntry } from \"./render.ts\";\nimport { checkpointSummary, keptStart, summaryInstruction } from \"./summary.ts\";\n\nconst CARD_TYPE = \"cached-compaction\";\n\nexport default function cachedCompaction(pi: ExtensionAPI): void {\n\tlet completed: CachedCompactionCard | undefined;\n\tlet pendingCard: CachedCompactionCard | undefined;\n\n\tpi.registerEntryRenderer(CARD_TYPE, renderCachedCompactionEntry);\n\n\tpi.on(\"session_before_compact\", async (event, ctx) => {\n\t\tcompleted = undefined;\n\t\tif (event.reason === \"overflow\") return;\n\t\tconst startedAt = Date.now();\n\t\ttry {\n\t\t\tconst snapshot = await ctx.getContextSnapshot();\n\t\t\tconst kept = keptStart(event.branchEntries, event.preparation.firstKeptEntryId, snapshot.messages);\n\t\t\tif (!kept) return;\n\t\t\tconst response = await ctx.modelRegistry\n\t\t\t\t.streamSimple(\n\t\t\t\t\tsnapshot.model,\n\t\t\t\t\t{\n\t\t\t\t\t\tmessages: [\n\t\t\t\t\t\t\t...snapshot.messages,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: summaryInstruction(kept, event.customInstructions) }],\n\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...snapshot.streamOptions,\n\t\t\t\t\t\treasoning: snapshot.thinkingLevel === \"off\" ? undefined : snapshot.thinkingLevel,\n\t\t\t\t\t\tsignal: event.signal,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.result();\n\t\t\tif (response.stopReason === \"aborted\") return { cancel: true };\n\t\t\tif (response.stopReason !== \"stop\" || response.content.some((block) => block.type === \"toolCall\")) return;\n\t\t\tconst text = contentText(response.content).trim();\n\t\t\tif (!text) return;\n\t\t\tconst checkpoint = checkpointSummary(text, event.preparation.fileOps, event.branchEntries);\n\t\t\tcompleted = {\n\t\t\t\treason: event.reason,\n\t\t\t\tcacheRead: response.usage.cacheRead,\n\t\t\t\tinput: response.usage.input,\n\t\t\t\tcacheWrite: response.usage.cacheWrite,\n\t\t\t\toutput: response.usage.output,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcompaction: {\n\t\t\t\t\tsummary: checkpoint.summary,\n\t\t\t\t\tfirstKeptEntryId: event.preparation.firstKeptEntryId,\n\t\t\t\t\ttokensBefore: event.preparation.tokensBefore,\n\t\t\t\t\tusage: response.usage,\n\t\t\t\t\tdetails: checkpoint.details,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch {\n\t\t\treturn event.signal.aborted ? { cancel: true } : undefined;\n\t\t}\n\t});\n\n\tpi.on(\"session_compact\", (event) => {\n\t\tif (!event.fromExtension || !completed) return;\n\t\tconst card = completed;\n\t\tcompleted = undefined;\n\t\tpendingCard = card;\n\t\tsetTimeout(() => {\n\t\t\tif (pendingCard !== card) return;\n\t\t\tpendingCard = undefined;\n\t\t\ttry {\n\t\t\t\tpi.appendEntry(CARD_TYPE, card);\n\t\t\t} catch {\n\t\t\t\t// The session may be disposed before the deferred card is appended.\n\t\t\t}\n\t\t}, 0);\n\t});\n\n\tpi.on(\"session_compact_failed\", () => {\n\t\tcompleted = undefined;\n\t});\n\tpi.on(\"session_shutdown\", () => {\n\t\tcompleted = undefined;\n\t\tpendingCard = undefined;\n\t});\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAA6B,2BAA2B,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEhF,MAAM,SAAS,GAAG,mBAAmB,CAAC;AAEtC,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAgB;IACxD,uGAAuG;IACvG,IAAI,SAA2C,CAAC;IAEhD,EAAE,CAAC,qBAAqB,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC;IAEjE,EAAE,CAAC,EAAE,CAAC,wBAAwB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACpD,SAAS,GAAG,SAAS,CAAC;QACtB,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,kBAAkB,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnG,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,aAAa;iBACtC,YAAY,CACZ,QAAQ,CAAC,KAAK,EACd;gBACC,QAAQ,EAAE;oBACT,GAAG,QAAQ,CAAC,QAAQ;oBACpB;wBACC,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC;wBACrF,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;qBACrB;iBACD;aACD,EACD;gBACC,GAAG,QAAQ,CAAC,aAAa;gBACzB,SAAS,EAAE,QAAQ,CAAC,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa;gBAChF,MAAM,EAAE,KAAK,CAAC,MAAM;aACpB,CACD;iBACA,MAAM,EAAE,CAAC;YACX,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS;gBAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAC/D,IAAI,QAAQ,CAAC,UAAU,KAAK,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;gBAAE,OAAO;YAC1G,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;YAC3F,SAAS,GAAG;gBACX,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS;gBACnC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK;gBAC3B,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,UAAU;gBACrC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM;gBAC7B,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;aAClC,CAAC;YACF,OAAO;gBACN,UAAU,EAAE;oBACX,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,gBAAgB,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB;oBACpD,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,YAAY;oBAC5C,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,OAAO,EAAE,UAAU,CAAC,OAAO;iBAC3B;aACD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5D,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,SAAS,CAAC;QACvB,SAAS,GAAG,SAAS,CAAC;QACtB,IAAI,KAAK,CAAC,aAAa,IAAI,IAAI;YAAE,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { contentText } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { type CachedCompactionCard, renderCachedCompactionEntry } from \"./render.ts\";\nimport { checkpointSummary, keptStart, summaryInstruction } from \"./summary.ts\";\n\nconst CARD_TYPE = \"cached-compaction\";\n\nexport default function cachedCompaction(pi: ExtensionAPI): void {\n\t/** Card for the summary returned to the current compaction; every compaction starts by clearing it. */\n\tlet completed: CachedCompactionCard | undefined;\n\n\tpi.registerEntryRenderer(CARD_TYPE, renderCachedCompactionEntry);\n\n\tpi.on(\"session_before_compact\", async (event, ctx) => {\n\t\tcompleted = undefined;\n\t\tif (event.reason === \"overflow\") return;\n\t\tconst startedAt = Date.now();\n\t\ttry {\n\t\t\tconst snapshot = await ctx.getContextSnapshot();\n\t\t\tconst kept = keptStart(event.branchEntries, event.preparation.firstKeptEntryId, snapshot.messages);\n\t\t\tif (!kept) return;\n\t\t\tconst response = await ctx.modelRegistry\n\t\t\t\t.streamSimple(\n\t\t\t\t\tsnapshot.model,\n\t\t\t\t\t{\n\t\t\t\t\t\tmessages: [\n\t\t\t\t\t\t\t...snapshot.messages,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: summaryInstruction(kept, event.customInstructions) }],\n\t\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...snapshot.streamOptions,\n\t\t\t\t\t\treasoning: snapshot.thinkingLevel === \"off\" ? undefined : snapshot.thinkingLevel,\n\t\t\t\t\t\tsignal: event.signal,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.result();\n\t\t\tif (response.stopReason === \"aborted\") return { cancel: true };\n\t\t\tif (response.stopReason !== \"stop\" || response.content.some((block) => block.type === \"toolCall\")) return;\n\t\t\tconst text = contentText(response.content).trim();\n\t\t\tif (!text) return;\n\t\t\tconst checkpoint = checkpointSummary(text, event.preparation.fileOps, event.branchEntries);\n\t\t\tcompleted = {\n\t\t\t\treason: event.reason,\n\t\t\t\tcacheRead: response.usage.cacheRead,\n\t\t\t\tinput: response.usage.input,\n\t\t\t\tcacheWrite: response.usage.cacheWrite,\n\t\t\t\toutput: response.usage.output,\n\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcompaction: {\n\t\t\t\t\tsummary: checkpoint.summary,\n\t\t\t\t\tfirstKeptEntryId: event.preparation.firstKeptEntryId,\n\t\t\t\t\ttokensBefore: event.preparation.tokensBefore,\n\t\t\t\t\tusage: response.usage,\n\t\t\t\t\tdetails: checkpoint.details,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch {\n\t\t\treturn event.signal.aborted ? { cancel: true } : undefined;\n\t\t}\n\t});\n\n\tpi.on(\"session_compact\", (event) => {\n\t\tconst card = completed;\n\t\tcompleted = undefined;\n\t\tif (event.fromExtension && card) pi.appendEntry(CARD_TYPE, card);\n\t});\n}\n"]}
@@ -7,5 +7,6 @@ export interface CachedCompactionCard {
7
7
  output: number;
8
8
  durationMs: number;
9
9
  }
10
+ /** A footnote to the native compaction summary above it, expanding with it. */
10
11
  export declare const renderCachedCompactionEntry: EntryRenderer<CachedCompactionCard>;
11
12
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAEpE,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACnB;AAQD,eAAO,MAAM,2BAA2B,EAAE,aAAa,CAAC,oBAAoB,CAQ3E,CAAC"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAMpE,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACnB;AAqBD,+EAA+E;AAC/E,eAAO,MAAM,2BAA2B,EAAE,aAAa,CAAC,oBAAoB,CAmB3E,CAAC"}
@@ -1,19 +1,47 @@
1
1
  import { Text } from "@earendil-works/pi-tui";
2
- function formatTokens(count) {
3
- if (count >= 1_000_000)
4
- return `${(count / 1_000_000).toFixed(1)}m`;
5
- if (count >= 1000)
6
- return `${(count / 1000).toFixed(1)}k`;
7
- return String(count);
2
+ import { cacheHitPercent } from "../../core/usage-totals.js";
3
+ import { formatTokens } from "../../modes/interactive/components/footer.js";
4
+ import { formatDuration } from "../../utils/duration.js";
5
+ /** Cache reuse is why this path exists, so its rate is the one colored segment. */
6
+ function hitRate(card, theme) {
7
+ const percent = cacheHitPercent(card);
8
+ if (percent === undefined)
9
+ return undefined;
10
+ return theme.fg(percent >= 80 ? "success" : percent < 50 ? "warning" : "dim", `CH ${percent.toFixed(1)}%`);
11
+ }
12
+ /** The prompt split by how the provider billed it; parts it did not use are left out. */
13
+ function promptBreakdown(card) {
14
+ const total = card.input + card.cacheRead + card.cacheWrite;
15
+ if (total === 0)
16
+ return undefined;
17
+ const parts = [
18
+ card.cacheRead > 0 ? `R${formatTokens(card.cacheRead)} cached` : undefined,
19
+ card.cacheWrite > 0 ? `W${formatTokens(card.cacheWrite)} written` : undefined,
20
+ card.input > 0 ? `↑${formatTokens(card.input)} uncached` : undefined,
21
+ ];
22
+ return `Prompt ${formatTokens(total)} = ${parts.filter(Boolean).join(" + ")}`;
8
23
  }
9
- export const renderCachedCompactionEntry = (entry, _options, theme) => {
10
- const data = entry.data;
11
- if (!data)
24
+ /** A footnote to the native compaction summary above it, expanding with it. */
25
+ export const renderCachedCompactionEntry = (entry, { expanded }, theme) => {
26
+ const card = entry.data;
27
+ if (!card)
12
28
  return undefined;
13
- const promptTokens = data.input + data.cacheRead + data.cacheWrite;
14
- const percentage = promptTokens > 0 ? ((100 * data.cacheRead) / promptTokens).toFixed(1) : "0.0";
15
- const title = `Cached compaction · ${data.reason === "manual" ? "manual" : "automatic"}`;
16
- const stats = `Cache ${formatTokens(data.cacheRead)}/${formatTokens(promptTokens)} (${percentage}%) · output ${formatTokens(data.output)} · ${(data.durationMs / 1000).toFixed(1)}s`;
17
- return new Text(`${theme.fg("accent", title)}\n${theme.fg("dim", stats)}`, 1, 0);
29
+ const dim = (text) => theme.fg("dim", text);
30
+ const reason = card.reason === "manual" ? "manual" : "auto";
31
+ const head = [
32
+ dim("From cache"),
33
+ expanded || reason === "auto" ? dim(reason) : undefined,
34
+ hitRate(card, theme),
35
+ expanded ? undefined : dim(`↓${formatTokens(card.output)}`),
36
+ dim(formatDuration(card.durationMs)),
37
+ ];
38
+ const lines = [head.filter(Boolean).join(dim(" · "))];
39
+ if (expanded) {
40
+ const breakdown = promptBreakdown(card);
41
+ if (breakdown)
42
+ lines.push(dim(breakdown));
43
+ lines.push(dim(`Output ↓${formatTokens(card.output)}`));
44
+ }
45
+ return new Text(lines.join("\n"), 1, 0);
18
46
  };
19
47
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAY9C,SAAS,YAAY,CAAC,KAAa;IAClC,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAwC,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;IAC1G,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;IACnE,MAAM,UAAU,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACjG,MAAM,KAAK,GAAG,uBAAuB,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACzF,MAAM,KAAK,GAAG,SAAS,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,YAAY,CAAC,YAAY,CAAC,KAAK,UAAU,eAAe,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACrL,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAClF,CAAC,CAAC","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { EntryRenderer } from \"../../core/extensions/types.ts\";\n\nexport interface CachedCompactionCard {\n\treason: \"manual\" | \"threshold\";\n\tcacheRead: number;\n\tinput: number;\n\tcacheWrite: number;\n\toutput: number;\n\tdurationMs: number;\n}\n\nfunction formatTokens(count: number): string {\n\tif (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}m`;\n\tif (count >= 1000) return `${(count / 1000).toFixed(1)}k`;\n\treturn String(count);\n}\n\nexport const renderCachedCompactionEntry: EntryRenderer<CachedCompactionCard> = (entry, _options, theme) => {\n\tconst data = entry.data;\n\tif (!data) return undefined;\n\tconst promptTokens = data.input + data.cacheRead + data.cacheWrite;\n\tconst percentage = promptTokens > 0 ? ((100 * data.cacheRead) / promptTokens).toFixed(1) : \"0.0\";\n\tconst title = `Cached compaction · ${data.reason === \"manual\" ? \"manual\" : \"automatic\"}`;\n\tconst stats = `Cache ${formatTokens(data.cacheRead)}/${formatTokens(promptTokens)} (${percentage}%) · output ${formatTokens(data.output)} · ${(data.durationMs / 1000).toFixed(1)}s`;\n\treturn new Text(`${theme.fg(\"accent\", title)}\\n${theme.fg(\"dim\", stats)}`, 1, 0);\n};\n"]}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/cached-compaction/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\nimport type { EntryRenderer } from \"../../core/extensions/types.ts\";\nimport { cacheHitPercent } from \"../../core/usage-totals.ts\";\nimport { formatTokens } from \"../../modes/interactive/components/footer.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { formatDuration } from \"../../utils/duration.ts\";\n\nexport interface CachedCompactionCard {\n\treason: \"manual\" | \"threshold\";\n\tcacheRead: number;\n\tinput: number;\n\tcacheWrite: number;\n\toutput: number;\n\tdurationMs: number;\n}\n\n/** Cache reuse is why this path exists, so its rate is the one colored segment. */\nfunction hitRate(card: CachedCompactionCard, theme: Theme): string | undefined {\n\tconst percent = cacheHitPercent(card);\n\tif (percent === undefined) return undefined;\n\treturn theme.fg(percent >= 80 ? \"success\" : percent < 50 ? \"warning\" : \"dim\", `CH ${percent.toFixed(1)}%`);\n}\n\n/** The prompt split by how the provider billed it; parts it did not use are left out. */\nfunction promptBreakdown(card: CachedCompactionCard): string | undefined {\n\tconst total = card.input + card.cacheRead + card.cacheWrite;\n\tif (total === 0) return undefined;\n\tconst parts = [\n\t\tcard.cacheRead > 0 ? `R${formatTokens(card.cacheRead)} cached` : undefined,\n\t\tcard.cacheWrite > 0 ? `W${formatTokens(card.cacheWrite)} written` : undefined,\n\t\tcard.input > 0 ? `↑${formatTokens(card.input)} uncached` : undefined,\n\t];\n\treturn `Prompt ${formatTokens(total)} = ${parts.filter(Boolean).join(\" + \")}`;\n}\n\n/** A footnote to the native compaction summary above it, expanding with it. */\nexport const renderCachedCompactionEntry: EntryRenderer<CachedCompactionCard> = (entry, { expanded }, theme) => {\n\tconst card = entry.data;\n\tif (!card) return undefined;\n\tconst dim = (text: string) => theme.fg(\"dim\", text);\n\tconst reason = card.reason === \"manual\" ? \"manual\" : \"auto\";\n\tconst head = [\n\t\tdim(\"From cache\"),\n\t\texpanded || reason === \"auto\" ? dim(reason) : undefined,\n\t\thitRate(card, theme),\n\t\texpanded ? undefined : dim(`↓${formatTokens(card.output)}`),\n\t\tdim(formatDuration(card.durationMs)),\n\t];\n\tconst lines = [head.filter(Boolean).join(dim(\" · \"))];\n\tif (expanded) {\n\t\tconst breakdown = promptBreakdown(card);\n\t\tif (breakdown) lines.push(dim(breakdown));\n\t\tlines.push(dim(`Output ↓${formatTokens(card.output)}`));\n\t}\n\treturn new Text(lines.join(\"\\n\"), 1, 0);\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/extensions/deepwiki/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAA2B,MAAM,aAAa,CAAC;AAW3E,KAAK,gBAAgB,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,cAAc,CAAC;AA0BtF,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAkHD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE1D;AAmBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA+DrH"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/extensions/deepwiki/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAA2B,MAAM,aAAa,CAAC;AAO3E,KAAK,gBAAgB,GAAG,qBAAqB,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAEtF,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AA2ED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE1D;AAmBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8BrH"}
@@ -1,14 +1,9 @@
1
1
  import { PAGE_HEADER_RE } from "./contents.js";
2
- import { fetchWithRetry } from "./http.js";
3
2
  import { normalizeDeepWikiParams } from "./schema.js";
4
- const DEEPWIKI_MCP_URL = "https://mcp.deepwiki.com/mcp";
5
- const MCP_PROTOCOL_VERSION = "2024-11-05";
6
- const REQUEST_TIMEOUT_MS = 45_000;
3
+ import { callDeepWikiTool } from "./transport.js";
7
4
  const CACHE_TTL_MS = 10 * 60_000;
8
5
  /** Long-lived process guard: entries are only otherwise dropped on re-read after expiry. */
9
6
  const MAX_CACHE_ENTRIES = 50;
10
- /** Transient-failure retries (network blips, 5xx, 429). Aborts/timeouts are not retried. */
11
- const MAX_RETRIES = 2;
12
7
  const responseCache = new Map();
13
8
  function toolNameForAction(action) {
14
9
  if (action === "structure")
@@ -38,47 +33,6 @@ function cloneResponse(response, cacheHit) {
38
33
  cacheHit,
39
34
  };
40
35
  }
41
- function truncate(text, maxLength = 500) {
42
- if (text.length <= maxLength)
43
- return text;
44
- return `${text.slice(0, maxLength - 3)}...`;
45
- }
46
- function parseJson(text) {
47
- try {
48
- return JSON.parse(text);
49
- }
50
- catch (error) {
51
- const message = error instanceof Error ? error.message : String(error);
52
- throw new Error(`DeepWiki returned invalid JSON: ${message}`);
53
- }
54
- }
55
- function parseSse(text) {
56
- const blocks = text.split(/\r?\n\r?\n/);
57
- let fallback;
58
- for (const block of blocks) {
59
- const dataLines = block
60
- .split(/\r?\n/)
61
- .filter((line) => line.startsWith("data:"))
62
- .map((line) => line.slice(5).replace(/^ /, ""));
63
- if (dataLines.length === 0)
64
- continue;
65
- const data = dataLines.join("\n").trim();
66
- if (!data || data === "[DONE]")
67
- continue;
68
- const envelope = parseJson(data);
69
- if (envelope.error || envelope.result !== undefined)
70
- return envelope;
71
- fallback = envelope;
72
- }
73
- if (fallback)
74
- return fallback;
75
- throw new Error("DeepWiki returned an empty event stream");
76
- }
77
- function parseEnvelope(text, contentType) {
78
- if (contentType?.includes("text/event-stream"))
79
- return parseSse(text);
80
- return parseJson(text);
81
- }
82
36
  function extractStructuredResult(result) {
83
37
  if (!result.structuredContent || typeof result.structuredContent !== "object")
84
38
  return undefined;
@@ -150,50 +104,24 @@ export async function callDeepWiki(params, signal) {
150
104
  if (cached)
151
105
  responseCache.delete(key);
152
106
  const toolName = toolNameForAction(normalizedParams.action);
153
- const bodyJson = JSON.stringify({
154
- jsonrpc: "2.0",
155
- id: 1,
156
- method: "tools/call",
157
- params: {
158
- name: toolName,
159
- arguments: argumentsForParams(normalizedParams),
160
- },
161
- });
162
- // Timeout + bounded transient retry live in this extension's http.ts; non-retryable
163
- // statuses come back here for the domain-specific HTTP error below.
164
- const { response, text } = await fetchWithRetry(DEEPWIKI_MCP_URL, {
165
- method: "POST",
166
- headers: {
167
- Accept: "application/json, text/event-stream",
168
- "Content-Type": "application/json",
169
- "MCP-Protocol-Version": MCP_PROTOCOL_VERSION,
170
- },
171
- body: bodyJson,
172
- }, { timeoutMs: REQUEST_TIMEOUT_MS, retries: MAX_RETRIES, signal, label: "DeepWiki" });
107
+ const result = await callDeepWikiTool(toolName, argumentsForParams(normalizedParams), signal);
173
108
  signal?.throwIfAborted();
174
- if (!response.ok) {
175
- throw new Error(`DeepWiki HTTP ${response.status}: ${truncate(text)}`);
176
- }
177
- const envelope = parseEnvelope(text, response.headers.get("content-type"));
178
- if (envelope.error) {
179
- throw new Error(envelope.error.message ?? `DeepWiki JSON-RPC error ${envelope.error.code ?? "unknown"}`);
180
- }
181
- const resultText = extractToolText(envelope.result);
109
+ const resultText = extractToolText(result);
182
110
  const pageTitles = extractPageTitles(toolName, resultText);
183
- const result = {
111
+ const response = {
184
112
  toolName,
185
113
  text: resultText,
186
114
  outputLength: resultText.length,
187
115
  ...(pageTitles.length ? { pageTitles } : {}),
188
116
  };
189
117
  signal?.throwIfAborted();
190
- responseCache.set(key, { expiresAt: Date.now() + CACHE_TTL_MS, response: cloneResponse(result, false) });
118
+ responseCache.set(key, { expiresAt: Date.now() + CACHE_TTL_MS, response: cloneResponse(response, false) });
191
119
  while (responseCache.size > MAX_CACHE_ENTRIES) {
192
120
  const oldest = responseCache.keys().next().value;
193
121
  if (oldest === undefined)
194
122
  break;
195
123
  responseCache.delete(oldest);
196
124
  }
197
- return result;
125
+ return response;
198
126
  }
199
127
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/extensions/deepwiki/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { PAGE_HEADER_RE } from \"./contents.ts\";\nimport { fetchWithRetry } from \"./http.ts\";\nimport { type DeepWikiParams, normalizeDeepWikiParams } from \"./schema.ts\";\n\nconst DEEPWIKI_MCP_URL = \"https://mcp.deepwiki.com/mcp\";\nconst MCP_PROTOCOL_VERSION = \"2024-11-05\";\nconst REQUEST_TIMEOUT_MS = 45_000;\nconst CACHE_TTL_MS = 10 * 60_000;\n/** Long-lived process guard: entries are only otherwise dropped on re-read after expiry. */\nconst MAX_CACHE_ENTRIES = 50;\n/** Transient-failure retries (network blips, 5xx, 429). Aborts/timeouts are not retried. */\nconst MAX_RETRIES = 2;\n\ntype DeepWikiToolName = \"read_wiki_structure\" | \"read_wiki_contents\" | \"ask_question\";\n\ninterface JsonRpcErrorPayload {\n\tcode?: number;\n\tmessage?: string;\n\tdata?: unknown;\n}\n\ninterface JsonRpcEnvelope {\n\tjsonrpc?: string;\n\tid?: string | number | null;\n\tresult?: unknown;\n\terror?: JsonRpcErrorPayload;\n}\n\ninterface McpTextContent {\n\ttype: \"text\";\n\ttext: string;\n}\n\ninterface McpToolCallResult {\n\tcontent?: unknown;\n\tstructuredContent?: unknown;\n\tisError?: boolean;\n}\n\nexport interface DeepWikiResponse {\n\ttoolName: DeepWikiToolName;\n\ttext: string;\n\toutputLength: number;\n\tpageTitles?: string[];\n\tcacheHit?: boolean;\n}\n\ninterface CacheEntry {\n\texpiresAt: number;\n\tresponse: DeepWikiResponse;\n}\n\nconst responseCache = new Map<string, CacheEntry>();\n\nfunction toolNameForAction(action: DeepWikiParams[\"action\"]): DeepWikiToolName {\n\tif (action === \"structure\") return \"read_wiki_structure\";\n\tif (action === \"contents\") return \"read_wiki_contents\";\n\treturn \"ask_question\";\n}\n\n// Callers pass params already normalized by callDeepWiki's entry gate; no re-normalization.\nfunction argumentsForParams(params: DeepWikiParams): Record<string, unknown> {\n\tif (params.action === \"question\") {\n\t\tconst question = params.question?.trim();\n\t\tif (!question) throw new Error(\"question is required when action is question\");\n\t\treturn { repoName: params.repoName, question };\n\t}\n\treturn { repoName: params.repoName };\n}\n\nfunction cacheKey(params: DeepWikiParams): string {\n\tconst repos = Array.isArray(params.repoName) ? params.repoName : [params.repoName];\n\treturn JSON.stringify([params.action, repos, params.question ?? \"\"]);\n}\n\nfunction cloneResponse(response: DeepWikiResponse, cacheHit: boolean): DeepWikiResponse {\n\treturn {\n\t\t...response,\n\t\t...(response.pageTitles ? { pageTitles: [...response.pageTitles] } : {}),\n\t\tcacheHit,\n\t};\n}\n\nfunction truncate(text: string, maxLength = 500): string {\n\tif (text.length <= maxLength) return text;\n\treturn `${text.slice(0, maxLength - 3)}...`;\n}\n\nfunction parseJson(text: string): JsonRpcEnvelope {\n\ttry {\n\t\treturn JSON.parse(text) as JsonRpcEnvelope;\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new Error(`DeepWiki returned invalid JSON: ${message}`);\n\t}\n}\n\nfunction parseSse(text: string): JsonRpcEnvelope {\n\tconst blocks = text.split(/\\r?\\n\\r?\\n/);\n\tlet fallback: JsonRpcEnvelope | undefined;\n\tfor (const block of blocks) {\n\t\tconst dataLines = block\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.filter((line) => line.startsWith(\"data:\"))\n\t\t\t.map((line) => line.slice(5).replace(/^ /, \"\"));\n\t\tif (dataLines.length === 0) continue;\n\n\t\tconst data = dataLines.join(\"\\n\").trim();\n\t\tif (!data || data === \"[DONE]\") continue;\n\t\tconst envelope = parseJson(data);\n\t\tif (envelope.error || envelope.result !== undefined) return envelope;\n\t\tfallback = envelope;\n\t}\n\tif (fallback) return fallback;\n\tthrow new Error(\"DeepWiki returned an empty event stream\");\n}\n\nfunction parseEnvelope(text: string, contentType: string | null): JsonRpcEnvelope {\n\tif (contentType?.includes(\"text/event-stream\")) return parseSse(text);\n\treturn parseJson(text);\n}\n\nfunction extractStructuredResult(result: McpToolCallResult): string | undefined {\n\tif (!result.structuredContent || typeof result.structuredContent !== \"object\") return undefined;\n\tconst value = (result.structuredContent as Record<string, unknown>).result;\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction extractContentResult(result: McpToolCallResult): string {\n\tif (!Array.isArray(result.content)) return \"\";\n\treturn result.content\n\t\t.filter((part): part is McpTextContent => {\n\t\t\tif (!part || typeof part !== \"object\") return false;\n\t\t\tconst record = part as Record<string, unknown>;\n\t\t\treturn record.type === \"text\" && typeof record.text === \"string\";\n\t\t})\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\")\n\t\t.trim();\n}\n\nfunction isDeepWikiErrorText(text: string): boolean {\n\tconst trimmed = text.trim();\n\treturn (\n\t\t/^Error fetching wiki for .+?: Repository not found\\./i.test(trimmed) ||\n\t\t/^Error processing question: Repository not found\\./i.test(trimmed)\n\t);\n}\n\nfunction extractToolText(result: unknown): string {\n\tif (!result || typeof result !== \"object\") throw new Error(\"DeepWiki returned no result object\");\n\n\tconst toolResult = result as McpToolCallResult;\n\tconst text = extractStructuredResult(toolResult) ?? extractContentResult(toolResult);\n\tif (!text) throw new Error(\"DeepWiki returned no text content\");\n\tif (toolResult.isError || isDeepWikiErrorText(text)) throw new Error(text);\n\treturn text;\n}\n\nexport function extractStructureSections(text: string): string[] {\n\treturn uniqueTitles(text.split(\"\\n\").map((line) => line.match(/^\\s*-\\s+\\d+\\s+(.+)$/)?.[1]?.trim()));\n}\n\nexport function extractContentPages(text: string): string[] {\n\treturn uniqueTitles(text.split(\"\\n\").map((line) => line.match(PAGE_HEADER_RE)?.[1]?.trim()));\n}\n\nfunction uniqueTitles(titles: Array<string | undefined>): string[] {\n\tconst seen = new Set<string>();\n\tconst result: string[] = [];\n\tfor (const title of titles) {\n\t\tif (!title || seen.has(title)) continue;\n\t\tseen.add(title);\n\t\tresult.push(title);\n\t}\n\treturn result;\n}\n\nfunction extractPageTitles(toolName: DeepWikiToolName, text: string): string[] {\n\tif (toolName === \"read_wiki_structure\") return extractStructureSections(text);\n\tif (toolName === \"read_wiki_contents\") return extractContentPages(text);\n\treturn [];\n}\n\nexport async function callDeepWiki(params: DeepWikiParams, signal: AbortSignal | undefined): Promise<DeepWikiResponse> {\n\tsignal?.throwIfAborted();\n\tconst normalizedParams = normalizeDeepWikiParams(params);\n\tconst key = cacheKey(normalizedParams);\n\tconst cached = responseCache.get(key);\n\tif (cached && cached.expiresAt > Date.now()) {\n\t\treturn cloneResponse(cached.response, true);\n\t}\n\tif (cached) responseCache.delete(key);\n\n\tconst toolName = toolNameForAction(normalizedParams.action);\n\tconst bodyJson = JSON.stringify({\n\t\tjsonrpc: \"2.0\",\n\t\tid: 1,\n\t\tmethod: \"tools/call\",\n\t\tparams: {\n\t\t\tname: toolName,\n\t\t\targuments: argumentsForParams(normalizedParams),\n\t\t},\n\t});\n\n\t// Timeout + bounded transient retry live in this extension's http.ts; non-retryable\n\t// statuses come back here for the domain-specific HTTP error below.\n\tconst { response, text } = await fetchWithRetry(\n\t\tDEEPWIKI_MCP_URL,\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json, text/event-stream\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"MCP-Protocol-Version\": MCP_PROTOCOL_VERSION,\n\t\t\t},\n\t\t\tbody: bodyJson,\n\t\t},\n\t\t{ timeoutMs: REQUEST_TIMEOUT_MS, retries: MAX_RETRIES, signal, label: \"DeepWiki\" },\n\t);\n\tsignal?.throwIfAborted();\n\n\tif (!response.ok) {\n\t\tthrow new Error(`DeepWiki HTTP ${response.status}: ${truncate(text)}`);\n\t}\n\n\tconst envelope = parseEnvelope(text, response.headers.get(\"content-type\"));\n\tif (envelope.error) {\n\t\tthrow new Error(envelope.error.message ?? `DeepWiki JSON-RPC error ${envelope.error.code ?? \"unknown\"}`);\n\t}\n\n\tconst resultText = extractToolText(envelope.result);\n\tconst pageTitles = extractPageTitles(toolName, resultText);\n\tconst result: DeepWikiResponse = {\n\t\ttoolName,\n\t\ttext: resultText,\n\t\toutputLength: resultText.length,\n\t\t...(pageTitles.length ? { pageTitles } : {}),\n\t};\n\tsignal?.throwIfAborted();\n\tresponseCache.set(key, { expiresAt: Date.now() + CACHE_TTL_MS, response: cloneResponse(result, false) });\n\twhile (responseCache.size > MAX_CACHE_ENTRIES) {\n\t\tconst oldest = responseCache.keys().next().value;\n\t\tif (oldest === undefined) break;\n\t\tresponseCache.delete(oldest);\n\t}\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/extensions/deepwiki/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CallToolResult, TextContent } from \"@earendil-works/pi-mcp\";\nimport { PAGE_HEADER_RE } from \"./contents.ts\";\nimport { type DeepWikiParams, normalizeDeepWikiParams } from \"./schema.ts\";\nimport { callDeepWikiTool } from \"./transport.ts\";\n\nconst CACHE_TTL_MS = 10 * 60_000;\n/** Long-lived process guard: entries are only otherwise dropped on re-read after expiry. */\nconst MAX_CACHE_ENTRIES = 50;\n\ntype DeepWikiToolName = \"read_wiki_structure\" | \"read_wiki_contents\" | \"ask_question\";\n\nexport interface DeepWikiResponse {\n\ttoolName: DeepWikiToolName;\n\ttext: string;\n\toutputLength: number;\n\tpageTitles?: string[];\n\tcacheHit?: boolean;\n}\n\ninterface CacheEntry {\n\texpiresAt: number;\n\tresponse: DeepWikiResponse;\n}\n\nconst responseCache = new Map<string, CacheEntry>();\n\nfunction toolNameForAction(action: DeepWikiParams[\"action\"]): DeepWikiToolName {\n\tif (action === \"structure\") return \"read_wiki_structure\";\n\tif (action === \"contents\") return \"read_wiki_contents\";\n\treturn \"ask_question\";\n}\n\n// Callers pass params already normalized by callDeepWiki's entry gate; no re-normalization.\nfunction argumentsForParams(params: DeepWikiParams): Record<string, unknown> {\n\tif (params.action === \"question\") {\n\t\tconst question = params.question?.trim();\n\t\tif (!question) throw new Error(\"question is required when action is question\");\n\t\treturn { repoName: params.repoName, question };\n\t}\n\treturn { repoName: params.repoName };\n}\n\nfunction cacheKey(params: DeepWikiParams): string {\n\tconst repos = Array.isArray(params.repoName) ? params.repoName : [params.repoName];\n\treturn JSON.stringify([params.action, repos, params.question ?? \"\"]);\n}\n\nfunction cloneResponse(response: DeepWikiResponse, cacheHit: boolean): DeepWikiResponse {\n\treturn {\n\t\t...response,\n\t\t...(response.pageTitles ? { pageTitles: [...response.pageTitles] } : {}),\n\t\tcacheHit,\n\t};\n}\n\nfunction extractStructuredResult(result: Partial<CallToolResult>): string | undefined {\n\tif (!result.structuredContent || typeof result.structuredContent !== \"object\") return undefined;\n\tconst value = (result.structuredContent as Record<string, unknown>).result;\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction extractContentResult(result: Partial<CallToolResult>): string {\n\tif (!Array.isArray(result.content)) return \"\";\n\treturn result.content\n\t\t.filter((part): part is TextContent => {\n\t\t\tif (!part || typeof part !== \"object\") return false;\n\t\t\tconst record = part as unknown as Record<string, unknown>;\n\t\t\treturn record.type === \"text\" && typeof record.text === \"string\";\n\t\t})\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\")\n\t\t.trim();\n}\n\nfunction isDeepWikiErrorText(text: string): boolean {\n\tconst trimmed = text.trim();\n\treturn (\n\t\t/^Error fetching wiki for .+?: Repository not found\\./i.test(trimmed) ||\n\t\t/^Error processing question: Repository not found\\./i.test(trimmed)\n\t);\n}\n\nfunction extractToolText(result: unknown): string {\n\tif (!result || typeof result !== \"object\") throw new Error(\"DeepWiki returned no result object\");\n\n\tconst toolResult = result as Partial<CallToolResult>;\n\tconst text = extractStructuredResult(toolResult) ?? extractContentResult(toolResult);\n\tif (!text) throw new Error(\"DeepWiki returned no text content\");\n\tif (toolResult.isError || isDeepWikiErrorText(text)) throw new Error(text);\n\treturn text;\n}\n\nexport function extractStructureSections(text: string): string[] {\n\treturn uniqueTitles(text.split(\"\\n\").map((line) => line.match(/^\\s*-\\s+\\d+\\s+(.+)$/)?.[1]?.trim()));\n}\n\nexport function extractContentPages(text: string): string[] {\n\treturn uniqueTitles(text.split(\"\\n\").map((line) => line.match(PAGE_HEADER_RE)?.[1]?.trim()));\n}\n\nfunction uniqueTitles(titles: Array<string | undefined>): string[] {\n\tconst seen = new Set<string>();\n\tconst result: string[] = [];\n\tfor (const title of titles) {\n\t\tif (!title || seen.has(title)) continue;\n\t\tseen.add(title);\n\t\tresult.push(title);\n\t}\n\treturn result;\n}\n\nfunction extractPageTitles(toolName: DeepWikiToolName, text: string): string[] {\n\tif (toolName === \"read_wiki_structure\") return extractStructureSections(text);\n\tif (toolName === \"read_wiki_contents\") return extractContentPages(text);\n\treturn [];\n}\n\nexport async function callDeepWiki(params: DeepWikiParams, signal: AbortSignal | undefined): Promise<DeepWikiResponse> {\n\tsignal?.throwIfAborted();\n\tconst normalizedParams = normalizeDeepWikiParams(params);\n\tconst key = cacheKey(normalizedParams);\n\tconst cached = responseCache.get(key);\n\tif (cached && cached.expiresAt > Date.now()) {\n\t\treturn cloneResponse(cached.response, true);\n\t}\n\tif (cached) responseCache.delete(key);\n\n\tconst toolName = toolNameForAction(normalizedParams.action);\n\tconst result = await callDeepWikiTool(toolName, argumentsForParams(normalizedParams), signal);\n\tsignal?.throwIfAborted();\n\n\tconst resultText = extractToolText(result);\n\tconst pageTitles = extractPageTitles(toolName, resultText);\n\tconst response: DeepWikiResponse = {\n\t\ttoolName,\n\t\ttext: resultText,\n\t\toutputLength: resultText.length,\n\t\t...(pageTitles.length ? { pageTitles } : {}),\n\t};\n\tsignal?.throwIfAborted();\n\tresponseCache.set(key, { expiresAt: Date.now() + CACHE_TTL_MS, response: cloneResponse(response, false) });\n\twhile (responseCache.size > MAX_CACHE_ENTRIES) {\n\t\tconst oldest = responseCache.keys().next().value;\n\t\tif (oldest === undefined) break;\n\t\tresponseCache.delete(oldest);\n\t}\n\treturn response;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ /** Call a DeepWiki MCP tool and return the raw `result` of the JSON-RPC response. */
2
+ export declare function callDeepWikiTool(toolName: string, args: Record<string, unknown>, signal: AbortSignal | undefined): Promise<unknown>;
3
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/extensions/deepwiki/transport.ts"],"names":[],"mappings":"AA6DA,qFAAqF;AACrF,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,WAAW,GAAG,SAAS,GAC7B,OAAO,CAAC,OAAO,CAAC,CAoClB"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * transport.ts — one stateless MCP `tools/call` round trip to DeepWiki.
3
+ *
4
+ * DeepWiki's public endpoint issues no `Mcp-Session-Id`, so a session-bearing
5
+ * `McpClient` would only add an initialize handshake to every uncached call.
6
+ * The request therefore stays a single POST. Retry and abort semantics come from
7
+ * `management-http`, body bounding from `http-response`, and JSON-RPC validation
8
+ * from `@earendil-works/pi-mcp`. The SSE framing is the only local protocol code
9
+ * because pi-mcp does not export its stream parser.
10
+ */
11
+ import { isJsonRpcResponse, McpError, parseJsonRpcMessage, } from "@earendil-works/pi-mcp";
12
+ import { readResponseTextBounded } from "../../utils/http-response.js";
13
+ import { fetchWithRetry } from "../../utils/management-http.js";
14
+ const DEEPWIKI_MCP_URL = "https://mcp.deepwiki.com/mcp";
15
+ const REQUEST_TIMEOUT_MS = 45_000;
16
+ const RESPONSE_BODY_BYTES = 8 * 1024 * 1024;
17
+ const ERROR_BODY_CHARS = 500;
18
+ /** Pinned, not pi-mcp's latest: this call never negotiates, so it sends the version DeepWiki is known to accept. */
19
+ const PROTOCOL_VERSION = "2024-11-05";
20
+ function parseJson(text) {
21
+ try {
22
+ return JSON.parse(text);
23
+ }
24
+ catch (error) {
25
+ throw new Error(`DeepWiki returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
26
+ }
27
+ }
28
+ function parseJsonRpcResponse(value) {
29
+ const message = parseJsonRpcMessage(value);
30
+ if (!isJsonRpcResponse(message))
31
+ throw new Error("DeepWiki returned a JSON-RPC message that is not a response");
32
+ return message;
33
+ }
34
+ /** The first JSON-RPC response in an SSE body; notifications and `[DONE]` are skipped. */
35
+ function parseSseResponse(text) {
36
+ for (const block of text.split(/\r?\n\r?\n/)) {
37
+ const data = block
38
+ .split(/\r?\n/)
39
+ .filter((line) => line.startsWith("data:"))
40
+ .map((line) => line.slice(5).replace(/^ /, ""))
41
+ .join("\n")
42
+ .trim();
43
+ if (!data || data === "[DONE]")
44
+ continue;
45
+ const message = parseJsonRpcMessage(parseJson(data));
46
+ if (isJsonRpcResponse(message))
47
+ return message;
48
+ }
49
+ throw new Error("DeepWiki returned an empty event stream");
50
+ }
51
+ function truncate(text) {
52
+ return text.length <= ERROR_BODY_CHARS ? text : `${text.slice(0, ERROR_BODY_CHARS - 3)}...`;
53
+ }
54
+ /** Call a DeepWiki MCP tool and return the raw `result` of the JSON-RPC response. */
55
+ export async function callDeepWikiTool(toolName, args, signal) {
56
+ // One budget for connect, retries, and body read; it is terminal, so a timeout is never retried.
57
+ const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);
58
+ const requestSignal = signal ? AbortSignal.any([signal, timeout]) : timeout;
59
+ try {
60
+ const response = await fetchWithRetry(DEEPWIKI_MCP_URL, {
61
+ method: "POST",
62
+ headers: {
63
+ Accept: "application/json, text/event-stream",
64
+ "Content-Type": "application/json",
65
+ "MCP-Protocol-Version": PROTOCOL_VERSION,
66
+ },
67
+ body: JSON.stringify({
68
+ jsonrpc: "2.0",
69
+ id: 1,
70
+ method: "tools/call",
71
+ params: { name: toolName, arguments: args },
72
+ }),
73
+ signal: requestSignal,
74
+ });
75
+ const text = await readResponseTextBounded(response, {
76
+ maxBytes: RESPONSE_BODY_BYTES,
77
+ overflowMessage: `DeepWiki response exceeded ${RESPONSE_BODY_BYTES} bytes`,
78
+ signal: requestSignal,
79
+ });
80
+ if (!response.ok)
81
+ throw new Error(`DeepWiki HTTP ${response.status}: ${truncate(text)}`);
82
+ const isSse = response.headers.get("content-type")?.includes("text/event-stream");
83
+ const message = isSse ? parseSseResponse(text) : parseJsonRpcResponse(parseJson(text));
84
+ if ("error" in message)
85
+ throw new McpError(message.error.code, message.error.message, message.error.data);
86
+ return message.result;
87
+ }
88
+ catch (error) {
89
+ if (signal?.aborted)
90
+ throw new Error("DeepWiki request aborted");
91
+ if (timeout.aborted)
92
+ throw new Error(`DeepWiki request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`);
93
+ throw error;
94
+ }
95
+ }
96
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/extensions/deepwiki/transport.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * transport.ts — one stateless MCP `tools/call` round trip to DeepWiki.\n *\n * DeepWiki's public endpoint issues no `Mcp-Session-Id`, so a session-bearing\n * `McpClient` would only add an initialize handshake to every uncached call.\n * The request therefore stays a single POST. Retry and abort semantics come from\n * `management-http`, body bounding from `http-response`, and JSON-RPC validation\n * from `@earendil-works/pi-mcp`. The SSE framing is the only local protocol code\n * because pi-mcp does not export its stream parser.\n */\nimport {\n\tisJsonRpcResponse,\n\ttype JsonRpcResponse,\n\tMcpError,\n\tparseJsonRpcMessage,\n\ttype SupportedProtocolVersion,\n} from \"@earendil-works/pi-mcp\";\nimport { readResponseTextBounded } from \"../../utils/http-response.ts\";\nimport { fetchWithRetry } from \"../../utils/management-http.ts\";\n\nconst DEEPWIKI_MCP_URL = \"https://mcp.deepwiki.com/mcp\";\nconst REQUEST_TIMEOUT_MS = 45_000;\nconst RESPONSE_BODY_BYTES = 8 * 1024 * 1024;\nconst ERROR_BODY_CHARS = 500;\n/** Pinned, not pi-mcp's latest: this call never negotiates, so it sends the version DeepWiki is known to accept. */\nconst PROTOCOL_VERSION: SupportedProtocolVersion = \"2024-11-05\";\n\nfunction parseJson(text: string): unknown {\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch (error) {\n\t\tthrow new Error(`DeepWiki returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`);\n\t}\n}\n\nfunction parseJsonRpcResponse(value: unknown): JsonRpcResponse {\n\tconst message = parseJsonRpcMessage(value);\n\tif (!isJsonRpcResponse(message)) throw new Error(\"DeepWiki returned a JSON-RPC message that is not a response\");\n\treturn message;\n}\n\n/** The first JSON-RPC response in an SSE body; notifications and `[DONE]` are skipped. */\nfunction parseSseResponse(text: string): JsonRpcResponse {\n\tfor (const block of text.split(/\\r?\\n\\r?\\n/)) {\n\t\tconst data = block\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.filter((line) => line.startsWith(\"data:\"))\n\t\t\t.map((line) => line.slice(5).replace(/^ /, \"\"))\n\t\t\t.join(\"\\n\")\n\t\t\t.trim();\n\t\tif (!data || data === \"[DONE]\") continue;\n\t\tconst message = parseJsonRpcMessage(parseJson(data));\n\t\tif (isJsonRpcResponse(message)) return message;\n\t}\n\tthrow new Error(\"DeepWiki returned an empty event stream\");\n}\n\nfunction truncate(text: string): string {\n\treturn text.length <= ERROR_BODY_CHARS ? text : `${text.slice(0, ERROR_BODY_CHARS - 3)}...`;\n}\n\n/** Call a DeepWiki MCP tool and return the raw `result` of the JSON-RPC response. */\nexport async function callDeepWikiTool(\n\ttoolName: string,\n\targs: Record<string, unknown>,\n\tsignal: AbortSignal | undefined,\n): Promise<unknown> {\n\t// One budget for connect, retries, and body read; it is terminal, so a timeout is never retried.\n\tconst timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);\n\tconst requestSignal = signal ? AbortSignal.any([signal, timeout]) : timeout;\n\ttry {\n\t\tconst response = await fetchWithRetry(DEEPWIKI_MCP_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json, text/event-stream\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"MCP-Protocol-Version\": PROTOCOL_VERSION,\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\tid: 1,\n\t\t\t\tmethod: \"tools/call\",\n\t\t\t\tparams: { name: toolName, arguments: args },\n\t\t\t}),\n\t\t\tsignal: requestSignal,\n\t\t});\n\t\tconst text = await readResponseTextBounded(response, {\n\t\t\tmaxBytes: RESPONSE_BODY_BYTES,\n\t\t\toverflowMessage: `DeepWiki response exceeded ${RESPONSE_BODY_BYTES} bytes`,\n\t\t\tsignal: requestSignal,\n\t\t});\n\t\tif (!response.ok) throw new Error(`DeepWiki HTTP ${response.status}: ${truncate(text)}`);\n\n\t\tconst isSse = response.headers.get(\"content-type\")?.includes(\"text/event-stream\");\n\t\tconst message = isSse ? parseSseResponse(text) : parseJsonRpcResponse(parseJson(text));\n\t\tif (\"error\" in message) throw new McpError(message.error.code, message.error.message, message.error.data);\n\t\treturn message.result;\n\t} catch (error) {\n\t\tif (signal?.aborted) throw new Error(\"DeepWiki request aborted\");\n\t\tif (timeout.aborted) throw new Error(`DeepWiki request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`);\n\t\tthrow error;\n\t}\n}\n"]}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import "../keybindings.ts";
9
9
  import { type CatalogEntry } from "../catalog.ts";
10
- import type { EditorHost, EditorPane, ModelHandle } from "./pane.ts";
10
+ import type { EditorPane, ModelHandle, ProviderPaneHost } from "./pane.ts";
11
11
  import { type ScrollWindowInfo } from "./value-row.ts";
12
12
  export declare class BuiltinCandidatesPane implements EditorPane {
13
13
  readonly crumb = "Use Built-in Data";
@@ -17,7 +17,7 @@ export declare class BuiltinCandidatesPane implements EditorPane {
17
17
  private focused;
18
18
  private readonly host;
19
19
  private readonly model;
20
- constructor(host: EditorHost, model: ModelHandle);
20
+ constructor(host: ProviderPaneHost, model: ModelHandle);
21
21
  private candidates;
22
22
  render(width: number): string[];
23
23
  scrollWindow(): ScrollWindowInfo;
@@ -40,7 +40,7 @@ export declare class BuiltinPreviewPane implements EditorPane {
40
40
  private readonly host;
41
41
  private readonly model;
42
42
  private readonly reference;
43
- constructor(host: EditorHost, model: ModelHandle, reference: CatalogEntry);
43
+ constructor(host: ProviderPaneHost, model: ModelHandle, reference: CatalogEntry);
44
44
  private rowCount;
45
45
  render(width: number): string[];
46
46
  scrollWindow(): ScrollWindowInfo;
@@ -1 +1 @@
1
- {"version":3,"file":"builtin-data.d.ts","sourceRoot":"","sources":["../../../../src/extensions/provider/ui/builtin-data.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,mBAAmB,CAAC;AAI3B,OAAO,EAAE,KAAK,YAAY,EAA6D,MAAM,eAAe,CAAC;AAI7G,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAmC,KAAK,gBAAgB,EAAe,MAAM,gBAAgB,CAAC;AAOrG,qBAAa,qBAAsB,YAAW,UAAU;IACvD,QAAQ,CAAC,KAAK,uBAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;gBACxB,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW;IAYhD,OAAO,CAAC,UAAU;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA4B/B,YAAY,IAAI,gBAAgB;IAKhC,OAAO,CAAC,WAAW;IAMnB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAwB/B,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKlC,SAAS,IAAI,OAAO;IAIpB,KAAK,IAAI,MAAM;CAQf;AAED,qBAAa,kBAAmB,YAAW,UAAU;IACpD,QAAQ,CAAC,KAAK,sCAAiC;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAC7B,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY;IAYzE,OAAO,CAAC,QAAQ;IAIhB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAsC/B,YAAY,IAAI,gBAAgB;IAahC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAwC/B,OAAO,CAAC,KAAK;IA+Bb,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIlC,KAAK,IAAI,MAAM;CAOf"}
1
+ {"version":3,"file":"builtin-data.d.ts","sourceRoot":"","sources":["../../../../src/extensions/provider/ui/builtin-data.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,mBAAmB,CAAC;AAI3B,OAAO,EAAE,KAAK,YAAY,EAA6D,MAAM,eAAe,CAAC;AAI7G,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAmC,KAAK,gBAAgB,EAAe,MAAM,gBAAgB,CAAC;AAOrG,qBAAa,qBAAsB,YAAW,UAAU;IACvD,QAAQ,CAAC,KAAK,uBAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;gBACxB,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW;IAYtD,OAAO,CAAC,UAAU;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA4B/B,YAAY,IAAI,gBAAgB;IAKhC,OAAO,CAAC,WAAW;IAMnB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAwB/B,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKlC,SAAS,IAAI,OAAO;IAIpB,KAAK,IAAI,MAAM;CAQf;AAED,qBAAa,kBAAmB,YAAW,UAAU;IACpD,QAAQ,CAAC,KAAK,sCAAiC;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAC7B,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY;IAY/E,OAAO,CAAC,QAAQ;IAIhB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAsC/B,YAAY,IAAI,gBAAgB;IAahC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAwC/B,OAAO,CAAC,KAAK;IA+Bb,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIlC,KAAK,IAAI,MAAM;CAOf"}