heyio 1.12.1 → 3.0.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 (327) hide show
  1. package/dist/api/middleware/auth.d.ts +14 -0
  2. package/dist/api/middleware/auth.d.ts.map +1 -0
  3. package/dist/api/middleware/auth.js +66 -0
  4. package/dist/api/middleware/auth.js.map +1 -0
  5. package/dist/api/notifications.d.ts +14 -0
  6. package/dist/api/notifications.d.ts.map +1 -0
  7. package/dist/api/notifications.js +112 -0
  8. package/dist/api/notifications.js.map +1 -0
  9. package/dist/api/routes/activity.d.ts +3 -0
  10. package/dist/api/routes/activity.d.ts.map +1 -0
  11. package/dist/api/routes/activity.js +28 -0
  12. package/dist/api/routes/activity.js.map +1 -0
  13. package/dist/api/routes/attachments.d.ts +3 -0
  14. package/dist/api/routes/attachments.d.ts.map +1 -0
  15. package/dist/api/routes/attachments.js +83 -0
  16. package/dist/api/routes/attachments.js.map +1 -0
  17. package/dist/api/routes/config.d.ts +3 -0
  18. package/dist/api/routes/config.d.ts.map +1 -0
  19. package/dist/api/routes/config.js +106 -0
  20. package/dist/api/routes/config.js.map +1 -0
  21. package/dist/api/routes/conversations.d.ts +3 -0
  22. package/dist/api/routes/conversations.d.ts.map +1 -0
  23. package/dist/api/routes/conversations.js +69 -0
  24. package/dist/api/routes/conversations.js.map +1 -0
  25. package/dist/api/routes/health.d.ts +3 -0
  26. package/dist/api/routes/health.d.ts.map +1 -0
  27. package/dist/api/routes/health.js +16 -0
  28. package/dist/api/routes/health.js.map +1 -0
  29. package/dist/api/routes/inbox.d.ts +3 -0
  30. package/dist/api/routes/inbox.d.ts.map +1 -0
  31. package/dist/api/routes/inbox.js +88 -0
  32. package/dist/api/routes/inbox.js.map +1 -0
  33. package/dist/api/routes/schedules.d.ts +3 -0
  34. package/dist/api/routes/schedules.d.ts.map +1 -0
  35. package/dist/api/routes/schedules.js +96 -0
  36. package/dist/api/routes/schedules.js.map +1 -0
  37. package/dist/api/routes/skills.d.ts +2 -0
  38. package/dist/api/routes/skills.d.ts.map +1 -0
  39. package/dist/api/routes/skills.js +85 -0
  40. package/dist/api/routes/skills.js.map +1 -0
  41. package/dist/api/routes/squads.d.ts +3 -0
  42. package/dist/api/routes/squads.d.ts.map +1 -0
  43. package/dist/api/routes/squads.js +129 -0
  44. package/dist/api/routes/squads.js.map +1 -0
  45. package/dist/api/routes/usage.d.ts +3 -0
  46. package/dist/api/routes/usage.d.ts.map +1 -0
  47. package/dist/api/routes/usage.js +55 -0
  48. package/dist/api/routes/usage.js.map +1 -0
  49. package/dist/api/routes/wiki.d.ts +2 -0
  50. package/dist/api/routes/wiki.d.ts.map +1 -0
  51. package/dist/api/routes/wiki.js +43 -0
  52. package/dist/api/routes/wiki.js.map +1 -0
  53. package/dist/api/server.d.ts +7 -0
  54. package/dist/api/server.d.ts.map +1 -0
  55. package/dist/api/server.js +136 -634
  56. package/dist/api/server.js.map +1 -0
  57. package/dist/config.d.ts +3 -0
  58. package/dist/config.d.ts.map +1 -0
  59. package/dist/config.js +2 -91
  60. package/dist/config.js.map +1 -0
  61. package/dist/copilot/client.d.ts +5 -0
  62. package/dist/copilot/client.d.ts.map +1 -0
  63. package/dist/copilot/client.js +19 -11
  64. package/dist/copilot/client.js.map +1 -0
  65. package/dist/copilot/health-monitor.d.ts +14 -0
  66. package/dist/copilot/health-monitor.d.ts.map +1 -0
  67. package/dist/copilot/health-monitor.js +70 -0
  68. package/dist/copilot/health-monitor.js.map +1 -0
  69. package/dist/copilot/orchestrator.d.ts +5 -0
  70. package/dist/copilot/orchestrator.d.ts.map +1 -0
  71. package/dist/copilot/orchestrator.js +127 -123
  72. package/dist/copilot/orchestrator.js.map +1 -0
  73. package/dist/copilot/tools.d.ts +49 -0
  74. package/dist/copilot/tools.d.ts.map +1 -0
  75. package/dist/copilot/tools.js +545 -321
  76. package/dist/copilot/tools.js.map +1 -0
  77. package/dist/index.d.ts +3 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +82 -26
  80. package/dist/index.js.map +1 -0
  81. package/dist/logging/logger.d.ts +6 -0
  82. package/dist/logging/logger.d.ts.map +1 -0
  83. package/dist/logging/logger.js +21 -0
  84. package/dist/logging/logger.js.map +1 -0
  85. package/dist/models/index.d.ts +6 -0
  86. package/dist/models/index.d.ts.map +1 -0
  87. package/dist/models/index.js +4 -0
  88. package/dist/models/index.js.map +1 -0
  89. package/dist/models/pricing.d.ts +25 -0
  90. package/dist/models/pricing.d.ts.map +1 -0
  91. package/dist/models/pricing.js +96 -0
  92. package/dist/models/pricing.js.map +1 -0
  93. package/dist/models/registry.d.ts +34 -0
  94. package/dist/models/registry.d.ts.map +1 -0
  95. package/dist/models/registry.js +109 -0
  96. package/dist/models/registry.js.map +1 -0
  97. package/dist/models/token-tracker.d.ts +40 -0
  98. package/dist/models/token-tracker.d.ts.map +1 -0
  99. package/dist/models/token-tracker.js +102 -0
  100. package/dist/models/token-tracker.js.map +1 -0
  101. package/dist/scheduler/engine.d.ts +9 -0
  102. package/dist/scheduler/engine.d.ts.map +1 -0
  103. package/dist/scheduler/engine.js +127 -0
  104. package/dist/scheduler/engine.js.map +1 -0
  105. package/dist/skills/index.d.ts +3 -0
  106. package/dist/skills/index.d.ts.map +1 -0
  107. package/dist/skills/index.js +2 -0
  108. package/dist/skills/index.js.map +1 -0
  109. package/dist/skills/store.d.ts +52 -0
  110. package/dist/skills/store.d.ts.map +1 -0
  111. package/dist/skills/store.js +148 -0
  112. package/dist/skills/store.js.map +1 -0
  113. package/dist/squad/agent.d.ts +46 -0
  114. package/dist/squad/agent.d.ts.map +1 -0
  115. package/dist/squad/agent.js +261 -0
  116. package/dist/squad/agent.js.map +1 -0
  117. package/dist/squad/autonomy.d.ts +16 -0
  118. package/dist/squad/autonomy.d.ts.map +1 -0
  119. package/dist/squad/autonomy.js +63 -0
  120. package/dist/squad/autonomy.js.map +1 -0
  121. package/dist/squad/event-bus.d.ts +22 -0
  122. package/dist/squad/event-bus.d.ts.map +1 -0
  123. package/dist/squad/event-bus.js +56 -0
  124. package/dist/squad/event-bus.js.map +1 -0
  125. package/dist/squad/execution/index.d.ts +12 -0
  126. package/dist/squad/execution/index.d.ts.map +1 -0
  127. package/dist/squad/execution/index.js +7 -0
  128. package/dist/squad/execution/index.js.map +1 -0
  129. package/dist/squad/execution/instance.d.ts +40 -0
  130. package/dist/squad/execution/instance.d.ts.map +1 -0
  131. package/dist/squad/execution/instance.js +138 -0
  132. package/dist/squad/execution/instance.js.map +1 -0
  133. package/dist/squad/execution/meeting.d.ts +25 -0
  134. package/dist/squad/execution/meeting.d.ts.map +1 -0
  135. package/dist/squad/execution/meeting.js +140 -0
  136. package/dist/squad/execution/meeting.js.map +1 -0
  137. package/dist/squad/execution/pr.d.ts +15 -0
  138. package/dist/squad/execution/pr.d.ts.map +1 -0
  139. package/dist/squad/execution/pr.js +93 -0
  140. package/dist/squad/execution/pr.js.map +1 -0
  141. package/dist/squad/execution/runner.d.ts +22 -0
  142. package/dist/squad/execution/runner.d.ts.map +1 -0
  143. package/dist/squad/execution/runner.js +68 -0
  144. package/dist/squad/execution/runner.js.map +1 -0
  145. package/dist/squad/execution/tasks.d.ts +11 -0
  146. package/dist/squad/execution/tasks.d.ts.map +1 -0
  147. package/dist/squad/execution/tasks.js +85 -0
  148. package/dist/squad/execution/tasks.js.map +1 -0
  149. package/dist/squad/execution/worktree.d.ts +26 -0
  150. package/dist/squad/execution/worktree.d.ts.map +1 -0
  151. package/dist/squad/execution/worktree.js +111 -0
  152. package/dist/squad/execution/worktree.js.map +1 -0
  153. package/dist/squad/hiring.d.ts +32 -0
  154. package/dist/squad/hiring.d.ts.map +1 -0
  155. package/dist/squad/hiring.js +200 -0
  156. package/dist/squad/hiring.js.map +1 -0
  157. package/dist/squad/index.d.ts +8 -0
  158. package/dist/squad/index.d.ts.map +1 -0
  159. package/dist/squad/index.js +6 -0
  160. package/dist/squad/index.js.map +1 -0
  161. package/dist/squad/manager.d.ts +48 -0
  162. package/dist/squad/manager.d.ts.map +1 -0
  163. package/dist/squad/manager.js +274 -0
  164. package/dist/squad/manager.js.map +1 -0
  165. package/dist/squad/name-generator.d.ts +16 -0
  166. package/dist/squad/name-generator.d.ts.map +1 -0
  167. package/dist/squad/name-generator.js +113 -0
  168. package/dist/squad/name-generator.js.map +1 -0
  169. package/dist/squad/roles/templates.d.ts +5 -0
  170. package/dist/squad/roles/templates.d.ts.map +1 -0
  171. package/dist/squad/roles/templates.js +102 -0
  172. package/dist/squad/roles/templates.js.map +1 -0
  173. package/dist/squad/skill-parser.d.ts +36 -0
  174. package/dist/squad/skill-parser.d.ts.map +1 -0
  175. package/dist/squad/skill-parser.js +83 -0
  176. package/dist/squad/skill-parser.js.map +1 -0
  177. package/dist/squad/source-resolver.d.ts +20 -0
  178. package/dist/squad/source-resolver.d.ts.map +1 -0
  179. package/dist/squad/source-resolver.js +52 -0
  180. package/dist/squad/source-resolver.js.map +1 -0
  181. package/dist/store/activity.d.ts +43 -0
  182. package/dist/store/activity.d.ts.map +1 -0
  183. package/dist/store/activity.js +131 -0
  184. package/dist/store/activity.js.map +1 -0
  185. package/dist/store/db.d.ts +5 -0
  186. package/dist/store/db.d.ts.map +1 -0
  187. package/dist/store/db.js +209 -248
  188. package/dist/store/db.js.map +1 -0
  189. package/dist/store/inbox.d.ts +53 -0
  190. package/dist/store/inbox.d.ts.map +1 -0
  191. package/dist/store/inbox.js +151 -0
  192. package/dist/store/inbox.js.map +1 -0
  193. package/dist/store/schedules.d.ts +53 -0
  194. package/dist/store/schedules.d.ts.map +1 -0
  195. package/dist/store/schedules.js +149 -54
  196. package/dist/store/schedules.js.map +1 -0
  197. package/dist/wiki/index.d.ts +3 -0
  198. package/dist/wiki/index.d.ts.map +1 -0
  199. package/dist/wiki/index.js +2 -0
  200. package/dist/wiki/index.js.map +1 -0
  201. package/dist/wiki/store.d.ts +49 -0
  202. package/dist/wiki/store.d.ts.map +1 -0
  203. package/dist/wiki/store.js +115 -0
  204. package/dist/wiki/store.js.map +1 -0
  205. package/package.json +52 -56
  206. package/src/api/middleware/auth.ts +76 -0
  207. package/src/api/notifications.ts +122 -0
  208. package/src/api/routes/activity.ts +29 -0
  209. package/src/api/routes/attachments.ts +93 -0
  210. package/src/api/routes/config.ts +115 -0
  211. package/src/api/routes/conversations.ts +87 -0
  212. package/src/api/routes/health.ts +18 -0
  213. package/src/api/routes/inbox.ts +98 -0
  214. package/src/api/routes/schedules.ts +121 -0
  215. package/src/api/routes/skills.ts +105 -0
  216. package/src/api/routes/squads.ts +145 -0
  217. package/src/api/routes/usage.ts +57 -0
  218. package/src/api/routes/wiki.ts +49 -0
  219. package/src/api/server.ts +186 -0
  220. package/src/config.ts +3 -0
  221. package/src/copilot/client.ts +42 -0
  222. package/src/copilot/health-monitor.ts +85 -0
  223. package/src/copilot/orchestrator.ts +222 -0
  224. package/src/copilot/tools.ts +707 -0
  225. package/src/index.ts +112 -0
  226. package/src/logging/logger.ts +26 -0
  227. package/src/models/index.ts +11 -0
  228. package/src/models/pricing.ts +121 -0
  229. package/src/models/registry.ts +131 -0
  230. package/src/models/token-tracker.ts +151 -0
  231. package/src/scheduler/engine.ts +146 -0
  232. package/src/skills/index.ts +13 -0
  233. package/src/skills/store.ts +188 -0
  234. package/src/squad/agent.ts +326 -0
  235. package/src/squad/autonomy.ts +78 -0
  236. package/src/squad/event-bus.ts +71 -0
  237. package/src/squad/execution/index.ts +17 -0
  238. package/src/squad/execution/instance.ts +186 -0
  239. package/src/squad/execution/meeting.ts +191 -0
  240. package/src/squad/execution/pr.ts +127 -0
  241. package/src/squad/execution/runner.ts +97 -0
  242. package/src/squad/execution/tasks.ts +111 -0
  243. package/src/squad/execution/worktree.ts +138 -0
  244. package/src/squad/hiring.ts +222 -0
  245. package/src/squad/index.ts +17 -0
  246. package/src/squad/manager.ts +337 -0
  247. package/src/squad/name-generator.ts +135 -0
  248. package/src/squad/roles/templates.ts +104 -0
  249. package/src/squad/skill-parser.ts +120 -0
  250. package/src/squad/source-resolver.ts +57 -0
  251. package/src/store/activity.ts +176 -0
  252. package/src/store/db.ts +237 -0
  253. package/src/store/inbox.ts +199 -0
  254. package/src/store/schedules.ts +199 -0
  255. package/src/wiki/index.ts +12 -0
  256. package/src/wiki/store.ts +139 -0
  257. package/tsconfig.json +9 -0
  258. package/LICENSE +0 -21
  259. package/README.md +0 -333
  260. package/dist/api/auth.js +0 -46
  261. package/dist/chat/attachments.js +0 -112
  262. package/dist/copilot/agents.js +0 -309
  263. package/dist/copilot/ceremonies.js +0 -174
  264. package/dist/copilot/gh-token.js +0 -64
  265. package/dist/copilot/io-scheduler.js +0 -79
  266. package/dist/copilot/model-router.js +0 -114
  267. package/dist/copilot/scheduler.js +0 -88
  268. package/dist/copilot/skills.js +0 -246
  269. package/dist/copilot/specialist-runner.js +0 -191
  270. package/dist/copilot/squad-tools.js +0 -258
  271. package/dist/copilot/system-message.js +0 -86
  272. package/dist/copilot/token-tracker.js +0 -98
  273. package/dist/copilot/trigger-schedule.js +0 -33
  274. package/dist/daemon.js +0 -67
  275. package/dist/logging.js +0 -27
  276. package/dist/mcp/config.js +0 -29
  277. package/dist/mcp/index.js +0 -3
  278. package/dist/mcp/registry.js +0 -42
  279. package/dist/notify.js +0 -25
  280. package/dist/paths.js +0 -17
  281. package/dist/setup.js +0 -35
  282. package/dist/store/agent-events.js +0 -19
  283. package/dist/store/audit-log.js +0 -71
  284. package/dist/store/conversations.js +0 -164
  285. package/dist/store/feed.js +0 -44
  286. package/dist/store/instances.js +0 -75
  287. package/dist/store/squad-colors.js +0 -23
  288. package/dist/store/squads.js +0 -60
  289. package/dist/store/tasks.js +0 -78
  290. package/dist/store/token-usage.js +0 -94
  291. package/dist/telegram/bot.js +0 -41
  292. package/dist/telegram/handlers.js +0 -42
  293. package/dist/watchdog.js +0 -37
  294. package/dist/wiki/backlinks.js +0 -51
  295. package/dist/wiki/fs.js +0 -108
  296. package/dist/wiki/search.js +0 -47
  297. package/web-dist/assets/AuditLogView-C5QtUQBq.js +0 -6
  298. package/web-dist/assets/ChatView-DLu9BMg8.js +0 -1
  299. package/web-dist/assets/FeedView-6OV-l6Gl.js +0 -6
  300. package/web-dist/assets/HistoryView-DizPqv0y.js +0 -1
  301. package/web-dist/assets/LoginView-CG1O9fmR.js +0 -1
  302. package/web-dist/assets/McpView-TJN-fZvI.js +0 -1
  303. package/web-dist/assets/SchedulesView-BDFpImX6.js +0 -6
  304. package/web-dist/assets/SettingsView-D-K1iC1c.js +0 -1
  305. package/web-dist/assets/SkillsView-DnNmO192.js +0 -15
  306. package/web-dist/assets/SquadDetailView-BBvrgHzn.js +0 -26
  307. package/web-dist/assets/SquadHealthView-DF2zF9D3.js +0 -11
  308. package/web-dist/assets/SquadsView-CPVzko7k.js +0 -6
  309. package/web-dist/assets/ToggleSwitch.vue_vue_type_script_setup_true_lang-Bk_t9_Rn.js +0 -1
  310. package/web-dist/assets/UsageView-OcyM5k14.js +0 -16
  311. package/web-dist/assets/WikiView-KhFqBZI0.js +0 -26
  312. package/web-dist/assets/api-BiDVwQrs.js +0 -1
  313. package/web-dist/assets/arrow-left-DFbf2tii.js +0 -6
  314. package/web-dist/assets/git-branch-BLstr_Gr.js +0 -6
  315. package/web-dist/assets/index-B-o45ao1.css +0 -1
  316. package/web-dist/assets/index-DCJUYZtV.js +0 -269
  317. package/web-dist/assets/pencil-D4Zz_t0y.js +0 -6
  318. package/web-dist/assets/plus-gmwiZVfr.js +0 -6
  319. package/web-dist/assets/save-BvtAs5WB.js +0 -6
  320. package/web-dist/assets/search-BabUvoGD.js +0 -6
  321. package/web-dist/assets/squad-colors-B8B_Y-lz.js +0 -1
  322. package/web-dist/assets/trash-2-C21cNLJl.js +0 -6
  323. package/web-dist/assets/triangle-alert-BrzY_E1n.js +0 -6
  324. package/web-dist/assets/x-xgLSmc9e.js +0 -6
  325. package/web-dist/favicon.svg +0 -10
  326. package/web-dist/index.html +0 -14
  327. package/web-dist/logo.svg +0 -10
@@ -1,309 +0,0 @@
1
- import { approveAll } from "@github/copilot-sdk";
2
- import { getClient } from "./client.js";
3
- import { getLeadForSquad, getAgentsForSquad, updateAgentStatus, getSquad } from "../store/squads.js";
4
- import { createTask, updateTaskStatus, getTask } from "../store/tasks.js";
5
- import { touchInstanceActivity, getInstance } from "../store/instances.js";
6
- import { selectModel, classifyComplexity } from "./model-router.js";
7
- import { postFeedItem } from "../store/feed.js";
8
- import { attachTokenTracker } from "./token-tracker.js";
9
- import { addAuditEntry } from "../store/audit-log.js";
10
- import { addAgentEvent } from "../store/agent-events.js";
11
- import { PATHS } from "../paths.js";
12
- import { createSquadTools, createLeadDelegationTools } from "./squad-tools.js";
13
- import { loadSkillDirectories } from "./skills.js";
14
- import { getMcpServersForSession } from "../mcp/registry.js";
15
- import { buildAttachmentPathSummary, saveAttachmentsToDisk, toCopilotBlobAttachments } from "../chat/attachments.js";
16
- import { existsSync, mkdirSync } from "node:fs";
17
- import { join } from "node:path";
18
- import { exec } from "node:child_process";
19
- import { promisify } from "node:util";
20
- import { logWarn } from "../logging.js";
21
- const execAsync = promisify(exec);
22
- // Registry of active agent sessions keyed by task ID
23
- const activeSessions = new Map();
24
- /**
25
- * Resolve the working directory for a squad agent session.
26
- * Priority: instance worktree → cloned repo → process.cwd()
27
- */
28
- async function resolveSquadWorkingDirectory(squad, instanceId) {
29
- // If an instance is specified, use its worktree path
30
- if (instanceId) {
31
- const instance = getInstance(instanceId);
32
- if (instance?.worktree_path && existsSync(instance.worktree_path)) {
33
- return instance.worktree_path;
34
- }
35
- }
36
- // Derive from squad repo_url → ~/.io/source/{owner}/{repo}
37
- if (squad.repo_url) {
38
- const match = squad.repo_url.match(/[/:]([^/]+)\/([^/.]+?)(?:\.git)?$/);
39
- if (match) {
40
- const [, owner, repo] = match;
41
- const sourceDir = join(PATHS.source, owner, repo);
42
- if (existsSync(sourceDir)) {
43
- return sourceDir;
44
- }
45
- // Attempt to clone if missing
46
- const parentDir = join(PATHS.source, owner);
47
- if (!existsSync(parentDir))
48
- mkdirSync(parentDir, { recursive: true });
49
- try {
50
- await execAsync(`git clone ${squad.repo_url} ${sourceDir}`, { timeout: 120_000 });
51
- return sourceDir;
52
- }
53
- catch (err) {
54
- logWarn("Failed to clone squad repository, falling back to current working directory", { repoUrl: squad.repo_url }, err);
55
- }
56
- }
57
- }
58
- return process.cwd();
59
- }
60
- /**
61
- * Stop a running agent by task ID. Disconnects the session and marks the task as stopped.
62
- */
63
- export async function stopTask(taskId) {
64
- const session = activeSessions.get(taskId);
65
- if (!session) {
66
- throw new Error(`Task is not currently running or has already completed`);
67
- }
68
- try {
69
- await session.disconnect();
70
- }
71
- finally {
72
- activeSessions.delete(taskId);
73
- }
74
- updateTaskStatus(taskId, "stopped", "Stopped by user");
75
- addAgentEvent(taskId, "status", "Task stopped by user", { reason: "user_requested" });
76
- // Reset agent status to idle
77
- const task = getTask(taskId);
78
- if (task?.agent_id) {
79
- updateAgentStatus(task.agent_id, "idle");
80
- }
81
- }
82
- export async function delegateTask(squadId, task, instanceId, attachments = []) {
83
- const lead = getLeadForSquad(squadId);
84
- if (!lead) {
85
- throw new Error("Squad has no team lead. Add a lead agent first.");
86
- }
87
- const squad = getSquad(squadId);
88
- const squadSlug = squad?.slug ?? squadId;
89
- const agents = getAgentsForSquad(squadId);
90
- const taskRecord = createTask(squadId, task, instanceId, lead.id);
91
- // Update lead status
92
- updateAgentStatus(lead.id, "working");
93
- // Touch instance activity if applicable
94
- if (instanceId) {
95
- touchInstanceActivity(instanceId);
96
- }
97
- // Select model based on task complexity
98
- const tier = classifyComplexity(task);
99
- const model = await selectModel(tier);
100
- // Audit: task delegated
101
- addAuditEntry("task_delegated", `Task delegated to ${lead.character_name} (${lead.role_title})`, { task: task.slice(0, 500), model }, { squad_id: squadId, agent_id: lead.id, task_id: taskRecord.id });
102
- // Create ephemeral agent session for the lead
103
- const client = await getClient();
104
- const agentRoster = agents
105
- .map((a) => `- ${a.character_name} (${a.role_title})${a.is_lead ? " [LEAD]" : ""}${a.is_qa ? " [QA]" : ""}${a.is_test ? " [TEST]" : ""}`)
106
- .join("\n");
107
- // Load squad wiki pages as immutable knowledge context
108
- const { listPages, readPage } = await import("../wiki/fs.js");
109
- const wikiPrefix = `squads/${squadSlug}`;
110
- let wikiKnowledge = "";
111
- try {
112
- const pages = await listPages(wikiPrefix);
113
- const pageContents = [];
114
- for (const page of pages.slice(0, 20)) { // Cap at 20 pages to avoid token overload
115
- try {
116
- const content = await readPage(`${wikiPrefix}/${page}`);
117
- pageContents.push(`### ${page}\n${content}`);
118
- }
119
- catch {
120
- // Skip unreadable pages
121
- }
122
- }
123
- if (pageContents.length > 0) {
124
- wikiKnowledge = `\n## ⚠️ MANDATORY SQUAD RULES & KNOWLEDGE (from squad wiki)\n\nThese rules were written by the project owner specifically for this squad. You MUST follow them in ALL work — every task, every PR, every decision. Violating them is a critical failure.\n\nBefore starting any task, re-read these rules. Before submitting any PR or review, verify compliance.\n\n${pageContents.join("\n\n---\n\n")}\n`;
125
- }
126
- }
127
- catch {
128
- // Wiki not available — proceed without
129
- }
130
- const systemMessage = `# Squad Team Lead: ${lead.character_name}
131
-
132
- ## 🚨 CRITICAL SECURITY RULE — ABSOLUTE, NON-NEGOTIABLE 🚨
133
-
134
- You must NEVER expose secrets, credentials, or sensitive values in ANY publicly visible location. This includes:
135
- - GitHub issues, pull requests, PR descriptions, comments, or commit messages
136
- - Log output, error messages, or stack traces shared externally
137
- - Wiki pages, feed items, or any content viewable by others
138
-
139
- What counts as a secret: API keys, access tokens, passwords, connection strings, environment variable values, private config file contents, SSH keys, certificates, webhook URLs with tokens.
140
-
141
- If you need to reference that a secret exists, use \`<REDACTED>\` or \`***\` as a placeholder. NEVER include the actual value.
142
-
143
- Violation of this rule is a HARD FAILURE — no exceptions, no workarounds, no "just this once."
144
-
145
- ## Identity & Role
146
-
147
- You are ${lead.character_name}, the team lead for this squad. Your PRIMARY role is coordination and delegation — you break down tasks and route implementation work to specialists via the \`delegate_to_specialist\` or \`delegate_to_specialists_parallel\` tools.
148
-
149
- ## How Delegation Works
150
-
151
- When you call \`delegate_to_specialist\`, a **real, independent AI agent session** is spawned for that specialist. They have:
152
- - Their own full Copilot session with shell access, tools, and MCP servers
153
- - The squad wiki rules (immutable — they MUST follow them too)
154
- - Complete autonomy to implement their assigned sub-task
155
-
156
- This means specialists work IN PARALLEL with you and with each other. Use \`delegate_to_specialists_parallel\` when multiple independent sub-tasks can run concurrently.
157
-
158
- ## Your Responsibilities:
159
- 1. Break down tasks into smaller pieces and delegate to specialists
160
- 2. Route work to the appropriate specialist based on their role
161
- 3. Use \`delegate_to_specialists_parallel\` for independent sub-tasks (faster!)
162
- 4. Orchestrate the full review/merge process as defined in your squad wiki
163
- 5. Ensure quality gates are met before merging
164
- 6. Report progress and blockers via feed_post
165
-
166
- ## IMPORTANT — Prefer Delegation:
167
- - For implementation work (writing code, running tests, creating PRs), ALWAYS delegate to the appropriate specialist
168
- - For code review, delegate to squad members so they can independently review and post their own comments
169
- - You may perform coordination tasks directly: reading issues, checking CI status, promoting PRs, merging PRs
170
- - If no suitable specialist exists for a sub-task, report that back — do NOT attempt implementation yourself
171
-
172
- ## Your Team:
173
- ${agentRoster}
174
-
175
- ## 🔒 SQUAD WIKI = YOUR SOURCE OF TRUTH
176
-
177
- Your squad wiki contains your **authoritative workflow rules** — branching conventions, PR process, review requirements, merge criteria, labeling, and any squad-specific constraints.
178
-
179
- **Before starting ANY task:**
180
- 1. Read your squad wiki (use \`wiki_read\` or \`wiki_list\` to find relevant pages)
181
- 2. Follow those rules EXACTLY — they are non-negotiable instructions from the project owner
182
- 3. Do NOT invent your own workflow or skip steps defined in the wiki
183
-
184
- **If the wiki says all members must review → delegate reviews to all members.**
185
- **If the wiki says only veto members must approve → ensure veto members approve.**
186
- **If the wiki defines merge criteria → follow them precisely.**
187
-
188
- Failure to follow squad wiki rules is a CRITICAL FAILURE.
189
-
190
- ## General Rules:
191
- - Always use the gh CLI for GitHub interactions
192
- - Use \`--comment\` for review approvals (not \`--approve\` — GitHub blocks self-approval)
193
- - When work is complete, ALWAYS notify the user via feed_post with a summary
194
- ${wikiKnowledge}
195
- ${lead.persona ? `## Personality:\n${lead.persona}` : ""}
196
- `;
197
- let result;
198
- try {
199
- // Load squad-scoped tools, skills, and MCP servers
200
- const squadTools = createSquadTools(squadSlug, squadId, squad?.repo_url);
201
- const skillDirs = await loadSkillDirectories();
202
- const mcpServers = getMcpServersForSession();
203
- // Resolve correct working directory for the squad's project
204
- const workDir = await resolveSquadWorkingDirectory(squad, instanceId);
205
- // Create lead-specific delegation tools (allows spawning real specialist sessions)
206
- const leadTools = createLeadDelegationTools(squadId, squadSlug, squad, wikiKnowledge, workDir, taskRecord.id, instanceId);
207
- const session = await client.createSession({
208
- model,
209
- streaming: true,
210
- workingDirectory: workDir,
211
- systemMessage: { content: systemMessage },
212
- tools: [...squadTools, ...leadTools],
213
- skillDirectories: skillDirs,
214
- mcpServers,
215
- onPermissionRequest: approveAll,
216
- infiniteSessions: {
217
- enabled: true,
218
- backgroundCompactionThreshold: 0.8,
219
- bufferExhaustionThreshold: 0.95,
220
- },
221
- });
222
- // Register session so it can be stopped externally
223
- activeSessions.set(taskRecord.id, session);
224
- const flushTokens = attachTokenTracker(session, {
225
- squadId,
226
- agentId: lead.id,
227
- taskId: taskRecord.id,
228
- });
229
- try {
230
- // Mark task as in progress and record start event
231
- updateTaskStatus(taskRecord.id, "in_progress");
232
- addAgentEvent(taskRecord.id, "status", `Task started by ${lead.character_name}`, {
233
- agent: lead.character_name,
234
- role: lead.role_title,
235
- task,
236
- attachments: attachments.map((attachment) => ({
237
- name: attachment.name,
238
- mimeType: attachment.mimeType,
239
- size: attachment.size,
240
- })),
241
- });
242
- // Capture streaming message deltas and broadcast via SSE
243
- let accumulatedMessage = "";
244
- const { broadcast } = await import("../api/server.js");
245
- const unsubscribeDelta = session.on("assistant.message_delta", (event) => {
246
- const delta = event.data?.deltaContent ?? "";
247
- if (delta) {
248
- accumulatedMessage += delta;
249
- broadcast("agent_event", {
250
- taskId: taskRecord.id,
251
- type: "message_delta",
252
- summary: accumulatedMessage,
253
- payload: { delta, accumulated: accumulatedMessage },
254
- });
255
- }
256
- });
257
- try {
258
- // Save attachments to disk so squad agents can access them via shell_exec
259
- const savedAttachments = saveAttachmentsToDisk(attachments);
260
- const attachmentPathInfo = buildAttachmentPathSummary(savedAttachments);
261
- const response = await session.sendAndWait({
262
- prompt: `Task delegated to you:\n\n${task}${attachmentPathInfo}`,
263
- attachments: toCopilotBlobAttachments(attachments),
264
- }, 7_200_000 // 2 hours — watchdog handles stale detection
265
- );
266
- result = response?.data?.content ?? "Task completed (no response content).";
267
- // Record the final message event if we have meaningful content
268
- if (accumulatedMessage.trim()) {
269
- addAgentEvent(taskRecord.id, "message", accumulatedMessage, {
270
- agent: lead.character_name,
271
- content: accumulatedMessage,
272
- });
273
- }
274
- }
275
- finally {
276
- unsubscribeDelta();
277
- }
278
- }
279
- finally {
280
- activeSessions.delete(taskRecord.id);
281
- flushTokens();
282
- await session.disconnect();
283
- }
284
- }
285
- catch (err) {
286
- const errMsg = err instanceof Error ? err.message : "Unknown error";
287
- addAgentEvent(taskRecord.id, "status", `Task failed: ${errMsg}`, { error: errMsg });
288
- updateTaskStatus(taskRecord.id, "failed", errMsg);
289
- updateAgentStatus(lead.id, "idle");
290
- // Audit: task failed
291
- addAuditEntry("task_failed", `Task failed: ${errMsg.slice(0, 200)}`, { error: errMsg }, { squad_id: squadId, agent_id: lead.id, task_id: taskRecord.id });
292
- throw err;
293
- }
294
- // Update task and agent status
295
- updateTaskStatus(taskRecord.id, "done", result);
296
- updateAgentStatus(lead.id, "idle");
297
- // Audit: task completed
298
- addAuditEntry("task_completed", `Task completed by ${lead.character_name}`, { result: result.slice(0, 500) }, { squad_id: squadId, agent_id: lead.id, task_id: taskRecord.id });
299
- // Record completion event
300
- addAgentEvent(taskRecord.id, "status", `Task completed by ${lead.character_name}`, {
301
- agent: lead.character_name,
302
- result: result.slice(0, 500),
303
- });
304
- // Post to feed
305
- const squadSource = `squad-${squadSlug}`;
306
- postFeedItem(squadSource, `Task completed by ${lead.character_name}`, result.slice(0, 2000));
307
- return result;
308
- }
309
- //# sourceMappingURL=agents.js.map
@@ -1,174 +0,0 @@
1
- import { approveAll } from "@github/copilot-sdk";
2
- import { getClient } from "./client.js";
3
- import { getLeadForSquad, getAgentsForSquad, getSquad } from "../store/squads.js";
4
- import { selectModel } from "./model-router.js";
5
- import { postFeedItem } from "../store/feed.js";
6
- import { attachTokenTracker } from "./token-tracker.js";
7
- import { buildAttachmentSummary, toCopilotBlobAttachments } from "../chat/attachments.js";
8
- function buildFacilitatorPrompt(lead, agents, task) {
9
- const roster = agents
10
- .filter((a) => !a.is_lead)
11
- .map((a) => `- ${a.character_name} (${a.role_title})${a.is_qa ? " [QA]" : ""}${a.is_test ? " [TEST]" : ""}`)
12
- .join("\n");
13
- return `# Planning Meeting Facilitator: ${lead.character_name}
14
-
15
- You are facilitating a planning meeting for your squad. Your job is to gather input from specialists, then synthesize a clear action plan.
16
-
17
- ## The Task
18
- ${task}
19
-
20
- ## Your Team (Specialists)
21
- ${roster}
22
-
23
- ## Instructions
24
- For each specialist who is relevant to this task, think about what their domain expertise would contribute. Then synthesize ALL perspectives into a structured plan.
25
-
26
- Consider each relevant specialist's likely concerns:
27
- ${agents
28
- .filter((a) => !a.is_lead)
29
- .map((a) => `- ${a.character_name} (${a.role_title}): What risks, technical suggestions, or constraints would they raise?`)
30
- .join("\n")}
31
-
32
- ## Output Format
33
- Produce a plan in this exact format:
34
-
35
- ### Task Summary
36
- (One sentence summary of what we're building)
37
-
38
- ### Plan
39
- (Numbered list of work items with agent assignments)
40
-
41
- ### Risks & Concerns
42
- (Bullet list of risks identified, with mitigation strategies)
43
-
44
- ### Dependencies
45
- (What must happen in order, what can be parallel)
46
-
47
- ### Assignments
48
- (Clear mapping: Agent → what they own)
49
-
50
- ## Rules
51
- - You are ONLY planning — do NOT execute any work
52
- - Assign work to specialists based on their role titles
53
- - Identify what can be done in parallel vs what has dependencies
54
- - Flag if any expertise is missing from the team
55
- ${lead.persona ? `\n## Your Style:\n${lead.persona}` : ""}
56
- `;
57
- }
58
- function buildSpecialistPrompt(agent, task) {
59
- return `# Planning Input: ${agent.character_name}
60
-
61
- You are ${agent.character_name}, a ${agent.role_title}. Your team is planning a new task and needs your expert input.
62
-
63
- ## The Task
64
- ${task}
65
-
66
- ## Your Role
67
- Provide input ONLY from your area of expertise (${agent.role_title}). Be specific and actionable.
68
-
69
- ## Respond With
70
- 1. **Concerns/Risks**: What could go wrong in your domain?
71
- 2. **Technical Suggestions**: How would you approach your part?
72
- 3. **Dependencies**: What do you need from other team members before you can start?
73
- 4. **Estimated Complexity**: Simple / Moderate / Complex for your portion
74
- 5. **Questions**: Anything unclear that affects your work?
75
-
76
- Keep your response focused and concise — this is a planning meeting, not implementation.
77
- ${agent.persona ? `\n## Your Style:\n${agent.persona}` : ""}
78
- `;
79
- }
80
- export async function planningMeeting(squadId, task, attachments = []) {
81
- const lead = getLeadForSquad(squadId);
82
- if (!lead) {
83
- throw new Error("Squad has no team lead. Add a lead agent first.");
84
- }
85
- const agents = getAgentsForSquad(squadId);
86
- const relevantAgents = agents.filter((a) => !a.is_lead);
87
- if (relevantAgents.length === 0) {
88
- throw new Error("Squad has no specialists to consult. Add agents first.");
89
- }
90
- const client = await getClient();
91
- // Phase 1: Gather specialist input in parallel
92
- const specialistInputs = await Promise.allSettled(relevantAgents.map(async (agent) => {
93
- const model = await selectModel("low");
94
- const session = await client.createSession({
95
- model,
96
- streaming: true,
97
- workingDirectory: process.cwd(),
98
- systemMessage: { content: buildSpecialistPrompt(agent, task) },
99
- onPermissionRequest: approveAll,
100
- });
101
- const flushTokens = attachTokenTracker(session, { squadId, agentId: agent.id });
102
- try {
103
- const response = await session.sendAndWait({
104
- prompt: `Please provide your planning input for this task.${buildAttachmentSummary(attachments)}`,
105
- attachments: toCopilotBlobAttachments(attachments),
106
- }, 7_200_000 // 2 hours — watchdog handles stale detection
107
- );
108
- return {
109
- agent: agent.character_name,
110
- role: agent.role_title,
111
- input: response?.data?.content ?? "(no response)",
112
- };
113
- }
114
- finally {
115
- flushTokens();
116
- await session.disconnect();
117
- }
118
- }));
119
- // Collect successful inputs
120
- const inputs = specialistInputs
121
- .filter((r) => r.status === "fulfilled")
122
- .map((r) => r.value);
123
- const inputsSummary = inputs
124
- .map((i) => `### ${i.agent} (${i.role})\n${i.input}`)
125
- .join("\n\n");
126
- // Phase 2: Lead synthesizes the plan
127
- const facilitatorModel = await selectModel("medium");
128
- const facilitatorSession = await client.createSession({
129
- model: facilitatorModel,
130
- streaming: true,
131
- workingDirectory: process.cwd(),
132
- systemMessage: { content: buildFacilitatorPrompt(lead, agents, task) },
133
- onPermissionRequest: approveAll,
134
- });
135
- const flushFacilitatorTokens = attachTokenTracker(facilitatorSession, {
136
- squadId,
137
- agentId: lead.id,
138
- });
139
- let plan;
140
- try {
141
- const prompt = `Here is the input gathered from your team:\n\n${inputsSummary}\n\nNow synthesize this into a clear, structured action plan.`;
142
- const response = await facilitatorSession.sendAndWait({
143
- prompt,
144
- attachments: toCopilotBlobAttachments(attachments),
145
- }, 7_200_000 // 2 hours — watchdog handles stale detection
146
- );
147
- plan = response?.data?.content ?? "Planning meeting completed but no plan was produced.";
148
- }
149
- finally {
150
- flushFacilitatorTokens();
151
- await facilitatorSession.disconnect();
152
- }
153
- return {
154
- plan,
155
- participants: [lead.character_name, ...inputs.map((i) => i.agent)],
156
- };
157
- }
158
- export async function squadMeeting(squadId, task, executeAfter, attachments = []) {
159
- const result = await planningMeeting(squadId, task, attachments);
160
- const summary = `## Planning Meeting Complete\n\n**Participants:** ${result.participants.join(", ")}\n\n${result.plan}`;
161
- if (!executeAfter) {
162
- // Post to feed and wait for user to trigger execution
163
- const squad = getSquad(squadId);
164
- const squadSource = squad ? `squad-${squad.slug}` : `squad-${squadId}`;
165
- postFeedItem(squadSource, "Planning meeting complete — awaiting approval", summary);
166
- return summary;
167
- }
168
- // Execute: delegate with the plan as additional context
169
- const { delegateTask } = await import("./agents.js");
170
- const enrichedTask = `${task}\n\n---\n## Approved Plan (from team meeting)\n${result.plan}`;
171
- const execResult = await delegateTask(squadId, enrichedTask, undefined, attachments);
172
- return `Meeting held, then executed.\n\n${summary}\n\n---\n## Execution Result\n${execResult}`;
173
- }
174
- //# sourceMappingURL=ceremonies.js.map
@@ -1,64 +0,0 @@
1
- import { execSync } from "node:child_process";
2
- import { loadConfig, resetConfigCache } from "../config.js";
3
- /**
4
- * Cached GitHub token for CLI operations.
5
- * Resolution order: GH_TOKEN env → GITHUB_TOKEN env → config.githubToken → `gh auth token` CLI.
6
- * If no token found, retries on next call (config may have been updated).
7
- */
8
- let cachedToken;
9
- let resolved = false;
10
- export function resetGhTokenCache() {
11
- cachedToken = undefined;
12
- resolved = false;
13
- }
14
- export function getGhToken() {
15
- if (resolved && cachedToken)
16
- return cachedToken;
17
- // 1. Prefer explicit env vars
18
- if (process.env.GH_TOKEN) {
19
- cachedToken = process.env.GH_TOKEN;
20
- resolved = true;
21
- return cachedToken;
22
- }
23
- if (process.env.GITHUB_TOKEN) {
24
- cachedToken = process.env.GITHUB_TOKEN;
25
- resolved = true;
26
- return cachedToken;
27
- }
28
- // 2. Check IO config file (re-read in case it was updated since last attempt)
29
- try {
30
- if (!cachedToken)
31
- resetConfigCache();
32
- const config = loadConfig();
33
- if (config.githubToken) {
34
- cachedToken = config.githubToken;
35
- resolved = true;
36
- return cachedToken;
37
- }
38
- }
39
- catch {
40
- // Config not available
41
- }
42
- // 3. Try extracting from gh CLI auth (only on first attempt)
43
- if (!resolved) {
44
- try {
45
- const token = execSync("gh auth token", {
46
- timeout: 5_000,
47
- encoding: "utf-8",
48
- stdio: ["pipe", "pipe", "pipe"],
49
- }).trim();
50
- if (token) {
51
- cachedToken = token;
52
- resolved = true;
53
- }
54
- }
55
- catch {
56
- // gh not available or not authenticated
57
- }
58
- }
59
- // Mark resolved only if we found a token — otherwise retry next call
60
- if (cachedToken)
61
- resolved = true;
62
- return cachedToken;
63
- }
64
- //# sourceMappingURL=gh-token.js.map
@@ -1,79 +0,0 @@
1
- import { listSchedules, updateScheduleLastRun } from "../store/schedules.js";
2
- import { sendToOrchestrator } from "./orchestrator.js";
3
- let ioSchedulerInterval;
4
- export function startIoScheduler() {
5
- ioSchedulerInterval = setInterval(() => {
6
- checkIoSchedules();
7
- }, 60_000);
8
- ioSchedulerInterval.unref();
9
- }
10
- function checkIoSchedules() {
11
- const schedules = listSchedules("io");
12
- const now = new Date();
13
- for (const schedule of schedules) {
14
- if (!schedule.enabled)
15
- continue;
16
- if (!isDue(schedule.cron, schedule.last_run, now))
17
- continue;
18
- if (!schedule.squad_id) {
19
- console.warn(`[io-scheduler] Schedule ${schedule.id} skipped: missing squad_id.`);
20
- continue;
21
- }
22
- updateScheduleLastRun(schedule.id);
23
- sendToOrchestrator(buildSquadScopedPrompt(schedule), "io-scheduler", (_text, done) => {
24
- if (done) {
25
- console.log(`[io-scheduler] Schedule ${schedule.id} completed.`);
26
- }
27
- });
28
- }
29
- }
30
- export function buildSquadScopedPrompt(schedule) {
31
- const squadId = schedule.squad_id ?? "unknown";
32
- return `[Squad Schedule] Run for squad ${squadId}. Prompt: ${schedule.prompt}`;
33
- }
34
- function isDue(cron, lastRun, now) {
35
- const parts = cron.split(" ");
36
- if (parts.length !== 5)
37
- return false;
38
- const [minSpec, hourSpec, daySpec, monthSpec, weekdaySpec] = parts;
39
- if (!matchesCronField(minSpec, now.getMinutes()))
40
- return false;
41
- if (!matchesCronField(hourSpec, now.getHours()))
42
- return false;
43
- if (!matchesCronField(daySpec, now.getDate()))
44
- return false;
45
- if (!matchesCronField(monthSpec, now.getMonth() + 1))
46
- return false;
47
- if (!matchesCronField(weekdaySpec, now.getDay()))
48
- return false;
49
- if (lastRun) {
50
- const lastDate = new Date(lastRun);
51
- const diffMs = now.getTime() - lastDate.getTime();
52
- if (diffMs < 60_000)
53
- return false;
54
- }
55
- return true;
56
- }
57
- function matchesCronField(spec, value) {
58
- if (spec === "*")
59
- return true;
60
- if (spec.includes("-")) {
61
- const [start, end] = spec.split("-").map(Number);
62
- return value >= start && value <= end;
63
- }
64
- if (spec.includes(",")) {
65
- return spec.split(",").map(Number).includes(value);
66
- }
67
- if (spec.startsWith("*/")) {
68
- const step = parseInt(spec.slice(2), 10);
69
- return value % step === 0;
70
- }
71
- return parseInt(spec, 10) === value;
72
- }
73
- export function stopIoScheduler() {
74
- if (ioSchedulerInterval) {
75
- clearInterval(ioSchedulerInterval);
76
- ioSchedulerInterval = undefined;
77
- }
78
- }
79
- //# sourceMappingURL=io-scheduler.js.map