@herbertgao/pi-extensions 2026.8.8 → 2026.8.10

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 (266) hide show
  1. package/README.md +6 -3
  2. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +24 -0
  3. package/node_modules/@czottmann/pi-automode/README.md +78 -112
  4. package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +18 -14
  5. package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +44 -0
  6. package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +5 -0
  7. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +198 -104
  8. package/node_modules/@czottmann/pi-automode/docs/configuration.md +155 -0
  9. package/node_modules/@czottmann/pi-automode/docs/defaults.md +55 -14
  10. package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +90 -0
  11. package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +61 -26
  12. package/node_modules/@czottmann/pi-automode/examples/automode.local.json +5 -0
  13. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +172 -18
  14. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +127 -30
  15. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +3 -0
  16. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +273 -31
  17. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +60 -5
  18. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +92 -8
  19. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +203 -13
  20. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +1 -0
  21. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +11 -0
  22. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +9 -1
  23. package/node_modules/@czottmann/pi-automode/package.json +9 -2
  24. package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +63 -0
  25. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +3 -3
  26. package/node_modules/@herbertgao/pi-cc-extensions/README.md +3 -3
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +8 -3
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +56 -29
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +15 -13
  31. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  32. package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +29 -0
  33. package/node_modules/@herbertgao/pi-handoff/README.md +15 -18
  34. package/node_modules/@herbertgao/pi-handoff/package.json +11 -4
  35. package/node_modules/@herbertgao/pi-handoff/src/complete-text.ts +33 -0
  36. package/node_modules/@herbertgao/pi-handoff/src/index.ts +127 -232
  37. package/node_modules/@herbertgao/pi-handoff/src/session-query.ts +15 -30
  38. package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +14 -0
  39. package/node_modules/@herbertgao/pi-mermaid-open/README.md +21 -4
  40. package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +11 -0
  41. package/node_modules/@herbertgao/pi-mermaid-open/herdr-plugin/viewer.mjs +305 -0
  42. package/node_modules/@herbertgao/pi-mermaid-open/package.json +15 -4
  43. package/node_modules/@herbertgao/pi-mermaid-open/src/index.ts +351 -101
  44. package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +12 -0
  45. package/node_modules/@herbertgao/pi-preferred-thinking/README.md +30 -14
  46. package/node_modules/@herbertgao/pi-preferred-thinking/package.json +7 -4
  47. package/node_modules/@herbertgao/pi-preferred-thinking/src/index.ts +140 -85
  48. package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +12 -0
  49. package/node_modules/@herbertgao/pi-recap/README.md +5 -3
  50. package/node_modules/@herbertgao/pi-recap/package.json +9 -3
  51. package/node_modules/@herbertgao/pi-recap/src/index.ts +3 -7
  52. package/node_modules/@herbertgao/pi-recap/src/model-picker.ts +6 -19
  53. package/node_modules/@herbertgao/pi-recap/src/models.ts +9 -21
  54. package/node_modules/@herbertgao/pi-recap/src/tui.ts +1 -1
  55. package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +49 -0
  56. package/node_modules/@herbertgao/pi-rename/README.md +13 -11
  57. package/node_modules/@herbertgao/pi-rename/package.json +13 -3
  58. package/node_modules/@herbertgao/pi-rename/src/index.ts +135 -59
  59. package/node_modules/@herbertgao/pi-rename/src/models.ts +5 -13
  60. package/node_modules/@herbertgao/pi-rename/src/naming.ts +2 -6
  61. package/node_modules/@herbertgao/pi-stash/package.json +3 -3
  62. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
  63. package/node_modules/@herbertgao/pi-subagents/README.md +16 -3
  64. package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
  65. package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +15 -4
  66. package/node_modules/@herbertgao/pi-subagents/src/index.ts +16 -0
  67. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +5 -1
  68. package/node_modules/pi-web-access/CHANGELOG.md +13 -0
  69. package/node_modules/pi-web-access/README.md +2 -2
  70. package/node_modules/pi-web-access/chrome-cookies.ts +12 -7
  71. package/node_modules/pi-web-access/gemini-search.ts +28 -10
  72. package/node_modules/pi-web-access/index.ts +24 -10
  73. package/node_modules/pi-web-access/package.json +1 -1
  74. package/node_modules/resume-from/LICENSE +21 -0
  75. package/node_modules/resume-from/README.md +161 -0
  76. package/node_modules/resume-from/dist/adapters/claude-code/adapter.d.ts +25 -0
  77. package/node_modules/resume-from/dist/adapters/claude-code/adapter.js +60 -0
  78. package/node_modules/resume-from/dist/adapters/claude-code/contract.d.ts +8 -0
  79. package/node_modules/resume-from/dist/adapters/claude-code/contract.js +4 -0
  80. package/node_modules/resume-from/dist/adapters/claude-code/entries.d.ts +30 -0
  81. package/node_modules/resume-from/dist/adapters/claude-code/entries.js +107 -0
  82. package/node_modules/resume-from/dist/adapters/claude-code/index.d.ts +3 -0
  83. package/node_modules/resume-from/dist/adapters/claude-code/index.js +2 -0
  84. package/node_modules/resume-from/dist/adapters/claude-code/layout.d.ts +29 -0
  85. package/node_modules/resume-from/dist/adapters/claude-code/layout.js +80 -0
  86. package/node_modules/resume-from/dist/adapters/claude-code/readback.d.ts +9 -0
  87. package/node_modules/resume-from/dist/adapters/claude-code/readback.js +39 -0
  88. package/node_modules/resume-from/dist/adapters/claude-code/reader.d.ts +37 -0
  89. package/node_modules/resume-from/dist/adapters/claude-code/reader.js +415 -0
  90. package/node_modules/resume-from/dist/adapters/claude-code/redaction.d.ts +26 -0
  91. package/node_modules/resume-from/dist/adapters/claude-code/redaction.js +132 -0
  92. package/node_modules/resume-from/dist/adapters/claude-code/validation.d.ts +4 -0
  93. package/node_modules/resume-from/dist/adapters/claude-code/validation.js +39 -0
  94. package/node_modules/resume-from/dist/adapters/claude-code/writer.d.ts +23 -0
  95. package/node_modules/resume-from/dist/adapters/claude-code/writer.js +306 -0
  96. package/node_modules/resume-from/dist/adapters/codex/contract.d.ts +15 -0
  97. package/node_modules/resume-from/dist/adapters/codex/contract.js +4 -0
  98. package/node_modules/resume-from/dist/adapters/codex/index.d.ts +6 -0
  99. package/node_modules/resume-from/dist/adapters/codex/index.js +44 -0
  100. package/node_modules/resume-from/dist/adapters/codex/read.d.ts +28 -0
  101. package/node_modules/resume-from/dist/adapters/codex/read.js +270 -0
  102. package/node_modules/resume-from/dist/adapters/codex/readback.d.ts +9 -0
  103. package/node_modules/resume-from/dist/adapters/codex/readback.js +47 -0
  104. package/node_modules/resume-from/dist/adapters/codex/redaction.d.ts +26 -0
  105. package/node_modules/resume-from/dist/adapters/codex/redaction.js +132 -0
  106. package/node_modules/resume-from/dist/adapters/codex/rollout.d.ts +75 -0
  107. package/node_modules/resume-from/dist/adapters/codex/rollout.js +185 -0
  108. package/node_modules/resume-from/dist/adapters/codex/validation.d.ts +7 -0
  109. package/node_modules/resume-from/dist/adapters/codex/validation.js +78 -0
  110. package/node_modules/resume-from/dist/adapters/codex/write.d.ts +17 -0
  111. package/node_modules/resume-from/dist/adapters/codex/write.js +141 -0
  112. package/node_modules/resume-from/dist/adapters/contract.d.ts +74 -0
  113. package/node_modules/resume-from/dist/adapters/contract.js +4 -0
  114. package/node_modules/resume-from/dist/adapters/pi/adapter.d.ts +15 -0
  115. package/node_modules/resume-from/dist/adapters/pi/adapter.js +209 -0
  116. package/node_modules/resume-from/dist/adapters/pi/contract.d.ts +24 -0
  117. package/node_modules/resume-from/dist/adapters/pi/contract.js +4 -0
  118. package/node_modules/resume-from/dist/adapters/pi/format.d.ts +162 -0
  119. package/node_modules/resume-from/dist/adapters/pi/format.js +223 -0
  120. package/node_modules/resume-from/dist/adapters/pi/index.d.ts +7 -0
  121. package/node_modules/resume-from/dist/adapters/pi/index.js +10 -0
  122. package/node_modules/resume-from/dist/adapters/pi/parse.d.ts +41 -0
  123. package/node_modules/resume-from/dist/adapters/pi/parse.js +371 -0
  124. package/node_modules/resume-from/dist/adapters/pi/redaction.d.ts +26 -0
  125. package/node_modules/resume-from/dist/adapters/pi/redaction.js +132 -0
  126. package/node_modules/resume-from/dist/adapters/pi/serialize.d.ts +22 -0
  127. package/node_modules/resume-from/dist/adapters/pi/serialize.js +87 -0
  128. package/node_modules/resume-from/dist/adapters/pi/validate.d.ts +14 -0
  129. package/node_modules/resume-from/dist/adapters/pi/validate.js +134 -0
  130. package/node_modules/resume-from/dist/bin.d.ts +35 -0
  131. package/node_modules/resume-from/dist/bin.js +135 -0
  132. package/node_modules/resume-from/dist/contract.d.ts +10 -0
  133. package/node_modules/resume-from/dist/contract.js +4 -0
  134. package/node_modules/resume-from/dist/host/agents.d.ts +29 -0
  135. package/node_modules/resume-from/dist/host/agents.js +20 -0
  136. package/node_modules/resume-from/dist/host/cli/args.d.ts +21 -0
  137. package/node_modules/resume-from/dist/host/cli/args.js +187 -0
  138. package/node_modules/resume-from/dist/host/cli/contract.d.ts +27 -0
  139. package/node_modules/resume-from/dist/host/cli/contract.js +4 -0
  140. package/node_modules/resume-from/dist/host/cli/index.d.ts +2 -0
  141. package/node_modules/resume-from/dist/host/cli/index.js +1 -0
  142. package/node_modules/resume-from/dist/host/cli/presentation.d.ts +2 -0
  143. package/node_modules/resume-from/dist/host/cli/presentation.js +11 -0
  144. package/node_modules/resume-from/dist/host/cli/render.d.ts +3 -0
  145. package/node_modules/resume-from/dist/host/cli/render.js +70 -0
  146. package/node_modules/resume-from/dist/host/cli/runner.d.ts +8 -0
  147. package/node_modules/resume-from/dist/host/cli/runner.js +125 -0
  148. package/node_modules/resume-from/dist/host/contract.d.ts +42 -0
  149. package/node_modules/resume-from/dist/host/contract.js +4 -0
  150. package/node_modules/resume-from/dist/host/entry.d.ts +52 -0
  151. package/node_modules/resume-from/dist/host/entry.js +91 -0
  152. package/node_modules/resume-from/dist/host/index.d.ts +11 -0
  153. package/node_modules/resume-from/dist/host/index.js +10 -0
  154. package/node_modules/resume-from/dist/host/pi-extension/command.d.ts +18 -0
  155. package/node_modules/resume-from/dist/host/pi-extension/command.js +103 -0
  156. package/node_modules/resume-from/dist/host/pi-extension/contract.d.ts +34 -0
  157. package/node_modules/resume-from/dist/host/pi-extension/contract.js +4 -0
  158. package/node_modules/resume-from/dist/host/pi-extension/index.d.ts +6 -0
  159. package/node_modules/resume-from/dist/host/pi-extension/index.js +4 -0
  160. package/node_modules/resume-from/dist/host/pi-extension/picker.d.ts +16 -0
  161. package/node_modules/resume-from/dist/host/pi-extension/picker.js +35 -0
  162. package/node_modules/resume-from/dist/host/pi-extension/presentation.d.ts +2 -0
  163. package/node_modules/resume-from/dist/host/pi-extension/presentation.js +11 -0
  164. package/node_modules/resume-from/dist/host/pi-extension/register.d.ts +25 -0
  165. package/node_modules/resume-from/dist/host/pi-extension/register.js +11 -0
  166. package/node_modules/resume-from/dist/host/pi-extension/ui.d.ts +20 -0
  167. package/node_modules/resume-from/dist/host/pi-extension/ui.js +1 -0
  168. package/node_modules/resume-from/dist/host/profile.d.ts +8 -0
  169. package/node_modules/resume-from/dist/host/profile.js +31 -0
  170. package/node_modules/resume-from/dist/host/registry.d.ts +8 -0
  171. package/node_modules/resume-from/dist/host/registry.js +33 -0
  172. package/node_modules/resume-from/dist/host/wiring.d.ts +41 -0
  173. package/node_modules/resume-from/dist/host/wiring.js +67 -0
  174. package/node_modules/resume-from/dist/import/confirmation.d.ts +6 -0
  175. package/node_modules/resume-from/dist/import/confirmation.js +27 -0
  176. package/node_modules/resume-from/dist/import/contract.d.ts +41 -0
  177. package/node_modules/resume-from/dist/import/contract.js +4 -0
  178. package/node_modules/resume-from/dist/import/discovery/contract.d.ts +58 -0
  179. package/node_modules/resume-from/dist/import/discovery/contract.js +4 -0
  180. package/node_modules/resume-from/dist/import/discovery/errors.d.ts +9 -0
  181. package/node_modules/resume-from/dist/import/discovery/errors.js +12 -0
  182. package/node_modules/resume-from/dist/import/discovery/finder.d.ts +10 -0
  183. package/node_modules/resume-from/dist/import/discovery/finder.js +129 -0
  184. package/node_modules/resume-from/dist/import/discovery/homes.d.ts +23 -0
  185. package/node_modules/resume-from/dist/import/discovery/homes.js +83 -0
  186. package/node_modules/resume-from/dist/import/discovery/index.d.ts +2 -0
  187. package/node_modules/resume-from/dist/import/discovery/index.js +2 -0
  188. package/node_modules/resume-from/dist/import/discovery/ordering.d.ts +3 -0
  189. package/node_modules/resume-from/dist/import/discovery/ordering.js +21 -0
  190. package/node_modules/resume-from/dist/import/errors.d.ts +22 -0
  191. package/node_modules/resume-from/dist/import/errors.js +20 -0
  192. package/node_modules/resume-from/dist/import/index.d.ts +3 -0
  193. package/node_modules/resume-from/dist/import/index.js +5 -0
  194. package/node_modules/resume-from/dist/import/landing/contract.d.ts +44 -0
  195. package/node_modules/resume-from/dist/import/landing/contract.js +4 -0
  196. package/node_modules/resume-from/dist/import/landing/errors.d.ts +15 -0
  197. package/node_modules/resume-from/dist/import/landing/errors.js +15 -0
  198. package/node_modules/resume-from/dist/import/landing/handover.d.ts +5 -0
  199. package/node_modules/resume-from/dist/import/landing/handover.js +12 -0
  200. package/node_modules/resume-from/dist/import/landing/index.d.ts +4 -0
  201. package/node_modules/resume-from/dist/import/landing/index.js +4 -0
  202. package/node_modules/resume-from/dist/import/landing/lander.d.ts +7 -0
  203. package/node_modules/resume-from/dist/import/landing/lander.js +133 -0
  204. package/node_modules/resume-from/dist/import/landing/marker.d.ts +9 -0
  205. package/node_modules/resume-from/dist/import/landing/marker.js +46 -0
  206. package/node_modules/resume-from/dist/import/pipeline.d.ts +17 -0
  207. package/node_modules/resume-from/dist/import/pipeline.js +134 -0
  208. package/node_modules/resume-from/dist/import/preview/builder.d.ts +6 -0
  209. package/node_modules/resume-from/dist/import/preview/builder.js +76 -0
  210. package/node_modules/resume-from/dist/import/preview/contract.d.ts +39 -0
  211. package/node_modules/resume-from/dist/import/preview/contract.js +4 -0
  212. package/node_modules/resume-from/dist/import/preview/format.d.ts +19 -0
  213. package/node_modules/resume-from/dist/import/preview/format.js +45 -0
  214. package/node_modules/resume-from/dist/import/preview/index.d.ts +2 -0
  215. package/node_modules/resume-from/dist/import/preview/index.js +1 -0
  216. package/node_modules/resume-from/dist/import/preview/warnings.d.ts +11 -0
  217. package/node_modules/resume-from/dist/import/preview/warnings.js +80 -0
  218. package/node_modules/resume-from/dist/import/transfer/contract.d.ts +48 -0
  219. package/node_modules/resume-from/dist/import/transfer/contract.js +4 -0
  220. package/node_modules/resume-from/dist/import/transfer/index.d.ts +2 -0
  221. package/node_modules/resume-from/dist/import/transfer/index.js +1 -0
  222. package/node_modules/resume-from/dist/import/transfer/rules.d.ts +3 -0
  223. package/node_modules/resume-from/dist/import/transfer/rules.js +228 -0
  224. package/node_modules/resume-from/dist/import/wiring.d.ts +24 -0
  225. package/node_modules/resume-from/dist/import/wiring.js +27 -0
  226. package/node_modules/resume-from/dist/index.d.ts +36 -0
  227. package/node_modules/resume-from/dist/index.js +36 -0
  228. package/node_modules/resume-from/dist/platform/config/contract.d.ts +35 -0
  229. package/node_modules/resume-from/dist/platform/config/contract.js +4 -0
  230. package/node_modules/resume-from/dist/platform/config/defaults.d.ts +16 -0
  231. package/node_modules/resume-from/dist/platform/config/defaults.js +22 -0
  232. package/node_modules/resume-from/dist/platform/config/errors.d.ts +9 -0
  233. package/node_modules/resume-from/dist/platform/config/errors.js +12 -0
  234. package/node_modules/resume-from/dist/platform/config/index.d.ts +5 -0
  235. package/node_modules/resume-from/dist/platform/config/index.js +6 -0
  236. package/node_modules/resume-from/dist/platform/config/loader.d.ts +10 -0
  237. package/node_modules/resume-from/dist/platform/config/loader.js +47 -0
  238. package/node_modules/resume-from/dist/platform/config/paths.d.ts +13 -0
  239. package/node_modules/resume-from/dist/platform/config/paths.js +37 -0
  240. package/node_modules/resume-from/dist/platform/config/validate.d.ts +9 -0
  241. package/node_modules/resume-from/dist/platform/config/validate.js +117 -0
  242. package/node_modules/resume-from/dist/platform/repo/contract.d.ts +30 -0
  243. package/node_modules/resume-from/dist/platform/repo/contract.js +4 -0
  244. package/node_modules/resume-from/dist/platform/repo/git.d.ts +21 -0
  245. package/node_modules/resume-from/dist/platform/repo/git.js +74 -0
  246. package/node_modules/resume-from/dist/platform/repo/index.d.ts +2 -0
  247. package/node_modules/resume-from/dist/platform/repo/index.js +1 -0
  248. package/node_modules/resume-from/dist/platform/repo/reader.d.ts +8 -0
  249. package/node_modules/resume-from/dist/platform/repo/reader.js +130 -0
  250. package/node_modules/resume-from/dist/platform/store/contract.d.ts +31 -0
  251. package/node_modules/resume-from/dist/platform/store/contract.js +4 -0
  252. package/node_modules/resume-from/dist/platform/store/file-committer.d.ts +3 -0
  253. package/node_modules/resume-from/dist/platform/store/file-committer.js +391 -0
  254. package/node_modules/resume-from/dist/platform/store/index.d.ts +2 -0
  255. package/node_modules/resume-from/dist/platform/store/index.js +2 -0
  256. package/node_modules/resume-from/dist/platform/tokens/contract.d.ts +12 -0
  257. package/node_modules/resume-from/dist/platform/tokens/contract.js +4 -0
  258. package/node_modules/resume-from/dist/platform/tokens/estimator.d.ts +12 -0
  259. package/node_modules/resume-from/dist/platform/tokens/estimator.js +111 -0
  260. package/node_modules/resume-from/dist/platform/tokens/index.d.ts +2 -0
  261. package/node_modules/resume-from/dist/platform/tokens/index.js +1 -0
  262. package/node_modules/resume-from/dist/session/contract.d.ts +109 -0
  263. package/node_modules/resume-from/dist/session/contract.js +4 -0
  264. package/node_modules/resume-from/package.json +80 -0
  265. package/node_modules/resume-from/shims/pi/extensions/resume-from.js +118 -0
  266. package/package.json +19 -14
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The composition root. It builds everything and drives nothing: `createHost` loads the
3
+ * configuration, the platform services and the agent list, and the two starts below run the one
4
+ * entry point the target agent's declared capability names.
5
+ */
6
+ export { AGENTS } from "./agents.js";
7
+ export { activatePiExtension, entryPointFor, runCommandBinary, } from "./entry.js";
8
+ export { createTargetProfileBuilder } from "./profile.js";
9
+ export { createAgentRegistry } from "./registry.js";
10
+ export { createHost } from "./wiring.js";
@@ -0,0 +1,18 @@
1
+ import type { PiResumeFromCommand, SessionPicker } from "./contract.js";
2
+ import type { PiUi } from "./ui.js";
3
+ /** The name Pi shows for the command (FR-7). */
4
+ export declare const RESUME_FROM_COMMAND_NAME = "resume-from";
5
+ export interface ResumeFromDeps {
6
+ /** The picker opened when no argument names a session (FR-9). */
7
+ picker: SessionPicker;
8
+ /** How lines reach the user and how a confirmation is taken. */
9
+ ui: PiUi;
10
+ /**
11
+ * The context window of the Pi the user is in, in tokens. Required, not
12
+ * defaulted: this module holds no capability knowledge, so the size comes
13
+ * from the composition root that builds the command.
14
+ */
15
+ windowTokens: number;
16
+ }
17
+ /** Builds the /resume-from command. `run` is the only path to the switch (C-10). */
18
+ export declare function createResumeFromCommand(deps: ResumeFromDeps): PiResumeFromCommand;
@@ -0,0 +1,103 @@
1
+ /** The name Pi shows for the command (FR-7). */
2
+ export const RESUME_FROM_COMMAND_NAME = "resume-from";
3
+ const CONFIRM_QUESTION = "Import this session? (y/N)";
4
+ const CANCELLED_LINE = "Cancelled. Nothing was imported.";
5
+ const HELP_ARGUMENTS = new Set(["help", "-h", "--help"]);
6
+ const HELP_LINES = [
7
+ `Usage: /${RESUME_FROM_COMMAND_NAME} [<session-id> | <file-path>]`,
8
+ "No argument opens the session selector.",
9
+ "<session-id> previews the matching session.",
10
+ "<file-path> previews an absolute or relative session file.",
11
+ "Pi asks for confirmation before importing anything.",
12
+ ];
13
+ const USAGE_LINE = HELP_LINES[0] ?? `Usage: /${RESUME_FROM_COMMAND_NAME}`;
14
+ const BLOCKED_FALLBACK = "The import is blocked.";
15
+ /** Builds the /resume-from command. `run` is the only path to the switch (C-10). */
16
+ export function createResumeFromCommand(deps) {
17
+ return {
18
+ run: (ctx, args, pipeline) => runResumeFrom(deps, ctx, args, pipeline),
19
+ };
20
+ }
21
+ async function runResumeFrom(deps, ctx, args, pipeline) {
22
+ const scope = {
23
+ repoRoot: ctx.cwd,
24
+ target: targetOf(deps, ctx),
25
+ onlyAgent: null,
26
+ onlyHome: null,
27
+ };
28
+ const selection = await resolveSelection(deps, args, pipeline, scope);
29
+ if (selection === null)
30
+ return;
31
+ const request = { ...scope, selection };
32
+ const report = await pipeline.preview(request);
33
+ deps.ui.show(report.lines); // Verbatim and unreordered (FR-21).
34
+ if (report.blocked) {
35
+ deps.ui.show([report.blockedReason ?? BLOCKED_FALLBACK]);
36
+ return; // A blocked preview is never offered for confirmation (FR-33).
37
+ }
38
+ if ((await deps.ui.confirm(CONFIRM_QUESTION)) !== "selected") {
39
+ deps.ui.show([CANCELLED_LINE]);
40
+ return; // Nothing is written before the user confirms (FR-16, FR-20).
41
+ }
42
+ // Pi's own context is the runtime handle the Pi adapter switches with (FR-44).
43
+ const landing = await pipeline.commit(request, ctx, report.confirmationToken);
44
+ if (!landing.switched)
45
+ present(deps.ui, landing);
46
+ }
47
+ /** The import target is always the Pi home the user is in (FR-1, FR-2). */
48
+ function targetOf(deps, ctx) {
49
+ return { agent: "pi", home: ctx.home, windowTokens: deps.windowTokens };
50
+ }
51
+ /** The selection, or null when the user cancelled or there was nothing to pick. */
52
+ async function resolveSelection(deps, args, pipeline, scope) {
53
+ const given = args.filter((argument) => argument.trim().length > 0);
54
+ if (given.length === 1 && HELP_ARGUMENTS.has(given[0] ?? "")) {
55
+ deps.ui.show(HELP_LINES);
56
+ return null;
57
+ }
58
+ if (given.length > 1) {
59
+ deps.ui.show([USAGE_LINE]);
60
+ return null;
61
+ }
62
+ const [only] = given;
63
+ if (only !== undefined)
64
+ return parseArgument(only); // An argument skips the picker (FR-12).
65
+ const listing = await pipeline.list(scope);
66
+ if (listing.failures.length > 0) {
67
+ deps.ui.show(listing.failures.map(formatFailure)); // Skipped homes are never silent.
68
+ }
69
+ if (listing.rows.length === 0) {
70
+ deps.ui.show([`No sessions to import for ${scope.repoRoot}.`]);
71
+ return null; // A picker over nothing is a trap.
72
+ }
73
+ const picked = await deps.picker.pick(listing);
74
+ if (picked.choice !== "selected" || picked.selected === null) {
75
+ deps.ui.show([CANCELLED_LINE]);
76
+ return null;
77
+ }
78
+ // The file path, not the session ID: an ID is unique only inside one home and
79
+ // a SelectionInput carries no home.
80
+ return { by: "file-path", path: picked.selected.filePath };
81
+ }
82
+ /** A session ID or a file path (FR-12). Resolving the path is the pipeline's job. */
83
+ function parseArgument(argument) {
84
+ return argument.includes("/") || argument.includes("\\")
85
+ ? { by: "file-path", path: argument }
86
+ : { by: "session-id", id: argument };
87
+ }
88
+ function formatFailure(failure) {
89
+ return `Skipped ${failure.agent} home ${failure.home}: ${failure.message}`;
90
+ }
91
+ /**
92
+ * Shows the marker and handover when the switch did not happen (FR-45, FR-47).
93
+ * A successful switch invalidates the command context; the package shim renders
94
+ * the persisted provenance marker as a transcript entry in the replacement session instead.
95
+ */
96
+ function present(ui, landing) {
97
+ ui.show(landing.marker.lines);
98
+ if (landing.handover !== null)
99
+ ui.show(formatHandover(landing.handover));
100
+ }
101
+ function formatHandover(handover) {
102
+ return [`The session is ready: ${handover.sessionId}`, `Open it with: ${handover.command}`];
103
+ }
@@ -0,0 +1,34 @@
1
+ import type { PiSwitchContext, PiSwitchOptions, PiSwitchResult } from "../../adapters/pi/contract.js";
2
+ export type { PiSwitchContext, PiSwitchOptions, PiSwitchResult };
3
+ import type { AgentRuntime, HandoverInstruction, HomeFailure, ImportPipeline, ImportRequest, LandingResult, Listing, ListRequest, PreviewReport, PreviewWarning, SelectionError, SelectionInput, WarningKind } from "../../import/contract.js";
4
+ export type { AgentRuntime, HandoverInstruction, HomeFailure, ImportPipeline, ImportRequest, LandingResult, Listing, ListRequest, PreviewReport, PreviewWarning, SelectionError, SelectionInput, WarningKind, };
5
+ import type { AgentId, HomePath, ProvenanceMarker, SessionDescriptor, SessionId, SessionRef, TargetProfile } from "../../session/contract.js";
6
+ export type { AgentId, HomePath, ProvenanceMarker, SessionDescriptor, SessionId, SessionRef, TargetProfile, };
7
+ /** What the user did at the picker or the confirmation. */
8
+ export type UserChoice = "selected" | "cancelled";
9
+ /** The picker over the listing (FR-9). */
10
+ export interface SessionPicker {
11
+ /** Resolves with the chosen row, or with "cancelled" when the user escaped. */
12
+ pick(listing: Listing): Promise<PickResult>;
13
+ }
14
+ /** The result of one picker interaction. */
15
+ export interface PickResult {
16
+ choice: UserChoice;
17
+ /** Set when choice is "selected". */
18
+ selected: SessionDescriptor | null;
19
+ }
20
+ /** Pi's command context, as this module needs it. */
21
+ export interface PiCommandContext extends PiSwitchContext {
22
+ /** The directory Pi is running in. Used to find the repository (FR-13). */
23
+ cwd: string;
24
+ /** The Pi home the user is running, which is the import target (FR-1, FR-2). */
25
+ home: HomePath;
26
+ }
27
+ /** The /resume-from command inside Pi (FR-7, FR-9, FR-44). */
28
+ export interface PiResumeFromCommand {
29
+ /**
30
+ * Pi calls this when the user types /resume-from.
31
+ * It is a command handler, which is the only call site C-10 proved safe for switchSession.
32
+ */
33
+ run(ctx: PiCommandContext, args: string[], pipeline: ImportPipeline): Promise<void>;
34
+ }
@@ -0,0 +1,4 @@
1
+ // GENERATED from src/host/pi-extension/module.md — the Public Contract section is the normative home.
2
+ // Declarations only: no behaviour, no defaults. If this file and module.md disagree,
3
+ // the document wins and this file is corrected.
4
+ export {};
@@ -0,0 +1,6 @@
1
+ export { createResumeFromCommand, RESUME_FROM_COMMAND_NAME, type ResumeFromDeps, } from "./command.js";
2
+ export type { PiCommandContext, PickResult, PiResumeFromCommand, SessionPicker, UserChoice, } from "./contract.js";
3
+ export { createKeyPicker, formatRow, type KeyPickerDeps, type KeySource, type PickerKey, } from "./picker.js";
4
+ export { safeLines, safeText } from "./presentation.js";
5
+ export { type PiCommandDefinition, type PiCommandRegistrar, type RegisterDeps, registerResumeFrom, } from "./register.js";
6
+ export type { PiUi } from "./ui.js";
@@ -0,0 +1,4 @@
1
+ export { createResumeFromCommand, RESUME_FROM_COMMAND_NAME, } from "./command.js";
2
+ export { createKeyPicker, formatRow, } from "./picker.js";
3
+ export { safeLines, safeText } from "./presentation.js";
4
+ export { registerResumeFrom, } from "./register.js";
@@ -0,0 +1,16 @@
1
+ import type { SessionDescriptor, SessionPicker } from "./contract.js";
2
+ import type { PiUi } from "./ui.js";
3
+ /** The keys the picker understands (FR-9). */
4
+ export type PickerKey = "up" | "down" | "enter" | "escape";
5
+ /** Where the picker takes its keys from. Resolving with null ends the picker. */
6
+ export interface KeySource {
7
+ next(): Promise<PickerKey | null>;
8
+ }
9
+ export interface KeyPickerDeps {
10
+ keys: KeySource;
11
+ ui: PiUi;
12
+ }
13
+ /** One row of the picker: agent, home, time, title and turn count (FR-11). */
14
+ export declare function formatRow(row: SessionDescriptor): string;
15
+ /** A picker driven by keys: arrow keys move, Enter selects, Escape cancels (FR-9). */
16
+ export declare function createKeyPicker(deps: KeyPickerDeps): SessionPicker;
@@ -0,0 +1,35 @@
1
+ import { safeText } from "./presentation.js";
2
+ const HEADER = "Select a session — up/down to move, Enter to select, Escape to cancel:";
3
+ /** One row of the picker: agent, home, time, title and turn count (FR-11). */
4
+ export function formatRow(row) {
5
+ return `${safeText(row.ref.agent)} ${safeText(row.updatedAt)} ${safeText(row.title)} (${row.turnCount} turns) ${safeText(row.ref.home)}`;
6
+ }
7
+ function render(listing, cursor) {
8
+ return [
9
+ HEADER,
10
+ ...listing.rows.map((row, index) => `${index === cursor ? ">" : " "} ${formatRow(row)}`),
11
+ ];
12
+ }
13
+ const CANCELLED = { choice: "cancelled", selected: null };
14
+ /** A picker driven by keys: arrow keys move, Enter selects, Escape cancels (FR-9). */
15
+ export function createKeyPicker(deps) {
16
+ return {
17
+ async pick(listing) {
18
+ let cursor = 0;
19
+ for (;;) {
20
+ deps.ui.show(render(listing, cursor));
21
+ const key = await deps.keys.next();
22
+ if (key === null || key === "escape")
23
+ return CANCELLED;
24
+ if (key === "up")
25
+ cursor = Math.max(0, cursor - 1);
26
+ else if (key === "down")
27
+ cursor = Math.min(listing.rows.length - 1, cursor + 1);
28
+ else if (key === "enter") {
29
+ const selected = listing.rows[cursor];
30
+ return selected === undefined ? CANCELLED : { choice: "selected", selected };
31
+ }
32
+ }
33
+ },
34
+ };
35
+ }
@@ -0,0 +1,2 @@
1
+ export declare function safeText(value: string): string;
2
+ export declare function safeLines(lines: readonly string[]): string[];
@@ -0,0 +1,11 @@
1
+ function globalPattern(source) {
2
+ return new RegExp(source, "gu");
3
+ }
4
+ const ANSI_SEQUENCE = globalPattern(String.raw `\x1b(?:\][^\x07]*(?:\x07|\x1b\\)|\[[0-?]*[ -/]*[@-~])`);
5
+ const UNSAFE_CONTROL = globalPattern(String.raw `[\x00-\x1f\x7f-\x9f\u2028\u2029\u202a-\u202e\u2066-\u2069]`);
6
+ export function safeText(value) {
7
+ return value.replace(ANSI_SEQUENCE, " ").replace(UNSAFE_CONTROL, " ");
8
+ }
9
+ export function safeLines(lines) {
10
+ return lines.map(safeText);
11
+ }
@@ -0,0 +1,25 @@
1
+ import { type ResumeFromDeps } from "./command.js";
2
+ import type { ImportPipeline, PiCommandContext } from "./contract.js";
3
+ /**
4
+ * What Pi is given when the extension loads.
5
+ *
6
+ * `module.md` makes registration a responsibility of this module but names no
7
+ * API for it — Pi's extension surface is an internal of a moving application,
8
+ * measured once at 0.83.0 (C-10). The dependency is therefore structural: Pi
9
+ * passes anything that can register a command, and only this file knows the
10
+ * shape. When Pi's API changes, this file changes and nothing else does.
11
+ */
12
+ export interface PiCommandDefinition {
13
+ name: string;
14
+ description: string;
15
+ /** Pi calls this when the user types the command. It is the only call site (C-10). */
16
+ run(ctx: PiCommandContext, args: string[]): Promise<void>;
17
+ }
18
+ export interface PiCommandRegistrar {
19
+ registerCommand(definition: PiCommandDefinition): void;
20
+ }
21
+ export interface RegisterDeps extends ResumeFromDeps {
22
+ pipeline: ImportPipeline;
23
+ }
24
+ /** Registers /resume-from with Pi. */
25
+ export declare function registerResumeFrom(registrar: PiCommandRegistrar, deps: RegisterDeps): void;
@@ -0,0 +1,11 @@
1
+ import { createResumeFromCommand, RESUME_FROM_COMMAND_NAME, } from "./command.js";
2
+ const DESCRIPTION = "Continue another session here. Use /resume-from --help for accepted arguments.";
3
+ /** Registers /resume-from with Pi. */
4
+ export function registerResumeFrom(registrar, deps) {
5
+ const command = createResumeFromCommand(deps);
6
+ registrar.registerCommand({
7
+ name: RESUME_FROM_COMMAND_NAME,
8
+ description: DESCRIPTION,
9
+ run: (ctx, args) => command.run(ctx, args, deps.pipeline),
10
+ });
11
+ }
@@ -0,0 +1,20 @@
1
+ import type { UserChoice } from "./contract.js";
2
+ /**
3
+ * The user-facing channel of the Pi extension.
4
+ *
5
+ * There is deliberately no model-facing method here. FR-47 and FR-48 require the
6
+ * provenance marker to reach the user and never the model context, and FR-46
7
+ * requires the prompt to stay empty after landing. An interface with no way to
8
+ * send anything makes both structural instead of a convention, the same way the
9
+ * command handler being the only call site makes C-10 structural.
10
+ *
11
+ * Pi supplies the implementation. `module.md` names showing and confirming as
12
+ * responsibilities of this module but gives no API for either, so the shape is
13
+ * declared here and injected, not taken from the command context.
14
+ */
15
+ export interface PiUi {
16
+ /** Show one block of lines to the user, in the order given. */
17
+ show(lines: readonly string[]): void;
18
+ /** Ask the user to confirm. "selected" means confirmed, "cancelled" means not. */
19
+ confirm(question: string): Promise<UserChoice>;
20
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Where an import is going, and how much room it has (FR-3, FR-18).
3
+ *
4
+ * Three values, each from one source: the agent the entry point reported, the home the user named
5
+ * or the adapter declared, and the window the user configured or the adapter declared.
6
+ */
7
+ import type { AgentRegistry, TargetProfileBuilder } from "./contract.js";
8
+ export declare function createTargetProfileBuilder(registry: AgentRegistry): TargetProfileBuilder;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Where an import is going, and how much room it has (FR-3, FR-18).
3
+ *
4
+ * Three values, each from one source: the agent the entry point reported, the home the user named
5
+ * or the adapter declared, and the window the user configured or the adapter declared.
6
+ */
7
+ import { homedir } from "node:os";
8
+ import { join, resolve } from "node:path";
9
+ /** A home is always absolute (FR-2). `~` is the user's, and everything else is resolved. */
10
+ function resolveHome(home) {
11
+ if (home === "~")
12
+ return resolve(homedir());
13
+ if (home.startsWith("~/") || home.startsWith("~\\")) {
14
+ return join(resolve(homedir()), home.slice(2));
15
+ }
16
+ return resolve(home);
17
+ }
18
+ export function createTargetProfileBuilder(registry) {
19
+ return {
20
+ build(agent, home, config) {
21
+ // Rejects an agent with no adapter, rather than guessing one (FR-56).
22
+ const declared = registry.get(agent).capabilities();
23
+ const override = config.windowOverrides.find((entry) => entry.agent === agent);
24
+ return {
25
+ agent,
26
+ home: home === null ? declared.defaultHome : resolveHome(home),
27
+ windowTokens: override?.windowTokens ?? declared.defaultWindowTokens,
28
+ };
29
+ },
30
+ };
31
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The registry over the agent list. It answers three questions and decides nothing: which
3
+ * adapters exist, which one is an agent's, and which of them fill a role (FR-59).
4
+ *
5
+ * Every answer comes from what an adapter declares. Nothing here reads a name.
6
+ */
7
+ import type { AgentAdapter, AgentRegistry } from "./contract.js";
8
+ export declare function createAgentRegistry(adapters: readonly AgentAdapter[]): AgentRegistry;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The registry over the agent list. It answers three questions and decides nothing: which
3
+ * adapters exist, which one is an agent's, and which of them fill a role (FR-59).
4
+ *
5
+ * Every answer comes from what an adapter declares. Nothing here reads a name.
6
+ */
7
+ const SOURCE = "source";
8
+ const TARGET = "target";
9
+ /** Adapters whose declaration includes a role (FR-59). */
10
+ const withRole = (adapters, role) => adapters.filter((adapter) => adapter.capabilities().roles.includes(role));
11
+ export function createAgentRegistry(adapters) {
12
+ const all = [...adapters];
13
+ const byAgent = new Map();
14
+ for (const adapter of all) {
15
+ const agent = adapter.capabilities().agent;
16
+ if (!byAgent.has(agent))
17
+ byAgent.set(agent, adapter);
18
+ }
19
+ return {
20
+ all: () => [...all],
21
+ get(agent) {
22
+ const found = byAgent.get(agent);
23
+ if (found === undefined) {
24
+ // Not defaulted: importing into the wrong agent is worse than not importing (FR-56).
25
+ throw new Error(`There is no adapter for "${agent}", so the tool cannot run inside it. ` +
26
+ `The agents it knows are: ${[...byAgent.keys()].join(", ")}.`);
27
+ }
28
+ return found;
29
+ },
30
+ sources: () => withRole(all, SOURCE),
31
+ targets: () => withRole(all, TARGET),
32
+ };
33
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The construction order, as code (Internal Design, steps 1 to 5).
3
+ *
4
+ * 1. Configuration, once. Everything downstream reads the result, and a rejected configuration
5
+ * stops the command before an adapter exists or a home is read (FR-56).
6
+ * 2. The platform services: the estimator factory, the repository reader, the committer.
7
+ * 3. The adapters of the list. `capabilities()` is cheap and pure, so it may be read at once.
8
+ * 4. The target profile, built by the caller from the agent the entry point is running in.
9
+ * 5. The pipeline, wired with the services and the adapters.
10
+ *
11
+ * Every step is injectable, because a composition root whose parts cannot be replaced cannot be
12
+ * tested — and because the deps are thunks, not values, "nothing is built before the
13
+ * configuration is loaded" is a property a test can observe rather than a promise.
14
+ */
15
+ import { type AgentEntry } from "./agents.js";
16
+ import type { AgentRegistry, ConfigLoader, EstimatorFactory, FileCommitter, HostWiring, ImportConfig, ImportPipeline, RepoReader, TargetProfile, TargetProfileBuilder } from "./contract.js";
17
+ /** Everything the composition root builds, and what a test may replace. */
18
+ export interface HostDeps {
19
+ /** The agent list. Defaults to the one list of the tree (FR-57). */
20
+ agents?: readonly AgentEntry[];
21
+ configLoader?: ConfigLoader;
22
+ createEstimators?: () => EstimatorFactory;
23
+ createRepo?: () => RepoReader;
24
+ createCommitter?: () => FileCommitter;
25
+ /** The directory the command runs in. The repository reader reads git state from it (FR-13). */
26
+ cwd?: string;
27
+ /** The import time written into the marker (FR-47). Injected so a preview and a commit agree. */
28
+ now?: () => string;
29
+ }
30
+ /**
31
+ * The wiring, plus the two things an entry point needs to reach step 4: the configuration that
32
+ * was loaded once, and the builder that turns an agent and a home into a profile.
33
+ */
34
+ export interface Host extends HostWiring {
35
+ registry(): AgentRegistry;
36
+ profiles(): TargetProfileBuilder;
37
+ /** The one configuration of this process (Constraints: loaded once per process). */
38
+ config(): ImportConfig;
39
+ pipelineFor(target: TargetProfile): Promise<ImportPipeline>;
40
+ }
41
+ export declare function createHost(deps?: HostDeps): Promise<Host>;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The construction order, as code (Internal Design, steps 1 to 5).
3
+ *
4
+ * 1. Configuration, once. Everything downstream reads the result, and a rejected configuration
5
+ * stops the command before an adapter exists or a home is read (FR-56).
6
+ * 2. The platform services: the estimator factory, the repository reader, the committer.
7
+ * 3. The adapters of the list. `capabilities()` is cheap and pure, so it may be read at once.
8
+ * 4. The target profile, built by the caller from the agent the entry point is running in.
9
+ * 5. The pipeline, wired with the services and the adapters.
10
+ *
11
+ * Every step is injectable, because a composition root whose parts cannot be replaced cannot be
12
+ * tested — and because the deps are thunks, not values, "nothing is built before the
13
+ * configuration is loaded" is a property a test can observe rather than a promise.
14
+ */
15
+ import { createImportPipeline } from "../import/index.js";
16
+ import { createConfigLoader } from "../platform/config/index.js";
17
+ import { createRepoReader } from "../platform/repo/index.js";
18
+ import { createFileCommitter } from "../platform/store/index.js";
19
+ import { estimatorFactory } from "../platform/tokens/index.js";
20
+ import { AGENTS } from "./agents.js";
21
+ import { createTargetProfileBuilder } from "./profile.js";
22
+ import { createAgentRegistry } from "./registry.js";
23
+ /** The role an adapter must declare to receive an import (FR-59). */
24
+ const TARGET_ROLE = "target";
25
+ export async function createHost(deps = {}) {
26
+ // Step 1. It rejects before anything else exists, which is what FR-56 asks for.
27
+ const config = await (deps.configLoader ?? createConfigLoader()).load();
28
+ // Step 2.
29
+ const cwd = deps.cwd ?? process.cwd();
30
+ const estimators = (deps.createEstimators ?? (() => estimatorFactory))();
31
+ const repo = (deps.createRepo ?? (() => createRepoReader(cwd)))();
32
+ const committer = (deps.createCommitter ?? createFileCommitter)();
33
+ // Step 3. The list is the only place that knows which implementations exist. Each adapter
34
+ // names itself, so the family is keyed by what it declares and never by what the list assumed.
35
+ const families = new Map();
36
+ const adapters = (deps.agents ?? AGENTS).map((entry) => {
37
+ const adapter = entry.create();
38
+ const agent = adapter.capabilities().agent;
39
+ if (!families.has(agent))
40
+ families.set(agent, entry.family);
41
+ return adapter;
42
+ });
43
+ const registry = createAgentRegistry(adapters);
44
+ const profiles = createTargetProfileBuilder(registry);
45
+ return {
46
+ registry: () => registry,
47
+ profiles: () => profiles,
48
+ config: () => config,
49
+ // Step 5. Async so a refusal reaches the caller as a rejection, never as a throw.
50
+ async pipelineFor(target) {
51
+ const declared = registry.get(target.agent).capabilities();
52
+ if (!declared.roles.includes(TARGET_ROLE)) {
53
+ throw new Error(`The "${target.agent}" adapter cannot receive an import: it declares the role(s) ` +
54
+ `${declared.roles.join(", ")} and not "${TARGET_ROLE}" (FR-59). ` +
55
+ "Run the import from an agent whose adapter has that role.");
56
+ }
57
+ return createImportPipeline({
58
+ adapters,
59
+ config,
60
+ estimator: estimators.forFamily(families.get(target.agent) ?? "generic"),
61
+ committer,
62
+ repo,
63
+ ...(deps.now === undefined ? {} : { now: deps.now }),
64
+ });
65
+ },
66
+ };
67
+ }
@@ -0,0 +1,6 @@
1
+ import type { SessionDescriptor } from "../session/contract.js";
2
+ import type { PreviewContent } from "./preview/contract.js";
3
+ import type { TransferPlan } from "./transfer/contract.js";
4
+ /** Binds confirmation to every input that can affect the imported session or its preview. */
5
+ export declare function confirmationToken(descriptor: SessionDescriptor, plan: TransferPlan, report: PreviewContent): string;
6
+ export declare function confirmationMatches(expected: string, supplied: string): boolean;
@@ -0,0 +1,27 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ const TOKEN_PREFIX = "v1-sha256-";
3
+ const TOKEN_PATTERN = /^v1-sha256-[0-9a-f]{64}$/;
4
+ /** Binds confirmation to every input that can affect the imported session or its preview. */
5
+ export function confirmationToken(descriptor, plan, report) {
6
+ const payload = stableJson({ descriptor, plan, report });
7
+ return `${TOKEN_PREFIX}${createHash("sha256").update(payload).digest("hex")}`;
8
+ }
9
+ export function confirmationMatches(expected, supplied) {
10
+ if (!TOKEN_PATTERN.test(expected) || !TOKEN_PATTERN.test(supplied))
11
+ return false;
12
+ return timingSafeEqual(Buffer.from(expected), Buffer.from(supplied));
13
+ }
14
+ /** JSON with recursively sorted object keys, so separate CLI processes derive the same token. */
15
+ function stableJson(value) {
16
+ return JSON.stringify(normalize(value));
17
+ }
18
+ function normalize(value) {
19
+ if (Array.isArray(value))
20
+ return value.map(normalize);
21
+ if (value === null || typeof value !== "object")
22
+ return value;
23
+ return Object.fromEntries(Object.entries(value)
24
+ .filter(([, item]) => item !== undefined)
25
+ .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
26
+ .map(([key, item]) => [key, normalize(item)]));
27
+ }
@@ -0,0 +1,41 @@
1
+ import type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect } from "../adapters/contract.js";
2
+ export type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect, };
3
+ import type { HomeFailure, Listing, SearchScope, SelectionError, SelectionInput, SessionFinder } from "./discovery/contract.js";
4
+ export type { HomeFailure, Listing, SearchScope, SelectionError, SelectionInput, SessionFinder };
5
+ import type { HandoverInstruction, LandingError, LandingResult, LandingStage, SessionLander } from "./landing/contract.js";
6
+ export type { HandoverInstruction, LandingError, LandingResult, LandingStage, SessionLander };
7
+ import type { PreviewBuilder, PreviewContent, PreviewReport, PreviewWarning, WarningKind } from "./preview/contract.js";
8
+ export type { PreviewBuilder, PreviewContent, PreviewReport, PreviewWarning, WarningKind };
9
+ import type { DropReason, PinReason, TransferPlan, TransferRules, TurnDrop, TurnPin } from "./transfer/contract.js";
10
+ export type { DropReason, PinReason, TransferPlan, TransferRules, TurnDrop, TurnPin };
11
+ import type { HomeEntry, ImportConfig, WindowOverride } from "../platform/config/contract.js";
12
+ export type { HomeEntry, ImportConfig, WindowOverride };
13
+ import type { Bytes, CommitError, CommitHandle, CommitRefusal, FileCommitter, PendingFile } from "../platform/store/contract.js";
14
+ export type { Bytes, CommitError, CommitHandle, CommitRefusal, FileCommitter, PendingFile };
15
+ import type { TokenEstimator } from "../platform/tokens/contract.js";
16
+ export type { TokenEstimator };
17
+ import type { AgentId, CanonicalSession, CanonicalTurn, HomePath, ProvenanceMarker, RepoSnapshot, SessionDescriptor, SessionId, SessionRef, SourceProvenance, TargetProfile, ToolCallRecord, ToolEffect, TurnKind, TurnRole } from "../session/contract.js";
18
+ export type { AgentId, CanonicalSession, CanonicalTurn, HomePath, ProvenanceMarker, RepoSnapshot, SessionDescriptor, SessionId, SessionRef, SourceProvenance, TargetProfile, ToolCallRecord, ToolEffect, TurnKind, TurnRole, };
19
+ /** What to list (FR-10, FR-15). */
20
+ export interface ListRequest {
21
+ repoRoot: string;
22
+ target: TargetProfile;
23
+ onlyAgent: AgentId | null;
24
+ onlyHome: HomePath | null;
25
+ }
26
+ /** What to preview, and later what to commit (FR-16, FR-20). */
27
+ export interface ImportRequest {
28
+ repoRoot: string;
29
+ target: TargetProfile;
30
+ selection: SelectionInput;
31
+ onlyAgent: AgentId | null;
32
+ onlyHome: HomePath | null;
33
+ }
34
+ /** One import, from listing to landing. Every host drives these three calls. */
35
+ export interface ImportPipeline {
36
+ list(request: ListRequest): Promise<Listing>;
37
+ /** Writes nothing (FR-16). */
38
+ preview(request: ImportRequest): Promise<PreviewReport>;
39
+ /** Runs only after the user confirmed the preview (FR-20). */
40
+ commit(request: ImportRequest, runtime: AgentRuntime, confirmationToken: string): Promise<LandingResult>;
41
+ }
@@ -0,0 +1,4 @@
1
+ // GENERATED from src/import/module.md — the Public Contract section is the normative home.
2
+ // Declarations only: no behaviour, no defaults. If this file and module.md disagree,
3
+ // the document wins and this file is corrected.
4
+ export {};