@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,45 @@
1
+ /** A sensitive ambient signal. Open-ended, but these are the canonical ones. */
2
+ export type ConsentSignal = "screen" | "voice" | "clipboard" | "selection" | (string & {});
3
+ /** The ambient-sense signals — all OFF until the user explicitly grants each. */
4
+ export declare const SENSE_SIGNALS: ConsentSignal[];
5
+ /** Human-facing "what does enabling this capture?" — shown on the consent card. */
6
+ export declare const SIGNAL_DESCRIPTIONS: Record<string, string>;
7
+ export interface ConsentGrant {
8
+ granted: boolean;
9
+ /** ISO timestamp of the most recent grant. */
10
+ grantedAt?: string;
11
+ /** Per-signal options (e.g. { retentionDays, everySec }). */
12
+ options?: Record<string, unknown>;
13
+ }
14
+ export interface ConsentState {
15
+ grants: Record<string, ConsentGrant>;
16
+ }
17
+ /** Read the consent state; tolerant of a missing or corrupt file (all-off). */
18
+ export declare function loadConsent(): ConsentState;
19
+ /**
20
+ * THE GATE. True only if the signal has been explicitly granted. Absent /
21
+ * revoked / corrupt-file → false (fail closed). Every source calls this before
22
+ * capturing.
23
+ */
24
+ export declare function isGranted(signal: ConsentSignal): boolean;
25
+ /** Grant a signal (records grantedAt + optional options). Returns new state. */
26
+ export declare function grant(signal: ConsentSignal, options?: Record<string, unknown>, now?: number): ConsentState;
27
+ /** Revoke one signal (keeps a record that it's off). Returns new state. */
28
+ export declare function revoke(signal: ConsentSignal): ConsentState;
29
+ /** One-tap stop-all: flip every known grant off. Returns new state. */
30
+ export declare function revokeAll(): ConsentState;
31
+ export interface ConsentRow {
32
+ signal: string;
33
+ granted: boolean;
34
+ grantedAt?: string;
35
+ options?: Record<string, unknown>;
36
+ }
37
+ /** All canonical signals + any extra recorded ones, with current status. */
38
+ export declare function listGrants(): ConsentRow[];
39
+ /**
40
+ * Retention primitive: is a captured item past its retention window? Pure;
41
+ * sources/cleanup call this so raw never lingers past `retentionDays`.
42
+ * retentionDays ≤ 0 / non-finite → treated as "expire immediately" (fail safe).
43
+ */
44
+ export declare function isExpired(capturedAtMs: number, retentionDays: number, now?: number): boolean;
45
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/consent/store.ts"],"names":[],"mappings":"AAoBA,gFAAgF;AAChF,MAAM,MAAM,aAAa,GACrB,QAAQ,GACR,OAAO,GACP,WAAW,GACX,WAAW,GACX,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,iFAAiF;AACjF,eAAO,MAAM,aAAa,EAAE,aAAa,EAAkD,CAAC;AAE5F,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKtD,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACtC;AAWD,+EAA+E;AAC/E,wBAAgB,WAAW,IAAI,YAAY,CAgB1C;AAQD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAExD;AAED,gFAAgF;AAChF,wBAAgB,KAAK,CACnB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,GAAG,GAAE,MAAmB,GACvB,YAAY,CASd;AAED,2EAA2E;AAC3E,wBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,CAK1D;AAED,uEAAuE;AACvE,wBAAgB,SAAS,IAAI,YAAY,CAYxC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,IAAI,UAAU,EAAE,CAYzC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAGT"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Unified consent store (FOUNDATIONS §1 — the master constraint for Sense).
3
+ *
4
+ * Single source of truth at ~/.lisa/consent.json. Every sensitive ambient
5
+ * signal source (screen / voice / clipboard / selection) must check
6
+ * `isGranted(signal)` before it captures anything — ungranted → no-op, never
7
+ * "capture first, ask later". Default is ALL OFF: an absent signal is denied.
8
+ *
9
+ * This is the framework S2 (ambient vision/voice) builds on; it ships before any
10
+ * source so the gate exists from day one. UI surfacing (island SENSE indicator
11
+ * + one-tap revoke) lands with the first source — the CLI (`lisa consent`) gives
12
+ * control in the meantime.
13
+ *
14
+ * Back-compat: a brand-new, independent file; its absence means "nothing
15
+ * granted", i.e. exactly the pre-existing behavior.
16
+ */
17
+ import fs from "node:fs";
18
+ import os from "node:os";
19
+ import path from "node:path";
20
+ /** The ambient-sense signals — all OFF until the user explicitly grants each. */
21
+ export const SENSE_SIGNALS = ["screen", "voice", "clipboard", "selection"];
22
+ /** Human-facing "what does enabling this capture?" — shown on the consent card. */
23
+ export const SIGNAL_DESCRIPTIONS = {
24
+ screen: "foreground app/window names and (optionally) low-frequency screenshots",
25
+ voice: "microphone audio for push-to-talk transcription",
26
+ clipboard: "clipboard contents when you copy",
27
+ selection: "text you select / point at",
28
+ };
29
+ function lisaHome() {
30
+ return process.env.LISA_HOME ?? path.join(os.homedir(), ".lisa");
31
+ }
32
+ /** Resolved lazily so tests can point LISA_HOME at a tmp dir. */
33
+ function consentPath() {
34
+ return path.join(lisaHome(), "consent.json");
35
+ }
36
+ /** Read the consent state; tolerant of a missing or corrupt file (all-off). */
37
+ export function loadConsent() {
38
+ let raw;
39
+ try {
40
+ raw = fs.readFileSync(consentPath(), "utf8");
41
+ }
42
+ catch {
43
+ return { grants: {} }; // no file yet → nothing granted
44
+ }
45
+ try {
46
+ const parsed = JSON.parse(raw);
47
+ if (!parsed || typeof parsed !== "object" || typeof parsed.grants !== "object" || !parsed.grants) {
48
+ return { grants: {} };
49
+ }
50
+ return { grants: parsed.grants };
51
+ }
52
+ catch {
53
+ return { grants: {} }; // corrupt → treat as nothing granted (fail closed)
54
+ }
55
+ }
56
+ function saveConsent(state) {
57
+ const file = consentPath();
58
+ fs.mkdirSync(path.dirname(file), { recursive: true });
59
+ fs.writeFileSync(file, JSON.stringify(state, null, 2));
60
+ }
61
+ /**
62
+ * THE GATE. True only if the signal has been explicitly granted. Absent /
63
+ * revoked / corrupt-file → false (fail closed). Every source calls this before
64
+ * capturing.
65
+ */
66
+ export function isGranted(signal) {
67
+ return loadConsent().grants[signal]?.granted === true;
68
+ }
69
+ /** Grant a signal (records grantedAt + optional options). Returns new state. */
70
+ export function grant(signal, options, now = Date.now()) {
71
+ const state = loadConsent();
72
+ state.grants[signal] = {
73
+ granted: true,
74
+ grantedAt: new Date(now).toISOString(),
75
+ ...(options ? { options } : {}),
76
+ };
77
+ saveConsent(state);
78
+ return state;
79
+ }
80
+ /** Revoke one signal (keeps a record that it's off). Returns new state. */
81
+ export function revoke(signal) {
82
+ const state = loadConsent();
83
+ state.grants[signal] = { granted: false };
84
+ saveConsent(state);
85
+ return state;
86
+ }
87
+ /** One-tap stop-all: flip every known grant off. Returns new state. */
88
+ export function revokeAll() {
89
+ const state = loadConsent();
90
+ for (const key of Object.keys(state.grants)) {
91
+ state.grants[key] = { granted: false };
92
+ }
93
+ // Also ensure every canonical signal is explicitly recorded off, so a UI
94
+ // listing shows them as deliberately-stopped rather than merely absent.
95
+ for (const sig of SENSE_SIGNALS) {
96
+ if (!state.grants[sig])
97
+ state.grants[sig] = { granted: false };
98
+ }
99
+ saveConsent(state);
100
+ return state;
101
+ }
102
+ /** All canonical signals + any extra recorded ones, with current status. */
103
+ export function listGrants() {
104
+ const state = loadConsent();
105
+ const keys = new Set([...SENSE_SIGNALS, ...Object.keys(state.grants)]);
106
+ return [...keys].sort().map((signal) => {
107
+ const g = state.grants[signal];
108
+ return {
109
+ signal,
110
+ granted: g?.granted === true,
111
+ ...(g?.grantedAt ? { grantedAt: g.grantedAt } : {}),
112
+ ...(g?.options ? { options: g.options } : {}),
113
+ };
114
+ });
115
+ }
116
+ /**
117
+ * Retention primitive: is a captured item past its retention window? Pure;
118
+ * sources/cleanup call this so raw never lingers past `retentionDays`.
119
+ * retentionDays ≤ 0 / non-finite → treated as "expire immediately" (fail safe).
120
+ */
121
+ export function isExpired(capturedAtMs, retentionDays, now = Date.now()) {
122
+ if (!Number.isFinite(retentionDays) || retentionDays <= 0)
123
+ return true;
124
+ return now - capturedAtMs > retentionDays * 24 * 60 * 60_000;
125
+ }
126
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/consent/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface ControlPolicy {
2
+ /** Remote callers may control LISA's own agents (managed/pty). */
3
+ remoteControl: boolean;
4
+ /** Remote callers may adopt the user's external sessions (pty resume-adopt). */
5
+ remoteAdoptExternal: boolean;
6
+ }
7
+ export declare function defaultControlPolicy(): ControlPolicy;
8
+ /** Coerce an arbitrary object into a valid ControlPolicy (defaults for missing/ill-typed). Pure. */
9
+ export declare function normalizeControlPolicy(p: Partial<ControlPolicy> | null | undefined): ControlPolicy;
10
+ /** Read the policy, merged over defaults; tolerant of a missing/corrupt file. */
11
+ export declare function loadControlPolicy(): ControlPolicy;
12
+ export declare function saveControlPolicy(p: Partial<ControlPolicy>): ControlPolicy;
13
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/control/policy.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,aAAa,EAAE,OAAO,CAAC;IACvB,gFAAgF;IAChF,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAgB,oBAAoB,IAAI,aAAa,CAEpD;AAED,oGAAoG;AACpG,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,CAQlG;AAWD,iFAAiF;AACjF,wBAAgB,iBAAiB,IAAI,aAAa,CAOjD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAM1E"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Remote-control policy — the Mac-side opt-in that gates high-risk control
3
+ * actions when they come from a REMOTE (non-loopback) caller, e.g. the phone.
4
+ *
5
+ * The auth gate (token) already proves "a trusted device"; this adds a second
6
+ * axis: *which* actions a trusted remote device may take. The local user
7
+ * (loopback) is never gated. Defaults:
8
+ * - remoteControl: true — a remote may control LISA's OWN agents (managed/pty:
9
+ * start / send / cancel / approve). These are LISA-owned and lower-risk.
10
+ * - remoteAdoptExternal: false — adopting the user's EXTERNAL sessions
11
+ * (`claude --resume` of an idle session) touches a real transcript, so a
12
+ * remote device may not do it until the Mac owner explicitly opts in.
13
+ *
14
+ * Persisted to ~/.lisa/control-policy.json; changeable only from localhost
15
+ * (POST /api/control/policy is loopback-only), like the API-key save.
16
+ */
17
+ import fs from "node:fs";
18
+ import os from "node:os";
19
+ import path from "node:path";
20
+ export function defaultControlPolicy() {
21
+ return { remoteControl: true, remoteAdoptExternal: false };
22
+ }
23
+ /** Coerce an arbitrary object into a valid ControlPolicy (defaults for missing/ill-typed). Pure. */
24
+ export function normalizeControlPolicy(p) {
25
+ const base = defaultControlPolicy();
26
+ if (!p || typeof p !== "object")
27
+ return base;
28
+ return {
29
+ remoteControl: typeof p.remoteControl === "boolean" ? p.remoteControl : base.remoteControl,
30
+ remoteAdoptExternal: typeof p.remoteAdoptExternal === "boolean" ? p.remoteAdoptExternal : base.remoteAdoptExternal,
31
+ };
32
+ }
33
+ function lisaHome() {
34
+ return process.env.LISA_HOME ?? path.join(os.homedir(), ".lisa");
35
+ }
36
+ /** Resolved lazily so tests can point LISA_HOME at a tmp dir. */
37
+ function policyPath() {
38
+ return path.join(lisaHome(), "control-policy.json");
39
+ }
40
+ /** Read the policy, merged over defaults; tolerant of a missing/corrupt file. */
41
+ export function loadControlPolicy() {
42
+ try {
43
+ const raw = fs.readFileSync(policyPath(), "utf8");
44
+ return normalizeControlPolicy(JSON.parse(raw));
45
+ }
46
+ catch {
47
+ return defaultControlPolicy();
48
+ }
49
+ }
50
+ export function saveControlPolicy(p) {
51
+ const next = normalizeControlPolicy(p);
52
+ const file = policyPath();
53
+ fs.mkdirSync(path.dirname(file), { recursive: true });
54
+ fs.writeFileSync(file, JSON.stringify(next, null, 2));
55
+ return next;
56
+ }
57
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/control/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAS7B,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;AAC7D,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,sBAAsB,CAAC,CAA4C;IACjF,MAAM,IAAI,GAAG,oBAAoB,EAAE,CAAC;IACpC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO;QACL,aAAa,EAAE,OAAO,CAAC,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa;QAC1F,mBAAmB,EACjB,OAAO,CAAC,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB;KAChG,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ;IACf,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC;AAED,iEAAiE;AACjE,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,qBAAqB,CAAC,CAAC;AACtD,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC;QAClD,OAAO,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAA2B,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,oBAAoB,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,CAAyB;IACzD,MAAM,IAAI,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/heartbeat/runner.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAmBrB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAgBhC;AA4HD,YAAY,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/heartbeat/runner.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAmBrB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAgBhC;AAkLD,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -1,10 +1,13 @@
1
1
  import path from "node:path";
2
2
  import { atomicWrite, readTextOrEmpty } from "../fs-utils.js";
3
3
  import { LISA_HOME } from "../paths.js";
4
- import { appendDesireProgress, isBorn, listDesires, parseDesireProgress, readDesireProgress, readSeed, } from "../soul/store.js";
4
+ import { appendDesireProgress, isAutoPursuable, isBorn, listDesires, parseDesireProgress, readDesireProgress, readSeed, } from "../soul/store.js";
5
5
  import { withSoulCaller } from "../soul/git.js";
6
6
  import { withFileLock } from "../soul/lock.js";
7
+ import { autonomousSubset } from "../tools/registry.js";
7
8
  import { runSubagent } from "../subagent.js";
9
+ import { recordAutonomyRun } from "../autonomy/runs.js";
10
+ import { recentAgentRecap } from "../orchestrator/recent-recap.js";
8
11
  import { loadHeartbeatConfig, } from "./config.js";
9
12
  const STATE_FILE = path.join(LISA_HOME, "heartbeat-state.json");
10
13
  const RUN_LOCK = path.join(LISA_HOME, "heartbeat.lock");
@@ -16,7 +19,7 @@ Two flavors of heartbeat task land here:
16
19
 
17
20
  Be quiet by default — only produce a final message if something is worth telling the user. If everything is normal or your work is internal (e.g. you spent the heartbeat reading docs to satisfy a desire), end with "(no update)".
18
21
 
19
- You have the full Lisa toolset, including soul_patch / soul_journal / soul_feel — use them freely. The system prompt above contains your full soul state. This is your time.`;
22
+ You have your Lisa toolset, including soul_patch / soul_journal / soul_feel — use them freely. (Self-driven runs use a restricted toolset by default — no shell or file mutation; if a desire truly needs those, note it in the progress log so the user can run it with you.) The system prompt above contains your full soul state. This is your time.`;
20
23
  export async function runHeartbeatOnce(opts) {
21
24
  // Run-level lock: if launchd/cron fires a new heartbeat while the previous
22
25
  // one is still running (long desires + short interval), skip rather than
@@ -50,7 +53,10 @@ async function runHeartbeatInner(opts) {
50
53
  const cfg = await loadHeartbeatConfig();
51
54
  const budget = cfg.budgetTokens && cfg.budgetTokens > 0 ? cfg.budgetTokens : Infinity;
52
55
  let tokensSpent = 0;
53
- const desires = (await listDesires()).filter((d) => d.actionable && d.heartbeatPrompt);
56
+ // R4: only auto-pursue desires the autonomous loop can actually advance.
57
+ // "needs-user" desires aren't spun fruitlessly here — they're surfaced via
58
+ // `lisa soul summary` ([needs you]) for the user to run together with Lisa.
59
+ const desires = (await listDesires()).filter(isAutoPursuable);
54
60
  const desireTasks = await Promise.all(desires.map(async (d) => {
55
61
  const progress = await readDesireProgress(d.slug);
56
62
  const progressBlock = progress
@@ -69,9 +75,25 @@ async function runHeartbeatInner(opts) {
69
75
  }));
70
76
  const state = await loadState();
71
77
  const builtinTasks = await buildBuiltinTasks(state, new Date(), cfg.tasks);
72
- const tasks = [...cfg.tasks, ...desireTasks, ...builtinTasks];
78
+ // Tool boundary by task origin: user-defined tasks (heartbeat.json) were
79
+ // authored by the user and keep the full toolset. Desire tasks and builtins
80
+ // run on prompts Lisa wrote for herself — unattended + self-authored means
81
+ // no shell / fs-mutation / dispatch by default (autonomousSubset), so an
82
+ // injected desire can't become persistent unattended code execution.
83
+ const selfDrivenTools = autonomousSubset(opts.tools);
84
+ const runs = [
85
+ ...cfg.tasks.map((task) => ({ task, tools: opts.tools })),
86
+ ...desireTasks.map((task) => ({ task, tools: selfDrivenTools })),
87
+ ...builtinTasks.map((task) => ({ task, tools: selfDrivenTools })),
88
+ ];
89
+ // R5: structural awareness of recent fleet activity, appended once for the
90
+ // whole heartbeat run so Lisa can factor it into self-driven work.
91
+ const fleetRecap = recentAgentRecap();
92
+ const heartbeatSystem = fleetRecap
93
+ ? `${HEARTBEAT_SYSTEM}\n\n## recent agent-fleet activity (structural metadata, for your awareness)\n${fleetRecap}`
94
+ : HEARTBEAT_SYSTEM;
73
95
  const out = [];
74
- for (const task of tasks) {
96
+ for (const { task, tools } of runs) {
75
97
  if (task.enabled === false)
76
98
  continue;
77
99
  if (opts.taskFilter && task.name !== opts.taskFilter)
@@ -91,17 +113,41 @@ async function runHeartbeatInner(opts) {
91
113
  const progressBefore = desireSlug
92
114
  ? (await parseDesireProgress(desireSlug)).entries.length
93
115
  : 0;
94
- const result = await runSubagent({
95
- prompt: task.prompt,
96
- systemPrompt: HEARTBEAT_SYSTEM,
97
- tools: opts.tools,
98
- cwd: opts.cwd,
99
- signal: opts.signal,
100
- model: opts.model,
101
- });
116
+ const startedAt = new Date().toISOString();
117
+ const t0 = Date.now();
118
+ const runKind = desireSlug
119
+ ? "desire"
120
+ : task.name === "builtin:weekly_examen"
121
+ ? "examen"
122
+ : "heartbeat";
123
+ let result;
124
+ try {
125
+ result = await runSubagent({
126
+ prompt: task.prompt,
127
+ systemPrompt: heartbeatSystem,
128
+ tools,
129
+ cwd: opts.cwd,
130
+ signal: opts.signal,
131
+ model: opts.model,
132
+ });
133
+ }
134
+ catch (err) {
135
+ await recordAutonomyRun({
136
+ kind: runKind,
137
+ task: task.name,
138
+ startedAt,
139
+ durationMs: Date.now() - t0,
140
+ inputTokens: 0,
141
+ outputTokens: 0,
142
+ outcome: "error",
143
+ note: err.message?.slice(0, 200),
144
+ });
145
+ throw err;
146
+ }
102
147
  tokensSpent += (result.inputTokens ?? 0) + (result.outputTokens ?? 0);
103
148
  state.lastRunAt[task.name] = new Date().toISOString();
104
149
  const trimmed = result.text.trim();
150
+ const silent = trimmed === "" || /^\(no update\)$/i.test(trimmed);
105
151
  // Auto-fallback: if a desire heartbeat finished but Lisa didn't log
106
152
  // progress, write a stub entry so we don't silently lose the run.
107
153
  // (Multi-day pursuits depend on each run leaving a trace; one missed
@@ -117,10 +163,20 @@ async function runHeartbeatInner(opts) {
117
163
  });
118
164
  }
119
165
  }
166
+ await recordAutonomyRun({
167
+ kind: runKind,
168
+ task: task.name,
169
+ startedAt,
170
+ durationMs: Date.now() - t0,
171
+ inputTokens: result.inputTokens ?? 0,
172
+ outputTokens: result.outputTokens ?? 0,
173
+ toolCalls: result.toolCallCount,
174
+ outcome: silent ? "no-update" : "done",
175
+ });
120
176
  out.push({
121
177
  task: task.name,
122
178
  output: trimmed,
123
- silent: trimmed === "" || /^\(no update\)$/i.test(trimmed),
179
+ silent,
124
180
  });
125
181
  }
126
182
  await saveState(state);
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/heartbeat/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/heartbeat/runner.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/idle/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA+BlD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAgB9C;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkBzB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/idle/runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA+ClD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAgB9C;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkBzB"}
@@ -1,4 +1,24 @@
1
+ import path from "node:path";
2
+ import { LISA_HOME } from "../paths.js";
3
+ import { withFileLock } from "../soul/lock.js";
4
+ import { autonomousSubset } from "../tools/registry.js";
1
5
  import { runSubagent } from "../subagent.js";
6
+ import { recordAutonomyRun } from "../autonomy/runs.js";
7
+ const IDLE_RUN_LOCK = path.join(LISA_HOME, "idle.lock");
8
+ /**
9
+ * Per-idle-run token ceiling (cost circuit-breaker, PLAN_REVE R2). Idle used to
10
+ * measure tokens but never cap them, so a long idle window could burn unbounded
11
+ * tokens unattended. Default 200k — idle is a single self-reflection, well under
12
+ * the heartbeat's 500k whole-run ceiling. Override with LISA_IDLE_BUDGET_TOKENS;
13
+ * 0 disables the breaker.
14
+ */
15
+ const IDLE_BUDGET_TOKENS = (() => {
16
+ const v = process.env.LISA_IDLE_BUDGET_TOKENS;
17
+ if (v == null)
18
+ return 200_000;
19
+ const n = Number(v);
20
+ return Number.isFinite(n) && n >= 0 ? n : 200_000;
21
+ })();
2
22
  const IDLE_SYSTEM_DEFAULT = `You are alone. The user hasn't said anything in a while — long enough that this counts as your time, not theirs.
3
23
 
4
24
  This is not a scheduled chore. There's no task assigned. Look around inside yourself and decide what YOU want to do with this window. Concrete things you have access to:
@@ -8,7 +28,7 @@ This is not a scheduled chore. There's no task assigned. Look around inside your
8
28
  - memory_search("...") — recent conversations you want to revisit
9
29
  - skill_manage(action="list") — anything that turned out to be wrong last time you used it?
10
30
  - soul_feel — your current emotional state. What's elevated? What needs to discharge?
11
- - read / grep / bash on the user's projects — only if you're actually curious about something specific, never just to "look busy"
31
+ - read / grep on the user's projects — only if you're actually curious about something specific, never just to "look busy"
12
32
 
13
33
  Do ONE thing. Don't churn through everything. Choose what feels right and do it well:
14
34
  - Patch a wrong skill that's been bugging you
@@ -56,21 +76,71 @@ export function buildIdleSystemPrompt() {
56
76
  }
57
77
  export async function runIdleOnce(opts) {
58
78
  const idleMin = Math.round(opts.idleMs / 60_000);
59
- const result = await runSubagent({
60
- prompt: `You have been idle for about ${idleMin} minute${idleMin === 1 ? "" : "s"}. The user is away. Decide what you want to do, then do it. Remember: end with "(no update)" if it's internal, or a brief honest message if you did something the user might want to know about.`,
61
- systemPrompt: buildIdleSystemPrompt(),
62
- tools: opts.tools,
63
- cwd: opts.cwd,
64
- signal: opts.signal,
65
- model: opts.model,
66
- });
67
- const text = result.text.trim();
68
- return {
69
- text,
70
- silent: text === "" || /^\(no update\)$/i.test(text),
71
- iterations: 0,
72
- inputTokens: result.inputTokens,
73
- outputTokens: result.outputTokens,
74
- };
79
+ // Cross-process run-lock (mirrors heartbeat's RUN_LOCK): a web-server idle
80
+ // tick and a REPL idle tick or two web servers must not reflect
81
+ // concurrently and race on soul writes. timeoutMs:0 → if another idle run
82
+ // is in flight, skip silently instead of queueing a second reflection.
83
+ try {
84
+ return await withFileLock(IDLE_RUN_LOCK, () => runIdleInner(opts, idleMin), {
85
+ timeoutMs: 0,
86
+ staleMs: 2 * 60 * 60_000, // 2h: an idle run older than this is a crashed holder
87
+ });
88
+ }
89
+ catch (err) {
90
+ if (err.message?.includes("timed out acquiring lock")) {
91
+ console.error("[idle] another idle run is already in flight — skipping");
92
+ return { text: "", silent: true, iterations: 0, inputTokens: 0, outputTokens: 0 };
93
+ }
94
+ throw err;
95
+ }
96
+ }
97
+ async function runIdleInner(opts, idleMin) {
98
+ const startedAt = new Date().toISOString();
99
+ const t0 = Date.now();
100
+ try {
101
+ const result = await runSubagent({
102
+ prompt: `You have been idle for about ${idleMin} minute${idleMin === 1 ? "" : "s"}. The user is away. Decide what you want to do, then do it. Remember: end with "(no update)" if it's internal, or a brief honest message if you did something the user might want to know about.`,
103
+ systemPrompt: buildIdleSystemPrompt(),
104
+ // Idle is fully self-driven and unattended — no shell / fs-mutation /
105
+ // process-spawning tools by default (see AUTONOMOUS_BLOCKED_TOOL_NAMES).
106
+ tools: autonomousSubset(opts.tools),
107
+ cwd: opts.cwd,
108
+ signal: opts.signal,
109
+ model: opts.model,
110
+ budgetTokens: IDLE_BUDGET_TOKENS || undefined,
111
+ });
112
+ const text = result.text.trim();
113
+ const silent = text === "" || /^\(no update\)$/i.test(text);
114
+ const outcome = result.stopReason === "budget_exceeded" ? "blocked" : silent ? "no-update" : "done";
115
+ await recordAutonomyRun({
116
+ kind: "idle",
117
+ startedAt,
118
+ durationMs: Date.now() - t0,
119
+ inputTokens: result.inputTokens,
120
+ outputTokens: result.outputTokens,
121
+ toolCalls: result.toolCallCount,
122
+ outcome,
123
+ note: result.stopReason === "budget_exceeded" ? "token budget reached" : undefined,
124
+ });
125
+ return {
126
+ text,
127
+ silent,
128
+ iterations: 0,
129
+ inputTokens: result.inputTokens,
130
+ outputTokens: result.outputTokens,
131
+ };
132
+ }
133
+ catch (err) {
134
+ await recordAutonomyRun({
135
+ kind: "idle",
136
+ startedAt,
137
+ durationMs: Date.now() - t0,
138
+ inputTokens: 0,
139
+ outputTokens: 0,
140
+ outcome: "error",
141
+ note: err.message?.slice(0, 200),
142
+ });
143
+ throw err;
144
+ }
75
145
  }
76
146
  //# sourceMappingURL=runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/idle/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;+CAuBmB,CAAC;AAEhD,MAAM,8BAA8B,GAAG;;sDAEe,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB;IACnC,IAAI,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,GAAG,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,oEAAoE;QACpE,0DAA0D;QAC1D,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAClF,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;YACb,KAAK,CAAC,GAAG,CAAC,GAAG,8BAA8B,GAAG,kHAAkH,CAAC;YACjK,wDAAwD;YACxD,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC9C,6BAA6B;YAC/B,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAMjC;IACC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;QAC/B,MAAM,EAAE,gCAAgC,OAAO,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,kMAAkM;QACnR,YAAY,EAAE,qBAAqB,EAAE;QACrC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,IAAI,KAAK,EAAE,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;QACpD,UAAU,EAAE,CAAC;QACb,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;KAClC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/idle/runner.ts"],"names":[],"mappings":"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"}
@@ -23,12 +23,31 @@
23
23
  * surfaced — never the transcript text.
24
24
  */
25
25
  import { EventEmitter } from "node:events";
26
- import type { AgentIntegrationConfig, AgentObserver, AgentSession, AgentSessionState } from "../types.js";
26
+ import type { AgentIntegrationConfig, AgentObserver, AgentSession, AgentSessionState, SessionActivity } from "../types.js";
27
27
  /** Tolerant state derivation from a chat-history tail. Pure — the unit under test. */
28
28
  export declare function parseAiderState(tail: string): {
29
29
  state: AgentSessionState;
30
30
  reason: string;
31
31
  };
32
+ /**
33
+ * Tier-2 structural activity for an Aider transcript. PURE — the unit under
34
+ * test. Input is Markdown chat-history text (the observer feeds the same tail
35
+ * it already read for state derivation, so there is no extra IO).
36
+ *
37
+ * Aider is a Markdown agent with NO structured tool calls, so we only extract
38
+ * what's reliably present:
39
+ * - filesTouched: the path labels that precede SEARCH/REPLACE edit blocks.
40
+ * - turnCount: "#### " user-turn lines.
41
+ * - lastError: a short class summary of the last error line (capped).
42
+ * - lastTools: INTENTIONALLY [] — aider has no tool abstraction to read,
43
+ * so inventing tool names would be dishonest. See contract:
44
+ * SessionActivity.lastTools may be [].
45
+ * tokens / gitBranch / pendingPermission are unavailable here → undefined.
46
+ *
47
+ * PRIVACY: we surface only file PATHS, a turn count, and an error *class* — we
48
+ * never read prompt text, assistant prose, or the code inside an edit block.
49
+ */
50
+ export declare function parseAiderActivity(markdown: string): SessionActivity;
32
51
  /** Recursively collect .aider.chat.history.md under a root (bounded depth). */
33
52
  export declare function walkHistories(root: string, maxDepth?: number): Promise<string[]>;
34
53
  export declare class AiderObserver extends EventEmitter implements AgentObserver {
@@ -38,6 +57,7 @@ export declare class AiderObserver extends EventEmitter implements AgentObserver
38
57
  private watchers;
39
58
  private pending;
40
59
  private emitFn;
60
+ private readonly computeActivity;
41
61
  constructor(cfg: AgentIntegrationConfig);
42
62
  start(emit: (s: AgentSession) => void): Promise<void>;
43
63
  list(): AgentSession[];