@made-by-moonlight/athene-core 0.9.1

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 (285) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +241 -0
  3. package/dist/activity-events.d.ts +42 -0
  4. package/dist/activity-events.d.ts.map +1 -0
  5. package/dist/activity-events.js +192 -0
  6. package/dist/activity-events.js.map +1 -0
  7. package/dist/activity-log.d.ts +71 -0
  8. package/dist/activity-log.d.ts.map +1 -0
  9. package/dist/activity-log.js +203 -0
  10. package/dist/activity-log.js.map +1 -0
  11. package/dist/activity-signal.d.ts +20 -0
  12. package/dist/activity-signal.d.ts.map +1 -0
  13. package/dist/activity-signal.js +91 -0
  14. package/dist/activity-signal.js.map +1 -0
  15. package/dist/agent-report.d.ts +148 -0
  16. package/dist/agent-report.d.ts.map +1 -0
  17. package/dist/agent-report.js +516 -0
  18. package/dist/agent-report.js.map +1 -0
  19. package/dist/agent-selection.d.ts +31 -0
  20. package/dist/agent-selection.d.ts.map +1 -0
  21. package/dist/agent-selection.js +69 -0
  22. package/dist/agent-selection.js.map +1 -0
  23. package/dist/agent-workspace-hooks.d.ts +74 -0
  24. package/dist/agent-workspace-hooks.d.ts.map +1 -0
  25. package/dist/agent-workspace-hooks.js +988 -0
  26. package/dist/agent-workspace-hooks.js.map +1 -0
  27. package/dist/atomic-write.d.ts +6 -0
  28. package/dist/atomic-write.d.ts.map +1 -0
  29. package/dist/atomic-write.js +49 -0
  30. package/dist/atomic-write.js.map +1 -0
  31. package/dist/cleanup-stack.d.ts +37 -0
  32. package/dist/cleanup-stack.d.ts.map +1 -0
  33. package/dist/cleanup-stack.js +45 -0
  34. package/dist/cleanup-stack.js.map +1 -0
  35. package/dist/code-review-manager.d.ts +118 -0
  36. package/dist/code-review-manager.d.ts.map +1 -0
  37. package/dist/code-review-manager.js +719 -0
  38. package/dist/code-review-manager.js.map +1 -0
  39. package/dist/code-review-store.d.ts +114 -0
  40. package/dist/code-review-store.d.ts.map +1 -0
  41. package/dist/code-review-store.js +346 -0
  42. package/dist/code-review-store.js.map +1 -0
  43. package/dist/config-generator.d.ts +84 -0
  44. package/dist/config-generator.d.ts.map +1 -0
  45. package/dist/config-generator.js +295 -0
  46. package/dist/config-generator.js.map +1 -0
  47. package/dist/config.d.ts +55 -0
  48. package/dist/config.d.ts.map +1 -0
  49. package/dist/config.js +852 -0
  50. package/dist/config.js.map +1 -0
  51. package/dist/daemon-children.d.ts +55 -0
  52. package/dist/daemon-children.d.ts.map +1 -0
  53. package/dist/daemon-children.js +435 -0
  54. package/dist/daemon-children.js.map +1 -0
  55. package/dist/dashboard-notifications.d.ts +42 -0
  56. package/dist/dashboard-notifications.d.ts.map +1 -0
  57. package/dist/dashboard-notifications.js +123 -0
  58. package/dist/dashboard-notifications.js.map +1 -0
  59. package/dist/events-db.d.ts +39 -0
  60. package/dist/events-db.d.ts.map +1 -0
  61. package/dist/events-db.js +185 -0
  62. package/dist/events-db.js.map +1 -0
  63. package/dist/feature-flags.d.ts +2 -0
  64. package/dist/feature-flags.d.ts.map +1 -0
  65. package/dist/feature-flags.js +9 -0
  66. package/dist/feature-flags.js.map +1 -0
  67. package/dist/feedback-tools.d.ts +97 -0
  68. package/dist/feedback-tools.d.ts.map +1 -0
  69. package/dist/feedback-tools.js +161 -0
  70. package/dist/feedback-tools.js.map +1 -0
  71. package/dist/file-lock.d.ts +5 -0
  72. package/dist/file-lock.d.ts.map +1 -0
  73. package/dist/file-lock.js +59 -0
  74. package/dist/file-lock.js.map +1 -0
  75. package/dist/format-automated-comments.d.ts +18 -0
  76. package/dist/format-automated-comments.d.ts.map +1 -0
  77. package/dist/gh-trace.d.ts +57 -0
  78. package/dist/gh-trace.d.ts.map +1 -0
  79. package/dist/gh-trace.js +320 -0
  80. package/dist/gh-trace.js.map +1 -0
  81. package/dist/git-activity.d.ts +10 -0
  82. package/dist/git-activity.d.ts.map +1 -0
  83. package/dist/git-activity.js +30 -0
  84. package/dist/git-activity.js.map +1 -0
  85. package/dist/global-config.d.ts +1085 -0
  86. package/dist/global-config.d.ts.map +1 -0
  87. package/dist/global-config.js +1067 -0
  88. package/dist/global-config.js.map +1 -0
  89. package/dist/index.d.ts +91 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +59 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/key-value.d.ts +7 -0
  94. package/dist/key-value.d.ts.map +1 -0
  95. package/dist/key-value.js +24 -0
  96. package/dist/key-value.js.map +1 -0
  97. package/dist/lifecycle-manager.d.ts +22 -0
  98. package/dist/lifecycle-manager.d.ts.map +1 -0
  99. package/dist/lifecycle-manager.js +2813 -0
  100. package/dist/lifecycle-manager.js.map +1 -0
  101. package/dist/lifecycle-state.d.ts +28 -0
  102. package/dist/lifecycle-state.d.ts.map +1 -0
  103. package/dist/lifecycle-state.js +446 -0
  104. package/dist/lifecycle-state.js.map +1 -0
  105. package/dist/lifecycle-status-decisions.d.ts +85 -0
  106. package/dist/lifecycle-status-decisions.d.ts.map +1 -0
  107. package/dist/lifecycle-status-decisions.js +262 -0
  108. package/dist/lifecycle-status-decisions.js.map +1 -0
  109. package/dist/lifecycle-transition.d.ts +81 -0
  110. package/dist/lifecycle-transition.d.ts.map +1 -0
  111. package/dist/lifecycle-transition.js +207 -0
  112. package/dist/lifecycle-transition.js.map +1 -0
  113. package/dist/metadata.d.ts +54 -0
  114. package/dist/metadata.d.ts.map +1 -0
  115. package/dist/metadata.js +484 -0
  116. package/dist/metadata.js.map +1 -0
  117. package/dist/migration/storage-v2.d.ts +76 -0
  118. package/dist/migration/storage-v2.d.ts.map +1 -0
  119. package/dist/migration/storage-v2.js +1614 -0
  120. package/dist/migration/storage-v2.js.map +1 -0
  121. package/dist/notification-data.d.ts +135 -0
  122. package/dist/notification-data.d.ts.map +1 -0
  123. package/dist/notification-data.js +204 -0
  124. package/dist/notification-data.js.map +1 -0
  125. package/dist/notification-observability.d.ts +21 -0
  126. package/dist/notification-observability.d.ts.map +1 -0
  127. package/dist/notification-observability.js +154 -0
  128. package/dist/notification-observability.js.map +1 -0
  129. package/dist/notifier-resolution.d.ts +14 -0
  130. package/dist/notifier-resolution.d.ts.map +1 -0
  131. package/dist/notifier-resolution.js +23 -0
  132. package/dist/notifier-resolution.js.map +1 -0
  133. package/dist/observability.d.ts +100 -0
  134. package/dist/observability.d.ts.map +1 -0
  135. package/dist/observability.js +535 -0
  136. package/dist/observability.js.map +1 -0
  137. package/dist/opencode-agents-md.d.ts +3 -0
  138. package/dist/opencode-agents-md.d.ts.map +1 -0
  139. package/dist/opencode-agents-md.js +40 -0
  140. package/dist/opencode-agents-md.js.map +1 -0
  141. package/dist/opencode-config.d.ts +2 -0
  142. package/dist/opencode-config.d.ts.map +1 -0
  143. package/dist/opencode-config.js +17 -0
  144. package/dist/opencode-config.js.map +1 -0
  145. package/dist/opencode-session-id.d.ts +2 -0
  146. package/dist/opencode-session-id.d.ts.map +1 -0
  147. package/dist/opencode-session-id.js +12 -0
  148. package/dist/opencode-session-id.js.map +1 -0
  149. package/dist/opencode-shared.d.ts +80 -0
  150. package/dist/opencode-shared.d.ts.map +1 -0
  151. package/dist/opencode-shared.js +202 -0
  152. package/dist/opencode-shared.js.map +1 -0
  153. package/dist/orchestrator-prompt.d.ts +19 -0
  154. package/dist/orchestrator-prompt.d.ts.map +1 -0
  155. package/dist/orchestrator-prompt.js +130 -0
  156. package/dist/orchestrator-prompt.js.map +1 -0
  157. package/dist/orchestrator-session-strategy.d.ts +5 -0
  158. package/dist/orchestrator-session-strategy.d.ts.map +1 -0
  159. package/dist/orchestrator-session-strategy.js +13 -0
  160. package/dist/orchestrator-session-strategy.js.map +1 -0
  161. package/dist/paths.d.ts +145 -0
  162. package/dist/paths.d.ts.map +1 -0
  163. package/dist/paths.js +288 -0
  164. package/dist/paths.js.map +1 -0
  165. package/dist/platform.d.ts +32 -0
  166. package/dist/platform.d.ts.map +1 -0
  167. package/dist/platform.js +211 -0
  168. package/dist/platform.js.map +1 -0
  169. package/dist/plugin-registry.d.ts +15 -0
  170. package/dist/plugin-registry.d.ts.map +1 -0
  171. package/dist/plugin-registry.js +499 -0
  172. package/dist/plugin-registry.js.map +1 -0
  173. package/dist/portfolio-projects.d.ts +7 -0
  174. package/dist/portfolio-projects.d.ts.map +1 -0
  175. package/dist/portfolio-projects.js +65 -0
  176. package/dist/portfolio-projects.js.map +1 -0
  177. package/dist/portfolio-registry.d.ts +42 -0
  178. package/dist/portfolio-registry.d.ts.map +1 -0
  179. package/dist/portfolio-registry.js +311 -0
  180. package/dist/portfolio-registry.js.map +1 -0
  181. package/dist/portfolio-routing.d.ts +5 -0
  182. package/dist/portfolio-routing.d.ts.map +1 -0
  183. package/dist/portfolio-routing.js +24 -0
  184. package/dist/portfolio-routing.js.map +1 -0
  185. package/dist/portfolio-session-service.d.ts +15 -0
  186. package/dist/portfolio-session-service.d.ts.map +1 -0
  187. package/dist/portfolio-session-service.js +206 -0
  188. package/dist/portfolio-session-service.js.map +1 -0
  189. package/dist/process-cache.d.ts +32 -0
  190. package/dist/process-cache.d.ts.map +1 -0
  191. package/dist/process-cache.js +44 -0
  192. package/dist/process-cache.js.map +1 -0
  193. package/dist/project-resolver.d.ts +5 -0
  194. package/dist/project-resolver.d.ts.map +1 -0
  195. package/dist/project-resolver.js +20 -0
  196. package/dist/project-resolver.js.map +1 -0
  197. package/dist/prompt-builder.d.ts +42 -0
  198. package/dist/prompt-builder.d.ts.map +1 -0
  199. package/dist/prompt-builder.js +182 -0
  200. package/dist/prompt-builder.js.map +1 -0
  201. package/dist/prompts/orchestrator.md.js +4 -0
  202. package/dist/prompts/orchestrator.md.js.map +1 -0
  203. package/dist/query-activity-events.d.ts +42 -0
  204. package/dist/query-activity-events.d.ts.map +1 -0
  205. package/dist/query-activity-events.js +170 -0
  206. package/dist/query-activity-events.js.map +1 -0
  207. package/dist/recovery/actions.d.ts +7 -0
  208. package/dist/recovery/actions.d.ts.map +1 -0
  209. package/dist/recovery/index.d.ts +8 -0
  210. package/dist/recovery/index.d.ts.map +1 -0
  211. package/dist/recovery/logger.d.ts +12 -0
  212. package/dist/recovery/logger.d.ts.map +1 -0
  213. package/dist/recovery/manager.d.ts +24 -0
  214. package/dist/recovery/manager.d.ts.map +1 -0
  215. package/dist/recovery/scanner.d.ts +11 -0
  216. package/dist/recovery/scanner.d.ts.map +1 -0
  217. package/dist/recovery/types.d.ts +170 -0
  218. package/dist/recovery/types.d.ts.map +1 -0
  219. package/dist/recovery/validator.d.ts +8 -0
  220. package/dist/recovery/validator.d.ts.map +1 -0
  221. package/dist/report-watcher.d.ts +93 -0
  222. package/dist/report-watcher.d.ts.map +1 -0
  223. package/dist/report-watcher.js +182 -0
  224. package/dist/report-watcher.js.map +1 -0
  225. package/dist/scm-webhook-utils.d.ts +6 -0
  226. package/dist/scm-webhook-utils.d.ts.map +1 -0
  227. package/dist/scm-webhook-utils.js +36 -0
  228. package/dist/scm-webhook-utils.js.map +1 -0
  229. package/dist/session-manager.d.ts +22 -0
  230. package/dist/session-manager.d.ts.map +1 -0
  231. package/dist/session-manager.js +3077 -0
  232. package/dist/session-manager.js.map +1 -0
  233. package/dist/spawn-target.d.ts +23 -0
  234. package/dist/spawn-target.d.ts.map +1 -0
  235. package/dist/spawn-target.js +39 -0
  236. package/dist/spawn-target.js.map +1 -0
  237. package/dist/storage-key.d.ts +9 -0
  238. package/dist/storage-key.d.ts.map +1 -0
  239. package/dist/storage-key.js +59 -0
  240. package/dist/storage-key.js.map +1 -0
  241. package/dist/tmux.d.ts +39 -0
  242. package/dist/tmux.d.ts.map +1 -0
  243. package/dist/tmux.js +141 -0
  244. package/dist/tmux.js.map +1 -0
  245. package/dist/types.d.ts +1496 -0
  246. package/dist/types.d.ts.map +1 -0
  247. package/dist/types.js +215 -0
  248. package/dist/types.js.map +1 -0
  249. package/dist/update-cache.d.ts +59 -0
  250. package/dist/update-cache.d.ts.map +1 -0
  251. package/dist/update-cache.js +77 -0
  252. package/dist/update-cache.js.map +1 -0
  253. package/dist/utils/metadata-flatten.d.ts +3 -0
  254. package/dist/utils/metadata-flatten.d.ts.map +1 -0
  255. package/dist/utils/metadata-flatten.js +18 -0
  256. package/dist/utils/metadata-flatten.js.map +1 -0
  257. package/dist/utils/pr.d.ts +7 -0
  258. package/dist/utils/pr.d.ts.map +1 -0
  259. package/dist/utils/pr.js +97 -0
  260. package/dist/utils/pr.js.map +1 -0
  261. package/dist/utils/session-from-metadata.d.ts +16 -0
  262. package/dist/utils/session-from-metadata.d.ts.map +1 -0
  263. package/dist/utils/session-from-metadata.js +87 -0
  264. package/dist/utils/session-from-metadata.js.map +1 -0
  265. package/dist/utils/session-id.d.ts +4 -0
  266. package/dist/utils/session-id.d.ts.map +1 -0
  267. package/dist/utils/session-id.js +9 -0
  268. package/dist/utils/session-id.js.map +1 -0
  269. package/dist/utils/validation.d.ts +9 -0
  270. package/dist/utils/validation.d.ts.map +1 -0
  271. package/dist/utils/validation.js +45 -0
  272. package/dist/utils/validation.js.map +1 -0
  273. package/dist/utils.d.ts +65 -0
  274. package/dist/utils.d.ts.map +1 -0
  275. package/dist/utils.js +189 -0
  276. package/dist/utils.js.map +1 -0
  277. package/dist/version-compare.d.ts +27 -0
  278. package/dist/version-compare.d.ts.map +1 -0
  279. package/dist/version-compare.js +121 -0
  280. package/dist/version-compare.js.map +1 -0
  281. package/dist/windows-pty-registry.d.ts +27 -0
  282. package/dist/windows-pty-registry.d.ts.map +1 -0
  283. package/dist/windows-pty-registry.js +109 -0
  284. package/dist/windows-pty-registry.js.map +1 -0
  285. package/package.json +110 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Composio, Inc.
4
+ Copyright (c) 2026 slievr (Athene fork)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,241 @@
1
+ # @made-by-moonlight/athene-core
2
+
3
+ Core services, types, and configuration for the Athene system.
4
+
5
+ ## What's Here
6
+
7
+ - **`src/types.ts`** — All TypeScript interfaces (Runtime, Agent, Workspace, Tracker, SCM, Notifier, Terminal, Session, events)
8
+ - **`src/services/`** — Core services (SessionManager, LifecycleManager, PluginRegistry)
9
+ - **`src/config.ts`** — Configuration loading + Zod schemas
10
+ - **`src/utils/`** — Shared utilities (shell escaping, metadata parsing, etc.)
11
+
12
+ ## Key Files
13
+
14
+ ### `src/types.ts` — The Source of Truth
15
+
16
+ Every interface the system uses is defined here. If you're working on any part of the orchestrator, start by reading this file.
17
+
18
+ **Main interfaces:**
19
+
20
+ - `Runtime` — where sessions execute (tmux on Unix, `process` / ConPTY via node-pty on Windows, docker, k8s)
21
+ - `Agent` — AI coding tool adapter (claude-code, codex, aider)
22
+ - `Workspace` — code isolation (worktree, clone)
23
+ - `Tracker` — issue tracking (GitHub Issues, Linear)
24
+ - `SCM` — PR/CI/reviews (GitHub, GitLab)
25
+ - `Notifier` — push notifications (desktop, Slack, webhook)
26
+ - `Terminal` — human interaction UI (iTerm2, web)
27
+ - `Session` — running agent instance (state, metadata, handles)
28
+ - `OrchestratorEvent` — events emitted by lifecycle manager
29
+ - `PluginModule` — what every plugin exports
30
+
31
+ ### `src/services/session-manager.ts` — Session CRUD
32
+
33
+ Handles session lifecycle:
34
+
35
+ - `spawn(config)` — create new session (workspace + runtime + agent)
36
+ - `list(projectId?)` — list all sessions
37
+ - `get(sessionId)` — get session details
38
+ - `kill(sessionId)` — terminate session
39
+ - `cleanup(projectId?)` — kill completed/merged sessions
40
+ - `send(sessionId, message)` — send message to agent
41
+
42
+ **Data flow in `spawn()`:**
43
+
44
+ 1. Load project config
45
+ 2. **Validate issue exists** via `Tracker.getIssue()` (if issueId provided, fails-fast if not found)
46
+ 3. Reserve session ID
47
+ 4. Determine branch name
48
+ 5. Create workspace via `Workspace.create()`
49
+ 6. Generate prompt via `Tracker.generatePrompt()`
50
+ 7. Build layered worker prompt via `buildPrompt()` into `systemPrompt` + `taskPrompt`
51
+ 8. Persist `systemPromptFile` for the session and, for OpenCode workers, write `OPENCODE_CONFIG`
52
+ 9. Build launch command via `Agent.getLaunchCommand()`
53
+ 10. Create runtime session via `Runtime.create()`
54
+ 11. Run `Agent.postLaunchSetup()` (optional)
55
+ 12. Write metadata file
56
+ 13. Return Session object
57
+
58
+ **Note:** If issue validation fails (not found, auth error), spawn fails before creating any resources (no workspace, no runtime, no session ID). This prevents spawning sessions with broken issue references.
59
+ Worker sessions keep persistent instructions in the prompt file. OpenCode workers consume that file through `OPENCODE_CONFIG`, while OpenCode orchestrators continue to project their system prompt into workspace `AGENTS.md`.
60
+
61
+ ### `src/services/lifecycle-manager.ts` — State Machine + Reactions
62
+
63
+ Polls sessions, detects state changes, triggers reactions:
64
+
65
+ **State machine:**
66
+
67
+ ```
68
+ spawning → working → pr_open → ci_failed/review_pending/approved → mergeable → merged
69
+ ```
70
+
71
+ **Reactions:**
72
+
73
+ - `ci-failed` → send fix prompt to agent
74
+ - `changes-requested` → send review comments to agent
75
+ - `approved-and-green` → notify human (or auto-merge)
76
+ - `agent-stuck` → notify human
77
+
78
+ **Polling loop:**
79
+
80
+ 1. For each session: check agent activity state (`Agent.getActivityState()`)
81
+ 2. If PR exists: check CI status (`SCM.getCISummary()`), review state (`SCM.getReviewDecision()`)
82
+ 3. Update session status based on state
83
+ 4. Trigger reactions if state changed
84
+ 5. Emit events
85
+
86
+ ### `src/services/plugin-registry.ts` — Plugin Discovery + Loading
87
+
88
+ Loads plugins and provides access to them:
89
+
90
+ - `register(plugin, config?)` — register a plugin instance
91
+ - `get<T>(slot, name)` — get plugin by slot + name
92
+ - `list(slot)` — list all plugins for a slot
93
+ - `loadBuiltins(config?)` — load built-in plugins (runtime-tmux, agent-claude-code, etc.)
94
+ - `loadFromConfig(config)` — load built-ins today; external plugin descriptors are the marketplace extension point
95
+
96
+ **Built-in plugins** (loaded by default):
97
+
98
+ - runtime-tmux, runtime-process
99
+ - agent-claude-code, agent-codex, agent-aider, agent-cursor, agent-kimicode, agent-opencode
100
+ - workspace-worktree, workspace-clone
101
+ - tracker-github, tracker-linear, tracker-gitlab
102
+ - scm-github, scm-gitlab
103
+ - notifier-desktop, notifier-discord, notifier-slack, notifier-composio, notifier-openclaw, notifier-webhook
104
+ - terminal-iterm2, terminal-web
105
+
106
+ ### `src/config.ts` — Configuration Loading
107
+
108
+ Loads and validates `agent-orchestrator.yaml`:
109
+
110
+ **Main config sections:**
111
+
112
+ - Runtime data paths are auto-derived from the config location under `~/.agent-orchestrator/{hash}-{projectId}/`
113
+ - `port` — web dashboard port (default 3000, set different values for multiple projects)
114
+ - `terminalPort` — terminal WebSocket port (auto-detected if not set)
115
+ - `directTerminalPort` — direct terminal WebSocket port (auto-detected if not set)
116
+ - `defaults` — default plugins (runtime, agent, workspace, notifiers)
117
+ - `plugins` — installer-managed external plugin descriptors (registry, npm, or local)
118
+ - `projects` — per-project config (repo, path, branch, symlinks, reactions, agentRules)
119
+ - `notifiers` — notification channel config (Slack webhooks, etc.)
120
+ - `notificationRouting` — which notifiers get which priority events
121
+ - `reactions` — auto-response config (ci-failed, changes-requested, approved-and-green, etc.)
122
+
123
+ **Zod schemas** validate all config at load time.
124
+
125
+ ## Common Tasks
126
+
127
+ ### Adding a Field to Session
128
+
129
+ 1. Edit `src/types.ts` → `Session` interface
130
+ 2. Edit `src/services/session-manager.ts` → initialize field in `spawn()`
131
+ 3. Rebuild: `pnpm --filter @made-by-moonlight/athene-core build`
132
+
133
+ ### Adding an Event Type
134
+
135
+ 1. Edit `src/types.ts` → `EventType` union
136
+ 2. Emit the event: `eventEmitter.emit()` in relevant service
137
+ 3. Add reaction handler (optional): `src/services/lifecycle-manager.ts`
138
+
139
+ ### Adding a Reaction
140
+
141
+ 1. Edit `src/services/lifecycle-manager.ts` → add handler function
142
+ 2. Wire it up in the polling loop
143
+ 3. Add config schema in `src/config.ts` if new reaction type
144
+
145
+ ### Feedback Tools (v1)
146
+
147
+ `@made-by-moonlight/athene-core` exports two structured feedback tool contracts:
148
+
149
+ - `bug_report`
150
+ - `improvement_suggestion`
151
+
152
+ Both share the same required input fields:
153
+
154
+ - `title`
155
+ - `body`
156
+ - `evidence` (array of strings)
157
+ - `session`
158
+ - `source`
159
+ - `confidence` (0..1)
160
+
161
+ Example:
162
+
163
+ ```ts
164
+ import { FEEDBACK_TOOL_NAMES, FeedbackReportStore, getFeedbackReportsDir } from "@made-by-moonlight/athene-core";
165
+
166
+ const reportsDir = getFeedbackReportsDir(configPath, projectPath);
167
+ const store = new FeedbackReportStore(reportsDir);
168
+
169
+ const saved = store.persist(FEEDBACK_TOOL_NAMES.BUG_REPORT, {
170
+ title: "SSO login loop",
171
+ body: "Google SSO redirects back to /login repeatedly.",
172
+ evidence: ["trace_id=abc123", "screenshot: login-loop.png"],
173
+ session: "ao-22",
174
+ source: "agent",
175
+ confidence: 0.84,
176
+ });
177
+ ```
178
+
179
+ Storage format:
180
+
181
+ - Reports are persisted under `~/.agent-orchestrator/{hash}-{projectId}/feedback-reports`
182
+ - Each report is a typed key=value file (`report_<timestamp>_<id>.kv`) for easy inspection
183
+ - A deterministic dedupe key (`sha256`, 16 hex chars) is generated from normalized tool+content
184
+
185
+ Migration notes:
186
+
187
+ - No migration needed for existing AO installs
188
+ - The `feedback-reports` directory is created lazily on first persisted report
189
+
190
+ ## Testing
191
+
192
+ ```bash
193
+ # Run all core tests
194
+ pnpm --filter @made-by-moonlight/athene-core test
195
+
196
+ # Run in watch mode
197
+ pnpm --filter @made-by-moonlight/athene-core test -- --watch
198
+
199
+ # Run specific test
200
+ pnpm --filter @made-by-moonlight/athene-core test -- session-manager.test.ts
201
+ ```
202
+
203
+ Tests are in `src/__tests__/`:
204
+
205
+ - `session-manager.test.ts` — session CRUD, spawn, cleanup
206
+ - `lifecycle-manager.test.ts` — state machine, reactions
207
+ - `plugin-registry.test.ts` — plugin loading, resolution
208
+ - `tmux.test.ts` — tmux utility functions (not a plugin test)
209
+ - `prompt-builder.test.ts` — prompt generation utilities
210
+
211
+ ## Building
212
+
213
+ ```bash
214
+ # Build core
215
+ pnpm --filter @made-by-moonlight/athene-core build
216
+
217
+ # Typecheck
218
+ pnpm --filter @made-by-moonlight/athene-core typecheck
219
+ ```
220
+
221
+ This package is a dependency of all other packages. Build it first if working on the codebase.
222
+
223
+ ## Architecture Notes
224
+
225
+ **Why flat metadata files?**
226
+
227
+ - Debuggability: `cat ~/.agent-orchestrator/<hash>-my-app/sessions/app-3` shows full state
228
+ - No database dependency (survives crashes, easy to inspect)
229
+ - Backwards-compatible with bash script orchestrator
230
+
231
+ **Why polling instead of webhooks?**
232
+
233
+ - Simpler (no webhook setup, no ngrok for local dev)
234
+ - Works offline (CI/review state is fetched, not pushed)
235
+ - Survives orchestrator restarts (no missed events)
236
+
237
+ **Why plugin slots?**
238
+
239
+ - Swappability: use tmux on Linux/macOS, `process` (ConPTY) on Windows, docker in CI, k8s in prod — same agent/workspace stack across all of them
240
+ - Testability: mock plugins for tests
241
+ - Extensibility: users can add custom plugins (e.g., company-specific notifier)
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Activity event logging — write API.
3
+ *
4
+ * recordActivityEvent() is synchronous and best-effort: it never throws.
5
+ * If the DB is unavailable or a write fails, the event is dropped and
6
+ * droppedEventCount is incremented.
7
+ *
8
+ * droppedEventCount is process-local. Events dropped in other processes
9
+ * (web server, lifecycle manager) are not reflected here.
10
+ */
11
+ export type ActivityEventSource = "lifecycle" | "session-manager" | "api" | "ui" | "scm" | "runtime" | "agent" | "tracker" | "workspace" | "notifier" | "reaction" | "report-watcher" | "cli" | "config" | "plugin-registry" | "migration" | "recovery";
12
+ export type ActivityEventKind = "session.spawn_started" | "session.spawned" | "session.spawn_failed" | "session.spawn_step_failed" | "session.killed" | "session.kill_started" | "session.send_failed" | "session.restore_failed" | "session.restore_fallback" | "session.rollback_started" | "session.rollback_step_failed" | "session.workspace_hooks_failed" | "session.cleanup_error" | "session.orchestrator_conflict" | "runtime.lost_detected" | "runtime.lost_persist_failed" | "runtime.destroy_failed" | "workspace.destroy_failed" | "agent.opencode_purge_failed" | "tracker.issue_fetch_failed" | "tracker.generate_prompt_failed" | "metadata.corrupt_detected" | "activity.transition" | "lifecycle.transition" | "ci.failing" | "review.pending" | "scm.batch_enrich_failed" | "scm.detect_pr_succeeded" | "scm.detect_pr_failed" | "scm.review_fetch_failed" | "scm.poll_pr_failed" | "runtime.probe_failed" | "agent.process_probe_failed" | "agent.activity_probe_failed" | "scm.gh_unavailable" | "scm.batch_enrich_pr_failed" | "scm.ci_summary_failclosed" | "workspace.post_create_failed" | "workspace.branch_collision" | "workspace.destroy_fell_back" | "workspace.corrupt_clone_skipped" | "tracker.dep_missing" | "tracker.api_timeout" | "notifier.auth_failed" | "notifier.unreachable" | "notifier.rate_limited" | "notifier.dep_missing" | "reaction.escalated" | "reaction.send_to_agent_failed" | "reaction.action_succeeded" | "session.auto_cleanup_deferred" | "session.auto_cleanup_completed" | "session.auto_cleanup_failed" | "lifecycle.poll_failed" | "detecting.escalated" | "notification.delivery_failed" | "notification.target_missing" | "report_watcher.triggered" | "config.project_resolve_failed" | "config.project_malformed" | "config.project_invalid" | "config.migrated" | "plugin-registry.load_failed" | "plugin-registry.validation_failed" | "plugin-registry.specifier_failed" | "migration.blocked" | "migration.project_failed" | "migration.rename_failed" | "migration.completed" | "migration.rollback_skipped" | "api.webhook_unverified" | "api.webhook_rejected" | "api.webhook_received" | "api.webhook_failed" | "ui.terminal_connected" | "ui.terminal_disconnected" | "ui.terminal_heartbeat_lost" | "ui.terminal_pty_lost" | "ui.terminal_protocol_error" | "ui.session_broadcast_failed" | "recovery.session_failed" | "recovery.action_failed" | "api.agent_report.session_not_found" | "api.agent_report.transition_rejected" | "api.agent_report.apply_failed";
13
+ export type ActivityEventLevel = "debug" | "info" | "warn" | "error";
14
+ export interface ActivityEventInput {
15
+ projectId?: string;
16
+ sessionId?: string;
17
+ source: ActivityEventSource | string;
18
+ kind: ActivityEventKind | string;
19
+ level?: ActivityEventLevel;
20
+ summary: string;
21
+ data?: Record<string, unknown>;
22
+ }
23
+ export interface ActivityEvent {
24
+ id: number;
25
+ tsEpoch: number;
26
+ ts: string;
27
+ projectId: string | null;
28
+ sessionId: string | null;
29
+ source: string;
30
+ kind: string;
31
+ level: string;
32
+ summary: string;
33
+ data: string | null;
34
+ rank?: number;
35
+ }
36
+ /** Number of events dropped due to DB errors in this process. */
37
+ export declare function droppedEventCount(): number;
38
+ /**
39
+ * Record an activity event. Synchronous, best-effort — never throws.
40
+ */
41
+ export declare function recordActivityEvent(event: ActivityEventInput): void;
42
+ //# sourceMappingURL=activity-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-events.d.ts","sourceRoot":"","sources":["../src/activity-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,192 @@
1
+ import { getDb } from './events-db.js';
2
+
3
+ /**
4
+ * Activity event logging — write API.
5
+ *
6
+ * recordActivityEvent() is synchronous and best-effort: it never throws.
7
+ * If the DB is unavailable or a write fails, the event is dropped and
8
+ * droppedEventCount is incremented.
9
+ *
10
+ * droppedEventCount is process-local. Events dropped in other processes
11
+ * (web server, lifecycle manager) are not reflected here.
12
+ */
13
+ let _droppedEventCount = 0;
14
+ let _lastPruneMs = 0;
15
+ const PRUNE_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
16
+ const RETENTION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
17
+ const PRUNE_BATCH_SIZE = 1000;
18
+ /** Number of events dropped due to DB errors in this process. */
19
+ function droppedEventCount() {
20
+ return _droppedEventCount;
21
+ }
22
+ function pruneOldEvents(db, cutoff) {
23
+ db?.prepare(`DELETE FROM activity_events
24
+ WHERE rowid IN (
25
+ SELECT rowid FROM activity_events WHERE ts_epoch < ? LIMIT ?
26
+ )`).run(cutoff, PRUNE_BATCH_SIZE);
27
+ }
28
+ // Patterns that indicate sensitive field names
29
+ const SENSITIVE_KEY_RE = /token|password|secret|authorization|cookie|api[-_]?key/i;
30
+ // URL credentials: https://token@host or http://user:pass@host.
31
+ // Linear scan — find :// then scan forward for the next @ before a path
32
+ // separator or whitespace. O(n) worst case, no regex backtracking, no length
33
+ // limits. Replaces the previous CREDENTIAL_URL_RE which either ReDoS'd
34
+ // (unbounded quantifier) or missed >200-char userinfo (bounded quantifier).
35
+ function redactCredentialUrls(input) {
36
+ let result = input;
37
+ let offset = 0;
38
+ while (offset < result.length) {
39
+ const proto = result.indexOf("://", offset);
40
+ if (proto === -1)
41
+ break;
42
+ // Only match http:// or https:// (case-insensitive, matching old /gi flag)
43
+ if (proto < 4) {
44
+ offset = proto + 3;
45
+ continue;
46
+ }
47
+ const schemeEnd = result.slice(Math.max(0, proto - 5), proto).toLowerCase();
48
+ if (!schemeEnd.endsWith("http") && !schemeEnd.endsWith("https")) {
49
+ offset = proto + 3;
50
+ continue;
51
+ }
52
+ let cursor = proto + 3;
53
+ while (cursor < result.length) {
54
+ const ch = result.charCodeAt(cursor);
55
+ // Space/control chars or '/' mean no '@' is coming in userinfo
56
+ if (ch <= 0x20 || ch === 0x2f)
57
+ break;
58
+ if (ch === 0x40) {
59
+ // '@' found — redact everything between :// and @
60
+ // Lowercase the scheme to match the old /gi regex behavior
61
+ const before = result.slice(0, proto + 3).toLowerCase();
62
+ const suffix = result.slice(cursor);
63
+ result = before + "[redacted]" + suffix;
64
+ offset = proto + 3 + "[redacted]".length + 1;
65
+ break;
66
+ }
67
+ cursor++;
68
+ }
69
+ // No '@' found — not a credential URL, move past this ://
70
+ if (cursor >= result.length ||
71
+ result.charCodeAt(cursor) <= 0x20 ||
72
+ result.charCodeAt(cursor) === 0x2f) {
73
+ offset = proto + 3;
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ // Per-string-value cap. The whole-data 16 KB cap still applies on top of this;
79
+ // truncating individual strings limits blast radius if a pattern below misses a
80
+ // new token format and a long error message gets pasted in.
81
+ const STRING_VALUE_MAX_CHARS = 500;
82
+ // Token-shape patterns matched against ANY string value, not just keys.
83
+ // Order: more-specific first. Replacement strings preserve the prefix where
84
+ // the prefix itself is informative (e.g. "Bearer [redacted]" so RCA can still
85
+ // see this was a bearer-auth failure).
86
+ //
87
+ // SENSITIVE_KEY_RE above redacts entire values under sensitive *key* names;
88
+ // these patterns redact token-shaped *substrings* anywhere — including under
89
+ // keys like `message` and `errorMessage`, which are the leak vector flagged
90
+ // in PR #1620 review (data column is FTS5-indexed in events-db.ts).
91
+ const TOKEN_PATTERNS = [
92
+ // Bearer auth headers (also catches JWTs prefixed with Bearer)
93
+ [/\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/gi, "Bearer [redacted]"],
94
+ // GitHub Personal Access Tokens — classic (ghp_/gho_/ghu_/ghs_/ghr_)
95
+ [/\bgh[pousr]_[A-Za-z0-9_]{20,}\b/g, "[redacted]"],
96
+ // GitHub fine-grained PATs
97
+ [/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, "[redacted]"],
98
+ // OpenAI / Anthropic sk- keys (incl. sk-proj-, sk-svcacct-, sk-ant-)
99
+ [/\bsk-(?:ant-)?(?:proj-|svcacct-)?[A-Za-z0-9_-]{16,}\b/g, "[redacted]"],
100
+ // Slack tokens (xoxb-, xoxp-, xoxa-, xoxr-, xoxs-)
101
+ [/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, "[redacted]"],
102
+ // AWS access key IDs (16 trailing chars exactly per AWS spec)
103
+ [/\bAKIA[0-9A-Z]{16}\b/g, "[redacted]"],
104
+ // JWTs — three base64url segments, eyJ prefix on header
105
+ [/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g, "[redacted]"],
106
+ // ENV-style assignments: MY_API_TOKEN=value, GITHUB_SECRET=..., etc.
107
+ // Scoped to ALL_CAPS keys containing a sensitive word so prose like
108
+ // "the message=hello" doesn't redact.
109
+ [
110
+ /\b([A-Z][A-Z0-9_]*(?:TOKEN|PASSWORD|SECRET|AUTHORIZATION|COOKIE|API_KEY|APIKEY)[A-Z0-9_]*)=([^\s"'`]{6,})/g,
111
+ "$1=[redacted]",
112
+ ],
113
+ ];
114
+ function sanitizeString(value) {
115
+ let cleaned = redactCredentialUrls(value);
116
+ for (const [pattern, replacement] of TOKEN_PATTERNS) {
117
+ cleaned = cleaned.replace(pattern, replacement);
118
+ }
119
+ if (cleaned.length > STRING_VALUE_MAX_CHARS) {
120
+ cleaned = `${cleaned.slice(0, STRING_VALUE_MAX_CHARS - 3)}...`;
121
+ }
122
+ return cleaned;
123
+ }
124
+ function sanitizeValue(value, seen) {
125
+ if (typeof value === "bigint")
126
+ return value.toString();
127
+ if (typeof value === "string")
128
+ return sanitizeString(value);
129
+ if (value === null || typeof value !== "object")
130
+ return value;
131
+ if (seen.has(value))
132
+ return "[circular]";
133
+ seen.add(value);
134
+ if (Array.isArray(value)) {
135
+ return value.map((item) => sanitizeValue(item, seen));
136
+ }
137
+ const cleaned = {};
138
+ for (const [k, v] of Object.entries(value)) {
139
+ cleaned[k] = SENSITIVE_KEY_RE.test(k) ? "[redacted]" : sanitizeValue(v, seen);
140
+ }
141
+ return cleaned;
142
+ }
143
+ function sanitizeData(data) {
144
+ const cleaned = sanitizeValue(data, new WeakSet());
145
+ let json;
146
+ try {
147
+ json = JSON.stringify(cleaned);
148
+ }
149
+ catch {
150
+ return undefined;
151
+ }
152
+ // Reject if over 16 KB after sanitization (slicing would produce malformed JSON)
153
+ if (json.length > 16 * 1024) {
154
+ return undefined;
155
+ }
156
+ return json;
157
+ }
158
+ function sanitizeSummary(summary) {
159
+ if (summary.length <= 500)
160
+ return summary;
161
+ return `${summary.slice(0, 497)}...`;
162
+ }
163
+ /**
164
+ * Record an activity event. Synchronous, best-effort — never throws.
165
+ */
166
+ function recordActivityEvent(event) {
167
+ try {
168
+ const db = getDb();
169
+ if (!db) {
170
+ _droppedEventCount++;
171
+ return;
172
+ }
173
+ const now = Date.now();
174
+ const ts = new Date(now).toISOString();
175
+ const summary = sanitizeSummary(event.summary);
176
+ const data = event.data ? sanitizeData(event.data) : undefined;
177
+ db.prepare(`INSERT INTO activity_events
178
+ (ts_epoch, ts, project_id, session_id, source, type, log_level, summary, data)
179
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(now, ts, event.projectId ?? null, event.sessionId ?? null, event.source, event.kind, event.level ?? "info", summary, data ?? null);
180
+ // Periodically purge old events so long-lived processes don't grow the DB indefinitely
181
+ if (now - _lastPruneMs >= PRUNE_INTERVAL_MS) {
182
+ _lastPruneMs = now;
183
+ pruneOldEvents(db, now - RETENTION_MS);
184
+ }
185
+ }
186
+ catch {
187
+ _droppedEventCount++;
188
+ }
189
+ }
190
+
191
+ export { droppedEventCount, recordActivityEvent };
192
+ //# sourceMappingURL=activity-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-events.js","sources":["../src/activity-events.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import type { ActivityState, ActivityLogEntry, ActivityDetection } from "./types.js";
2
+ /**
3
+ * @deprecated Actionable states no longer decay on wallclock. Retained until
4
+ * the activity-reducer cleanup removes the old activity-log module.
5
+ */
6
+ export declare const ACTIVITY_INPUT_STALENESS_MS: number;
7
+ /**
8
+ * Get the path to the activity JSONL log for a session.
9
+ * Location: `{workspacePath}/.ao/activity.jsonl`
10
+ */
11
+ export declare function getActivityLogPath(workspacePath: string): string;
12
+ /**
13
+ * Append an activity observation to the session's JSONL log.
14
+ * Creates the `.ao/` directory if it doesn't exist.
15
+ */
16
+ export declare function appendActivityEntry(workspacePath: string, state: ActivityState, source: "terminal" | "native" | "hook", trigger?: string): Promise<void>;
17
+ /**
18
+ * Read the last activity entry from the session's JSONL log.
19
+ * Returns the parsed entry with the file's modification time, or null if
20
+ * the file doesn't exist or is empty.
21
+ */
22
+ export declare function readLastActivityEntry(workspacePath: string): Promise<{
23
+ entry: ActivityLogEntry;
24
+ modifiedAt: Date;
25
+ } | null>;
26
+ /**
27
+ * Check the AO activity JSONL for actionable states only.
28
+ *
29
+ * Only returns `waiting_input`/`blocked`.
30
+ * Non-critical states (`active`, `ready`, `idle`) always return `null` so
31
+ * callers fall through to their native signals (git commits, chat history,
32
+ * API queries, native JSONL). This prevents the lifecycle manager's
33
+ * `recordActivity` writes (which refresh `mtime` every poll cycle) from
34
+ * shadowing those richer detection methods and breaking stuck-detection.
35
+ */
36
+ export declare function checkActivityLogState(activityResult: {
37
+ entry: ActivityLogEntry;
38
+ modifiedAt: Date;
39
+ } | null): ActivityDetection | null;
40
+ /**
41
+ * Derive an activity state from the JSONL entry with age-based decay.
42
+ *
43
+ * Unlike `checkActivityLogState` (which only returns actionable states),
44
+ * this returns any state — but reclassifies `active`/`ready` entries as
45
+ * `ready`/`idle` if they've aged past the active window / threshold.
46
+ * Use this as a last-resort fallback when native signals are unavailable.
47
+ */
48
+ export declare function getActivityFallbackState(activityResult: {
49
+ entry: ActivityLogEntry;
50
+ modifiedAt: Date;
51
+ } | null, activeWindowMs: number, thresholdMs: number): ActivityDetection | null;
52
+ /**
53
+ * Build the arguments for `appendActivityEntry` from terminal output.
54
+ *
55
+ * Classifies terminal output via the provided `detectActivity` function and
56
+ * returns the state + trigger. Plugins call `appendActivityEntry` themselves
57
+ * (keeping it mockable in tests).
58
+ */
59
+ export declare function classifyTerminalActivity(terminalOutput: string, detectActivity: (output: string) => ActivityState): {
60
+ state: ActivityState;
61
+ trigger: string | undefined;
62
+ };
63
+ /**
64
+ * Shared `recordActivity` implementation for all agents.
65
+ *
66
+ * Classifies terminal output, deduplicates writes (skips when the state
67
+ * hasn't changed and the last entry is recent), and appends to the JSONL.
68
+ * Actionable states (waiting_input/blocked) always write immediately.
69
+ */
70
+ export declare function recordTerminalActivity(workspacePath: string, terminalOutput: string, detectActivity: (output: string) => ActivityState): Promise<void>;
71
+ //# sourceMappingURL=activity-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-log.d.ts","sourceRoot":"","sources":["../src/activity-log.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,QAAgB,CAAC;AAEzD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,EACtC,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CAAC,CA+D/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,GACnE,iBAAiB,GAAG,IAAI,CAa1B;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,EACpE,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,iBAAiB,GAAG,IAAI,CAyB1B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,aAAa,GAChD;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAOvD;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,aAAa,GAChD,OAAO,CAAC,IAAI,CAAC,CAcf"}