@oratis/lisa 0.9.0 → 0.11.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 (296) hide show
  1. package/README.md +123 -16
  2. package/README.zh-CN.md +101 -15
  3. package/completions/_lisa +56 -0
  4. package/completions/lisa.bash +35 -1
  5. package/completions/lisa.fish +18 -1
  6. package/dist/advisor/engine.d.ts +7 -0
  7. package/dist/advisor/engine.d.ts.map +1 -1
  8. package/dist/advisor/engine.js +12 -0
  9. package/dist/advisor/engine.js.map +1 -1
  10. package/dist/agent.d.ts +14 -0
  11. package/dist/agent.d.ts.map +1 -1
  12. package/dist/agent.js +58 -7
  13. package/dist/agent.js.map +1 -1
  14. package/dist/agents/managed.d.ts +108 -0
  15. package/dist/agents/managed.d.ts.map +1 -0
  16. package/dist/agents/managed.js +241 -0
  17. package/dist/agents/managed.js.map +1 -0
  18. package/dist/agents/pty.d.ts +155 -0
  19. package/dist/agents/pty.d.ts.map +1 -0
  20. package/dist/agents/pty.js +299 -0
  21. package/dist/agents/pty.js.map +1 -0
  22. package/dist/approval.d.ts +13 -0
  23. package/dist/approval.d.ts.map +1 -1
  24. package/dist/approval.js +25 -2
  25. package/dist/approval.js.map +1 -1
  26. package/dist/autonomy/runs.d.ts +33 -0
  27. package/dist/autonomy/runs.d.ts.map +1 -0
  28. package/dist/autonomy/runs.js +106 -0
  29. package/dist/autonomy/runs.js.map +1 -0
  30. package/dist/channels/feishu.d.ts.map +1 -1
  31. package/dist/channels/feishu.js +65 -0
  32. package/dist/channels/feishu.js.map +1 -1
  33. package/dist/channels/router.d.ts +7 -0
  34. package/dist/channels/router.d.ts.map +1 -1
  35. package/dist/channels/router.js +1 -1
  36. package/dist/channels/router.js.map +1 -1
  37. package/dist/cli/agents-pty.d.ts +18 -0
  38. package/dist/cli/agents-pty.d.ts.map +1 -0
  39. package/dist/cli/agents-pty.js +182 -0
  40. package/dist/cli/agents-pty.js.map +1 -0
  41. package/dist/cli/agents.d.ts +2 -0
  42. package/dist/cli/agents.d.ts.map +1 -0
  43. package/dist/cli/agents.js +65 -0
  44. package/dist/cli/agents.js.map +1 -0
  45. package/dist/cli/consent.d.ts +2 -0
  46. package/dist/cli/consent.d.ts.map +1 -0
  47. package/dist/cli/consent.js +57 -0
  48. package/dist/cli/consent.js.map +1 -0
  49. package/dist/cli/model.d.ts +2 -0
  50. package/dist/cli/model.d.ts.map +1 -0
  51. package/dist/cli/model.js +121 -0
  52. package/dist/cli/model.js.map +1 -0
  53. package/dist/cli/sense.d.ts +2 -0
  54. package/dist/cli/sense.d.ts.map +1 -0
  55. package/dist/cli/sense.js +36 -0
  56. package/dist/cli/sense.js.map +1 -0
  57. package/dist/cli.js +117 -12
  58. package/dist/cli.js.map +1 -1
  59. package/dist/consent/blacklist.d.ts +28 -0
  60. package/dist/consent/blacklist.d.ts.map +1 -0
  61. package/dist/consent/blacklist.js +78 -0
  62. package/dist/consent/blacklist.js.map +1 -0
  63. package/dist/consent/store.d.ts +45 -0
  64. package/dist/consent/store.d.ts.map +1 -0
  65. package/dist/consent/store.js +126 -0
  66. package/dist/consent/store.js.map +1 -0
  67. package/dist/control/policy.d.ts +13 -0
  68. package/dist/control/policy.d.ts.map +1 -0
  69. package/dist/control/policy.js +57 -0
  70. package/dist/control/policy.js.map +1 -0
  71. package/dist/heartbeat/runner.d.ts.map +1 -1
  72. package/dist/heartbeat/runner.js +70 -14
  73. package/dist/heartbeat/runner.js.map +1 -1
  74. package/dist/idle/runner.d.ts.map +1 -1
  75. package/dist/idle/runner.js +87 -17
  76. package/dist/idle/runner.js.map +1 -1
  77. package/dist/integrations/aider/observer.d.ts +21 -1
  78. package/dist/integrations/aider/observer.d.ts.map +1 -1
  79. package/dist/integrations/aider/observer.js +110 -1
  80. package/dist/integrations/aider/observer.js.map +1 -1
  81. package/dist/integrations/claude-code/liveness.d.ts +10 -0
  82. package/dist/integrations/claude-code/liveness.d.ts.map +1 -0
  83. package/dist/integrations/claude-code/liveness.js +62 -0
  84. package/dist/integrations/claude-code/liveness.js.map +1 -0
  85. package/dist/integrations/claude-code/watcher.d.ts +39 -4
  86. package/dist/integrations/claude-code/watcher.d.ts.map +1 -1
  87. package/dist/integrations/claude-code/watcher.js +94 -57
  88. package/dist/integrations/claude-code/watcher.js.map +1 -1
  89. package/dist/integrations/codex/observer.d.ts +19 -6
  90. package/dist/integrations/codex/observer.d.ts.map +1 -1
  91. package/dist/integrations/codex/observer.js +228 -4
  92. package/dist/integrations/codex/observer.js.map +1 -1
  93. package/dist/integrations/dispatch-ledger.d.ts +30 -1
  94. package/dist/integrations/dispatch-ledger.d.ts.map +1 -1
  95. package/dist/integrations/dispatch-ledger.js +75 -9
  96. package/dist/integrations/dispatch-ledger.js.map +1 -1
  97. package/dist/integrations/git/branch.d.ts +11 -0
  98. package/dist/integrations/git/branch.d.ts.map +1 -0
  99. package/dist/integrations/git/branch.js +49 -0
  100. package/dist/integrations/git/branch.js.map +1 -0
  101. package/dist/integrations/git/observer.d.ts +39 -0
  102. package/dist/integrations/git/observer.d.ts.map +1 -0
  103. package/dist/integrations/git/observer.js +252 -0
  104. package/dist/integrations/git/observer.js.map +1 -0
  105. package/dist/integrations/github-pr/observer.d.ts.map +1 -1
  106. package/dist/integrations/github-pr/observer.js +7 -2
  107. package/dist/integrations/github-pr/observer.js.map +1 -1
  108. package/dist/integrations/hub.d.ts +8 -0
  109. package/dist/integrations/hub.d.ts.map +1 -1
  110. package/dist/integrations/hub.js +39 -1
  111. package/dist/integrations/hub.js.map +1 -1
  112. package/dist/integrations/managed/observer.d.ts +17 -0
  113. package/dist/integrations/managed/observer.d.ts.map +1 -0
  114. package/dist/integrations/managed/observer.js +46 -0
  115. package/dist/integrations/managed/observer.js.map +1 -0
  116. package/dist/integrations/opencode/observer.d.ts +53 -5
  117. package/dist/integrations/opencode/observer.d.ts.map +1 -1
  118. package/dist/integrations/opencode/observer.js +242 -20
  119. package/dist/integrations/opencode/observer.js.map +1 -1
  120. package/dist/integrations/pty/observer.d.ts +25 -0
  121. package/dist/integrations/pty/observer.d.ts.map +1 -0
  122. package/dist/integrations/pty/observer.js +48 -0
  123. package/dist/integrations/pty/observer.js.map +1 -0
  124. package/dist/integrations/registry.d.ts.map +1 -1
  125. package/dist/integrations/registry.js +5 -0
  126. package/dist/integrations/registry.js.map +1 -1
  127. package/dist/integrations/shell/observer.d.ts +33 -0
  128. package/dist/integrations/shell/observer.d.ts.map +1 -0
  129. package/dist/integrations/shell/observer.js +223 -0
  130. package/dist/integrations/shell/observer.js.map +1 -0
  131. package/dist/integrations/takoapi/a2a.d.ts +38 -0
  132. package/dist/integrations/takoapi/a2a.d.ts.map +1 -0
  133. package/dist/integrations/takoapi/a2a.js +70 -0
  134. package/dist/integrations/takoapi/a2a.js.map +1 -0
  135. package/dist/integrations/takoapi/ledger.d.ts +32 -0
  136. package/dist/integrations/takoapi/ledger.d.ts.map +1 -0
  137. package/dist/integrations/takoapi/ledger.js +96 -0
  138. package/dist/integrations/takoapi/ledger.js.map +1 -0
  139. package/dist/integrations/takoapi/observer.d.ts +39 -0
  140. package/dist/integrations/takoapi/observer.d.ts.map +1 -0
  141. package/dist/integrations/takoapi/observer.js +102 -0
  142. package/dist/integrations/takoapi/observer.js.map +1 -0
  143. package/dist/integrations/types.d.ts +17 -0
  144. package/dist/integrations/types.d.ts.map +1 -1
  145. package/dist/mcp/client.d.ts +5 -0
  146. package/dist/mcp/client.d.ts.map +1 -1
  147. package/dist/mcp/client.js +1 -1
  148. package/dist/mcp/client.js.map +1 -1
  149. package/dist/memory/embedding.d.ts +45 -0
  150. package/dist/memory/embedding.d.ts.map +1 -0
  151. package/dist/memory/embedding.js +139 -0
  152. package/dist/memory/embedding.js.map +1 -0
  153. package/dist/memory/search_tool.d.ts.map +1 -1
  154. package/dist/memory/search_tool.js +6 -2
  155. package/dist/memory/search_tool.js.map +1 -1
  156. package/dist/memory/vector.d.ts +14 -3
  157. package/dist/memory/vector.d.ts.map +1 -1
  158. package/dist/memory/vector.js +50 -0
  159. package/dist/memory/vector.js.map +1 -1
  160. package/dist/model/local.d.ts +43 -0
  161. package/dist/model/local.d.ts.map +1 -0
  162. package/dist/model/local.js +118 -0
  163. package/dist/model/local.js.map +1 -0
  164. package/dist/model/plan-usage.d.ts +41 -0
  165. package/dist/model/plan-usage.d.ts.map +1 -0
  166. package/dist/model/plan-usage.js +168 -0
  167. package/dist/model/plan-usage.js.map +1 -0
  168. package/dist/model/plans.d.ts +73 -0
  169. package/dist/model/plans.d.ts.map +1 -0
  170. package/dist/model/plans.js +246 -0
  171. package/dist/model/plans.js.map +1 -0
  172. package/dist/orchestrator/recent-recap.d.ts +2 -0
  173. package/dist/orchestrator/recent-recap.d.ts.map +1 -0
  174. package/dist/orchestrator/recent-recap.js +20 -0
  175. package/dist/orchestrator/recent-recap.js.map +1 -0
  176. package/dist/providers/anthropic.d.ts +1 -0
  177. package/dist/providers/anthropic.d.ts.map +1 -1
  178. package/dist/providers/anthropic.js +10 -2
  179. package/dist/providers/anthropic.js.map +1 -1
  180. package/dist/providers/fallback.d.ts +23 -0
  181. package/dist/providers/fallback.d.ts.map +1 -0
  182. package/dist/providers/fallback.js +29 -0
  183. package/dist/providers/fallback.js.map +1 -0
  184. package/dist/providers/gemini.d.ts +2 -0
  185. package/dist/providers/gemini.d.ts.map +1 -1
  186. package/dist/providers/gemini.js +24 -10
  187. package/dist/providers/gemini.js.map +1 -1
  188. package/dist/providers/openai.d.ts.map +1 -1
  189. package/dist/providers/openai.js +4 -1
  190. package/dist/providers/openai.js.map +1 -1
  191. package/dist/providers/registry.d.ts +18 -2
  192. package/dist/providers/registry.d.ts.map +1 -1
  193. package/dist/providers/registry.js +56 -9
  194. package/dist/providers/registry.js.map +1 -1
  195. package/dist/reflect.d.ts +55 -0
  196. package/dist/reflect.d.ts.map +1 -1
  197. package/dist/reflect.js +148 -54
  198. package/dist/reflect.js.map +1 -1
  199. package/dist/sense/log.d.ts +9 -0
  200. package/dist/sense/log.d.ts.map +1 -0
  201. package/dist/sense/log.js +63 -0
  202. package/dist/sense/log.js.map +1 -0
  203. package/dist/sense/screen.d.ts +43 -0
  204. package/dist/sense/screen.d.ts.map +1 -0
  205. package/dist/sense/screen.js +107 -0
  206. package/dist/sense/screen.js.map +1 -0
  207. package/dist/sense/service.d.ts +16 -0
  208. package/dist/sense/service.d.ts.map +1 -0
  209. package/dist/sense/service.js +33 -0
  210. package/dist/sense/service.js.map +1 -0
  211. package/dist/sense/types.d.ts +35 -0
  212. package/dist/sense/types.d.ts.map +1 -0
  213. package/dist/sense/types.js +11 -0
  214. package/dist/sense/types.js.map +1 -0
  215. package/dist/sense/voice.d.ts +28 -0
  216. package/dist/sense/voice.d.ts.map +1 -0
  217. package/dist/sense/voice.js +64 -0
  218. package/dist/sense/voice.js.map +1 -0
  219. package/dist/soul/git.d.ts.map +1 -1
  220. package/dist/soul/git.js +35 -16
  221. package/dist/soul/git.js.map +1 -1
  222. package/dist/soul/store.d.ts +22 -0
  223. package/dist/soul/store.d.ts.map +1 -1
  224. package/dist/soul/store.js +69 -14
  225. package/dist/soul/store.js.map +1 -1
  226. package/dist/soul/summary.d.ts +10 -0
  227. package/dist/soul/summary.d.ts.map +1 -0
  228. package/dist/soul/summary.js +57 -0
  229. package/dist/soul/summary.js.map +1 -0
  230. package/dist/soul/tools.d.ts.map +1 -1
  231. package/dist/soul/tools.js +13 -24
  232. package/dist/soul/tools.js.map +1 -1
  233. package/dist/soul/types.d.ts +9 -0
  234. package/dist/soul/types.d.ts.map +1 -1
  235. package/dist/soul/types.js.map +1 -1
  236. package/dist/subagent.d.ts +7 -0
  237. package/dist/subagent.d.ts.map +1 -1
  238. package/dist/subagent.js +3 -1
  239. package/dist/subagent.js.map +1 -1
  240. package/dist/tools/dispatch_agent.d.ts +13 -1
  241. package/dist/tools/dispatch_agent.d.ts.map +1 -1
  242. package/dist/tools/dispatch_agent.js +56 -12
  243. package/dist/tools/dispatch_agent.js.map +1 -1
  244. package/dist/tools/dispatch_status.d.ts +22 -0
  245. package/dist/tools/dispatch_status.d.ts.map +1 -0
  246. package/dist/tools/dispatch_status.js +57 -0
  247. package/dist/tools/dispatch_status.js.map +1 -0
  248. package/dist/tools/registry.d.ts +29 -0
  249. package/dist/tools/registry.d.ts.map +1 -1
  250. package/dist/tools/registry.js +67 -0
  251. package/dist/tools/registry.js.map +1 -1
  252. package/dist/tools/run_on_plan.d.ts +46 -0
  253. package/dist/tools/run_on_plan.d.ts.map +1 -0
  254. package/dist/tools/run_on_plan.js +89 -0
  255. package/dist/tools/run_on_plan.js.map +1 -0
  256. package/dist/tools/takoapi.d.ts +60 -0
  257. package/dist/tools/takoapi.d.ts.map +1 -0
  258. package/dist/tools/takoapi.js +181 -0
  259. package/dist/tools/takoapi.js.map +1 -0
  260. package/dist/tools/validate.d.ts +22 -0
  261. package/dist/tools/validate.d.ts.map +1 -0
  262. package/dist/tools/validate.js +50 -0
  263. package/dist/tools/validate.js.map +1 -0
  264. package/dist/web/agent-roster.d.ts +56 -0
  265. package/dist/web/agent-roster.d.ts.map +1 -0
  266. package/dist/web/agent-roster.js +109 -0
  267. package/dist/web/agent-roster.js.map +1 -0
  268. package/dist/web/devices.d.ts +27 -0
  269. package/dist/web/devices.d.ts.map +1 -0
  270. package/dist/web/devices.js +113 -0
  271. package/dist/web/devices.js.map +1 -0
  272. package/dist/web/island.d.ts +5 -1
  273. package/dist/web/island.d.ts.map +1 -1
  274. package/dist/web/island.js +410 -63
  275. package/dist/web/island.js.map +1 -1
  276. package/dist/web/lisa-client.d.ts +20 -0
  277. package/dist/web/lisa-client.d.ts.map +1 -0
  278. package/dist/web/lisa-client.js +1323 -0
  279. package/dist/web/lisa-client.js.map +1 -0
  280. package/dist/web/lisa-css.d.ts +13 -0
  281. package/dist/web/lisa-css.d.ts.map +1 -0
  282. package/dist/web/lisa-css.js +1163 -0
  283. package/dist/web/lisa-css.js.map +1 -0
  284. package/dist/web/lisa-html.d.ts +1 -1
  285. package/dist/web/lisa-html.d.ts.map +1 -1
  286. package/dist/web/lisa-html.js +15 -2136
  287. package/dist/web/lisa-html.js.map +1 -1
  288. package/dist/web/push.d.ts +76 -0
  289. package/dist/web/push.d.ts.map +1 -0
  290. package/dist/web/push.js +163 -0
  291. package/dist/web/push.js.map +1 -0
  292. package/dist/web/server.d.ts +19 -0
  293. package/dist/web/server.d.ts.map +1 -1
  294. package/dist/web/server.js +878 -64
  295. package/dist/web/server.js.map +1 -1
  296. package/package.json +5 -2
@@ -0,0 +1,41 @@
1
+ import type { PlanId } from "./plans.js";
2
+ /** Claude subscription limits reset on a rolling ~5h basis. */
3
+ export declare const WINDOW_HOURS = 5;
4
+ export interface PlanUsage {
5
+ /** Gross tokens (input + output + cache create + cache read) in the rolling window. */
6
+ windowTokens: number;
7
+ windowHours: number;
8
+ /** Gross tokens since local midnight. */
9
+ todayTokens: number;
10
+ /** Transcript files that contributed to the window/today. */
11
+ sessions: number;
12
+ }
13
+ interface UsageEntry {
14
+ atMs: number;
15
+ tokens: number;
16
+ }
17
+ /** Sum the billable token fields from a Claude `usage` object. Pure. */
18
+ export declare function usageTokens(u: Record<string, unknown>): number;
19
+ /** Local midnight (ms) for the day containing nowMs. Pure-ish (no Date.now). */
20
+ export declare function startOfLocalDay(nowMs: number): number;
21
+ /** Bucket timestamped token entries into rolling-window + today sums. Pure. */
22
+ export declare function aggregateUsage(entries: UsageEntry[], nowMs: number, windowMs: number, dayStartMs: number): {
23
+ windowTokens: number;
24
+ todayTokens: number;
25
+ };
26
+ /**
27
+ * Read Claude Code's local transcripts and sum token usage over the rolling
28
+ * window + today. Returns null if the projects dir is absent/unreadable.
29
+ */
30
+ export declare function readClaudeUsage(opts: {
31
+ home?: string;
32
+ nowMs: number;
33
+ }): PlanUsage | null;
34
+ /** Usage for a plan, or null if it has no readable local token log. */
35
+ export declare function planUsage(id: PlanId, nowMs: number): PlanUsage | null;
36
+ /** Compact token count, e.g. 1234567 → "1.2M". Pure. */
37
+ export declare function formatTokens(n: number): string;
38
+ /** One-line usage summary, e.g. "1.2M tok in 5h · 4.8M today". Pure. */
39
+ export declare function formatUsage(u: PlanUsage): string;
40
+ export {};
41
+ //# sourceMappingURL=plan-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-usage.d.ts","sourceRoot":"","sources":["../../src/model/plan-usage.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,+DAA+D;AAC/D,eAAO,MAAM,YAAY,IAAI,CAAC;AAI9B,MAAM,WAAW,SAAS;IACxB,uFAAuF;IACvF,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAO9D;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAC5B,OAAO,EAAE,UAAU,EAAE,EACrB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAS/C;AA6BD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAAG,IAAI,CAwDxF;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGrE;AAED,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9C;AAED,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Real coding-plan usage (CODING_PLANS Phase 5a) — honest, local, no faked %.
3
+ *
4
+ * Subscription plans are rate-limited, not metered, and the per-window limit
5
+ * isn't published in token terms — so we do NOT invent a "headroom %". What we
6
+ * CAN show truthfully is *consumption*: Claude Code records per-turn token usage
7
+ * in its local transcripts (`~/.claude/projects/**​/*.jsonl`), each line stamped
8
+ * with a `timestamp` and a `message.usage` object. Summing those over Claude's
9
+ * rolling ~5-hour limit window (and since local midnight) is real usage from
10
+ * local data — the same `usage` field the claude-code observer already reads, so
11
+ * the metadata-not-payload privacy posture holds (we read token COUNTS and
12
+ * timestamps only, never message content).
13
+ *
14
+ * Codex / Copilot have no comparable standard local token log, so usage is null
15
+ * for them rather than guessed.
16
+ */
17
+ import { readdirSync, statSync, readFileSync } from "node:fs";
18
+ import { homedir } from "node:os";
19
+ import { join } from "node:path";
20
+ /** Claude subscription limits reset on a rolling ~5h basis. */
21
+ export const WINDOW_HOURS = 5;
22
+ /** Safety cap on transcript files scanned per call (newest first). */
23
+ const MAX_FILES = 80;
24
+ function num(v) {
25
+ return typeof v === "number" && Number.isFinite(v) ? v : 0;
26
+ }
27
+ /** Sum the billable token fields from a Claude `usage` object. Pure. */
28
+ export function usageTokens(u) {
29
+ return (num(u.input_tokens) +
30
+ num(u.output_tokens) +
31
+ num(u.cache_creation_input_tokens) +
32
+ num(u.cache_read_input_tokens));
33
+ }
34
+ /** Local midnight (ms) for the day containing nowMs. Pure-ish (no Date.now). */
35
+ export function startOfLocalDay(nowMs) {
36
+ const d = new Date(nowMs);
37
+ d.setHours(0, 0, 0, 0);
38
+ return d.getTime();
39
+ }
40
+ /** Bucket timestamped token entries into rolling-window + today sums. Pure. */
41
+ export function aggregateUsage(entries, nowMs, windowMs, dayStartMs) {
42
+ const windowStart = nowMs - windowMs;
43
+ let windowTokens = 0;
44
+ let todayTokens = 0;
45
+ for (const e of entries) {
46
+ if (e.atMs >= windowStart)
47
+ windowTokens += e.tokens;
48
+ if (e.atMs >= dayStartMs)
49
+ todayTokens += e.tokens;
50
+ }
51
+ return { windowTokens, todayTokens };
52
+ }
53
+ /** Recursively collect `*.jsonl` paths under dir (Claude nests one level). */
54
+ function listTranscripts(dir) {
55
+ const out = [];
56
+ const walk = (d, depth) => {
57
+ let ents;
58
+ try {
59
+ ents = readdirSync(d, { withFileTypes: true });
60
+ }
61
+ catch {
62
+ return;
63
+ }
64
+ for (const ent of ents) {
65
+ const p = join(d, ent.name);
66
+ if (ent.isDirectory()) {
67
+ if (depth < 3)
68
+ walk(p, depth + 1);
69
+ }
70
+ else if (ent.isFile() && ent.name.endsWith(".jsonl")) {
71
+ try {
72
+ out.push({ path: p, mtimeMs: statSync(p).mtimeMs });
73
+ }
74
+ catch {
75
+ /* unreadable → skip */
76
+ }
77
+ }
78
+ }
79
+ };
80
+ walk(dir, 0);
81
+ return out;
82
+ }
83
+ /**
84
+ * Read Claude Code's local transcripts and sum token usage over the rolling
85
+ * window + today. Returns null if the projects dir is absent/unreadable.
86
+ */
87
+ export function readClaudeUsage(opts) {
88
+ const home = opts.home ?? process.env.CLAUDE_HOME ?? join(homedir(), ".claude");
89
+ const projects = join(home, "projects");
90
+ const nowMs = opts.nowMs;
91
+ const windowMs = WINDOW_HOURS * 3_600_000;
92
+ const dayStart = startOfLocalDay(nowMs);
93
+ const scanFrom = Math.min(nowMs - windowMs, dayStart);
94
+ let files;
95
+ try {
96
+ files = listTranscripts(projects);
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ if (files.length === 0)
102
+ return null;
103
+ // Only files touched within the scan window can hold in-window entries.
104
+ // Newest first, capped, so a heavy history can't make this unbounded.
105
+ const recent = files
106
+ .filter((f) => f.mtimeMs >= scanFrom)
107
+ .sort((a, b) => b.mtimeMs - a.mtimeMs)
108
+ .slice(0, MAX_FILES);
109
+ const entries = [];
110
+ let sessions = 0;
111
+ for (const f of recent) {
112
+ let raw;
113
+ try {
114
+ raw = readFileSync(f.path, "utf8");
115
+ }
116
+ catch {
117
+ continue;
118
+ }
119
+ let contributed = false;
120
+ for (const line of raw.split("\n")) {
121
+ if (!line)
122
+ continue;
123
+ let e;
124
+ try {
125
+ e = JSON.parse(line);
126
+ }
127
+ catch {
128
+ continue;
129
+ }
130
+ const atMs = Date.parse(typeof e.timestamp === "string" ? e.timestamp : "");
131
+ if (!Number.isFinite(atMs) || atMs < scanFrom)
132
+ continue;
133
+ const u = e.message?.usage;
134
+ if (!u || typeof u !== "object")
135
+ continue;
136
+ const tokens = usageTokens(u);
137
+ if (tokens > 0) {
138
+ entries.push({ atMs, tokens });
139
+ contributed = true;
140
+ }
141
+ }
142
+ if (contributed)
143
+ sessions++;
144
+ }
145
+ const { windowTokens, todayTokens } = aggregateUsage(entries, nowMs, windowMs, dayStart);
146
+ return { windowTokens, windowHours: WINDOW_HOURS, todayTokens, sessions };
147
+ }
148
+ /** Usage for a plan, or null if it has no readable local token log. */
149
+ export function planUsage(id, nowMs) {
150
+ if (id === "claude")
151
+ return readClaudeUsage({ nowMs });
152
+ return null; // codex / copilot: no standard local token log
153
+ }
154
+ /** Compact token count, e.g. 1234567 → "1.2M". Pure. */
155
+ export function formatTokens(n) {
156
+ if (n >= 1e9)
157
+ return (n / 1e9).toFixed(1) + "B";
158
+ if (n >= 1e6)
159
+ return (n / 1e6).toFixed(1) + "M";
160
+ if (n >= 1e3)
161
+ return Math.round(n / 1e3) + "K";
162
+ return String(n);
163
+ }
164
+ /** One-line usage summary, e.g. "1.2M tok in 5h · 4.8M today". Pure. */
165
+ export function formatUsage(u) {
166
+ return `${formatTokens(u.windowTokens)} tok in ${u.windowHours}h · ${formatTokens(u.todayTokens)} today`;
167
+ }
168
+ //# sourceMappingURL=plan-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-usage.js","sourceRoot":"","sources":["../../src/model/plan-usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ export type PlanId = "claude" | "codex" | "copilot";
2
+ export declare const PLAN_IDS: readonly PlanId[];
3
+ export interface PlanStatus {
4
+ id: PlanId;
5
+ /** Human label, e.g. "Claude Pro/Max". */
6
+ label: string;
7
+ /** The vendor CLI that owns this plan's auth. */
8
+ cli: string;
9
+ /** Resolved binary path/name, or null if not found. */
10
+ binary: string | null;
11
+ /** Is the CLI installed (binary present)? */
12
+ available: boolean;
13
+ /**
14
+ * Best-effort login signal from credential *presence* (never contents):
15
+ * true = a credential file / token env was found, false = looked and found
16
+ * none, null = can't tell (e.g. macOS Keychain — opaque without reading it).
17
+ */
18
+ loggedIn: boolean | null;
19
+ /** Short human hint about state / how to enable. */
20
+ detail: string;
21
+ }
22
+ /** Injectable view of the host used for presence-only detection. Pure inputs. */
23
+ export interface PlanProbe {
24
+ home: string;
25
+ platform: NodeJS.Platform;
26
+ env: Record<string, string | undefined>;
27
+ /** Does a file/dir exist at this absolute path? */
28
+ exists(p: string): boolean;
29
+ /** Directory entries, or [] on any error. */
30
+ readdir(p: string): string[];
31
+ /** Is `cmd` an executable on PATH (or an existing absolute path)? */
32
+ onPath(cmd: string): boolean;
33
+ }
34
+ /** The real host probe (filesystem + PATH + env). */
35
+ export declare function defaultPlanProbe(): PlanProbe;
36
+ /** Is `cmd` resolvable on PATH? Absolute/relative paths are checked directly. Pure-ish. */
37
+ export declare function onPath(cmd: string, env: Record<string, string | undefined>): boolean;
38
+ /** Parse a `plan://<id>` reference into a known PlanId, else null. Pure. */
39
+ export declare function parsePlanRef(ref: string): PlanId | null;
40
+ /** Currently selected coding-plan delegation target, if any (LISA_CODING_PLAN). */
41
+ export declare function selectedPlan(env?: Record<string, string | undefined>): PlanId | null;
42
+ /** Detect one plan's status. */
43
+ export declare function detectPlan(id: PlanId, probe?: PlanProbe): PlanStatus;
44
+ /** Detect every known plan. */
45
+ export declare function detectPlans(probe?: PlanProbe): PlanStatus[];
46
+ /**
47
+ * The headless dispatch CLI kind a plan delegates through. Each plan id is also
48
+ * its CLI kind in launchAgent: claude → `claude -p`, codex → `codex exec`,
49
+ * copilot → `copilot -p`.
50
+ */
51
+ export declare function planDispatchKind(id: PlanId): "claude" | "codex" | "copilot";
52
+ export interface PlanPreflight {
53
+ ok: boolean;
54
+ /** Why delegation can't proceed (only when ok=false). */
55
+ reason?: string;
56
+ }
57
+ /**
58
+ * Can we delegate coding work to this detected plan right now? Pure. A null
59
+ * (unknown) login passes — on macOS the credential lives in the Keychain and
60
+ * "installed but login unverifiable" should not block; the CLI itself will
61
+ * prompt if truly logged out.
62
+ */
63
+ export declare function planPreflight(status: PlanStatus): PlanPreflight;
64
+ /** Status glyph: ✓ logged in · ✗ unavailable/logged-out · ? installed, login unknown. Pure. */
65
+ export declare function planMark(s: PlanStatus): "✓" | "✗" | "?";
66
+ /**
67
+ * One-line coding-plan summary for surfaces like `lisa agents`. Pure. Shows the
68
+ * selected delegation target (★) and each plan's glyph. Headroom/rate-limit
69
+ * numbers are intentionally omitted — they'd need version-fragile parsing of the
70
+ * vendor CLI's output, and a wrong number is worse than none.
71
+ */
72
+ export declare function planSummaryLine(statuses: PlanStatus[], selected: PlanId | null): string;
73
+ //# sourceMappingURL=plans.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../../src/model/plans.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpD,eAAO,MAAM,QAAQ,EAAE,SAAS,MAAM,EAAmC,CAAC;AAE1E,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,mDAAmD;IACnD,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,6CAA6C;IAC7C,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,qEAAqE;IACrE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B;AAED,qDAAqD;AACrD,wBAAgB,gBAAgB,IAAI,SAAS,CAsB5C;AAED,2FAA2F;AAC3F,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAsBpF;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKvD;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,MAAM,GAAG,IAAI,CAGjG;AAkGD,gCAAgC;AAChC,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,GAAE,SAA8B,GAAG,UAAU,CASxF;AAED,+BAA+B;AAC/B,wBAAgB,WAAW,CAAC,KAAK,GAAE,SAA8B,GAAG,UAAU,EAAE,CAE/E;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAE3E;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAK/D;AAID,+FAA+F;AAC/F,wBAAgB,QAAQ,CAAC,CAAC,EAAE,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAIvD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAIvF"}
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Coding-plan backends (CODING_PLANS.md, Phase 1 — detection + picker).
3
+ *
4
+ * A "coding plan" is a flat-rate subscription (Claude Pro/Max, a ChatGPT plan
5
+ * via Codex, GitHub Copilot) that the user already pays for. LISA can spend that
6
+ * budget on *coding work* by DELEGATING to the vendor's own CLI — never by
7
+ * extracting or replaying its subscription token (Anthropic's terms forbid that,
8
+ * and enforced it against OpenClaw; see docs/CODING_PLANS.md).
9
+ *
10
+ * This module is the Phase-1 slice: *detect* which plan CLIs are installed /
11
+ * logged in, and *select* one as the default delegation target. It performs NO
12
+ * authentication and reads NO secrets — detection is presence-only (binary on
13
+ * PATH / credential file exists), exactly the metadata-not-payload posture of
14
+ * every LISA observer. Actually routing coding work to the selected plan is a
15
+ * later phase that builds on the existing PTY bridge (src/agents/pty.ts).
16
+ *
17
+ * The probe (filesystem / PATH / env) is injectable so detection is unit-testable
18
+ * without a real claude/codex install.
19
+ */
20
+ import { existsSync, readdirSync } from "node:fs";
21
+ import { homedir } from "node:os";
22
+ import { join } from "node:path";
23
+ export const PLAN_IDS = ["claude", "codex", "copilot"];
24
+ /** The real host probe (filesystem + PATH + env). */
25
+ export function defaultPlanProbe() {
26
+ const env = process.env;
27
+ return {
28
+ home: homedir(),
29
+ platform: process.platform,
30
+ env,
31
+ exists: (p) => {
32
+ try {
33
+ return existsSync(p);
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ },
39
+ readdir: (p) => {
40
+ try {
41
+ return readdirSync(p);
42
+ }
43
+ catch {
44
+ return [];
45
+ }
46
+ },
47
+ onPath: (cmd) => onPath(cmd, env),
48
+ };
49
+ }
50
+ /** Is `cmd` resolvable on PATH? Absolute/relative paths are checked directly. Pure-ish. */
51
+ export function onPath(cmd, env) {
52
+ if (cmd.includes("/") || cmd.includes("\\")) {
53
+ try {
54
+ return existsSync(cmd);
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ }
60
+ const isWin = process.platform === "win32";
61
+ const sep = isWin ? ";" : ":";
62
+ const exts = isWin ? ["", ".exe", ".cmd", ".bat"] : [""];
63
+ for (const dir of (env.PATH ?? "").split(sep)) {
64
+ if (!dir)
65
+ continue;
66
+ for (const ext of exts) {
67
+ try {
68
+ if (existsSync(join(dir, cmd + ext)))
69
+ return true;
70
+ }
71
+ catch {
72
+ /* unreadable dir → skip */
73
+ }
74
+ }
75
+ }
76
+ return false;
77
+ }
78
+ /** Parse a `plan://<id>` reference into a known PlanId, else null. Pure. */
79
+ export function parsePlanRef(ref) {
80
+ const m = ref.match(/^plan:\/\/(.+)$/i);
81
+ if (!m)
82
+ return null;
83
+ const id = m[1].trim().toLowerCase();
84
+ return PLAN_IDS.includes(id) ? id : null;
85
+ }
86
+ /** Currently selected coding-plan delegation target, if any (LISA_CODING_PLAN). */
87
+ export function selectedPlan(env = process.env) {
88
+ const v = (env.LISA_CODING_PLAN ?? "").trim().toLowerCase();
89
+ return PLAN_IDS.includes(v) ? v : null;
90
+ }
91
+ // ── per-plan detection (presence-only) ───────────────────────────────────────
92
+ function cmpVersionDesc(a, b) {
93
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
94
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
95
+ for (let i = 0; i < 3; i++)
96
+ if ((pb[i] || 0) !== (pa[i] || 0))
97
+ return (pb[i] || 0) - (pa[i] || 0);
98
+ return 0;
99
+ }
100
+ /** Newest app-bundled `claude` binary on macOS (mirrors pty.detectClaudeBinary). */
101
+ function claudeAppBundle(probe) {
102
+ if (probe.platform !== "darwin")
103
+ return null;
104
+ const root = join(probe.home, "Library", "Application Support", "Claude", "claude-code");
105
+ const versions = probe.readdir(root).filter((v) => /^\d+\.\d+\.\d+/.test(v)).sort(cmpVersionDesc);
106
+ for (const v of versions) {
107
+ const bin = join(root, v, "claude.app", "Contents", "MacOS", "claude");
108
+ if (probe.exists(bin))
109
+ return bin;
110
+ }
111
+ return null;
112
+ }
113
+ function detectClaude(probe) {
114
+ const override = probe.env.LISA_PTY_CLAUDE_CMD;
115
+ const binary = override
116
+ ? probe.onPath(override)
117
+ ? override
118
+ : null
119
+ : (claudeAppBundle(probe) ?? (probe.onPath("claude") ? "claude" : null));
120
+ // Login: token env, else credentials file (Linux/Windows). On macOS the creds
121
+ // live in the Keychain (opaque) → unknown rather than "logged out".
122
+ const configDir = probe.env.CLAUDE_CONFIG_DIR
123
+ ? probe.env.CLAUDE_CONFIG_DIR
124
+ : join(probe.home, ".claude");
125
+ let loggedIn;
126
+ if (probe.env.CLAUDE_CODE_OAUTH_TOKEN || probe.env.ANTHROPIC_AUTH_TOKEN)
127
+ loggedIn = true;
128
+ else if (probe.exists(join(configDir, ".credentials.json")))
129
+ loggedIn = true;
130
+ else if (probe.platform === "darwin")
131
+ loggedIn = null; // Keychain — can't tell from presence
132
+ else
133
+ loggedIn = false;
134
+ return {
135
+ id: "claude",
136
+ label: "Claude Pro/Max",
137
+ cli: "claude",
138
+ binary,
139
+ available: binary !== null,
140
+ loggedIn,
141
+ detail: hint(binary !== null, loggedIn, "claude", "`claude` (Claude Code)"),
142
+ };
143
+ }
144
+ function detectCodex(probe) {
145
+ const cli = probe.env.LISA_PTY_CODEX_CMD || "codex";
146
+ const binary = probe.onPath(cli) ? cli : null;
147
+ const codexHome = probe.env.CODEX_HOME ? probe.env.CODEX_HOME : join(probe.home, ".codex");
148
+ // auth.json exists → logged in. Absent could mean OS-keyring storage → unknown.
149
+ const loggedIn = probe.exists(join(codexHome, "auth.json")) ? true : binary ? null : false;
150
+ return {
151
+ id: "codex",
152
+ label: "ChatGPT plan (Codex)",
153
+ cli: "codex",
154
+ binary,
155
+ available: binary !== null,
156
+ loggedIn,
157
+ detail: hint(binary !== null, loggedIn, "codex", "`codex` (OpenAI Codex)"),
158
+ };
159
+ }
160
+ function detectCopilot(probe) {
161
+ // The delegate target is the standalone agentic `copilot` CLI, which runs a
162
+ // task non-interactively via `copilot -p "<task>"`. The older `gh copilot`
163
+ // (suggest/explain) is NOT agentic and can't run a task, so it doesn't count.
164
+ const binary = probe.onPath("copilot") ? "copilot" : null;
165
+ // Copilot login sits behind GitHub auth — not cheaply checkable without
166
+ // spawning, so: installed → unknown, absent → false.
167
+ const loggedIn = binary ? null : false;
168
+ return {
169
+ id: "copilot",
170
+ label: "GitHub Copilot",
171
+ cli: "copilot",
172
+ binary,
173
+ available: binary !== null,
174
+ loggedIn,
175
+ detail: binary
176
+ ? "installed — login state unknown (GitHub auth)"
177
+ : "install the GitHub Copilot CLI (`copilot`) to enable",
178
+ };
179
+ }
180
+ function hint(available, loggedIn, loginCmd, what) {
181
+ if (!available)
182
+ return `install ${what} to enable`;
183
+ if (loggedIn === true)
184
+ return "ready";
185
+ if (loggedIn === false)
186
+ return `installed — run \`${loginCmd} login\` to sign in`;
187
+ return "installed — login state unknown (stored in the OS keychain)";
188
+ }
189
+ /** Detect one plan's status. */
190
+ export function detectPlan(id, probe = defaultPlanProbe()) {
191
+ switch (id) {
192
+ case "claude":
193
+ return detectClaude(probe);
194
+ case "codex":
195
+ return detectCodex(probe);
196
+ case "copilot":
197
+ return detectCopilot(probe);
198
+ }
199
+ }
200
+ /** Detect every known plan. */
201
+ export function detectPlans(probe = defaultPlanProbe()) {
202
+ return PLAN_IDS.map((id) => detectPlan(id, probe));
203
+ }
204
+ // ── delegation (CODING_PLANS Phase 2) ────────────────────────────────────────
205
+ /**
206
+ * The headless dispatch CLI kind a plan delegates through. Each plan id is also
207
+ * its CLI kind in launchAgent: claude → `claude -p`, codex → `codex exec`,
208
+ * copilot → `copilot -p`.
209
+ */
210
+ export function planDispatchKind(id) {
211
+ return id; // each plan id is also its headless dispatch CLI kind
212
+ }
213
+ /**
214
+ * Can we delegate coding work to this detected plan right now? Pure. A null
215
+ * (unknown) login passes — on macOS the credential lives in the Keychain and
216
+ * "installed but login unverifiable" should not block; the CLI itself will
217
+ * prompt if truly logged out.
218
+ */
219
+ export function planPreflight(status) {
220
+ if (!status.available)
221
+ return { ok: false, reason: `${status.cli} isn't installed — ${status.detail}` };
222
+ if (status.loggedIn === false)
223
+ return { ok: false, reason: `${status.cli} is installed but not logged in — ${status.detail}` };
224
+ return { ok: true };
225
+ }
226
+ // ── surfacing (CODING_PLANS Phase 4) ─────────────────────────────────────────
227
+ /** Status glyph: ✓ logged in · ✗ unavailable/logged-out · ? installed, login unknown. Pure. */
228
+ export function planMark(s) {
229
+ if (!s.available || s.loggedIn === false)
230
+ return "✗";
231
+ if (s.loggedIn === true)
232
+ return "✓";
233
+ return "?";
234
+ }
235
+ /**
236
+ * One-line coding-plan summary for surfaces like `lisa agents`. Pure. Shows the
237
+ * selected delegation target (★) and each plan's glyph. Headroom/rate-limit
238
+ * numbers are intentionally omitted — they'd need version-fragile parsing of the
239
+ * vendor CLI's output, and a wrong number is worse than none.
240
+ */
241
+ export function planSummaryLine(statuses, selected) {
242
+ const bits = statuses.map((s) => `${s.label} ${planMark(s)}${s.id === selected ? " ★" : ""}`);
243
+ const head = selected ? `coding plan → ${selected}` : "coding plan → none selected";
244
+ return `${head} · ${bits.join(" · ")}`;
245
+ }
246
+ //# sourceMappingURL=plans.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plans.js","sourceRoot":"","sources":["../../src/model/plans.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function recentAgentRecap(windowMs?: number, now?: number): string | null;
2
+ //# sourceMappingURL=recent-recap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recent-recap.d.ts","sourceRoot":"","sources":["../../src/orchestrator/recent-recap.ts"],"names":[],"mappings":"AAaA,wBAAgB,gBAAgB,CAC9B,QAAQ,GAAE,MAAwB,EAClC,GAAG,GAAE,MAAmB,GACvB,MAAM,GAAG,IAAI,CAKf"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Recent agent-fleet recap, ready to inject into Lisa's self-driven runs
3
+ * (PLAN_REVE_v1.0 R5). The orchestrator journal records what every agent did;
4
+ * before this, that record was write-only — reflection and heartbeat never read
5
+ * it. This composes journal + recap so Lisa can factor "what my fleet did" into
6
+ * how she reflects and what she pursues.
7
+ *
8
+ * Returns null when there was no activity in the window, so callers can inject
9
+ * conditionally. Structural metadata only (no prompts/replies/file contents).
10
+ */
11
+ import { eventsSince } from "./journal.js";
12
+ import { buildRecap, formatRecap } from "./recap.js";
13
+ export function recentAgentRecap(windowMs = 2 * 60 * 60_000, now = Date.now()) {
14
+ const sinceMs = now - windowMs;
15
+ const recap = buildRecap(eventsSince(sinceMs), sinceMs, now);
16
+ if (recap.totalSessions === 0)
17
+ return null;
18
+ return formatRecap(recap);
19
+ }
20
+ //# sourceMappingURL=recent-recap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recent-recap.js","sourceRoot":"","sources":["../../src/orchestrator/recent-recap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,CAAC,GAAG,EAAE,GAAG,MAAM,EAClC,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,MAAM,OAAO,GAAG,GAAG,GAAG,QAAQ,CAAC;IAC/B,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7D,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
@@ -4,6 +4,7 @@ export declare class AnthropicProvider implements Provider {
4
4
  private client;
5
5
  constructor(opts?: {
6
6
  apiKey?: string;
7
+ authToken?: string;
7
8
  baseURL?: string;
8
9
  });
9
10
  runTurn(opts: ProviderRunOpts): Promise<ProviderResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,qBAAa,iBAAkB,YAAW,QAAQ;IAChD,QAAQ,CAAC,IAAI,eAAe;IAC5B,OAAO,CAAC,MAAM,CAAY;gBAEd,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;IActD,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;CAyD9D"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,qBAAa,iBAAkB,YAAW,QAAQ;IAChD,QAAQ,CAAC,IAAI,eAAe;IAC5B,OAAO,CAAC,MAAM,CAAY;gBAEd,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;IAmB1E,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;CAgE9D"}
@@ -10,8 +10,13 @@ export class AnthropicProvider {
10
10
  // baseURL overrides the default https://api.anthropic.com — used to
11
11
  // route through an Anthropic-compatible proxy (one-api, openrouter,
12
12
  // self-hosted relay) when direct access is blocked.
13
+ // authToken sends `Authorization: Bearer …` instead of the default
14
+ // `x-api-key` header — the sanctioned path for an Anthropic-compatible
15
+ // LLM gateway / proxy (matches Claude Code's ANTHROPIC_AUTH_TOKEN). When
16
+ // set it takes precedence over apiKey, so callers pass one or the other.
13
17
  this.client = new Anthropic({
14
18
  apiKey: opts.apiKey,
19
+ authToken: opts.authToken,
15
20
  baseURL: opts.baseURL,
16
21
  fetch: proxyAwareFetch,
17
22
  });
@@ -43,12 +48,15 @@ export class AnthropicProvider {
43
48
  }
44
49
  const onText = (delta) => opts.handlers?.onTextDelta?.(delta);
45
50
  const onThinking = (delta) => opts.handlers?.onThinkingDelta?.(delta);
51
+ // Second argument is the SDK's per-request options; `signal` aborts the
52
+ // in-flight HTTP stream (the SDK then throws APIUserAbortError).
53
+ const requestOpts = { signal: opts.signal };
46
54
  let message;
47
55
  if (opts.compaction) {
48
56
  const stream = this.client.beta.messages.stream({
49
57
  ...params,
50
58
  ...extras,
51
- });
59
+ }, requestOpts);
52
60
  if (opts.handlers?.onTextDelta)
53
61
  stream.on("text", onText);
54
62
  if (opts.handlers?.onThinkingDelta)
@@ -56,7 +64,7 @@ export class AnthropicProvider {
56
64
  message = (await stream.finalMessage());
57
65
  }
58
66
  else {
59
- const stream = this.client.messages.stream(params);
67
+ const stream = this.client.messages.stream(params, requestOpts);
60
68
  if (opts.handlers?.onTextDelta)
61
69
  stream.on("text", onText);
62
70
  if (opts.handlers?.onThinkingDelta)