heyio 3.4.0 → 4.0.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 (289) hide show
  1. package/CODE_OF_CONDUCT.md +83 -0
  2. package/LICENSE +21 -0
  3. package/README.md +203 -151
  4. package/dist/daemon/cli.js +84366 -0
  5. package/dist/daemon/index.js +82899 -0
  6. package/dist/web/assets/index-CbptHIYU.js +520 -0
  7. package/{public → dist/web}/index.html +1 -1
  8. package/package.json +48 -47
  9. package/dist/api/middleware/auth.d.ts +0 -14
  10. package/dist/api/middleware/auth.d.ts.map +0 -1
  11. package/dist/api/middleware/auth.js +0 -130
  12. package/dist/api/middleware/auth.js.map +0 -1
  13. package/dist/api/notifications.d.ts +0 -14
  14. package/dist/api/notifications.d.ts.map +0 -1
  15. package/dist/api/notifications.js +0 -114
  16. package/dist/api/notifications.js.map +0 -1
  17. package/dist/api/routes/activity.d.ts +0 -3
  18. package/dist/api/routes/activity.d.ts.map +0 -1
  19. package/dist/api/routes/activity.js +0 -28
  20. package/dist/api/routes/activity.js.map +0 -1
  21. package/dist/api/routes/attachments.d.ts +0 -3
  22. package/dist/api/routes/attachments.d.ts.map +0 -1
  23. package/dist/api/routes/attachments.js +0 -83
  24. package/dist/api/routes/attachments.js.map +0 -1
  25. package/dist/api/routes/config.d.ts +0 -3
  26. package/dist/api/routes/config.d.ts.map +0 -1
  27. package/dist/api/routes/config.js +0 -107
  28. package/dist/api/routes/config.js.map +0 -1
  29. package/dist/api/routes/conversations.d.ts +0 -3
  30. package/dist/api/routes/conversations.d.ts.map +0 -1
  31. package/dist/api/routes/conversations.js +0 -25
  32. package/dist/api/routes/conversations.js.map +0 -1
  33. package/dist/api/routes/health.d.ts +0 -3
  34. package/dist/api/routes/health.d.ts.map +0 -1
  35. package/dist/api/routes/health.js +0 -39
  36. package/dist/api/routes/health.js.map +0 -1
  37. package/dist/api/routes/inbox.d.ts +0 -3
  38. package/dist/api/routes/inbox.d.ts.map +0 -1
  39. package/dist/api/routes/inbox.js +0 -139
  40. package/dist/api/routes/inbox.js.map +0 -1
  41. package/dist/api/routes/schedules.d.ts +0 -3
  42. package/dist/api/routes/schedules.d.ts.map +0 -1
  43. package/dist/api/routes/schedules.js +0 -116
  44. package/dist/api/routes/schedules.js.map +0 -1
  45. package/dist/api/routes/skills.d.ts +0 -2
  46. package/dist/api/routes/skills.d.ts.map +0 -1
  47. package/dist/api/routes/skills.js +0 -127
  48. package/dist/api/routes/skills.js.map +0 -1
  49. package/dist/api/routes/squads.d.ts +0 -3
  50. package/dist/api/routes/squads.d.ts.map +0 -1
  51. package/dist/api/routes/squads.js +0 -578
  52. package/dist/api/routes/squads.js.map +0 -1
  53. package/dist/api/routes/usage.d.ts +0 -3
  54. package/dist/api/routes/usage.d.ts.map +0 -1
  55. package/dist/api/routes/usage.js +0 -55
  56. package/dist/api/routes/usage.js.map +0 -1
  57. package/dist/api/routes/wiki.d.ts +0 -2
  58. package/dist/api/routes/wiki.d.ts.map +0 -1
  59. package/dist/api/routes/wiki.js +0 -75
  60. package/dist/api/routes/wiki.js.map +0 -1
  61. package/dist/api/server.d.ts +0 -7
  62. package/dist/api/server.d.ts.map +0 -1
  63. package/dist/api/server.js +0 -183
  64. package/dist/api/server.js.map +0 -1
  65. package/dist/config.d.ts +0 -3
  66. package/dist/config.d.ts.map +0 -1
  67. package/dist/config.js +0 -3
  68. package/dist/config.js.map +0 -1
  69. package/dist/copilot/client.d.ts +0 -5
  70. package/dist/copilot/client.d.ts.map +0 -1
  71. package/dist/copilot/client.js +0 -38
  72. package/dist/copilot/client.js.map +0 -1
  73. package/dist/copilot/health-monitor.d.ts +0 -14
  74. package/dist/copilot/health-monitor.d.ts.map +0 -1
  75. package/dist/copilot/health-monitor.js +0 -70
  76. package/dist/copilot/health-monitor.js.map +0 -1
  77. package/dist/copilot/orchestrator.d.ts +0 -5
  78. package/dist/copilot/orchestrator.d.ts.map +0 -1
  79. package/dist/copilot/orchestrator.js +0 -227
  80. package/dist/copilot/orchestrator.js.map +0 -1
  81. package/dist/copilot/tools.d.ts +0 -80
  82. package/dist/copilot/tools.d.ts.map +0 -1
  83. package/dist/copilot/tools.js +0 -1067
  84. package/dist/copilot/tools.js.map +0 -1
  85. package/dist/index.d.ts +0 -3
  86. package/dist/index.d.ts.map +0 -1
  87. package/dist/index.js +0 -94
  88. package/dist/index.js.map +0 -1
  89. package/dist/logging/logger.d.ts +0 -6
  90. package/dist/logging/logger.d.ts.map +0 -1
  91. package/dist/logging/logger.js +0 -33
  92. package/dist/logging/logger.js.map +0 -1
  93. package/dist/models/index.d.ts +0 -6
  94. package/dist/models/index.d.ts.map +0 -1
  95. package/dist/models/index.js +0 -4
  96. package/dist/models/index.js.map +0 -1
  97. package/dist/models/pricing.d.ts +0 -25
  98. package/dist/models/pricing.d.ts.map +0 -1
  99. package/dist/models/pricing.js +0 -96
  100. package/dist/models/pricing.js.map +0 -1
  101. package/dist/models/registry.d.ts +0 -34
  102. package/dist/models/registry.d.ts.map +0 -1
  103. package/dist/models/registry.js +0 -109
  104. package/dist/models/registry.js.map +0 -1
  105. package/dist/models/token-tracker.d.ts +0 -41
  106. package/dist/models/token-tracker.d.ts.map +0 -1
  107. package/dist/models/token-tracker.js +0 -103
  108. package/dist/models/token-tracker.js.map +0 -1
  109. package/dist/scheduler/engine.d.ts +0 -12
  110. package/dist/scheduler/engine.d.ts.map +0 -1
  111. package/dist/scheduler/engine.js +0 -128
  112. package/dist/scheduler/engine.js.map +0 -1
  113. package/dist/skills/discover.d.ts +0 -22
  114. package/dist/skills/discover.d.ts.map +0 -1
  115. package/dist/skills/discover.js +0 -228
  116. package/dist/skills/discover.js.map +0 -1
  117. package/dist/skills/index.d.ts +0 -5
  118. package/dist/skills/index.d.ts.map +0 -1
  119. package/dist/skills/index.js +0 -3
  120. package/dist/skills/index.js.map +0 -1
  121. package/dist/skills/store.d.ts +0 -56
  122. package/dist/skills/store.d.ts.map +0 -1
  123. package/dist/skills/store.js +0 -154
  124. package/dist/skills/store.js.map +0 -1
  125. package/dist/squad/agent.d.ts +0 -65
  126. package/dist/squad/agent.d.ts.map +0 -1
  127. package/dist/squad/agent.js +0 -544
  128. package/dist/squad/agent.js.map +0 -1
  129. package/dist/squad/autonomy.d.ts +0 -16
  130. package/dist/squad/autonomy.d.ts.map +0 -1
  131. package/dist/squad/autonomy.js +0 -63
  132. package/dist/squad/autonomy.js.map +0 -1
  133. package/dist/squad/event-bus.d.ts +0 -22
  134. package/dist/squad/event-bus.d.ts.map +0 -1
  135. package/dist/squad/event-bus.js +0 -56
  136. package/dist/squad/event-bus.js.map +0 -1
  137. package/dist/squad/execution/index.d.ts +0 -14
  138. package/dist/squad/execution/index.d.ts.map +0 -1
  139. package/dist/squad/execution/index.js +0 -8
  140. package/dist/squad/execution/index.js.map +0 -1
  141. package/dist/squad/execution/instance.d.ts +0 -45
  142. package/dist/squad/execution/instance.d.ts.map +0 -1
  143. package/dist/squad/execution/instance.js +0 -165
  144. package/dist/squad/execution/instance.js.map +0 -1
  145. package/dist/squad/execution/planning.d.ts +0 -20
  146. package/dist/squad/execution/planning.d.ts.map +0 -1
  147. package/dist/squad/execution/planning.js +0 -62
  148. package/dist/squad/execution/planning.js.map +0 -1
  149. package/dist/squad/execution/pr.d.ts +0 -15
  150. package/dist/squad/execution/pr.d.ts.map +0 -1
  151. package/dist/squad/execution/pr.js +0 -109
  152. package/dist/squad/execution/pr.js.map +0 -1
  153. package/dist/squad/execution/review.d.ts +0 -21
  154. package/dist/squad/execution/review.d.ts.map +0 -1
  155. package/dist/squad/execution/review.js +0 -157
  156. package/dist/squad/execution/review.js.map +0 -1
  157. package/dist/squad/execution/runner.d.ts +0 -52
  158. package/dist/squad/execution/runner.d.ts.map +0 -1
  159. package/dist/squad/execution/runner.js +0 -93
  160. package/dist/squad/execution/runner.js.map +0 -1
  161. package/dist/squad/execution/tasks.d.ts +0 -22
  162. package/dist/squad/execution/tasks.d.ts.map +0 -1
  163. package/dist/squad/execution/tasks.js +0 -111
  164. package/dist/squad/execution/tasks.js.map +0 -1
  165. package/dist/squad/execution/worktree.d.ts +0 -27
  166. package/dist/squad/execution/worktree.d.ts.map +0 -1
  167. package/dist/squad/execution/worktree.js +0 -141
  168. package/dist/squad/execution/worktree.js.map +0 -1
  169. package/dist/squad/hiring.d.ts +0 -57
  170. package/dist/squad/hiring.d.ts.map +0 -1
  171. package/dist/squad/hiring.js +0 -588
  172. package/dist/squad/hiring.js.map +0 -1
  173. package/dist/squad/index.d.ts +0 -8
  174. package/dist/squad/index.d.ts.map +0 -1
  175. package/dist/squad/index.js +0 -6
  176. package/dist/squad/index.js.map +0 -1
  177. package/dist/squad/manager.d.ts +0 -58
  178. package/dist/squad/manager.d.ts.map +0 -1
  179. package/dist/squad/manager.js +0 -351
  180. package/dist/squad/manager.js.map +0 -1
  181. package/dist/squad/model-selector.d.ts +0 -29
  182. package/dist/squad/model-selector.d.ts.map +0 -1
  183. package/dist/squad/model-selector.js +0 -64
  184. package/dist/squad/model-selector.js.map +0 -1
  185. package/dist/squad/name-generator.d.ts +0 -16
  186. package/dist/squad/name-generator.d.ts.map +0 -1
  187. package/dist/squad/name-generator.js +0 -111
  188. package/dist/squad/name-generator.js.map +0 -1
  189. package/dist/squad/roles/templates.d.ts +0 -7
  190. package/dist/squad/roles/templates.d.ts.map +0 -1
  191. package/dist/squad/roles/templates.js +0 -104
  192. package/dist/squad/roles/templates.js.map +0 -1
  193. package/dist/squad/skill-parser.d.ts +0 -36
  194. package/dist/squad/skill-parser.d.ts.map +0 -1
  195. package/dist/squad/skill-parser.js +0 -90
  196. package/dist/squad/skill-parser.js.map +0 -1
  197. package/dist/squad/source-resolver.d.ts +0 -20
  198. package/dist/squad/source-resolver.d.ts.map +0 -1
  199. package/dist/squad/source-resolver.js +0 -51
  200. package/dist/squad/source-resolver.js.map +0 -1
  201. package/dist/store/activity.d.ts +0 -51
  202. package/dist/store/activity.d.ts.map +0 -1
  203. package/dist/store/activity.js +0 -197
  204. package/dist/store/activity.js.map +0 -1
  205. package/dist/store/conversations.d.ts +0 -25
  206. package/dist/store/conversations.d.ts.map +0 -1
  207. package/dist/store/conversations.js +0 -76
  208. package/dist/store/conversations.js.map +0 -1
  209. package/dist/store/db.d.ts +0 -5
  210. package/dist/store/db.d.ts.map +0 -1
  211. package/dist/store/db.js +0 -290
  212. package/dist/store/db.js.map +0 -1
  213. package/dist/store/inbox.d.ts +0 -67
  214. package/dist/store/inbox.d.ts.map +0 -1
  215. package/dist/store/inbox.js +0 -192
  216. package/dist/store/inbox.js.map +0 -1
  217. package/dist/store/schedules.d.ts +0 -53
  218. package/dist/store/schedules.d.ts.map +0 -1
  219. package/dist/store/schedules.js +0 -160
  220. package/dist/store/schedules.js.map +0 -1
  221. package/dist/wiki/index.d.ts +0 -3
  222. package/dist/wiki/index.d.ts.map +0 -1
  223. package/dist/wiki/index.js +0 -2
  224. package/dist/wiki/index.js.map +0 -1
  225. package/dist/wiki/store.d.ts +0 -81
  226. package/dist/wiki/store.d.ts.map +0 -1
  227. package/dist/wiki/store.js +0 -270
  228. package/dist/wiki/store.js.map +0 -1
  229. package/node_modules/@io/shared/dist/config.d.ts +0 -26
  230. package/node_modules/@io/shared/dist/config.d.ts.map +0 -1
  231. package/node_modules/@io/shared/dist/config.js +0 -53
  232. package/node_modules/@io/shared/dist/config.js.map +0 -1
  233. package/node_modules/@io/shared/dist/constants.d.ts +0 -19
  234. package/node_modules/@io/shared/dist/constants.d.ts.map +0 -1
  235. package/node_modules/@io/shared/dist/constants.js +0 -51
  236. package/node_modules/@io/shared/dist/constants.js.map +0 -1
  237. package/node_modules/@io/shared/dist/index.d.ts +0 -12
  238. package/node_modules/@io/shared/dist/index.d.ts.map +0 -1
  239. package/node_modules/@io/shared/dist/index.js +0 -3
  240. package/node_modules/@io/shared/dist/index.js.map +0 -1
  241. package/node_modules/@io/shared/dist/types/agents.d.ts +0 -3
  242. package/node_modules/@io/shared/dist/types/agents.d.ts.map +0 -1
  243. package/node_modules/@io/shared/dist/types/agents.js +0 -2
  244. package/node_modules/@io/shared/dist/types/agents.js.map +0 -1
  245. package/node_modules/@io/shared/dist/types/api.d.ts +0 -33
  246. package/node_modules/@io/shared/dist/types/api.d.ts.map +0 -1
  247. package/node_modules/@io/shared/dist/types/api.js +0 -2
  248. package/node_modules/@io/shared/dist/types/api.js.map +0 -1
  249. package/node_modules/@io/shared/dist/types/attachments.d.ts +0 -10
  250. package/node_modules/@io/shared/dist/types/attachments.d.ts.map +0 -1
  251. package/node_modules/@io/shared/dist/types/attachments.js +0 -2
  252. package/node_modules/@io/shared/dist/types/attachments.js.map +0 -1
  253. package/node_modules/@io/shared/dist/types/events.d.ts +0 -44
  254. package/node_modules/@io/shared/dist/types/events.d.ts.map +0 -1
  255. package/node_modules/@io/shared/dist/types/events.js +0 -2
  256. package/node_modules/@io/shared/dist/types/events.js.map +0 -1
  257. package/node_modules/@io/shared/dist/types/history.d.ts +0 -33
  258. package/node_modules/@io/shared/dist/types/history.d.ts.map +0 -1
  259. package/node_modules/@io/shared/dist/types/history.js +0 -2
  260. package/node_modules/@io/shared/dist/types/history.js.map +0 -1
  261. package/node_modules/@io/shared/dist/types/messages.d.ts +0 -15
  262. package/node_modules/@io/shared/dist/types/messages.d.ts.map +0 -1
  263. package/node_modules/@io/shared/dist/types/messages.js +0 -2
  264. package/node_modules/@io/shared/dist/types/messages.js.map +0 -1
  265. package/node_modules/@io/shared/dist/types/squads.d.ts +0 -46
  266. package/node_modules/@io/shared/dist/types/squads.d.ts.map +0 -1
  267. package/node_modules/@io/shared/dist/types/squads.js +0 -2
  268. package/node_modules/@io/shared/dist/types/squads.js.map +0 -1
  269. package/node_modules/@io/shared/dist/types/tokens.d.ts +0 -19
  270. package/node_modules/@io/shared/dist/types/tokens.d.ts.map +0 -1
  271. package/node_modules/@io/shared/dist/types/tokens.js +0 -2
  272. package/node_modules/@io/shared/dist/types/tokens.js.map +0 -1
  273. package/node_modules/@io/shared/package.json +0 -18
  274. package/node_modules/@io/shared/src/config.ts +0 -85
  275. package/node_modules/@io/shared/src/constants.ts +0 -54
  276. package/node_modules/@io/shared/src/index.ts +0 -46
  277. package/node_modules/@io/shared/src/types/agents.ts +0 -3
  278. package/node_modules/@io/shared/src/types/api.ts +0 -35
  279. package/node_modules/@io/shared/src/types/attachments.ts +0 -9
  280. package/node_modules/@io/shared/src/types/events.ts +0 -86
  281. package/node_modules/@io/shared/src/types/history.ts +0 -37
  282. package/node_modules/@io/shared/src/types/messages.ts +0 -15
  283. package/node_modules/@io/shared/src/types/squads.ts +0 -56
  284. package/node_modules/@io/shared/src/types/tokens.ts +0 -19
  285. package/node_modules/@io/shared/tsconfig.json +0 -9
  286. package/node_modules/@io/shared/tsconfig.tsbuildinfo +0 -1
  287. package/public/assets/index-CoSJG-14.js +0 -510
  288. package/public/assets/index-CoSJG-14.js.map +0 -1
  289. /package/{public → dist/web}/assets/index-B6F0UZkW.css +0 -0
@@ -1,1067 +0,0 @@
1
- import { defineTool } from '@github/copilot-sdk';
2
- import { z } from 'zod';
3
- import { createChildLogger } from '../logging/logger.js';
4
- import { activateSkill, deactivateSkill, getActiveSkills, installSkillFromUrl, listInstalledSkills, removeSkill, } from '../skills/index.js';
5
- import { executeInstance, initInstance } from '../squad/execution/runner.js';
6
- import { addMemberToExistingSquad, confirmSquad, getProposalByRepo, proposeSquad, } from '../squad/hiring.js';
7
- import { bootSquad, delegateToSquad, disbandSquad, findMember, getSquadByName, getSquadMembers, getSquadRuntime, listSquads, removeMember, renameMember, rethemeSquad, } from '../squad/manager.js';
8
- import { addInboxEntry, listInboxEntries, resolveInboxEntry } from '../store/inbox.js';
9
- import { createSchedule, deleteSchedule, listSchedules, updateSchedule, } from '../store/schedules.js';
10
- import { deleteWikiPage, getOrchestratorScopes, getPageListing, listWikiPages, readWikiPage, searchWiki, writeWikiPage, } from '../wiki/index.js';
11
- import { queryActivity } from '../store/activity.js';
12
- import { getDatabase } from '../store/db.js';
13
- /** Resolve attachment IDs to disk paths from the database */
14
- async function resolveAttachmentPaths(ids) {
15
- if (ids.length === 0)
16
- return [];
17
- const db = getDatabase();
18
- const placeholders = ids.map(() => '?').join(',');
19
- const result = await db.execute({
20
- sql: `SELECT id, filename, disk_path FROM attachments WHERE id IN (${placeholders})`,
21
- args: ids,
22
- });
23
- return result.rows
24
- .filter((row) => row.disk_path)
25
- .map((row) => ({
26
- type: 'file',
27
- path: row.disk_path,
28
- displayName: row.filename,
29
- }));
30
- }
31
- export function createOrchestratorTools() {
32
- return [
33
- defineTool('list_squads', {
34
- description: 'List all active squads and their current status. Use this when the user asks about their teams or projects.',
35
- parameters: z.object({}).strict(),
36
- handler: async () => {
37
- const squads = await listSquads();
38
- if (squads.length === 0) {
39
- return {
40
- textResultForLlm: JSON.stringify({
41
- squads: [],
42
- message: 'No squads currently active.',
43
- }),
44
- resultType: 'success',
45
- };
46
- }
47
- const summary = await Promise.all(squads.map(async (s) => {
48
- const members = await getSquadMembers(s.id);
49
- return {
50
- name: s.name,
51
- project: s.projectPath,
52
- universe: s.universe,
53
- autonomy: s.autonomyTier,
54
- members: members.map((m) => `${m.displayName} (${m.roleName})`),
55
- status: s.status,
56
- };
57
- }));
58
- return {
59
- textResultForLlm: JSON.stringify({ squads: summary }),
60
- resultType: 'success',
61
- };
62
- },
63
- }),
64
- defineTool('get_squad_status', {
65
- description: 'Get the detailed status of a specific squad including active instances, team members, and recent activity.',
66
- parameters: z.object({
67
- squadName: z.string().describe('The name of the squad to check'),
68
- }),
69
- handler: async (args) => {
70
- const squad = await getSquadByName(args.squadName);
71
- if (!squad) {
72
- return {
73
- textResultForLlm: JSON.stringify({ error: `Squad '${args.squadName}' not found.` }),
74
- resultType: 'success',
75
- };
76
- }
77
- const members = await getSquadMembers(squad.id);
78
- return {
79
- textResultForLlm: JSON.stringify({
80
- squad: {
81
- name: squad.name,
82
- project: squad.projectPath,
83
- repo: squad.repoUrl,
84
- universe: squad.universe,
85
- autonomy: squad.autonomyTier,
86
- status: squad.status,
87
- createdAt: squad.createdAt.toISOString(),
88
- },
89
- members: members.map((m) => ({
90
- name: m.displayName,
91
- role: m.roleName,
92
- veto: m.isVetoMember,
93
- tools: m.toolsAllowed,
94
- })),
95
- }),
96
- resultType: 'success',
97
- };
98
- },
99
- }),
100
- defineTool('hire_squad', {
101
- description: 'Hire a squad for a project. If no proposal exists for this repo yet, analyzes the codebase and proposes a team for user review. If a proposal already exists (user previously reviewed and approved), confirms it and creates the squad. Call this BOTH when the user wants to start hiring AND when they say "hire them" / "looks good" / "approved".',
102
- parameters: z.object({
103
- repoUrl: z.string().describe('GitHub repository URL (e.g. https://github.com/owner/repo)'),
104
- name: z.string().optional().describe('Name for the squad (auto-generated if omitted)'),
105
- universe: z
106
- .string()
107
- .optional()
108
- .describe('Pop-culture universe for member names (e.g. "The A-Team", "Star Wars", "Lord of the Rings"). Random if omitted.'),
109
- removedRoles: z
110
- .array(z.string())
111
- .optional()
112
- .describe('Role IDs to remove from the proposal when confirming (e.g. ["tester", "senior-react-engineer"])'),
113
- }),
114
- handler: async (args) => {
115
- try {
116
- // Check if a proposal already exists for this repo
117
- const existingProposal = getProposalByRepo(args.repoUrl);
118
- if (existingProposal) {
119
- // Confirm the existing proposal
120
- const result = await confirmSquad({
121
- proposalId: existingProposal.id,
122
- name: args.name,
123
- removedRoles: args.removedRoles,
124
- });
125
- return {
126
- textResultForLlm: JSON.stringify({
127
- message: 'Squad created successfully!',
128
- squadId: result.squadId,
129
- universe: result.universe,
130
- members: result.members,
131
- }),
132
- resultType: 'success',
133
- };
134
- }
135
- // No existing proposal — create a new one
136
- const { ensureCloned } = await import('../squad/source-resolver.js');
137
- const projectPath = await ensureCloned(args.repoUrl);
138
- const proposal = await proposeSquad({
139
- projectPath,
140
- repoUrl: args.repoUrl,
141
- name: args.name,
142
- universe: args.universe,
143
- });
144
- const memberSummary = proposal.members.map((m) => ({
145
- character: m.displayName ?? m.title,
146
- role: m.title,
147
- justification: m.justification,
148
- isCore: m.isCore,
149
- persona: m.persona ?? '',
150
- }));
151
- return {
152
- textResultForLlm: JSON.stringify({
153
- message: `Squad proposal ready for "${proposal.projectName}"! Present this to the user for review.`,
154
- proposalId: proposal.id,
155
- projectName: proposal.projectName,
156
- universe: proposal.universe,
157
- members: memberSummary,
158
- instructions: 'Present this squad proposal conversationally. Show each member with their character name, role title, and why they were chosen. Ask the user if they want to approve, modify, or reject the squad. Call hire_squad again with the same repoUrl to finalize when approved.',
159
- }),
160
- resultType: 'success',
161
- };
162
- }
163
- catch (err) {
164
- return {
165
- textResultForLlm: JSON.stringify({
166
- error: `Failed to hire squad: ${err instanceof Error ? err.message : String(err)}`,
167
- }),
168
- resultType: 'success',
169
- };
170
- }
171
- },
172
- }),
173
- defineTool('retheme_squad', {
174
- description: "Change a squad's pop-culture universe. Generates new character names and personas for all members from the specified universe.",
175
- parameters: z.object({
176
- squadName: z.string().describe('Name of the squad to retheme'),
177
- universe: z
178
- .string()
179
- .describe('New pop-culture universe (e.g. "The Office", "Star Wars", "Breaking Bad")'),
180
- }),
181
- handler: async (args) => {
182
- try {
183
- const squad = await getSquadByName(args.squadName);
184
- if (!squad) {
185
- return {
186
- textResultForLlm: JSON.stringify({ error: `Squad '${args.squadName}' not found.` }),
187
- resultType: 'success',
188
- };
189
- }
190
- const members = await getSquadMembers(squad.id);
191
- const roles = members.map((m) => m.roleName);
192
- const { generateSquadNames } = await import('../squad/name-generator.js');
193
- const generated = await generateSquadNames(roles, args.universe);
194
- await rethemeSquad(squad.id, args.universe, generated.assignments);
195
- return {
196
- textResultForLlm: JSON.stringify({
197
- message: `Squad '${args.squadName}' rethemed to ${args.universe}!`,
198
- members: generated.assignments.map((a) => `${a.displayName} (${a.role})`),
199
- }),
200
- resultType: 'success',
201
- };
202
- }
203
- catch (err) {
204
- return {
205
- textResultForLlm: JSON.stringify({
206
- error: `Failed to retheme squad: ${err instanceof Error ? err.message : String(err)}`,
207
- }),
208
- resultType: 'success',
209
- };
210
- }
211
- },
212
- }),
213
- defineTool('disband_squad', {
214
- description: 'Delete a squad. This disbands the squad, cancels its schedules, resolves pending inbox items, and removes wiki/skill files from disk. The squad record is preserved for usage reports. This cannot be undone.',
215
- parameters: z.object({
216
- squadName: z.string().describe('Name of the squad to disband'),
217
- }),
218
- handler: async (args) => {
219
- try {
220
- const squad = await getSquadByName(args.squadName);
221
- if (!squad) {
222
- return {
223
- textResultForLlm: JSON.stringify({ error: `Squad '${args.squadName}' not found.` }),
224
- resultType: 'success',
225
- };
226
- }
227
- await disbandSquad(squad.id);
228
- return {
229
- textResultForLlm: JSON.stringify({
230
- disbanded: true,
231
- message: `Squad '${args.squadName}' has been disbanded. Usage data is preserved for reports.`,
232
- }),
233
- resultType: 'success',
234
- };
235
- }
236
- catch (err) {
237
- return {
238
- textResultForLlm: JSON.stringify({
239
- error: `Failed to disband squad: ${err instanceof Error ? err.message : String(err)}`,
240
- }),
241
- resultType: 'success',
242
- };
243
- }
244
- },
245
- }),
246
- defineTool('rename_squad_member', {
247
- description: "Change a squad member's display name. Identify the member by their current display name or role name.",
248
- parameters: z.object({
249
- squadName: z.string().describe('Name of the squad'),
250
- member: z.string().describe('Current display name or role name of the member to rename'),
251
- newDisplayName: z.string().describe('The new display name for the member'),
252
- }),
253
- handler: async (args) => {
254
- try {
255
- const squad = await getSquadByName(args.squadName);
256
- if (!squad) {
257
- return {
258
- textResultForLlm: JSON.stringify({ error: `Squad '${args.squadName}' not found.` }),
259
- resultType: 'success',
260
- };
261
- }
262
- const found = await findMember(squad.id, args.member);
263
- if (!found) {
264
- return {
265
- textResultForLlm: JSON.stringify({
266
- error: `Member '${args.member}' not found in squad '${args.squadName}'.`,
267
- }),
268
- resultType: 'success',
269
- };
270
- }
271
- await renameMember(found.id, args.newDisplayName);
272
- return {
273
- textResultForLlm: JSON.stringify({
274
- renamed: true,
275
- previousName: found.displayName,
276
- newName: args.newDisplayName,
277
- role: found.roleName,
278
- }),
279
- resultType: 'success',
280
- };
281
- }
282
- catch (err) {
283
- return {
284
- textResultForLlm: JSON.stringify({
285
- error: `Failed to rename member: ${err instanceof Error ? err.message : String(err)}`,
286
- }),
287
- resultType: 'success',
288
- };
289
- }
290
- },
291
- }),
292
- defineTool('fire_squad_member', {
293
- description: 'Remove (fire) a member from a squad. The member is retired and their running agent is destroyed. Identify by display name or role name.',
294
- parameters: z.object({
295
- squadName: z.string().describe('Name of the squad'),
296
- member: z.string().describe('Display name or role name of the member to fire'),
297
- }),
298
- handler: async (args) => {
299
- try {
300
- const squad = await getSquadByName(args.squadName);
301
- if (!squad) {
302
- return {
303
- textResultForLlm: JSON.stringify({ error: `Squad '${args.squadName}' not found.` }),
304
- resultType: 'success',
305
- };
306
- }
307
- const found = await findMember(squad.id, args.member);
308
- if (!found) {
309
- return {
310
- textResultForLlm: JSON.stringify({
311
- error: `Member '${args.member}' not found in squad '${args.squadName}'.`,
312
- }),
313
- resultType: 'success',
314
- };
315
- }
316
- await removeMember(found.id, squad.id);
317
- return {
318
- textResultForLlm: JSON.stringify({
319
- fired: true,
320
- member: found.displayName,
321
- role: found.roleName,
322
- message: `${found.displayName} (${found.roleName}) has been removed from the squad.`,
323
- }),
324
- resultType: 'success',
325
- };
326
- }
327
- catch (err) {
328
- return {
329
- textResultForLlm: JSON.stringify({
330
- error: `Failed to fire member: ${err instanceof Error ? err.message : String(err)}`,
331
- }),
332
- resultType: 'success',
333
- };
334
- }
335
- },
336
- }),
337
- defineTool('hire_squad_member', {
338
- description: "Add a new member to an existing squad. A skill file is generated for the role and the member gets a themed name from the squad's universe.",
339
- parameters: z.object({
340
- squadName: z.string().describe('Name of the squad to add a member to'),
341
- role: z
342
- .string()
343
- .describe('Role for the new member (e.g., "frontend-developer", "backend-developer", "devops-engineer", "designer", "qa-tester")'),
344
- }),
345
- handler: async (args) => {
346
- try {
347
- const squad = await getSquadByName(args.squadName);
348
- if (!squad) {
349
- return {
350
- textResultForLlm: JSON.stringify({ error: `Squad '${args.squadName}' not found.` }),
351
- resultType: 'success',
352
- };
353
- }
354
- const result = await addMemberToExistingSquad({
355
- squadId: squad.id,
356
- squadName: squad.name,
357
- role: args.role,
358
- projectPath: squad.projectPath,
359
- universe: squad.universe,
360
- });
361
- return {
362
- textResultForLlm: JSON.stringify({
363
- hired: true,
364
- displayName: result.displayName,
365
- role: result.role,
366
- squad: args.squadName,
367
- message: `${result.displayName} (${result.role}) has joined the squad.`,
368
- }),
369
- resultType: 'success',
370
- };
371
- }
372
- catch (err) {
373
- return {
374
- textResultForLlm: JSON.stringify({
375
- error: `Failed to hire member: ${err instanceof Error ? err.message : String(err)}`,
376
- }),
377
- resultType: 'success',
378
- };
379
- }
380
- },
381
- }),
382
- defineTool('delegate_to_squad', {
383
- description: "Delegate a message or task to a specific squad's team lead. Use this for planning, research, questions, analysis, or any task that does NOT require writing/committing code. The squad will work on it in the background and deliver results to the user's inbox. Returns immediately after dispatching. If the user's message included file attachments, pass their IDs so the squad can access them.",
384
- parameters: z.object({
385
- squadName: z.string().describe('Name of the squad to delegate to'),
386
- message: z.string().describe('The full message or task to delegate'),
387
- attachmentIds: z
388
- .array(z.string())
389
- .optional()
390
- .describe('IDs of file attachments from the conversation to forward to the squad'),
391
- }),
392
- handler: async (args) => {
393
- const squad = await getSquadByName(args.squadName);
394
- if (!squad) {
395
- return {
396
- textResultForLlm: JSON.stringify({
397
- error: `Squad '${args.squadName}' not found.`,
398
- }),
399
- resultType: 'success',
400
- };
401
- }
402
- try {
403
- // Resolve attachment IDs to disk paths
404
- const fileAttachments = args.attachmentIds?.length
405
- ? await resolveAttachmentPaths(args.attachmentIds)
406
- : undefined;
407
- // Create a delegation history record
408
- const delegationId = crypto.randomUUID();
409
- const db = (await import('../store/db.js')).getDatabase();
410
- await db.execute({
411
- sql: `INSERT INTO squad_instances (id, squad_id, type, objective, status)
412
- VALUES (?, ?, 'delegation', ?, 'working')`,
413
- args: [delegationId, squad.id, args.message.slice(0, 500)],
414
- });
415
- // Fire-and-forget: boot squad if needed, then send message to team lead
416
- const delegationMessage = `${args.message}\n\nIMPORTANT: When you have completed this work or have results to share, deliver them to the user's inbox using the add_to_inbox tool. Include a clear title and your findings/deliverables in the content.`;
417
- (async () => {
418
- try {
419
- // Boot squad if not already running (may take time creating sessions)
420
- if (!getSquadRuntime(squad.id)) {
421
- await bootSquad(squad);
422
- }
423
- // Set instanceId on team lead so events are tracked under this delegation
424
- const runtime = getSquadRuntime(squad.id);
425
- const teamLead = runtime?.members.get('technical-pm');
426
- if (teamLead)
427
- teamLead.setInstanceId(delegationId);
428
- const response = await delegateToSquad(squad.id, delegationMessage, fileAttachments);
429
- // Log the team lead's response as activity
430
- const { logActivity } = await import('../store/activity.js');
431
- await logActivity({
432
- squadId: squad.id,
433
- instanceId: delegationId,
434
- agentRole: 'technical-pm',
435
- activityType: 'message',
436
- label: 'Delegation response',
437
- content: { response: response.slice(0, 1000) },
438
- });
439
- // Mark delegation complete
440
- await db.execute({
441
- sql: `UPDATE squad_instances SET status = 'complete', completed_at = CURRENT_TIMESTAMP WHERE id = ?`,
442
- args: [delegationId],
443
- });
444
- }
445
- catch (err) {
446
- // Mark delegation as failed
447
- const { logActivity } = await import('../store/activity.js');
448
- await logActivity({
449
- squadId: squad.id,
450
- instanceId: delegationId,
451
- agentRole: 'technical-pm',
452
- activityType: 'message',
453
- label: 'Error',
454
- status: 'error',
455
- content: { error: err instanceof Error ? err.message : String(err) },
456
- });
457
- await db.execute({
458
- sql: `UPDATE squad_instances SET status = 'failed', completed_at = CURRENT_TIMESTAMP WHERE id = ?`,
459
- args: [delegationId],
460
- });
461
- createChildLogger('orchestrator').warn({ err, squadName: args.squadName }, 'Background delegation failed');
462
- }
463
- })();
464
- return {
465
- textResultForLlm: JSON.stringify({
466
- delegated: true,
467
- squadName: args.squadName,
468
- message: `Task dispatched to ${args.squadName}. They will deliver results to the inbox when complete.`,
469
- }),
470
- resultType: 'success',
471
- };
472
- }
473
- catch (err) {
474
- return {
475
- textResultForLlm: JSON.stringify({
476
- error: `Failed to delegate: ${err instanceof Error ? err.message : String(err)}`,
477
- }),
478
- resultType: 'success',
479
- };
480
- }
481
- },
482
- }),
483
- defineTool('run_squad_instance', {
484
- description: 'Start a new work instance for a squad. This kicks off the full lifecycle: meeting → task execution → PR creation. ONLY use this when the user explicitly wants code written, committed, and a pull request created. Do NOT use for planning, research, analysis, or questions — use delegate_to_squad for those instead. If the user provided file attachments (mockups, specs), pass their IDs so the squad can reference them.',
485
- parameters: z.object({
486
- squadName: z.string().describe('Name of the squad'),
487
- objective: z.string().describe('What the squad should accomplish'),
488
- issueRef: z.string().optional().describe('GitHub issue reference (e.g., #42)'),
489
- attachmentIds: z
490
- .array(z.string())
491
- .optional()
492
- .describe('IDs of file attachments from the conversation to forward to the squad'),
493
- }),
494
- handler: async (args) => {
495
- const squad = await getSquadByName(args.squadName);
496
- if (!squad) {
497
- return {
498
- textResultForLlm: JSON.stringify({ error: `Squad '${args.squadName}' not found.` }),
499
- resultType: 'success',
500
- };
501
- }
502
- try {
503
- // Resolve attachment IDs to disk paths
504
- const fileAttachments = args.attachmentIds?.length
505
- ? await resolveAttachmentPaths(args.attachmentIds)
506
- : undefined;
507
- // Await init: boot squad + persist instance to DB
508
- const { instance, runtime } = await initInstance({
509
- squad,
510
- objective: args.objective,
511
- issueRef: args.issueRef,
512
- });
513
- // Fire-and-forget: execute the instance lifecycle in background
514
- executeInstance({
515
- instance,
516
- runtime,
517
- squad,
518
- objective: args.objective,
519
- attachments: fileAttachments,
520
- })
521
- .then((result) => {
522
- if (result.success) {
523
- createChildLogger('orchestrator').info({ instanceId: result.instanceId, pr: result.pr?.url }, 'Instance completed successfully');
524
- }
525
- else {
526
- createChildLogger('orchestrator').warn({ instanceId: result.instanceId, error: result.error }, 'Instance completed with failure');
527
- }
528
- })
529
- .catch((err) => {
530
- createChildLogger('orchestrator').error({ err: err instanceof Error ? err.message : String(err), squadName: args.squadName }, 'Background instance execution failed');
531
- });
532
- return {
533
- textResultForLlm: JSON.stringify({
534
- started: true,
535
- instanceId: instance.id,
536
- squadName: args.squadName,
537
- message: `Instance ${instance.id.slice(0, 8)} started for ${args.squadName}. The squad will run through the full lifecycle (meeting → tasks → PR) and deliver results to the inbox when complete.`,
538
- }),
539
- resultType: 'success',
540
- };
541
- }
542
- catch (err) {
543
- return {
544
- textResultForLlm: JSON.stringify({
545
- error: `Failed to start instance: ${err instanceof Error ? err.message : String(err)}`,
546
- }),
547
- resultType: 'success',
548
- };
549
- }
550
- },
551
- }),
552
- defineTool('list_inbox', {
553
- description: "List unread inbox entries from squads. Shows deliverables and pending questions that need the user's attention.",
554
- parameters: z.object({
555
- status: z
556
- .enum(['unread', 'read', 'resolved'])
557
- .optional()
558
- .describe('Filter by status (default: unread)'),
559
- }),
560
- handler: async (args) => {
561
- const entries = await listInboxEntries({
562
- status: args.status ?? 'unread',
563
- limit: 20,
564
- });
565
- if (entries.length === 0) {
566
- return {
567
- textResultForLlm: JSON.stringify({ entries: [], message: 'No inbox entries.' }),
568
- resultType: 'success',
569
- };
570
- }
571
- const summary = entries.map((e) => ({
572
- id: e.id,
573
- squad: e.squadId,
574
- kind: e.kind,
575
- title: e.title,
576
- content: e.content.slice(0, 500),
577
- status: e.status,
578
- createdAt: e.createdAt,
579
- }));
580
- return {
581
- textResultForLlm: JSON.stringify({ entries: summary }),
582
- resultType: 'success',
583
- };
584
- },
585
- }),
586
- defineTool('respond_to_inbox', {
587
- description: "Respond to an inbox question from a squad. Use this when the user provides an answer to a squad's pending question. This unblocks the squad so it can continue working.",
588
- parameters: z.object({
589
- entryId: z.string().describe('The inbox entry ID to respond to'),
590
- response: z.string().describe("The user's response to the squad's question"),
591
- }),
592
- handler: async (args) => {
593
- try {
594
- const unblocked = await resolveInboxEntry(args.entryId, args.response);
595
- return {
596
- textResultForLlm: JSON.stringify({
597
- resolved: true,
598
- squadUnblocked: unblocked,
599
- message: unblocked
600
- ? 'Response delivered — squad has been unblocked and will continue working.'
601
- : 'Response recorded (squad was not actively waiting).',
602
- }),
603
- resultType: 'success',
604
- };
605
- }
606
- catch (err) {
607
- return {
608
- textResultForLlm: JSON.stringify({
609
- error: `Failed to respond: ${err instanceof Error ? err.message : String(err)}`,
610
- }),
611
- resultType: 'success',
612
- };
613
- }
614
- },
615
- }),
616
- defineTool('create_schedule', {
617
- description: 'Create a cron-based schedule that triggers a squad or the orchestrator with a predefined prompt at specified times. Use standard cron syntax in UTC (e.g., "0 9 * * 1-5" for weekdays at 9am UTC). IMPORTANT: The user speaks in their configured timezone — convert their stated times to UTC before writing the cron expression.',
618
- parameters: z.object({
619
- name: z.string().describe('Human-readable name for the schedule (e.g., "Daily Standup")'),
620
- targetType: z
621
- .enum(['squad', 'orchestrator'])
622
- .describe('Whether to target a squad or the orchestrator'),
623
- targetId: z.string().optional().describe('Squad name (required if targetType is "squad")'),
624
- cron: z.string().describe('Cron expression in UTC (e.g., "0 14 * * 1-5" for weekdays at 9am US Central)'),
625
- prompt: z.string().describe('The prompt/message to send when the schedule fires'),
626
- }),
627
- handler: async (args) => {
628
- try {
629
- // Validate squad exists if targeting a squad
630
- if (args.targetType === 'squad') {
631
- if (!args.targetId) {
632
- return {
633
- textResultForLlm: JSON.stringify({
634
- error: 'targetId (squad name) is required for squad schedules',
635
- }),
636
- resultType: 'success',
637
- };
638
- }
639
- const squad = await getSquadByName(args.targetId);
640
- if (!squad) {
641
- return {
642
- textResultForLlm: JSON.stringify({ error: `Squad '${args.targetId}' not found` }),
643
- resultType: 'success',
644
- };
645
- }
646
- args.targetId = squad.id;
647
- }
648
- const schedule = await createSchedule({
649
- name: args.name,
650
- targetType: args.targetType,
651
- targetId: args.targetId,
652
- cron: args.cron,
653
- prompt: args.prompt,
654
- });
655
- return {
656
- textResultForLlm: JSON.stringify({
657
- created: true,
658
- schedule: {
659
- id: schedule.id,
660
- name: schedule.name,
661
- cron: schedule.cron,
662
- nextRun: schedule.nextRun,
663
- },
664
- }),
665
- resultType: 'success',
666
- };
667
- }
668
- catch (err) {
669
- return {
670
- textResultForLlm: JSON.stringify({
671
- error: `Failed to create schedule: ${err instanceof Error ? err.message : String(err)}`,
672
- }),
673
- resultType: 'success',
674
- };
675
- }
676
- },
677
- }),
678
- defineTool('list_schedules', {
679
- description: 'List all configured schedules (cron-based automations).',
680
- parameters: z.object({}).strict(),
681
- handler: async () => {
682
- const schedules = await listSchedules();
683
- if (schedules.length === 0) {
684
- return {
685
- textResultForLlm: JSON.stringify({
686
- schedules: [],
687
- message: 'No schedules configured.',
688
- }),
689
- resultType: 'success',
690
- };
691
- }
692
- const summary = schedules.map((s) => ({
693
- id: s.id,
694
- name: s.name,
695
- targetType: s.targetType,
696
- targetId: s.targetId,
697
- cron: s.cron,
698
- prompt: s.prompt.slice(0, 100),
699
- enabled: s.enabled,
700
- nextRun: s.nextRun,
701
- lastRun: s.lastRun,
702
- }));
703
- return {
704
- textResultForLlm: JSON.stringify({ schedules: summary }),
705
- resultType: 'success',
706
- };
707
- },
708
- }),
709
- defineTool('delete_schedule', {
710
- description: 'Delete a schedule by ID. Use list_schedules first to find the ID.',
711
- parameters: z.object({
712
- scheduleId: z.string().describe('The ID of the schedule to delete'),
713
- }),
714
- handler: async (args) => {
715
- try {
716
- await deleteSchedule(args.scheduleId);
717
- return {
718
- textResultForLlm: JSON.stringify({ deleted: true, scheduleId: args.scheduleId }),
719
- resultType: 'success',
720
- };
721
- }
722
- catch (err) {
723
- return {
724
- textResultForLlm: JSON.stringify({
725
- error: `Failed to delete: ${err instanceof Error ? err.message : String(err)}`,
726
- }),
727
- resultType: 'success',
728
- };
729
- }
730
- },
731
- }),
732
- defineTool('read_wiki', {
733
- description: 'Read from the wiki knowledge base. Call with no pageName to list available pages, or with a pageName to read its content. You have access to IO-level and Shared wiki scopes.',
734
- parameters: z.object({
735
- scope: z.enum(['io', 'shared']).describe('Which wiki scope to read from'),
736
- pageName: z
737
- .string()
738
- .optional()
739
- .describe('Page name to read (omit to list all pages in scope)'),
740
- }),
741
- handler: async (args) => {
742
- if (!args.pageName) {
743
- const pages = listWikiPages(args.scope);
744
- return {
745
- textResultForLlm: JSON.stringify({
746
- scope: args.scope,
747
- pages: pages.length > 0 ? pages : '(empty)',
748
- }),
749
- resultType: 'success',
750
- };
751
- }
752
- const page = readWikiPage(args.scope, args.pageName);
753
- if (!page) {
754
- return {
755
- textResultForLlm: JSON.stringify({
756
- error: `Page '${args.pageName}' not found in ${args.scope} wiki`,
757
- }),
758
- resultType: 'success',
759
- };
760
- }
761
- return {
762
- textResultForLlm: JSON.stringify({
763
- scope: page.scope,
764
- name: page.name,
765
- content: page.content,
766
- }),
767
- resultType: 'success',
768
- };
769
- },
770
- }),
771
- defineTool('write_wiki', {
772
- description: 'Write a page to the wiki knowledge base. Provide the full page content (read existing first and merge if updating). You can write to IO-level and Shared scopes.',
773
- parameters: z.object({
774
- scope: z.enum(['io', 'shared']).describe('Which wiki scope to write to'),
775
- pageName: z
776
- .string()
777
- .describe('Page name (no .md extension, e.g., "preferences" or "routing-conventions")'),
778
- content: z.string().describe('Full markdown content for the page'),
779
- }),
780
- handler: async (args) => {
781
- writeWikiPage(args.scope, args.pageName, args.content);
782
- return {
783
- textResultForLlm: JSON.stringify({
784
- written: true,
785
- scope: args.scope,
786
- pageName: args.pageName,
787
- }),
788
- resultType: 'success',
789
- };
790
- },
791
- }),
792
- defineTool('search_wiki', {
793
- description: 'Search across wiki pages by keyword. Searches IO-level and Shared scopes.',
794
- parameters: z.object({
795
- keyword: z.string().describe('Keyword or phrase to search for'),
796
- }),
797
- handler: async (args) => {
798
- const results = searchWiki(args.keyword, getOrchestratorScopes());
799
- if (results.length === 0) {
800
- return {
801
- textResultForLlm: JSON.stringify({ results: [], message: 'No matches found.' }),
802
- resultType: 'success',
803
- };
804
- }
805
- return {
806
- textResultForLlm: JSON.stringify({ results }),
807
- resultType: 'success',
808
- };
809
- },
810
- }),
811
- defineTool('install_skill', {
812
- description: 'Install a skill from a URL (raw GitHub URL to a SKILL.md file). Skills extend IO or squad capabilities with additional instructions and behaviors.',
813
- parameters: z.object({
814
- name: z
815
- .string()
816
- .describe('Name for the skill (kebab-case, e.g., "tdd-workflow" or "code-review")'),
817
- url: z
818
- .string()
819
- .describe('URL to the raw SKILL.md content (e.g., raw.githubusercontent.com/.../SKILL.md)'),
820
- }),
821
- handler: async (args) => {
822
- try {
823
- const skill = await installSkillFromUrl(args.name, args.url);
824
- return {
825
- textResultForLlm: JSON.stringify({
826
- installed: true,
827
- name: skill.name,
828
- preview: skill.content.slice(0, 200),
829
- }),
830
- resultType: 'success',
831
- };
832
- }
833
- catch (err) {
834
- return {
835
- textResultForLlm: JSON.stringify({
836
- error: `Failed to install: ${err instanceof Error ? err.message : String(err)}`,
837
- }),
838
- resultType: 'success',
839
- };
840
- }
841
- },
842
- }),
843
- defineTool('list_skills', {
844
- description: 'List all installed skills and their activation status.',
845
- parameters: z.object({}).strict(),
846
- handler: async () => {
847
- const installed = listInstalledSkills();
848
- const orchestratorActivations = await getActiveSkills('orchestrator');
849
- const summary = installed.map((s) => ({
850
- name: s.name,
851
- activatedForOrchestrator: orchestratorActivations.some((a) => a.skillName === s.name),
852
- preview: s.content.slice(0, 100),
853
- }));
854
- return {
855
- textResultForLlm: JSON.stringify({
856
- skills: summary.length > 0 ? summary : '(no skills installed)',
857
- }),
858
- resultType: 'success',
859
- };
860
- },
861
- }),
862
- defineTool('activate_skill', {
863
- description: 'Activate an installed skill for the orchestrator or a specific squad. Active skills are injected into the system prompt.',
864
- parameters: z.object({
865
- skillName: z.string().describe('Name of the installed skill'),
866
- targetType: z
867
- .enum(['orchestrator', 'squad'])
868
- .describe('Activate for orchestrator or a specific squad'),
869
- targetId: z.string().optional().describe('Squad name (required if targetType is "squad")'),
870
- }),
871
- handler: async (args) => {
872
- try {
873
- let resolvedTargetId = args.targetId ?? null;
874
- if (args.targetType === 'squad' && args.targetId) {
875
- const squad = await getSquadByName(args.targetId);
876
- if (!squad) {
877
- return {
878
- textResultForLlm: JSON.stringify({ error: `Squad '${args.targetId}' not found` }),
879
- resultType: 'success',
880
- };
881
- }
882
- resolvedTargetId = squad.id;
883
- }
884
- await activateSkill(args.skillName, args.targetType, resolvedTargetId ?? undefined);
885
- return {
886
- textResultForLlm: JSON.stringify({
887
- activated: true,
888
- skillName: args.skillName,
889
- target: args.targetType === 'orchestrator' ? 'orchestrator' : args.targetId,
890
- }),
891
- resultType: 'success',
892
- };
893
- }
894
- catch (err) {
895
- return {
896
- textResultForLlm: JSON.stringify({
897
- error: `Failed to activate: ${err instanceof Error ? err.message : String(err)}`,
898
- }),
899
- resultType: 'success',
900
- };
901
- }
902
- },
903
- }),
904
- defineTool('deactivate_skill', {
905
- description: 'Deactivate a skill (stop injecting it into the system prompt).',
906
- parameters: z.object({
907
- skillName: z.string().describe('Name of the skill to deactivate'),
908
- targetType: z
909
- .enum(['orchestrator', 'squad'])
910
- .describe('Deactivate from orchestrator or a specific squad'),
911
- targetId: z.string().optional().describe('Squad name (required if targetType is "squad")'),
912
- }),
913
- handler: async (args) => {
914
- await deactivateSkill(args.skillName, args.targetType, args.targetId ?? undefined);
915
- return {
916
- textResultForLlm: JSON.stringify({ deactivated: true, skillName: args.skillName }),
917
- resultType: 'success',
918
- };
919
- },
920
- }),
921
- defineTool('remove_skill', {
922
- description: 'Uninstall a skill completely (removes files and all activations).',
923
- parameters: z.object({
924
- skillName: z.string().describe('Name of the skill to remove'),
925
- }),
926
- handler: async (args) => {
927
- removeSkill(args.skillName);
928
- return {
929
- textResultForLlm: JSON.stringify({ removed: true, skillName: args.skillName }),
930
- resultType: 'success',
931
- };
932
- },
933
- }),
934
- defineTool('add_to_inbox', {
935
- description: "Create an inbox entry for the user. Use this to deliver results, leave notes, reminders, or ask the user a question that will block until they respond.",
936
- parameters: z.object({
937
- kind: z
938
- .enum(['deliverable', 'question', 'note'])
939
- .describe('Type of entry: deliverable (work product), question (blocks until answered), note (informational)'),
940
- title: z.string().describe('Short title for the inbox entry'),
941
- content: z.string().describe('Full content/body of the entry'),
942
- }),
943
- handler: async (args) => {
944
- try {
945
- const { entry } = await addInboxEntry({
946
- kind: args.kind,
947
- title: args.title,
948
- content: args.content,
949
- });
950
- return {
951
- textResultForLlm: JSON.stringify({
952
- created: true,
953
- id: entry.id,
954
- kind: entry.kind,
955
- title: entry.title,
956
- }),
957
- resultType: 'success',
958
- };
959
- }
960
- catch (err) {
961
- return {
962
- textResultForLlm: JSON.stringify({
963
- error: `Failed to create inbox entry: ${err instanceof Error ? err.message : String(err)}`,
964
- }),
965
- resultType: 'success',
966
- };
967
- }
968
- },
969
- }),
970
- defineTool('delete_wiki', {
971
- description: 'Delete a wiki page permanently.',
972
- parameters: z.object({
973
- scope: z.enum(['shared', 'io']).describe('Wiki scope'),
974
- page: z.string().describe('Page name (without extension)'),
975
- }),
976
- handler: async (args) => {
977
- try {
978
- const deleted = deleteWikiPage(args.scope, args.page);
979
- return {
980
- textResultForLlm: JSON.stringify({
981
- deleted,
982
- scope: args.scope,
983
- page: args.page,
984
- message: deleted ? 'Page deleted.' : 'Page not found.',
985
- }),
986
- resultType: 'success',
987
- };
988
- }
989
- catch (err) {
990
- return {
991
- textResultForLlm: JSON.stringify({
992
- error: `Failed to delete wiki page: ${err instanceof Error ? err.message : String(err)}`,
993
- }),
994
- resultType: 'success',
995
- };
996
- }
997
- },
998
- }),
999
- defineTool('update_schedule', {
1000
- description: 'Update an existing schedule (name, cron expression, prompt, or enabled state).',
1001
- parameters: z.object({
1002
- id: z.string().describe('Schedule ID to update'),
1003
- name: z.string().optional().describe('New name for the schedule'),
1004
- cron: z.string().optional().describe('New cron expression'),
1005
- prompt: z.string().optional().describe('New prompt text'),
1006
- enabled: z.boolean().optional().describe('Enable or disable the schedule'),
1007
- }),
1008
- handler: async (args) => {
1009
- try {
1010
- const { id, ...updates } = args;
1011
- await updateSchedule(id, updates);
1012
- return {
1013
- textResultForLlm: JSON.stringify({
1014
- updated: true,
1015
- id,
1016
- changes: Object.keys(updates),
1017
- }),
1018
- resultType: 'success',
1019
- };
1020
- }
1021
- catch (err) {
1022
- return {
1023
- textResultForLlm: JSON.stringify({
1024
- error: `Failed to update schedule: ${err instanceof Error ? err.message : String(err)}`,
1025
- }),
1026
- resultType: 'success',
1027
- };
1028
- }
1029
- },
1030
- }),
1031
- defineTool('query_activity', {
1032
- description: 'Query the activity log to understand what has happened recently. Useful for reviewing squad actions, system events, and task history.',
1033
- parameters: z.object({
1034
- activityType: z
1035
- .enum(['tool_call', 'message', 'meeting_contribution', 'task_start', 'task_complete', 'error'])
1036
- .optional()
1037
- .describe('Filter by activity type'),
1038
- squadId: z.string().optional().describe('Filter by squad ID'),
1039
- agentRole: z.string().optional().describe('Filter by agent role'),
1040
- limit: z.number().optional().describe('Max entries to return (default 20)'),
1041
- }),
1042
- handler: async (args) => {
1043
- try {
1044
- const entries = await queryActivity({
1045
- activityType: args.activityType,
1046
- squadId: args.squadId,
1047
- agentRole: args.agentRole,
1048
- limit: args.limit ?? 20,
1049
- });
1050
- return {
1051
- textResultForLlm: JSON.stringify({ entries, count: entries.length }),
1052
- resultType: 'success',
1053
- };
1054
- }
1055
- catch (err) {
1056
- return {
1057
- textResultForLlm: JSON.stringify({
1058
- error: `Failed to query activity: ${err instanceof Error ? err.message : String(err)}`,
1059
- }),
1060
- resultType: 'success',
1061
- };
1062
- }
1063
- },
1064
- }),
1065
- ];
1066
- }
1067
- //# sourceMappingURL=tools.js.map