@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,223 @@
1
+ /**
2
+ * Shell observer (Sense S1c — what the user runs at the terminal).
3
+ *
4
+ * Tails the shell history file(s) and surfaces ONLY which programs were run
5
+ * (argv[0] — "git", "npm", "docker", "ssh") plus counts/recency. This widens
6
+ * Sense to the user's command-line rhythm without an agent involved.
7
+ *
8
+ * PRIVACY (the whole point of this adapter): it extracts the PROGRAM NAME ONLY.
9
+ * Never a full command line, never arguments, never paths, never the contents
10
+ * of `git commit -m "..."`. A planted-secret test asserts this. Off by default
11
+ * — shell history is sensitive; opt in via ~/.lisa/agents.json.
12
+ *
13
+ * Mapping to a session (a shell isn't an "agent"): one session per history
14
+ * file, project = the shell name ("zsh"/"bash"), state = "working" while there
15
+ * was recent activity (older ones drop out of the active window). cwd is
16
+ * unavailable (history records no directory), so it's omitted.
17
+ */
18
+ import fs from "node:fs";
19
+ import fsp from "node:fs/promises";
20
+ import path from "node:path";
21
+ import os from "node:os";
22
+ import { EventEmitter } from "node:events";
23
+ import { registerIntegration } from "../registry.js";
24
+ const ACTIVE_WINDOW_MS = 30 * 60_000; // 30m
25
+ const DEBOUNCE_MS = 500;
26
+ const TAIL_BYTES = 16 * 1024;
27
+ const ACTIVITY_MAX = 40; // how many recent commands to consider
28
+ const LAST_TOOLS_MAX = 8;
29
+ /**
30
+ * Extract argv[0] (the program name) from one history command line. Pure.
31
+ * Strips leading `VAR=val` assignments, takes the first token, basenames it,
32
+ * and returns null for anything that isn't a plain command name (flags, shell
33
+ * syntax). Deliberately surfaces ONLY the program name — nothing after it.
34
+ */
35
+ export function extractArgv0(command) {
36
+ let s = command.trim();
37
+ if (!s || s.startsWith("#"))
38
+ return null;
39
+ // Drop leading environment assignments: FOO=bar BAZ="x" cmd ...
40
+ s = s.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|\S+)\s+)+/, "");
41
+ // Drop a leading subshell/grouping paren so "(cd x && y)" doesn't leak "(cd".
42
+ s = s.replace(/^[({]\s*/, "");
43
+ const tok = s.split(/\s+/)[0];
44
+ if (!tok)
45
+ return null;
46
+ const base = (tok.split("/").pop() || tok).trim();
47
+ // Only a plausible program name — excludes flags, redirects, var expansions.
48
+ if (!base || !/^[A-Za-z0-9._@+-]+$/.test(base) || base.startsWith("-"))
49
+ return null;
50
+ return base;
51
+ }
52
+ /**
53
+ * Parse a shell-history tail into a list of argv[0]s (program names only).
54
+ * Handles zsh EXTENDED_HISTORY (": <ts>:<elapsed>;<cmd>") and bash
55
+ * HISTTIMEFORMAT ("#<epoch>" lines) as well as plain command-per-line. Pure.
56
+ */
57
+ export function parseHistoryArgv0s(raw) {
58
+ const out = [];
59
+ for (const line of raw.split("\n")) {
60
+ const trimmed = line.trim();
61
+ if (/^#\d+$/.test(trimmed))
62
+ continue; // bash timestamp comment line
63
+ const zsh = line.match(/^: \d+:\d+;(.*)$/); // zsh extended-history prefix
64
+ const cmd = zsh ? zsh[1] : line;
65
+ const a = extractArgv0(cmd);
66
+ if (a)
67
+ out.push(a);
68
+ }
69
+ return out;
70
+ }
71
+ function dedupeKeepRecent(items, max) {
72
+ const seen = new Set();
73
+ const out = [];
74
+ for (let i = items.length - 1; i >= 0; i--) {
75
+ if (!seen.has(items[i])) {
76
+ seen.add(items[i]);
77
+ out.unshift(items[i]);
78
+ }
79
+ }
80
+ return out.slice(-max);
81
+ }
82
+ /** Tier-2 structural activity from recent argv[0]s. Program names + counts only. Pure. */
83
+ export function shellActivity(argv0s) {
84
+ const recent = argv0s.slice(-ACTIVITY_MAX);
85
+ return {
86
+ turnCount: argv0s.length,
87
+ lastTools: dedupeKeepRecent(recent, LAST_TOOLS_MAX),
88
+ filesTouched: [], // shell history carries no file info we'd surface
89
+ lastCommandName: recent[recent.length - 1],
90
+ };
91
+ }
92
+ function deriveShellState(lastMtime, now) {
93
+ return now - lastMtime < ACTIVE_WINDOW_MS
94
+ ? { state: "working", reason: "recent commands" }
95
+ : { state: "idle", reason: "quiet" };
96
+ }
97
+ async function readTail(file) {
98
+ const st = await fsp.stat(file);
99
+ if (st.size === 0)
100
+ return "";
101
+ const fd = await fsp.open(file, "r");
102
+ try {
103
+ const len = Math.min(TAIL_BYTES, st.size);
104
+ const buf = Buffer.alloc(len);
105
+ await fd.read(buf, 0, len, st.size - len);
106
+ // latin1 avoids throwing on the non-UTF8 bytes zsh can write; we only ever
107
+ // keep ASCII program names out of it anyway.
108
+ return buf.toString("latin1");
109
+ }
110
+ finally {
111
+ await fd.close();
112
+ }
113
+ }
114
+ /** Default history files to watch when none are configured. */
115
+ function defaultHistoryFiles() {
116
+ const home = os.homedir();
117
+ return [path.join(home, ".zsh_history"), path.join(home, ".bash_history")];
118
+ }
119
+ export class ShellObserver extends EventEmitter {
120
+ agent = "shell";
121
+ files;
122
+ sessions = new Map();
123
+ watchers = [];
124
+ pending = new Map();
125
+ emitFn = null;
126
+ computeActivity;
127
+ constructor(cfg) {
128
+ super();
129
+ const raw = Array.isArray(cfg.files) ? cfg.files : null;
130
+ this.files = (raw ?? defaultHistoryFiles())
131
+ .filter((f) => typeof f === "string")
132
+ .map((f) => f.replace(/^~/, os.homedir()));
133
+ this.computeActivity = cfg.visibility === "activity" || cfg.visibility === "intent";
134
+ }
135
+ async start(emit) {
136
+ this.emitFn = emit;
137
+ for (const file of this.files) {
138
+ await this.record(file);
139
+ this.attach(file);
140
+ }
141
+ }
142
+ list() {
143
+ const cutoff = Date.now() - ACTIVE_WINDOW_MS;
144
+ return [...this.sessions.values()]
145
+ .filter((s) => s.lastMtime >= cutoff)
146
+ .sort((a, b) => b.lastMtime - a.lastMtime)
147
+ .map(toAgentSession);
148
+ }
149
+ async stop() {
150
+ for (const w of this.watchers)
151
+ w.close();
152
+ this.watchers = [];
153
+ for (const t of this.pending.values())
154
+ clearTimeout(t);
155
+ this.pending.clear();
156
+ }
157
+ attach(file) {
158
+ try {
159
+ const w = fs.watch(file, { persistent: false }, () => {
160
+ const prev = this.pending.get(file);
161
+ if (prev)
162
+ clearTimeout(prev);
163
+ this.pending.set(file, setTimeout(() => {
164
+ this.pending.delete(file);
165
+ void this.record(file).then(() => {
166
+ const info = this.sessions.get(file);
167
+ if (info && this.emitFn)
168
+ this.emitFn(toAgentSession(info));
169
+ });
170
+ }, DEBOUNCE_MS));
171
+ });
172
+ w.on("error", () => w.close());
173
+ this.watchers.push(w);
174
+ }
175
+ catch {
176
+ // file unwatchable (e.g. doesn't exist) → no-op
177
+ }
178
+ }
179
+ async record(file) {
180
+ try {
181
+ const st = await fsp.stat(file);
182
+ if (!st.isFile())
183
+ return;
184
+ const tail = await readTail(file);
185
+ const argv0s = parseHistoryArgv0s(tail);
186
+ const { state, reason } = deriveShellState(st.mtimeMs, Date.now());
187
+ this.sessions.set(file, {
188
+ sessionId: file,
189
+ project: shellName(file),
190
+ lastMtime: st.mtimeMs,
191
+ state,
192
+ stateReason: reason,
193
+ activity: this.computeActivity ? shellActivity(argv0s) : undefined,
194
+ });
195
+ }
196
+ catch {
197
+ this.sessions.delete(file); // file vanished
198
+ }
199
+ }
200
+ }
201
+ function shellName(file) {
202
+ const base = path.basename(file); // .zsh_history / .bash_history
203
+ if (base.includes("zsh"))
204
+ return "zsh";
205
+ if (base.includes("bash"))
206
+ return "bash";
207
+ if (base.includes("fish"))
208
+ return "fish";
209
+ return "shell";
210
+ }
211
+ function toAgentSession(i) {
212
+ return {
213
+ agent: "shell",
214
+ sessionId: i.sessionId,
215
+ project: i.project,
216
+ state: i.state,
217
+ stateReason: i.stateReason,
218
+ lastMtime: i.lastMtime,
219
+ activity: i.activity,
220
+ };
221
+ }
222
+ registerIntegration("shell", (cfg) => new ShellObserver(cfg));
223
+ //# sourceMappingURL=observer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.js","sourceRoot":"","sources":["../../../src/integrations/shell/observer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A2A task-state helpers for the TakoAPI observer (Dispatch D2b). Pure — the
3
+ * unit under test. No I/O, no fs, so the mapping and parsing are verifiable
4
+ * without the (still-evolving) live gateway.
5
+ */
6
+ import type { AgentSessionState } from "../types.js";
7
+ /**
8
+ * Map an A2A TaskState onto LISA's normalized session state. The A2A spec's
9
+ * lifecycle states collapse onto our six:
10
+ * submitted | working → working
11
+ * input-required | auth-required → waiting (the agent needs the user)
12
+ * completed → done
13
+ * failed | rejected → error
14
+ * canceled → done (reason: canceled)
15
+ * anything else → unknown
16
+ * Case-insensitive; tolerates the British "cancelled" spelling.
17
+ */
18
+ export declare function taskStateToSessionState(taskState: string): {
19
+ state: AgentSessionState;
20
+ reason: string;
21
+ };
22
+ /**
23
+ * Pull an A2A Task's state + id out of a /message response body, tolerating the
24
+ * shapes a gateway/agent might return: a bare Task, one nested under JSON-RPC
25
+ * `result`, or one under `task`; with the state at `status.state` (A2A) or a
26
+ * flat `state`. Returns null when the body carries no task object (e.g. a plain
27
+ * text reply or non-JSON) — the caller then treats a successful call as
28
+ * `completed`. Pure.
29
+ *
30
+ * SECURITY: the response comes from an untrusted remote agent (2nd-order prompt
31
+ * injection). We read ONLY the structural state/id strings here; the full reply
32
+ * never enters the ledger or the hub.
33
+ */
34
+ export declare function extractTaskState(body: string): {
35
+ state: string;
36
+ taskId?: string;
37
+ } | null;
38
+ //# sourceMappingURL=a2a.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a.d.ts","sourceRoot":"","sources":["../../../src/integrations/takoapi/a2a.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAmB9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GACX;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA0B3C"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Map an A2A TaskState onto LISA's normalized session state. The A2A spec's
3
+ * lifecycle states collapse onto our six:
4
+ * submitted | working → working
5
+ * input-required | auth-required → waiting (the agent needs the user)
6
+ * completed → done
7
+ * failed | rejected → error
8
+ * canceled → done (reason: canceled)
9
+ * anything else → unknown
10
+ * Case-insensitive; tolerates the British "cancelled" spelling.
11
+ */
12
+ export function taskStateToSessionState(taskState) {
13
+ switch ((taskState || "").toLowerCase()) {
14
+ case "submitted":
15
+ case "working":
16
+ return { state: "working", reason: taskState };
17
+ case "input-required":
18
+ case "auth-required":
19
+ return { state: "waiting", reason: taskState };
20
+ case "completed":
21
+ return { state: "done", reason: "completed" };
22
+ case "failed":
23
+ case "rejected":
24
+ return { state: "error", reason: taskState };
25
+ case "canceled":
26
+ case "cancelled":
27
+ return { state: "done", reason: "canceled" };
28
+ default:
29
+ return { state: "unknown", reason: taskState || "unknown" };
30
+ }
31
+ }
32
+ /**
33
+ * Pull an A2A Task's state + id out of a /message response body, tolerating the
34
+ * shapes a gateway/agent might return: a bare Task, one nested under JSON-RPC
35
+ * `result`, or one under `task`; with the state at `status.state` (A2A) or a
36
+ * flat `state`. Returns null when the body carries no task object (e.g. a plain
37
+ * text reply or non-JSON) — the caller then treats a successful call as
38
+ * `completed`. Pure.
39
+ *
40
+ * SECURITY: the response comes from an untrusted remote agent (2nd-order prompt
41
+ * injection). We read ONLY the structural state/id strings here; the full reply
42
+ * never enters the ledger or the hub.
43
+ */
44
+ export function extractTaskState(body) {
45
+ let json;
46
+ try {
47
+ json = JSON.parse(body);
48
+ }
49
+ catch {
50
+ return null; // non-JSON (plain text reply) → no task object
51
+ }
52
+ if (!json || typeof json !== "object")
53
+ return null;
54
+ const j = json;
55
+ // A2A task objects appear bare, under JSON-RPC `result`, or under `task`.
56
+ const candidates = [j.result, j.task, j].filter((t) => !!t && typeof t === "object");
57
+ for (const task of candidates) {
58
+ const state = (typeof task.status?.state === "string" && task.status.state) ||
59
+ (typeof task.state === "string" && task.state) ||
60
+ "";
61
+ if (!state)
62
+ continue;
63
+ const taskId = (typeof task.id === "string" && task.id) ||
64
+ (typeof task.taskId === "string" && task.taskId) ||
65
+ "";
66
+ return taskId ? { state, taskId } : { state };
67
+ }
68
+ return null;
69
+ }
70
+ //# sourceMappingURL=a2a.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a.js","sourceRoot":"","sources":["../../../src/integrations/takoapi/a2a.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CACrC,SAAiB;IAEjB,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACxC,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACjD,KAAK,gBAAgB,CAAC;QACtB,KAAK,eAAe;YAClB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACjD,KAAK,WAAW;YACd,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAChD,KAAK,QAAQ,CAAC;QACd,KAAK,UAAU;YACb,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/C,KAAK,UAAU,CAAC;QAChB,KAAK,WAAW;YACd,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAC/C;YACE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,SAAS,EAAE,CAAC;IAChE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY;IAEZ,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,+CAA+C;IAC9D,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,CAAC,GAAG,IAA2B,CAAC;IACtC,0EAA0E;IAC1E,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAC7C,CAAC,CAAC,EAA4B,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAC9D,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,KAAK,GACT,CAAC,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YAC7D,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC;YAC9C,EAAE,CAAC;QACL,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,MAAM,GACV,CAAC,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC,EAAE,CAAC;YACxC,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC;YAChD,EAAE,CAAC;QACL,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { EventEmitter } from "node:events";
2
+ export interface TakoCallEntry {
3
+ /** Agent slug — the session identity (one entry per slug; latest call wins). */
4
+ slug: string;
5
+ /** A2A task id, if the response carried one. */
6
+ taskId?: string;
7
+ /** Epoch ms of the first recorded call to this slug. */
8
+ startedAt: number;
9
+ /** Epoch ms of the most recent update. */
10
+ lastMtime: number;
11
+ /** Last observed A2A TaskState string (e.g. "completed", "working"). */
12
+ lastState: string;
13
+ }
14
+ /**
15
+ * Fires "change" after every successful write so the in-process observer can
16
+ * push a live update. The `takoapi` tool and the hub share one process, so an
17
+ * in-process event is enough (and simpler/safer than fs.watch).
18
+ */
19
+ export declare const takoLedgerEvents: EventEmitter<[never]>;
20
+ /** Read the ledger; tolerant of a missing or corrupt file (returns []). */
21
+ export declare function loadTakoLedger(): TakoCallEntry[];
22
+ /** Record (upsert by slug) a call LISA made to a remote agent. Returns the entry. */
23
+ export declare function recordTakoCall(d: {
24
+ slug: string;
25
+ state: string;
26
+ taskId?: string;
27
+ /** Override the clock (tests). */
28
+ now?: number;
29
+ }): TakoCallEntry;
30
+ /** All retained calls, newest first; prunes aged-out entries as a side effect. */
31
+ export declare function listTakoCalls(now?: number): TakoCallEntry[];
32
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../../src/integrations/takoapi/ledger.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,uBAAqB,CAAC;AAYnD,2EAA2E;AAC3E,wBAAgB,cAAc,IAAI,aAAa,EAAE,CAoBhD;AAQD,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,CAAC,EAAE;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,aAAa,CAuBhB;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,GAAG,SAAa,GAAG,aAAa,EAAE,CAM/D"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * TakoAPI call ledger (Dispatch D2b) — a small persistent record of the REMOTE
3
+ * agents LISA has called via the `takoapi` tool, so the orchestrator hub can
4
+ * surface them as first-class sessions (with their last A2A TaskState) alongside
5
+ * local agents. Mirrors dispatch-ledger.ts.
6
+ *
7
+ * DISCIPLINE: this records only agents LISA actually CALLED — never the
8
+ * ~200-agent registry. Discovery stays in the `takoapi discover` tool; the hub
9
+ * only ever shows agents you've interacted with (called) plus an explicit pin
10
+ * list (config).
11
+ *
12
+ * PRIVACY: structural only — slug, A2A task id, TaskState, timestamps. Never the
13
+ * prompt sent or the reply received (those flow through the tool, not here).
14
+ */
15
+ import fs from "node:fs";
16
+ import os from "node:os";
17
+ import path from "node:path";
18
+ import { EventEmitter } from "node:events";
19
+ /** How long a call is retained for readback after its last update. */
20
+ const RETAIN_MS = 24 * 60 * 60_000;
21
+ /**
22
+ * Fires "change" after every successful write so the in-process observer can
23
+ * push a live update. The `takoapi` tool and the hub share one process, so an
24
+ * in-process event is enough (and simpler/safer than fs.watch).
25
+ */
26
+ export const takoLedgerEvents = new EventEmitter();
27
+ takoLedgerEvents.setMaxListeners(64);
28
+ function lisaHome() {
29
+ return process.env.LISA_HOME ?? path.join(os.homedir(), ".lisa");
30
+ }
31
+ /** Resolved lazily (reads env at call time) so tests can point LISA_HOME at a tmp dir. */
32
+ function ledgerPath() {
33
+ return path.join(lisaHome(), "takoapi-calls.json");
34
+ }
35
+ /** Read the ledger; tolerant of a missing or corrupt file (returns []). */
36
+ export function loadTakoLedger() {
37
+ let raw;
38
+ try {
39
+ raw = fs.readFileSync(ledgerPath(), "utf8");
40
+ }
41
+ catch {
42
+ return []; // no file yet
43
+ }
44
+ try {
45
+ const parsed = JSON.parse(raw);
46
+ if (!Array.isArray(parsed))
47
+ return [];
48
+ return parsed.filter((e) => !!e &&
49
+ typeof e.slug === "string" &&
50
+ typeof e.lastState === "string" &&
51
+ typeof e.lastMtime === "number");
52
+ }
53
+ catch {
54
+ return []; // corrupt JSON — treat as empty rather than throwing
55
+ }
56
+ }
57
+ function saveTakoLedger(entries) {
58
+ const file = ledgerPath();
59
+ fs.mkdirSync(path.dirname(file), { recursive: true });
60
+ fs.writeFileSync(file, JSON.stringify(entries, null, 2));
61
+ }
62
+ /** Record (upsert by slug) a call LISA made to a remote agent. Returns the entry. */
63
+ export function recordTakoCall(d) {
64
+ const now = d.now ?? Date.now();
65
+ const existing = loadTakoLedger();
66
+ const prior = existing.find((e) => e.slug === d.slug);
67
+ const entry = {
68
+ slug: d.slug,
69
+ lastState: d.state,
70
+ lastMtime: now,
71
+ startedAt: prior?.startedAt ?? now,
72
+ // Keep the freshest task id; fall back to the prior one if this call had none.
73
+ ...(d.taskId
74
+ ? { taskId: d.taskId }
75
+ : prior?.taskId
76
+ ? { taskId: prior.taskId }
77
+ : {}),
78
+ };
79
+ // Replace the same-slug entry and age out calls older than the retention window.
80
+ const cutoff = now - RETAIN_MS;
81
+ const next = existing.filter((e) => e.slug !== d.slug && e.lastMtime >= cutoff);
82
+ next.push(entry);
83
+ saveTakoLedger(next);
84
+ takoLedgerEvents.emit("change");
85
+ return entry;
86
+ }
87
+ /** All retained calls, newest first; prunes aged-out entries as a side effect. */
88
+ export function listTakoCalls(now = Date.now()) {
89
+ const all = loadTakoLedger();
90
+ const cutoff = now - RETAIN_MS;
91
+ const keep = all.filter((e) => e.lastMtime >= cutoff);
92
+ if (keep.length !== all.length)
93
+ saveTakoLedger(keep);
94
+ return keep.sort((a, b) => b.lastMtime - a.lastMtime);
95
+ }
96
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../src/integrations/takoapi/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * TakoAPI observer (Dispatch D2b) — surfaces the REMOTE agents LISA has called
3
+ * (or the user pinned) as first-class sessions in the orchestrator hub, with
4
+ * their last A2A TaskState, alongside local agents.
5
+ *
6
+ * Source of truth is the call ledger (takoapi-calls.json), written by the
7
+ * `takoapi` tool when LISA delegates a task. The observer NEVER lists the
8
+ * registry — discovery is the tool's job (`takoapi discover`); monitoring shows
9
+ * only agents you've interacted with (called) plus a small explicit pin list:
10
+ * ~/.lisa/agents.json → { "takoapi": { "enabled": true, "pin": ["slug-a"] } }
11
+ *
12
+ * Off by default. With no calls and no pins it lists nothing (effective no-op).
13
+ * PRIVACY: structural only — slug, TaskState, timestamps; no prompts/replies.
14
+ */
15
+ import { EventEmitter } from "node:events";
16
+ import type { AgentIntegrationConfig, AgentObserver, AgentSession } from "../types.js";
17
+ import { type TakoCallEntry } from "./ledger.js";
18
+ /** Read the `pin` list off the integration config, ignoring junk. */
19
+ export declare function pinsOf(cfg: AgentIntegrationConfig): string[];
20
+ /**
21
+ * Build the hub session list from ledger entries + pinned slugs. Pure given its
22
+ * inputs (the unit under test):
23
+ * - called agents within the active window → their mapped TaskState
24
+ * - pinned slugs with no recent call → idle ("pinned"), kept visible
25
+ * One row per slug (a called pin uses its real call state, not "pinned").
26
+ */
27
+ export declare function buildTakoSessions(calls: TakoCallEntry[], pins: string[], now: number): AgentSession[];
28
+ export declare class TakoApiObserver extends EventEmitter implements AgentObserver {
29
+ readonly agent = "takoapi";
30
+ private pins;
31
+ private emitFn;
32
+ private readonly onChange;
33
+ constructor(cfg: AgentIntegrationConfig);
34
+ start(emit: (s: AgentSession) => void): Promise<void>;
35
+ list(): AgentSession[];
36
+ stop(): Promise<void>;
37
+ private flush;
38
+ }
39
+ //# sourceMappingURL=observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../../src/integrations/takoapi/observer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EACV,sBAAsB,EACtB,aAAa,EACb,YAAY,EACb,MAAM,aAAa,CAAC;AAErB,OAAO,EAAmC,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAMlF,qEAAqE;AACrE,wBAAgB,MAAM,CAAC,GAAG,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAK5D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,EAAE,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,GACV,YAAY,EAAE,CAiChB;AAED,qBAAa,eAAgB,SAAQ,YAAa,YAAW,aAAa;IACxE,QAAQ,CAAC,KAAK,aAAa;IAC3B,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;gBAEnC,GAAG,EAAE,sBAAsB;IAKjC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3D,IAAI,IAAI,YAAY,EAAE;IAIhB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,OAAO,CAAC,KAAK;CAId"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * TakoAPI observer (Dispatch D2b) — surfaces the REMOTE agents LISA has called
3
+ * (or the user pinned) as first-class sessions in the orchestrator hub, with
4
+ * their last A2A TaskState, alongside local agents.
5
+ *
6
+ * Source of truth is the call ledger (takoapi-calls.json), written by the
7
+ * `takoapi` tool when LISA delegates a task. The observer NEVER lists the
8
+ * registry — discovery is the tool's job (`takoapi discover`); monitoring shows
9
+ * only agents you've interacted with (called) plus a small explicit pin list:
10
+ * ~/.lisa/agents.json → { "takoapi": { "enabled": true, "pin": ["slug-a"] } }
11
+ *
12
+ * Off by default. With no calls and no pins it lists nothing (effective no-op).
13
+ * PRIVACY: structural only — slug, TaskState, timestamps; no prompts/replies.
14
+ */
15
+ import { EventEmitter } from "node:events";
16
+ import { registerIntegration } from "../registry.js";
17
+ import { taskStateToSessionState } from "./a2a.js";
18
+ import { listTakoCalls, takoLedgerEvents } from "./ledger.js";
19
+ /** Remote delegations linger longer than chat sessions but shouldn't pile up. */
20
+ const ACTIVE_WINDOW_MS = 3 * 60 * 60_000; // 3h
21
+ const MAX_LISTED = 10;
22
+ /** Read the `pin` list off the integration config, ignoring junk. */
23
+ export function pinsOf(cfg) {
24
+ const raw = cfg.pin;
25
+ return Array.isArray(raw)
26
+ ? raw.filter((s) => typeof s === "string")
27
+ : [];
28
+ }
29
+ /**
30
+ * Build the hub session list from ledger entries + pinned slugs. Pure given its
31
+ * inputs (the unit under test):
32
+ * - called agents within the active window → their mapped TaskState
33
+ * - pinned slugs with no recent call → idle ("pinned"), kept visible
34
+ * One row per slug (a called pin uses its real call state, not "pinned").
35
+ */
36
+ export function buildTakoSessions(calls, pins, now) {
37
+ const cutoff = now - ACTIVE_WINDOW_MS;
38
+ const bySlug = new Map();
39
+ for (const c of calls) {
40
+ if (c.lastMtime < cutoff)
41
+ continue;
42
+ const { state, reason } = taskStateToSessionState(c.lastState);
43
+ bySlug.set(c.slug, {
44
+ agent: "takoapi",
45
+ sessionId: c.slug,
46
+ project: c.slug,
47
+ state,
48
+ stateReason: reason,
49
+ lastMtime: c.lastMtime,
50
+ });
51
+ }
52
+ // Pins the user wants always visible, even when idle. A pin that WAS called
53
+ // recently keeps its real state (set above); only never-/stale-called pins
54
+ // are added as idle, stamped `now` so the frontend's window keeps them.
55
+ for (const slug of pins) {
56
+ if (!bySlug.has(slug)) {
57
+ bySlug.set(slug, {
58
+ agent: "takoapi",
59
+ sessionId: slug,
60
+ project: slug,
61
+ state: "idle",
62
+ stateReason: "pinned",
63
+ lastMtime: now,
64
+ });
65
+ }
66
+ }
67
+ return [...bySlug.values()]
68
+ .sort((a, b) => b.lastMtime - a.lastMtime)
69
+ .slice(0, MAX_LISTED);
70
+ }
71
+ export class TakoApiObserver extends EventEmitter {
72
+ agent = "takoapi";
73
+ pins;
74
+ emitFn = null;
75
+ onChange = () => this.flush();
76
+ constructor(cfg) {
77
+ super();
78
+ this.pins = pinsOf(cfg);
79
+ }
80
+ async start(emit) {
81
+ this.emitFn = emit;
82
+ // The tool records calls in this same process; re-emit on each ledger change
83
+ // so a fresh delegation shows up live (not just on the next snapshot fetch).
84
+ takoLedgerEvents.on("change", this.onChange);
85
+ this.flush(); // surface any past calls / pins immediately
86
+ }
87
+ list() {
88
+ return buildTakoSessions(listTakoCalls(), this.pins, Date.now());
89
+ }
90
+ async stop() {
91
+ takoLedgerEvents.off("change", this.onChange);
92
+ this.emitFn = null;
93
+ }
94
+ flush() {
95
+ if (!this.emitFn)
96
+ return;
97
+ for (const s of this.list())
98
+ this.emitFn(s);
99
+ }
100
+ }
101
+ registerIntegration("takoapi", (cfg) => new TakoApiObserver(cfg));
102
+ //# sourceMappingURL=observer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.js","sourceRoot":"","sources":["../../../src/integrations/takoapi/observer.ts"],"names":[],"mappings":"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"}