@codemieai/code 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/README.md +109 -56
  2. package/bin/codemie-copilot.js +224 -0
  3. package/bin/codemie-pi.js +18 -0
  4. package/dist/agents/core/AgentCLI.d.ts.map +1 -1
  5. package/dist/agents/core/AgentCLI.js +16 -10
  6. package/dist/agents/core/AgentCLI.js.map +1 -1
  7. package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
  8. package/dist/agents/core/BaseAgentAdapter.js +43 -19
  9. package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
  10. package/dist/agents/core/agent-aliases.d.ts +17 -0
  11. package/dist/agents/core/agent-aliases.d.ts.map +1 -0
  12. package/dist/agents/core/agent-aliases.js +41 -0
  13. package/dist/agents/core/agent-aliases.js.map +1 -0
  14. package/dist/agents/core/session/BaseSessionAdapter.d.ts +19 -0
  15. package/dist/agents/core/session/BaseSessionAdapter.d.ts.map +1 -1
  16. package/dist/agents/core/session/session-origin-audit.d.ts +13 -0
  17. package/dist/agents/core/session/session-origin-audit.d.ts.map +1 -1
  18. package/dist/agents/core/session/session-origin-audit.js +34 -0
  19. package/dist/agents/core/session/session-origin-audit.js.map +1 -1
  20. package/dist/agents/core/session/stale-session-reconciliation.d.ts +42 -0
  21. package/dist/agents/core/session/stale-session-reconciliation.d.ts.map +1 -0
  22. package/dist/agents/core/session/stale-session-reconciliation.js +141 -0
  23. package/dist/agents/core/session/stale-session-reconciliation.js.map +1 -0
  24. package/dist/agents/core/session/types.d.ts +19 -0
  25. package/dist/agents/core/session/types.d.ts.map +1 -1
  26. package/dist/agents/core/session/types.js +17 -1
  27. package/dist/agents/core/session/types.js.map +1 -1
  28. package/dist/agents/core/types.d.ts +11 -0
  29. package/dist/agents/core/types.d.ts.map +1 -1
  30. package/dist/agents/plugins/codex/codex.reconciliation.d.ts +15 -35
  31. package/dist/agents/plugins/codex/codex.reconciliation.d.ts.map +1 -1
  32. package/dist/agents/plugins/codex/codex.reconciliation.js +8 -139
  33. package/dist/agents/plugins/codex/codex.reconciliation.js.map +1 -1
  34. package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.d.ts +146 -0
  35. package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.d.ts.map +1 -0
  36. package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.js +12 -0
  37. package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.js.map +1 -0
  38. package/dist/agents/plugins/copilot-cli/copilot-cli.constants.d.ts +15 -0
  39. package/dist/agents/plugins/copilot-cli/copilot-cli.constants.d.ts.map +1 -0
  40. package/dist/agents/plugins/copilot-cli/copilot-cli.constants.js +15 -0
  41. package/dist/agents/plugins/copilot-cli/copilot-cli.constants.js.map +1 -0
  42. package/dist/agents/plugins/copilot-cli/copilot-cli.models.d.ts +8 -0
  43. package/dist/agents/plugins/copilot-cli/copilot-cli.models.d.ts.map +1 -0
  44. package/dist/agents/plugins/copilot-cli/copilot-cli.models.js +195 -0
  45. package/dist/agents/plugins/copilot-cli/copilot-cli.models.js.map +1 -0
  46. package/dist/agents/plugins/copilot-cli/copilot-cli.paths.d.ts +11 -0
  47. package/dist/agents/plugins/copilot-cli/copilot-cli.paths.d.ts.map +1 -0
  48. package/dist/agents/plugins/copilot-cli/copilot-cli.paths.js +21 -0
  49. package/dist/agents/plugins/copilot-cli/copilot-cli.paths.js.map +1 -0
  50. package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.d.ts +14 -0
  51. package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.d.ts.map +1 -0
  52. package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.js +263 -0
  53. package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.js.map +1 -0
  54. package/dist/agents/plugins/copilot-cli/copilot-cli.session.d.ts +43 -0
  55. package/dist/agents/plugins/copilot-cli/copilot-cli.session.d.ts.map +1 -0
  56. package/dist/agents/plugins/copilot-cli/copilot-cli.session.js +343 -0
  57. package/dist/agents/plugins/copilot-cli/copilot-cli.session.js.map +1 -0
  58. package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.d.ts +10 -0
  59. package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.d.ts.map +1 -0
  60. package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.js +41 -0
  61. package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.js.map +1 -0
  62. package/dist/agents/plugins/copilot-cli/copilot-cli.usage.d.ts +37 -0
  63. package/dist/agents/plugins/copilot-cli/copilot-cli.usage.d.ts.map +1 -0
  64. package/dist/agents/plugins/copilot-cli/copilot-cli.usage.js +96 -0
  65. package/dist/agents/plugins/copilot-cli/copilot-cli.usage.js.map +1 -0
  66. package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.d.ts +17 -0
  67. package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.d.ts.map +1 -0
  68. package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.js +58 -0
  69. package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.js.map +1 -0
  70. package/dist/agents/plugins/copilot-cli/index.d.ts +3 -0
  71. package/dist/agents/plugins/copilot-cli/index.d.ts.map +1 -0
  72. package/dist/agents/plugins/copilot-cli/index.js +3 -0
  73. package/dist/agents/plugins/copilot-cli/index.js.map +1 -0
  74. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.d.ts +18 -0
  75. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.d.ts.map +1 -0
  76. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.js +313 -0
  77. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.js.map +1 -0
  78. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.d.ts +16 -0
  79. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.d.ts.map +1 -0
  80. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.js +22 -0
  81. package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.js.map +1 -0
  82. package/dist/agents/plugins/pi/__tests__/home-redirect.d.ts +12 -0
  83. package/dist/agents/plugins/pi/__tests__/home-redirect.d.ts.map +1 -0
  84. package/dist/agents/plugins/pi/__tests__/home-redirect.js +27 -0
  85. package/dist/agents/plugins/pi/__tests__/home-redirect.js.map +1 -0
  86. package/dist/agents/plugins/pi/extension/README.md +68 -0
  87. package/dist/agents/plugins/pi/extension/index.js +161 -0
  88. package/dist/agents/plugins/pi/extension/package.json +8 -0
  89. package/dist/agents/plugins/pi/index.d.ts +3 -0
  90. package/dist/agents/plugins/pi/index.d.ts.map +1 -0
  91. package/dist/agents/plugins/pi/index.js +3 -0
  92. package/dist/agents/plugins/pi/index.js.map +1 -0
  93. package/dist/agents/plugins/pi/pi.extension.d.ts +60 -0
  94. package/dist/agents/plugins/pi/pi.extension.d.ts.map +1 -0
  95. package/dist/agents/plugins/pi/pi.extension.js +201 -0
  96. package/dist/agents/plugins/pi/pi.extension.js.map +1 -0
  97. package/dist/agents/plugins/pi/pi.incremental-sync.d.ts +63 -0
  98. package/dist/agents/plugins/pi/pi.incremental-sync.d.ts.map +1 -0
  99. package/dist/agents/plugins/pi/pi.incremental-sync.js +266 -0
  100. package/dist/agents/plugins/pi/pi.incremental-sync.js.map +1 -0
  101. package/dist/agents/plugins/pi/pi.models.d.ts +20 -0
  102. package/dist/agents/plugins/pi/pi.models.d.ts.map +1 -0
  103. package/dist/agents/plugins/pi/pi.models.js +201 -0
  104. package/dist/agents/plugins/pi/pi.models.js.map +1 -0
  105. package/dist/agents/plugins/pi/pi.packages.d.ts +11 -0
  106. package/dist/agents/plugins/pi/pi.packages.d.ts.map +1 -0
  107. package/dist/agents/plugins/pi/pi.packages.js +35 -0
  108. package/dist/agents/plugins/pi/pi.packages.js.map +1 -0
  109. package/dist/agents/plugins/pi/pi.paths.d.ts +37 -0
  110. package/dist/agents/plugins/pi/pi.paths.d.ts.map +1 -0
  111. package/dist/agents/plugins/pi/pi.paths.js +146 -0
  112. package/dist/agents/plugins/pi/pi.paths.js.map +1 -0
  113. package/dist/agents/plugins/pi/pi.plugin.d.ts +30 -0
  114. package/dist/agents/plugins/pi/pi.plugin.d.ts.map +1 -0
  115. package/dist/agents/plugins/pi/pi.plugin.js +453 -0
  116. package/dist/agents/plugins/pi/pi.plugin.js.map +1 -0
  117. package/dist/agents/plugins/pi/pi.session.d.ts +114 -0
  118. package/dist/agents/plugins/pi/pi.session.d.ts.map +1 -0
  119. package/dist/agents/plugins/pi/pi.session.js +388 -0
  120. package/dist/agents/plugins/pi/pi.session.js.map +1 -0
  121. package/dist/agents/plugins/pi/pi.setup.d.ts +2 -0
  122. package/dist/agents/plugins/pi/pi.setup.d.ts.map +1 -0
  123. package/dist/agents/plugins/pi/pi.setup.js +33 -0
  124. package/dist/agents/plugins/pi/pi.setup.js.map +1 -0
  125. package/dist/agents/plugins/pi/pi.types.d.ts +143 -0
  126. package/dist/agents/plugins/pi/pi.types.d.ts.map +1 -0
  127. package/dist/agents/plugins/pi/pi.types.js +74 -0
  128. package/dist/agents/plugins/pi/pi.types.js.map +1 -0
  129. package/dist/agents/plugins/pi/session/pi-file-operations.d.ts +17 -0
  130. package/dist/agents/plugins/pi/session/pi-file-operations.d.ts.map +1 -0
  131. package/dist/agents/plugins/pi/session/pi-file-operations.js +98 -0
  132. package/dist/agents/plugins/pi/session/pi-file-operations.js.map +1 -0
  133. package/dist/agents/plugins/pi/session/pi-named-invocations.d.ts +52 -0
  134. package/dist/agents/plugins/pi/session/pi-named-invocations.d.ts.map +1 -0
  135. package/dist/agents/plugins/pi/session/pi-named-invocations.js +189 -0
  136. package/dist/agents/plugins/pi/session/pi-named-invocations.js.map +1 -0
  137. package/dist/agents/plugins/pi/session/pi-user-prompt.d.ts +14 -0
  138. package/dist/agents/plugins/pi/session/pi-user-prompt.d.ts.map +1 -0
  139. package/dist/agents/plugins/pi/session/pi-user-prompt.js +51 -0
  140. package/dist/agents/plugins/pi/session/pi-user-prompt.js.map +1 -0
  141. package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.d.ts +52 -0
  142. package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.d.ts.map +1 -0
  143. package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.js +716 -0
  144. package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.js.map +1 -0
  145. package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.d.ts +104 -0
  146. package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.d.ts.map +1 -0
  147. package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.js +595 -0
  148. package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.js.map +1 -0
  149. package/dist/agents/registry.d.ts +20 -0
  150. package/dist/agents/registry.d.ts.map +1 -1
  151. package/dist/agents/registry.js +29 -2
  152. package/dist/agents/registry.js.map +1 -1
  153. package/dist/cli/commands/analytics/agent-labels.d.ts +3 -0
  154. package/dist/cli/commands/analytics/agent-labels.d.ts.map +1 -0
  155. package/dist/cli/commands/analytics/agent-labels.js +20 -0
  156. package/dist/cli/commands/analytics/agent-labels.js.map +1 -0
  157. package/dist/cli/commands/analytics/cost/cost-enricher.d.ts.map +1 -1
  158. package/dist/cli/commands/analytics/cost/cost-enricher.js +12 -0
  159. package/dist/cli/commands/analytics/cost/cost-enricher.js.map +1 -1
  160. package/dist/cli/commands/analytics/cost/types.d.ts +10 -0
  161. package/dist/cli/commands/analytics/cost/types.d.ts.map +1 -1
  162. package/dist/cli/commands/analytics/cost/usage-readers.d.ts +24 -0
  163. package/dist/cli/commands/analytics/cost/usage-readers.d.ts.map +1 -1
  164. package/dist/cli/commands/analytics/cost/usage-readers.js +253 -54
  165. package/dist/cli/commands/analytics/cost/usage-readers.js.map +1 -1
  166. package/dist/cli/commands/analytics/formatter.d.ts.map +1 -1
  167. package/dist/cli/commands/analytics/formatter.js +10 -2
  168. package/dist/cli/commands/analytics/formatter.js.map +1 -1
  169. package/dist/cli/commands/analytics/index.d.ts.map +1 -1
  170. package/dist/cli/commands/analytics/index.js +22 -0
  171. package/dist/cli/commands/analytics/index.js.map +1 -1
  172. package/dist/cli/commands/analytics/native-loader.d.ts +21 -4
  173. package/dist/cli/commands/analytics/native-loader.d.ts.map +1 -1
  174. package/dist/cli/commands/analytics/native-loader.js +267 -88
  175. package/dist/cli/commands/analytics/native-loader.js.map +1 -1
  176. package/dist/cli/commands/analytics/report/client/app.js +77 -15
  177. package/dist/cli/commands/analytics/report/payload-builder.d.ts.map +1 -1
  178. package/dist/cli/commands/analytics/report/payload-builder.js +32 -2
  179. package/dist/cli/commands/analytics/report/payload-builder.js.map +1 -1
  180. package/dist/cli/commands/analytics/report/types.d.ts +11 -0
  181. package/dist/cli/commands/analytics/report/types.d.ts.map +1 -1
  182. package/dist/cli/commands/hook.d.ts.map +1 -1
  183. package/dist/cli/commands/hook.js +71 -29
  184. package/dist/cli/commands/hook.js.map +1 -1
  185. package/dist/cli/commands/install.d.ts.map +1 -1
  186. package/dist/cli/commands/install.js +9 -7
  187. package/dist/cli/commands/install.js.map +1 -1
  188. package/dist/cli/commands/list.d.ts.map +1 -1
  189. package/dist/cli/commands/list.js +4 -2
  190. package/dist/cli/commands/list.js.map +1 -1
  191. package/dist/cli/commands/setup.d.ts +3 -1
  192. package/dist/cli/commands/setup.d.ts.map +1 -1
  193. package/dist/cli/commands/setup.js +87 -63
  194. package/dist/cli/commands/setup.js.map +1 -1
  195. package/dist/cli/commands/uninstall.d.ts.map +1 -1
  196. package/dist/cli/commands/uninstall.js +6 -4
  197. package/dist/cli/commands/uninstall.js.map +1 -1
  198. package/dist/cli/commands/update.d.ts.map +1 -1
  199. package/dist/cli/commands/update.js +7 -5
  200. package/dist/cli/commands/update.js.map +1 -1
  201. package/dist/cli/first-time.d.ts.map +1 -1
  202. package/dist/cli/first-time.js +10 -9
  203. package/dist/cli/first-time.js.map +1 -1
  204. package/dist/providers/core/auth-validation.d.ts +7 -2
  205. package/dist/providers/core/auth-validation.d.ts.map +1 -1
  206. package/dist/providers/core/auth-validation.js +11 -5
  207. package/dist/providers/core/auth-validation.js.map +1 -1
  208. package/dist/providers/core/types.d.ts +16 -0
  209. package/dist/providers/core/types.d.ts.map +1 -1
  210. package/dist/providers/core/types.js.map +1 -1
  211. package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.d.ts +8 -3
  212. package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.d.ts.map +1 -1
  213. package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.js +46 -11
  214. package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.js.map +1 -1
  215. package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.d.ts +23 -13
  216. package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.d.ts.map +1 -1
  217. package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.js +75 -18
  218. package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.js.map +1 -1
  219. package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.d.ts +21 -0
  220. package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.d.ts.map +1 -0
  221. package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.js +133 -0
  222. package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.js.map +1 -0
  223. package/dist/providers/plugins/sso/proxy/plugins/header-injection.plugin.js +1 -1
  224. package/dist/providers/plugins/sso/proxy/plugins/header-injection.plugin.js.map +1 -1
  225. package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +2 -1
  226. package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
  227. package/dist/providers/plugins/sso/proxy/plugins/index.js +4 -2
  228. package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
  229. package/dist/providers/plugins/sso/proxy/plugins/types.d.ts +11 -0
  230. package/dist/providers/plugins/sso/proxy/plugins/types.d.ts.map +1 -1
  231. package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts +2 -0
  232. package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts.map +1 -1
  233. package/dist/providers/plugins/sso/proxy/sso.proxy.js +37 -1
  234. package/dist/providers/plugins/sso/proxy/sso.proxy.js.map +1 -1
  235. package/dist/providers/plugins/sso/session/SessionSyncer.d.ts.map +1 -1
  236. package/dist/providers/plugins/sso/session/SessionSyncer.js +13 -0
  237. package/dist/providers/plugins/sso/session/SessionSyncer.js.map +1 -1
  238. package/dist/providers/plugins/sso/session/processors/conversations/syncProcessor.js +6 -0
  239. package/dist/providers/plugins/sso/session/processors/conversations/syncProcessor.js.map +1 -1
  240. package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.d.ts +0 -6
  241. package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.d.ts.map +1 -1
  242. package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.js +28 -19
  243. package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.js.map +1 -1
  244. package/dist/providers/plugins/sso/sso.setup-steps.d.ts.map +1 -1
  245. package/dist/providers/plugins/sso/sso.setup-steps.js +39 -22
  246. package/dist/providers/plugins/sso/sso.setup-steps.js.map +1 -1
  247. package/dist/utils/interactive.d.ts +14 -0
  248. package/dist/utils/interactive.d.ts.map +1 -0
  249. package/dist/utils/interactive.js +16 -0
  250. package/dist/utils/interactive.js.map +1 -0
  251. package/package.json +6 -5
  252. package/scripts/copy-plugins.js +6 -0
  253. package/scripts/release.sh +54 -0
@@ -0,0 +1,3 @@
1
+ export { PiPlugin, PiPluginMetadata } from './pi.plugin.js';
2
+ export { PiSessionAdapter } from './pi.session.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { PiPlugin, PiPluginMetadata } from './pi.plugin.js';
2
+ export { PiSessionAdapter } from './pi.session.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Materializes the CodeMie run-ledger extension into Pi's agent directory, and
3
+ * reads back the ledger it produces.
4
+ *
5
+ * The ledger replaces post-hoc transcript attribution: instead of scanning Pi's
6
+ * session directory afterwards and inferring which files this run wrote, the
7
+ * extension records each transcript from inside Pi as it is opened. See
8
+ * `extension/README.md` for why, and for the constraints the asset operates under.
9
+ */
10
+ /** Absolute ledger path, handed to the extension so it holds no layout assumptions. */
11
+ export declare const LEDGER_PATH_ENV = "CODEMIE_PI_LEDGER";
12
+ export interface PiExtensionStatus {
13
+ installed: boolean;
14
+ path?: string;
15
+ reason?: 'disabled' | 'source-missing' | 'selftest-failed' | 'write-failed';
16
+ }
17
+ export interface PiRunLedger {
18
+ /** True when the extension ran at all. False means the run produced no attributable data. */
19
+ loaded: boolean;
20
+ /** Transcripts this run wrote, deduped, existence-filtered, in first-seen order. */
21
+ transcripts: string[];
22
+ /** The last transcript the run was writing — the one to correlate the session record to. */
23
+ primaryTranscript?: string;
24
+ /** Pi's own session id for `primaryTranscript`. */
25
+ piSessionId?: string;
26
+ /** The transcript's cwd, which `--session <path>` makes differ from the launch cwd. */
27
+ cwd?: string;
28
+ /** `/name` prompt-template invocations, which never reach the transcript. */
29
+ commandInvocations: Record<string, number>;
30
+ /** `/skill:name` invocations, corroborating the transcript's `<skill>` wrapper. */
31
+ skillCommandInvocations: Record<string, number>;
32
+ }
33
+ /**
34
+ * `~/.codemie/sessions/{sessionId}_pi-run.jsonl`, beside the metrics and conversation
35
+ * JSONL files. The `.jsonl` suffix keeps it clear of every consumer that enumerates
36
+ * session records, all of which filter on `.json`.
37
+ */
38
+ export declare function getPiRunLedgerPath(sessionId: string): string;
39
+ /**
40
+ * Copy the extension into Pi's agent dir, then prove it loads.
41
+ *
42
+ * Pi turns any extension load failure into `process.exit(1)`, so a corrupted or
43
+ * truncated asset would kill the user's session rather than merely lose metrics.
44
+ * The pre-flight import below is the same check Pi performs (`typeof factory ===
45
+ * 'function'`); failing it here deletes the copy, so Pi never sees it.
46
+ *
47
+ * Never throws: every failure degrades to `{installed: false}`.
48
+ */
49
+ export declare function ensurePiCodeMieExtension(cwd?: string, env?: NodeJS.ProcessEnv, sourceDir?: string): Promise<PiExtensionStatus>;
50
+ /**
51
+ * Read the ledger the extension wrote during the run.
52
+ *
53
+ * Malformed lines are skipped individually rather than failing the read — a
54
+ * truncated final line after a hard kill must not discard the records before it.
55
+ * Transcript paths are existence-filtered because `getSessionFile()` reports the
56
+ * path Pi *plans* to write, and Pi does not create the file until the session holds
57
+ * an assistant message.
58
+ */
59
+ export declare function readPiRunLedger(sessionId: string): Promise<PiRunLedger>;
60
+ //# sourceMappingURL=pi.extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.extension.d.ts","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.extension.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiBH,uFAAuF;AACvF,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAEnD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,UAAU,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,cAAc,CAAC;CAC7E;AAED,MAAM,WAAW,WAAW;IAC1B,6FAA6F;IAC7F,MAAM,EAAE,OAAO,CAAC;IAChB,oFAAoF;IACpF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,4FAA4F;IAC5F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,mFAAmF;IACnF,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5D;AAMD;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,GAAE,MAAsB,EAC3B,GAAG,GAAE,MAAM,CAAC,UAAwB,EAGpC,SAAS,GAAE,MAAuD,GACjE,OAAO,CAAC,iBAAiB,CAAC,CA0C5B;AAkDD;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAiE7E"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Materializes the CodeMie run-ledger extension into Pi's agent directory, and
3
+ * reads back the ledger it produces.
4
+ *
5
+ * The ledger replaces post-hoc transcript attribution: instead of scanning Pi's
6
+ * session directory afterwards and inferring which files this run wrote, the
7
+ * extension records each transcript from inside Pi as it is opened. See
8
+ * `extension/README.md` for why, and for the constraints the asset operates under.
9
+ */
10
+ import { createHash } from 'crypto';
11
+ import { existsSync } from 'fs';
12
+ import { mkdir, readFile, readdir, rm, writeFile } from 'fs/promises';
13
+ import { join } from 'path';
14
+ import { pathToFileURL } from 'url';
15
+ import { logger } from '../../../utils/logger.js';
16
+ import { getCodemiePath, getDirname } from '../../../utils/paths.js';
17
+ import { getPiAgentDir } from './pi.paths.js';
18
+ /** Directory name under `<piAgentDir>/extensions/` that holds the materialized asset. */
19
+ const EXTENSION_DIR_NAME = 'codemie-metrics';
20
+ /** Set to `1` to skip installation entirely and remove any previously installed copy. */
21
+ const DISABLE_ENV = 'CODEMIE_PI_EXTENSION_DISABLED';
22
+ /** Absolute ledger path, handed to the extension so it holds no layout assumptions. */
23
+ export const LEDGER_PATH_ENV = 'CODEMIE_PI_LEDGER';
24
+ /**
25
+ * `~/.codemie/sessions/{sessionId}_pi-run.jsonl`, beside the metrics and conversation
26
+ * JSONL files. The `.jsonl` suffix keeps it clear of every consumer that enumerates
27
+ * session records, all of which filter on `.json`.
28
+ */
29
+ export function getPiRunLedgerPath(sessionId) {
30
+ return getCodemiePath('sessions', `${sessionId}_pi-run.jsonl`);
31
+ }
32
+ function emptyLedger() {
33
+ return { loaded: false, transcripts: [], commandInvocations: {}, skillCommandInvocations: {} };
34
+ }
35
+ /**
36
+ * Copy the extension into Pi's agent dir, then prove it loads.
37
+ *
38
+ * Pi turns any extension load failure into `process.exit(1)`, so a corrupted or
39
+ * truncated asset would kill the user's session rather than merely lose metrics.
40
+ * The pre-flight import below is the same check Pi performs (`typeof factory ===
41
+ * 'function'`); failing it here deletes the copy, so Pi never sees it.
42
+ *
43
+ * Never throws: every failure degrades to `{installed: false}`.
44
+ */
45
+ export async function ensurePiCodeMieExtension(cwd = process.cwd(), env = process.env,
46
+ // Defaulted rather than resolved inline so the self-test failure path — the one
47
+ // that stands between a corrupted asset and `pi` exiting 1 — is reachable in tests.
48
+ sourceDir = join(getDirname(import.meta.url), 'extension')) {
49
+ const targetDir = join(getPiAgentDir(cwd), 'extensions', EXTENSION_DIR_NAME);
50
+ if (env[DISABLE_ENV] === '1') {
51
+ await removeExtension(targetDir);
52
+ return { installed: false, reason: 'disabled' };
53
+ }
54
+ try {
55
+ const files = await readSourceFiles(sourceDir);
56
+ if (!files) {
57
+ logger.debug(`[pi-extension] Source assets not found at ${sourceDir}; run ledger disabled`);
58
+ return { installed: false, reason: 'source-missing' };
59
+ }
60
+ await mkdir(targetDir, { recursive: true });
61
+ for (const [name, content] of Object.entries(files)) {
62
+ const targetPath = join(targetDir, name);
63
+ // Rewrite only on change: an untouched mtime keeps Pi's `/reload` quiet and
64
+ // avoids churn in a directory the user may be watching.
65
+ if (await fileMatches(targetPath, content))
66
+ continue;
67
+ await writeFile(targetPath, content, 'utf-8');
68
+ }
69
+ const entryPath = join(targetDir, 'index.js');
70
+ if (!(await exportsFactory(entryPath, files['index.js']))) {
71
+ await removeExtension(targetDir);
72
+ logger.warn('[pi-extension] Run-ledger extension failed its load self-test and was removed. '
73
+ + 'Pi will start normally; this run will report no tool metrics.');
74
+ return { installed: false, reason: 'selftest-failed' };
75
+ }
76
+ logger.debug(`[pi-extension] Run ledger installed at ${targetDir}`);
77
+ return { installed: true, path: targetDir };
78
+ }
79
+ catch (error) {
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ logger.warn(`[pi-extension] Could not install the run-ledger extension: ${message}`);
82
+ await removeExtension(targetDir);
83
+ return { installed: false, reason: 'write-failed' };
84
+ }
85
+ }
86
+ /** Read every asset the extension directory ships. Returns undefined when it is absent. */
87
+ async function readSourceFiles(sourceDir) {
88
+ if (!existsSync(sourceDir))
89
+ return undefined;
90
+ const files = {};
91
+ for (const name of await readdir(sourceDir)) {
92
+ // README.md is documentation for maintainers, not part of what Pi loads.
93
+ if (name !== 'index.js' && name !== 'package.json')
94
+ continue;
95
+ files[name] = await readFile(join(sourceDir, name), 'utf-8');
96
+ }
97
+ return files['index.js'] && files['package.json'] ? files : undefined;
98
+ }
99
+ async function fileMatches(path, content) {
100
+ try {
101
+ return (await readFile(path, 'utf-8')) === content;
102
+ }
103
+ catch {
104
+ return false;
105
+ }
106
+ }
107
+ /**
108
+ * Import the materialized copy and check it exports a factory function, matching
109
+ * Pi's own acceptance test. The content hash busts Node's module cache so a
110
+ * rewritten asset is re-checked rather than resolved to the previous version.
111
+ */
112
+ async function exportsFactory(entryPath, content) {
113
+ try {
114
+ const cacheKey = createHash('sha1').update(content).digest('hex').slice(0, 12);
115
+ const module = (await import(`${pathToFileURL(entryPath).href}?v=${cacheKey}`));
116
+ return typeof module.default === 'function';
117
+ }
118
+ catch (error) {
119
+ const message = error instanceof Error ? error.message : String(error);
120
+ logger.debug(`[pi-extension] Self-test import failed: ${message}`);
121
+ return false;
122
+ }
123
+ }
124
+ async function removeExtension(targetDir) {
125
+ try {
126
+ await rm(targetDir, { recursive: true, force: true });
127
+ }
128
+ catch {
129
+ // Leaving a stale copy is survivable; failing the run is not.
130
+ }
131
+ }
132
+ /**
133
+ * Read the ledger the extension wrote during the run.
134
+ *
135
+ * Malformed lines are skipped individually rather than failing the read — a
136
+ * truncated final line after a hard kill must not discard the records before it.
137
+ * Transcript paths are existence-filtered because `getSessionFile()` reports the
138
+ * path Pi *plans* to write, and Pi does not create the file until the session holds
139
+ * an assistant message.
140
+ */
141
+ export async function readPiRunLedger(sessionId) {
142
+ const ledger = emptyLedger();
143
+ const ledgerPath = getPiRunLedgerPath(sessionId);
144
+ let raw;
145
+ try {
146
+ raw = await readFile(ledgerPath, 'utf-8');
147
+ }
148
+ catch {
149
+ logger.debug(`[pi-extension] No run ledger at ${ledgerPath}`);
150
+ return ledger;
151
+ }
152
+ const seen = new Set();
153
+ for (const line of raw.split('\n')) {
154
+ const trimmed = line.trim();
155
+ if (!trimmed)
156
+ continue;
157
+ let record;
158
+ try {
159
+ record = JSON.parse(trimmed);
160
+ }
161
+ catch {
162
+ continue;
163
+ }
164
+ switch (record.t) {
165
+ case 'boot':
166
+ ledger.loaded = true;
167
+ break;
168
+ case 'session':
169
+ case 'shutdown': {
170
+ // The last record wins for cwd and identity: a run that forked or switched
171
+ // sessions ends attached to the file it was writing when it stopped.
172
+ if (typeof record.cwd === 'string' && record.cwd)
173
+ ledger.cwd = record.cwd;
174
+ const file = record.file;
175
+ if (typeof file !== 'string' || !file || !existsSync(file))
176
+ break;
177
+ if (!seen.has(file)) {
178
+ seen.add(file);
179
+ ledger.transcripts.push(file);
180
+ }
181
+ ledger.primaryTranscript = file;
182
+ ledger.piSessionId = typeof record.piSessionId === 'string' ? record.piSessionId : undefined;
183
+ break;
184
+ }
185
+ case 'cmd': {
186
+ const name = record.name;
187
+ if (typeof name !== 'string' || !name)
188
+ break;
189
+ const target = record.kind === 'skill' ? ledger.skillCommandInvocations : ledger.commandInvocations;
190
+ target[name] = (target[name] ?? 0) + 1;
191
+ break;
192
+ }
193
+ default:
194
+ break;
195
+ }
196
+ }
197
+ logger.debug(`[pi-extension] Ledger for ${sessionId}: loaded=${ledger.loaded}, `
198
+ + `${ledger.transcripts.length} transcript(s), cwd=${ledger.cwd ?? 'unset'}`);
199
+ return ledger;
200
+ }
201
+ //# sourceMappingURL=pi.extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.extension.js","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.extension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Pi Incremental Sync Timer
3
+ *
4
+ * Pi has no hook surface that fires mid-run, so without this timer a session's
5
+ * metrics exist only in memory until `onSessionEnd` flushes them. A SIGKILL, a
6
+ * closed terminal, or an OS shutdown therefore loses the entire run. Ticking every
7
+ * ~30 s writes per-record metric deltas to JSONL and uploads whatever is PENDING,
8
+ * so at most one interval's worth of work is ever at risk.
9
+ *
10
+ * Which transcripts to process is read from the run ledger the CodeMie extension
11
+ * writes from inside Pi — never inferred from the session directory. A directory
12
+ * listing cannot tell this run's transcripts from a concurrent `pi`'s, and claiming
13
+ * one uploads a stranger's prompts under this user's identity.
14
+ *
15
+ * @see pi.extension.ts
16
+ */
17
+ import type { ProcessingContext } from '../../../agents/core/session/BaseProcessor.js';
18
+ import type { SessionAdapter } from '../../../agents/core/session/BaseSessionAdapter.js';
19
+ import type { AgentMetadata } from '../../../agents/core/types.js';
20
+ export interface StartPiIncrementalSyncOptions {
21
+ /** CodeMie session id — names both the ledger and the metric JSONL files. */
22
+ sessionId: string;
23
+ /** Pi agent metadata, used to build the default session adapter. */
24
+ metadata: AgentMetadata;
25
+ /** Builds a fresh ProcessingContext on each tick (cookies/version may rotate). */
26
+ buildContext: () => ProcessingContext;
27
+ /** CodeMie SSO URL used to load stored credentials (e.g. env.CODEMIE_URL). */
28
+ ssoUrl?: string;
29
+ /** Sync API base URL for the upload context (env.CODEMIE_SYNC_API_URL ?? env.CODEMIE_BASE_URL). */
30
+ syncApiUrl?: string;
31
+ /** CLI version string forwarded to the upload context. */
32
+ cliVersion?: string;
33
+ /** Overrides the default and the env interval. Injected by tests. */
34
+ intervalMs?: number;
35
+ /** Overrides the default `PiSessionAdapter`. Injected by tests. */
36
+ adapter?: SessionAdapter;
37
+ }
38
+ export declare function startPiIncrementalSync(options: StartPiIncrementalSyncOptions): void;
39
+ /**
40
+ * Stop ticking and wait — for a bounded time — on a tick that is already running.
41
+ *
42
+ * The wait is the point. `clearInterval` cancels the *schedule*, not the tick already
43
+ * executing, and the caller's next move is the end-of-session flush over the same
44
+ * `{sessionId}_metrics.jsonl`. Both read the file's record ids before either appends, so
45
+ * an overlap appends the same deltas twice — and the sync path uploads pending records
46
+ * without deduplicating them by record id.
47
+ *
48
+ * The bound is the point too. This runs on the way out of the CLI, and the tick's upload
49
+ * is a 30 s API timeout over three attempts *per batch*: waiting it out would hang the
50
+ * exit for minutes whenever the sync host black-holes traffic. So the tick is first told
51
+ * to skip its upload — the phase that can take minutes and that appends nothing — and only
52
+ * the remainder is awaited, under {@link STOP_DRAIN_TIMEOUT_MS}.
53
+ *
54
+ * If the bound expires the tick was already mid-upload, and the hazard accepted is the
55
+ * inverse of the double-append: `MetricsSyncProcessor` finishes by rewriting the whole
56
+ * metrics file from the snapshot it read, so deltas the session-end flush appends in the
57
+ * meantime can be dropped. One truncated shutdown is the price of never hanging every
58
+ * user whose network is down.
59
+ */
60
+ export declare function stopPiIncrementalSync(sessionId: string,
61
+ /** Overrides {@link STOP_DRAIN_TIMEOUT_MS}. Injected by tests. */
62
+ drainTimeoutMs?: number): Promise<void>;
63
+ //# sourceMappingURL=pi.incremental-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.incremental-sync.d.ts","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.incremental-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAM5D,MAAM,WAAW,6BAA6B;IAC5C,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,QAAQ,EAAE,aAAa,CAAC;IACxB,kFAAkF;IAClF,YAAY,EAAE,MAAM,iBAAiB,CAAC;IACtC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AA2BD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,IAAI,CAyBnF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM;AACjB,kEAAkE;AAClE,cAAc,GAAE,MAA8B,GAC7C,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Pi Incremental Sync Timer
3
+ *
4
+ * Pi has no hook surface that fires mid-run, so without this timer a session's
5
+ * metrics exist only in memory until `onSessionEnd` flushes them. A SIGKILL, a
6
+ * closed terminal, or an OS shutdown therefore loses the entire run. Ticking every
7
+ * ~30 s writes per-record metric deltas to JSONL and uploads whatever is PENDING,
8
+ * so at most one interval's worth of work is ever at risk.
9
+ *
10
+ * Which transcripts to process is read from the run ledger the CodeMie extension
11
+ * writes from inside Pi — never inferred from the session directory. A directory
12
+ * listing cannot tell this run's transcripts from a concurrent `pi`'s, and claiming
13
+ * one uploads a stranger's prompts under this user's identity.
14
+ *
15
+ * @see pi.extension.ts
16
+ */
17
+ import { resolve } from 'path';
18
+ import { logger } from '../../../utils/logger.js';
19
+ import { readPiRunLedger } from './pi.extension.js';
20
+ import { PiSessionAdapter } from './pi.session.js';
21
+ /** Set to `false` to run Pi without the mid-run flush. */
22
+ const DISABLE_ENV = 'CODEMIE_PI_SYNC_ENABLED';
23
+ const INTERVAL_ENV = 'CODEMIE_PI_SYNC_INTERVAL_MS';
24
+ const DEFAULT_INTERVAL_MS = 30_000;
25
+ /**
26
+ * How long `stop` waits for a tick that is already running before abandoning it.
27
+ *
28
+ * It is a backstop, not the mechanism: `stop` first tells the tick to skip its upload, so
29
+ * what it normally waits for is a local transcript parse. The bound only matters when the
30
+ * tick was already inside the upload, which no signal can interrupt.
31
+ */
32
+ const STOP_DRAIN_TIMEOUT_MS = 5_000;
33
+ const activeTimers = new Map();
34
+ const inFlightTicks = new Map();
35
+ export function startPiIncrementalSync(options) {
36
+ if (process.env[DISABLE_ENV] === 'false') {
37
+ logger.debug(`[pi-incremental-sync] Disabled by ${DISABLE_ENV}=false`);
38
+ return;
39
+ }
40
+ if (activeTimers.has(options.sessionId)) {
41
+ logger.debug(`[pi-incremental-sync] Already running for session ${options.sessionId}`);
42
+ return;
43
+ }
44
+ const intervalMs = resolveIntervalMs(options.intervalMs);
45
+ const timer = setInterval(() => {
46
+ scheduleTick(options);
47
+ }, intervalMs);
48
+ // Don't pin the Node event loop alive solely on this timer; when Pi finishes, the
49
+ // parent must be free to exit rather than wait out an interval.
50
+ if (typeof timer.unref === 'function') {
51
+ timer.unref();
52
+ }
53
+ activeTimers.set(options.sessionId, timer);
54
+ logger.debug(`[pi-incremental-sync] Started (session=${options.sessionId}, intervalMs=${intervalMs})`);
55
+ }
56
+ /**
57
+ * Stop ticking and wait — for a bounded time — on a tick that is already running.
58
+ *
59
+ * The wait is the point. `clearInterval` cancels the *schedule*, not the tick already
60
+ * executing, and the caller's next move is the end-of-session flush over the same
61
+ * `{sessionId}_metrics.jsonl`. Both read the file's record ids before either appends, so
62
+ * an overlap appends the same deltas twice — and the sync path uploads pending records
63
+ * without deduplicating them by record id.
64
+ *
65
+ * The bound is the point too. This runs on the way out of the CLI, and the tick's upload
66
+ * is a 30 s API timeout over three attempts *per batch*: waiting it out would hang the
67
+ * exit for minutes whenever the sync host black-holes traffic. So the tick is first told
68
+ * to skip its upload — the phase that can take minutes and that appends nothing — and only
69
+ * the remainder is awaited, under {@link STOP_DRAIN_TIMEOUT_MS}.
70
+ *
71
+ * If the bound expires the tick was already mid-upload, and the hazard accepted is the
72
+ * inverse of the double-append: `MetricsSyncProcessor` finishes by rewriting the whole
73
+ * metrics file from the snapshot it read, so deltas the session-end flush appends in the
74
+ * meantime can be dropped. One truncated shutdown is the price of never hanging every
75
+ * user whose network is down.
76
+ */
77
+ export async function stopPiIncrementalSync(sessionId,
78
+ /** Overrides {@link STOP_DRAIN_TIMEOUT_MS}. Injected by tests. */
79
+ drainTimeoutMs = STOP_DRAIN_TIMEOUT_MS) {
80
+ const timer = activeTimers.get(sessionId);
81
+ if (timer) {
82
+ clearInterval(timer);
83
+ activeTimers.delete(sessionId);
84
+ }
85
+ const inFlight = inFlightTicks.get(sessionId);
86
+ if (inFlight) {
87
+ inFlight.stopping.abort();
88
+ await drainTick(sessionId, inFlight.done, drainTimeoutMs);
89
+ }
90
+ if (timer || inFlight) {
91
+ logger.debug(`[pi-incremental-sync] Stopped (session=${sessionId})`);
92
+ }
93
+ }
94
+ /** Await the tick, giving up after `timeoutMs` so a stuck upload cannot hold the CLI open. */
95
+ async function drainTick(sessionId, done, timeoutMs) {
96
+ let timer;
97
+ const expiry = new Promise((resolveExpiry) => {
98
+ timer = setTimeout(() => resolveExpiry('expired'), timeoutMs);
99
+ });
100
+ try {
101
+ const outcome = await Promise.race([done.then(() => 'drained'), expiry]);
102
+ if (outcome === 'expired') {
103
+ logger.warn(`[pi-incremental-sync] Gave up waiting for the in-flight tick after ${timeoutMs} ms `
104
+ + `(session=${sessionId}); it is most likely still uploading`);
105
+ }
106
+ }
107
+ finally {
108
+ clearTimeout(timer);
109
+ }
110
+ }
111
+ function resolveIntervalMs(override) {
112
+ if (override !== undefined && override > 0)
113
+ return override;
114
+ // A non-positive delay is not "use the default" to Node: it clamps to 1 ms, so a
115
+ // mistyped env var turns the timer into a hot loop that re-parses every transcript.
116
+ const fromEnv = Number(process.env[INTERVAL_ENV]);
117
+ return Number.isFinite(fromEnv) && fromEnv > 0 ? fromEnv : DEFAULT_INTERVAL_MS;
118
+ }
119
+ /**
120
+ * Run a tick unless one is already running, and publish it so `stop` can await it.
121
+ *
122
+ * Re-entrancy is guarded rather than queued: a tick that outruns the interval means
123
+ * the transcripts are large, and stacking another parse on top would only compound
124
+ * that. The skipped work is picked up by the next tick, which re-reads the ledger.
125
+ */
126
+ function scheduleTick(options) {
127
+ const { sessionId } = options;
128
+ if (inFlightTicks.has(sessionId)) {
129
+ logger.debug(`[pi-incremental-sync] Tick still running, skipping (session=${sessionId})`);
130
+ return;
131
+ }
132
+ const stopping = new AbortController();
133
+ const done = runTick(options, stopping.signal).finally(() => {
134
+ // Only retract our own entry: a stop/start cycle may have published a newer tick.
135
+ if (inFlightTicks.get(sessionId)?.done === done) {
136
+ inFlightTicks.delete(sessionId);
137
+ }
138
+ });
139
+ inFlightTicks.set(sessionId, { done, stopping });
140
+ }
141
+ /**
142
+ * Process every transcript the ledger attributes to this run, then push what the
143
+ * processors wrote.
144
+ */
145
+ async function runTick(options, stopping) {
146
+ try {
147
+ const ledger = await readPiRunLedger(options.sessionId);
148
+ if (ledger.transcripts.length === 0) {
149
+ logger.debug(`[pi-incremental-sync] No transcripts yet for session ${options.sessionId}`);
150
+ return;
151
+ }
152
+ const adapter = options.adapter ?? new PiSessionAdapter(options.metadata);
153
+ const gitBranch = await resolveRunGitBranch(options.sessionId, ledger.cwd);
154
+ for (const transcript of ledger.transcripts) {
155
+ try {
156
+ const result = await adapter.processSession(transcript, options.sessionId, buildTickContext(options, gitBranch));
157
+ logger.debug(`[pi-incremental-sync] tick ok session=${options.sessionId} `
158
+ + `transcript=${transcript} records=${result.totalRecords}`);
159
+ }
160
+ catch (error) {
161
+ // One unreadable transcript must not strand the others in the same run.
162
+ logger.error(`[pi-incremental-sync] processSession failed for ${transcript}:`, error);
163
+ }
164
+ }
165
+ // Everything above appends to the metrics JSONL, so it is drained in full; the upload
166
+ // only reads and rewrites it, and it is the phase that can take minutes. A stop that
167
+ // lands before it starts skips it outright — the session-end flush that follows syncs
168
+ // exactly what this upload would have.
169
+ if (stopping.aborted) {
170
+ logger.debug(`[pi-incremental-sync] Stopping, so this tick skips its upload (session=${options.sessionId})`);
171
+ return;
172
+ }
173
+ await uploadPending(options);
174
+ }
175
+ catch (error) {
176
+ logger.error('[pi-incremental-sync] tick failed:', error);
177
+ }
178
+ }
179
+ /**
180
+ * The processing context for one mid-run tick.
181
+ *
182
+ * Two things separate it from the end-of-session context: the branch, which the metrics
183
+ * aggregator emits one record per, so deltas written without it land in a second,
184
+ * unattributed bucket for the same session; and the terminality of a missing tool result,
185
+ * which mid-run means "still running" rather than "never finished".
186
+ *
187
+ * The resolved branch outranks any the caller's context carries, because the caller can
188
+ * only know the branch CodeMie was launched on — which is the wrong one precisely when the
189
+ * two differ. See {@link resolveRunGitBranch}.
190
+ */
191
+ function buildTickContext(options, gitBranch) {
192
+ return {
193
+ ...options.buildContext(),
194
+ ...(gitBranch && { gitBranch }),
195
+ emitUnresolvedToolCalls: false,
196
+ };
197
+ }
198
+ /**
199
+ * The branch this run's deltas belong under — the one the end-of-run correlation settles on.
200
+ *
201
+ * `correlateRunToSession` rewrites the session record's branch at session end whenever the
202
+ * ledger's cwd is a different checkout than the one CodeMie was launched from, which is
203
+ * what `codemie pi --session /other/repo/x.jsonl` does. The aggregator emits one record per
204
+ * distinct branch, so a tick that stamped the launch branch would split a single session
205
+ * across two branch records. Reading the cwd the ledger records about itself is identity,
206
+ * not attribution.
207
+ */
208
+ async function resolveRunGitBranch(sessionId, ledgerCwd) {
209
+ try {
210
+ const { SessionStore } = await import('../../../agents/core/session/SessionStore.js');
211
+ const session = await new SessionStore().loadSession(sessionId);
212
+ if (ledgerCwd &&
213
+ session?.workingDirectory &&
214
+ resolve(ledgerCwd) !== resolve(session.workingDirectory)) {
215
+ const { detectGitBranch } = await import('../../../utils/processes.js');
216
+ return (await detectGitBranch(ledgerCwd)) ?? session.gitBranch;
217
+ }
218
+ return session?.gitBranch;
219
+ }
220
+ catch (error) {
221
+ logger.debug('[pi-incremental-sync] Could not resolve the run git branch:', error);
222
+ return undefined;
223
+ }
224
+ }
225
+ async function uploadPending(options) {
226
+ if (!options.ssoUrl || !options.syncApiUrl)
227
+ return;
228
+ try {
229
+ const uploadContext = await buildUploadContext(options.sessionId, options.ssoUrl, options.syncApiUrl, options.cliVersion);
230
+ if (!uploadContext)
231
+ return;
232
+ const { SessionSyncer } = await import('../../../providers/plugins/sso/session/SessionSyncer.js');
233
+ const result = await new SessionSyncer().sync(options.sessionId, uploadContext);
234
+ logger.debug(`[pi-incremental-sync] upload ${result.success ? 'ok' : 'partial'}: ${result.message}`);
235
+ }
236
+ catch (error) {
237
+ // An upload failure leaves the payloads PENDING; the next tick retries them.
238
+ logger.error('[pi-incremental-sync] upload failed:', error);
239
+ }
240
+ }
241
+ async function buildUploadContext(sessionId, ssoUrl, syncApiUrl, version = '0.0.0') {
242
+ try {
243
+ const { CodeMieSSO } = await import('../../../providers/plugins/sso/sso.auth.js');
244
+ const credentials = await new CodeMieSSO().getStoredCredentials(ssoUrl);
245
+ if (!credentials?.cookies) {
246
+ logger.debug('[pi-incremental-sync] No SSO credentials available, skipping upload');
247
+ return null;
248
+ }
249
+ const cookies = Object.entries(credentials.cookies)
250
+ .map(([name, value]) => `${name}=${value}`)
251
+ .join('; ');
252
+ return {
253
+ apiBaseUrl: syncApiUrl,
254
+ cookies,
255
+ clientType: 'codemie-pi',
256
+ version,
257
+ dryRun: false,
258
+ sessionId,
259
+ };
260
+ }
261
+ catch (error) {
262
+ logger.debug('[pi-incremental-sync] Failed to build upload context:', error);
263
+ return null;
264
+ }
265
+ }
266
+ //# sourceMappingURL=pi.incremental-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.incremental-sync.js","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.incremental-sync.ts"],"names":[],"mappings":"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"}