heyio 3.0.2 → 3.0.4

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 (65) hide show
  1. package/dist/api/server.js +1 -1
  2. package/dist/api/server.js.map +1 -1
  3. package/dist/index.js +8 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/logging/logger.d.ts.map +1 -1
  6. package/dist/logging/logger.js +13 -1
  7. package/dist/logging/logger.js.map +1 -1
  8. package/node_modules/@io/shared/package.json +1 -1
  9. package/package.json +7 -2
  10. package/public/assets/index-2RY89H3W.js +336 -0
  11. package/public/assets/index-2RY89H3W.js.map +1 -0
  12. package/public/assets/index-D3cGfBsj.css +1 -0
  13. package/public/index.html +14 -0
  14. package/src/api/middleware/auth.ts +0 -76
  15. package/src/api/notifications.ts +0 -122
  16. package/src/api/routes/activity.ts +0 -29
  17. package/src/api/routes/attachments.ts +0 -93
  18. package/src/api/routes/config.ts +0 -115
  19. package/src/api/routes/conversations.ts +0 -87
  20. package/src/api/routes/health.ts +0 -18
  21. package/src/api/routes/inbox.ts +0 -98
  22. package/src/api/routes/schedules.ts +0 -121
  23. package/src/api/routes/skills.ts +0 -105
  24. package/src/api/routes/squads.ts +0 -145
  25. package/src/api/routes/usage.ts +0 -57
  26. package/src/api/routes/wiki.ts +0 -49
  27. package/src/api/server.ts +0 -186
  28. package/src/config.ts +0 -3
  29. package/src/copilot/client.ts +0 -42
  30. package/src/copilot/health-monitor.ts +0 -85
  31. package/src/copilot/orchestrator.ts +0 -222
  32. package/src/copilot/tools.ts +0 -707
  33. package/src/index.ts +0 -113
  34. package/src/logging/logger.ts +0 -26
  35. package/src/models/index.ts +0 -11
  36. package/src/models/pricing.ts +0 -121
  37. package/src/models/registry.ts +0 -131
  38. package/src/models/token-tracker.ts +0 -151
  39. package/src/scheduler/engine.ts +0 -146
  40. package/src/skills/index.ts +0 -13
  41. package/src/skills/store.ts +0 -188
  42. package/src/squad/agent.ts +0 -326
  43. package/src/squad/autonomy.ts +0 -78
  44. package/src/squad/event-bus.ts +0 -71
  45. package/src/squad/execution/index.ts +0 -17
  46. package/src/squad/execution/instance.ts +0 -186
  47. package/src/squad/execution/meeting.ts +0 -191
  48. package/src/squad/execution/pr.ts +0 -127
  49. package/src/squad/execution/runner.ts +0 -97
  50. package/src/squad/execution/tasks.ts +0 -111
  51. package/src/squad/execution/worktree.ts +0 -138
  52. package/src/squad/hiring.ts +0 -222
  53. package/src/squad/index.ts +0 -17
  54. package/src/squad/manager.ts +0 -337
  55. package/src/squad/name-generator.ts +0 -135
  56. package/src/squad/roles/templates.ts +0 -104
  57. package/src/squad/skill-parser.ts +0 -120
  58. package/src/squad/source-resolver.ts +0 -57
  59. package/src/store/activity.ts +0 -176
  60. package/src/store/db.ts +0 -237
  61. package/src/store/inbox.ts +0 -199
  62. package/src/store/schedules.ts +0 -199
  63. package/src/wiki/index.ts +0 -12
  64. package/src/wiki/store.ts +0 -139
  65. package/tsconfig.json +0 -9
@@ -1,98 +0,0 @@
1
- import { Router } from 'express';
2
- import {
3
- type InboxKind,
4
- type InboxStatus,
5
- getInboxEntry,
6
- getUnreadCount,
7
- listInboxEntries,
8
- markInboxRead,
9
- resolveInboxEntry,
10
- } from '../../store/inbox.js';
11
-
12
- export function inboxRouter(): Router {
13
- const router = Router();
14
-
15
- /**
16
- * GET /api/inbox
17
- * List inbox entries with optional filters.
18
- * Query params: status, squad, kind, limit
19
- */
20
- router.get('/inbox', async (req, res) => {
21
- try {
22
- const entries = await listInboxEntries({
23
- status: req.query.status as InboxStatus | undefined,
24
- squadId: req.query.squad as string | undefined,
25
- kind: req.query.kind as InboxKind | undefined,
26
- limit: req.query.limit ? Number.parseInt(req.query.limit as string, 10) : undefined,
27
- });
28
- res.json({ entries });
29
- } catch {
30
- res.status(500).json({ error: 'Failed to list inbox entries' });
31
- }
32
- });
33
-
34
- /**
35
- * GET /api/inbox/unread-count
36
- * Get the number of unread inbox entries.
37
- */
38
- router.get('/inbox/unread-count', async (_req, res) => {
39
- try {
40
- const count = await getUnreadCount();
41
- res.json({ count });
42
- } catch {
43
- res.status(500).json({ error: 'Failed to get unread count' });
44
- }
45
- });
46
-
47
- /**
48
- * GET /api/inbox/:id
49
- * Get a single inbox entry.
50
- */
51
- router.get('/inbox/:id', async (req, res) => {
52
- try {
53
- const entry = await getInboxEntry(req.params.id);
54
- if (!entry) {
55
- res.status(404).json({ error: 'Entry not found' });
56
- return;
57
- }
58
- res.json({ entry });
59
- } catch {
60
- res.status(500).json({ error: 'Failed to get inbox entry' });
61
- }
62
- });
63
-
64
- /**
65
- * POST /api/inbox/:id/read
66
- * Mark an entry as read.
67
- */
68
- router.post('/inbox/:id/read', async (req, res) => {
69
- try {
70
- await markInboxRead(req.params.id);
71
- res.json({ status: 'ok' });
72
- } catch {
73
- res.status(500).json({ error: 'Failed to mark entry as read' });
74
- }
75
- });
76
-
77
- /**
78
- * POST /api/inbox/:id/respond
79
- * Respond to an inbox question. Resolves any blocking squad.
80
- * Body: { response: string }
81
- */
82
- router.post('/inbox/:id/respond', async (req, res) => {
83
- try {
84
- const { response } = req.body as { response?: string };
85
- if (!response) {
86
- res.status(400).json({ error: 'response is required' });
87
- return;
88
- }
89
-
90
- const unblocked = await resolveInboxEntry(req.params.id, response);
91
- res.json({ status: 'ok', squadUnblocked: unblocked });
92
- } catch {
93
- res.status(500).json({ error: 'Failed to respond to entry' });
94
- }
95
- });
96
-
97
- return router;
98
- }
@@ -1,121 +0,0 @@
1
- import { Router } from 'express';
2
- import {
3
- type ScheduleTargetType,
4
- createSchedule,
5
- deleteSchedule,
6
- getSchedule,
7
- listSchedules,
8
- updateSchedule,
9
- } from '../../store/schedules.js';
10
-
11
- export function schedulesRouter(): Router {
12
- const router = Router();
13
-
14
- /**
15
- * GET /api/schedules
16
- * List all schedules. Query param: enabled=true to filter.
17
- */
18
- router.get('/schedules', async (req, res) => {
19
- try {
20
- const enabledOnly = req.query.enabled === 'true';
21
- const schedules = await listSchedules(enabledOnly || undefined);
22
- res.json({ schedules });
23
- } catch {
24
- res.status(500).json({ error: 'Failed to list schedules' });
25
- }
26
- });
27
-
28
- /**
29
- * GET /api/schedules/:id
30
- * Get a single schedule.
31
- */
32
- router.get('/schedules/:id', async (req, res) => {
33
- try {
34
- const schedule = await getSchedule(req.params.id);
35
- if (!schedule) {
36
- res.status(404).json({ error: 'Schedule not found' });
37
- return;
38
- }
39
- res.json({ schedule });
40
- } catch {
41
- res.status(500).json({ error: 'Failed to get schedule' });
42
- }
43
- });
44
-
45
- /**
46
- * POST /api/schedules
47
- * Create a new schedule.
48
- * Body: { name, targetType, targetId?, cron, prompt, enabled? }
49
- */
50
- router.post('/schedules', async (req, res) => {
51
- try {
52
- const { name, targetType, targetId, cron, prompt, enabled } = req.body as {
53
- name?: string;
54
- targetType?: ScheduleTargetType;
55
- targetId?: string;
56
- cron?: string;
57
- prompt?: string;
58
- enabled?: boolean;
59
- };
60
-
61
- if (!name || !targetType || !cron || !prompt) {
62
- res.status(400).json({ error: 'name, targetType, cron, and prompt are required' });
63
- return;
64
- }
65
-
66
- if (targetType !== 'squad' && targetType !== 'orchestrator') {
67
- res.status(400).json({ error: 'targetType must be "squad" or "orchestrator"' });
68
- return;
69
- }
70
-
71
- const schedule = await createSchedule({ name, targetType, targetId, cron, prompt, enabled });
72
- res.status(201).json({ schedule });
73
- } catch (err) {
74
- const msg = err instanceof Error ? err.message : 'Failed to create schedule';
75
- res.status(400).json({ error: msg });
76
- }
77
- });
78
-
79
- /**
80
- * PATCH /api/schedules/:id
81
- * Update a schedule (partial). Body: { name?, cron?, prompt?, enabled? }
82
- */
83
- router.patch('/schedules/:id', async (req, res) => {
84
- try {
85
- const existing = await getSchedule(req.params.id);
86
- if (!existing) {
87
- res.status(404).json({ error: 'Schedule not found' });
88
- return;
89
- }
90
-
91
- const { name, cron, prompt, enabled } = req.body as {
92
- name?: string;
93
- cron?: string;
94
- prompt?: string;
95
- enabled?: boolean;
96
- };
97
-
98
- await updateSchedule(req.params.id, { name, cron, prompt, enabled });
99
- const updated = await getSchedule(req.params.id);
100
- res.json({ schedule: updated });
101
- } catch (err) {
102
- const msg = err instanceof Error ? err.message : 'Failed to update schedule';
103
- res.status(400).json({ error: msg });
104
- }
105
- });
106
-
107
- /**
108
- * DELETE /api/schedules/:id
109
- * Delete a schedule.
110
- */
111
- router.delete('/schedules/:id', async (req, res) => {
112
- try {
113
- await deleteSchedule(req.params.id);
114
- res.json({ status: 'ok' });
115
- } catch {
116
- res.status(500).json({ error: 'Failed to delete schedule' });
117
- }
118
- });
119
-
120
- return router;
121
- }
@@ -1,105 +0,0 @@
1
- import { Router } from 'express';
2
- import {
3
- activateSkill,
4
- deactivateSkill,
5
- getActiveSkills,
6
- getSkill,
7
- installSkill,
8
- installSkillFromUrl,
9
- listInstalledSkills,
10
- removeSkill,
11
- } from '../../skills/index.js';
12
-
13
- export const skillsRouter = Router();
14
-
15
- // List installed skills
16
- skillsRouter.get('/skills', async (_req, res) => {
17
- const skills = listInstalledSkills();
18
- const orchestratorActivations = await getActiveSkills('orchestrator');
19
-
20
- const result = skills.map((s) => ({
21
- name: s.name,
22
- activatedForOrchestrator: orchestratorActivations.some((a) => a.skillName === s.name),
23
- preview: s.content.slice(0, 200),
24
- }));
25
-
26
- res.json({ skills: result });
27
- });
28
-
29
- // Get a specific skill
30
- skillsRouter.get('/skills/:name', (req, res) => {
31
- const skill = getSkill(req.params.name);
32
- if (!skill) {
33
- res.status(404).json({ error: `Skill '${req.params.name}' not found` });
34
- return;
35
- }
36
- res.json(skill);
37
- });
38
-
39
- // Install a skill (from URL or content)
40
- skillsRouter.post('/skills/install', async (req, res) => {
41
- const { name, url, content } = req.body;
42
-
43
- if (!name) {
44
- res.status(400).json({ error: 'name is required' });
45
- return;
46
- }
47
-
48
- try {
49
- if (url) {
50
- const skill = await installSkillFromUrl(name, url);
51
- res.status(201).json({ installed: true, name: skill.name });
52
- } else if (content) {
53
- const skill = installSkill(name, content);
54
- res.status(201).json({ installed: true, name: skill.name });
55
- } else {
56
- res.status(400).json({ error: 'Either "url" or "content" is required' });
57
- }
58
- } catch (err) {
59
- res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
60
- }
61
- });
62
-
63
- // Activate a skill
64
- skillsRouter.post('/skills/:name/activate', async (req, res) => {
65
- const { targetType, targetId } = req.body;
66
- if (!targetType || !['orchestrator', 'squad'].includes(targetType)) {
67
- res.status(400).json({ error: 'targetType must be "orchestrator" or "squad"' });
68
- return;
69
- }
70
-
71
- const skill = getSkill(req.params.name);
72
- if (!skill) {
73
- res.status(404).json({ error: `Skill '${req.params.name}' not found` });
74
- return;
75
- }
76
-
77
- await activateSkill(req.params.name, targetType, targetId);
78
- res.json({ activated: true, skillName: req.params.name, targetType, targetId });
79
- });
80
-
81
- // Deactivate a skill
82
- skillsRouter.post('/skills/:name/deactivate', async (req, res) => {
83
- const { targetType, targetId } = req.body;
84
- if (!targetType || !['orchestrator', 'squad'].includes(targetType)) {
85
- res.status(400).json({ error: 'targetType must be "orchestrator" or "squad"' });
86
- return;
87
- }
88
-
89
- await deactivateSkill(req.params.name, targetType, targetId);
90
- res.json({ deactivated: true, skillName: req.params.name });
91
- });
92
-
93
- // Remove a skill
94
- skillsRouter.delete('/skills/:name', (req, res) => {
95
- removeSkill(req.params.name);
96
- res.status(204).end();
97
- });
98
-
99
- // Get activations for a target
100
- skillsRouter.get('/skills-activations', async (req, res) => {
101
- const targetType = (req.query.targetType as string) ?? 'orchestrator';
102
- const targetId = req.query.targetId as string | undefined;
103
- const activations = await getActiveSkills(targetType as 'orchestrator' | 'squad', targetId);
104
- res.json({ activations });
105
- });
@@ -1,145 +0,0 @@
1
- import { Router } from 'express';
2
- import { getSquadInstances } from '../../squad/execution/instance.js';
3
- import { runInstance } from '../../squad/execution/runner.js';
4
- import { getSquadByName, getSquadMembers, listSquads } from '../../squad/manager.js';
5
-
6
- export function squadsRouter(): Router {
7
- const router = Router();
8
-
9
- /**
10
- * GET /api/squads
11
- * List all active squads.
12
- */
13
- router.get('/squads', async (_req, res) => {
14
- try {
15
- const squads = await listSquads();
16
- const results = await Promise.all(
17
- squads.map(async (s) => {
18
- const members = await getSquadMembers(s.id);
19
- const instances = getSquadInstances(s.id);
20
- return {
21
- id: s.id,
22
- name: s.name,
23
- projectPath: s.projectPath,
24
- repoUrl: s.repoUrl,
25
- universe: s.universe,
26
- autonomyTier: s.autonomyTier,
27
- status: s.status,
28
- memberCount: members.length,
29
- activeInstances: instances.filter(
30
- (i) => i.status !== 'complete' && i.status !== 'failed',
31
- ).length,
32
- createdAt: s.createdAt.toISOString(),
33
- };
34
- }),
35
- );
36
- res.json({ squads: results });
37
- } catch (err) {
38
- res.status(500).json({ error: 'Failed to list squads' });
39
- }
40
- });
41
-
42
- /**
43
- * GET /api/squads/:name
44
- * Get detailed squad info.
45
- */
46
- router.get('/squads/:name', async (req, res) => {
47
- try {
48
- const squad = await getSquadByName(req.params.name);
49
- if (!squad) {
50
- res.status(404).json({ error: `Squad '${req.params.name}' not found` });
51
- return;
52
- }
53
-
54
- const members = await getSquadMembers(squad.id);
55
- const instances = getSquadInstances(squad.id);
56
-
57
- // Build a map of role -> current task (from active instances)
58
- const currentTasks = new Map<string, string>();
59
- for (const inst of instances) {
60
- if (inst.status !== 'complete' && inst.status !== 'failed') {
61
- for (const task of inst.tasks) {
62
- if (task.status === 'in_progress') {
63
- currentTasks.set(task.assignedTo, task.description);
64
- }
65
- }
66
- }
67
- }
68
-
69
- res.json({
70
- squad: {
71
- id: squad.id,
72
- name: squad.name,
73
- projectPath: squad.projectPath,
74
- repoUrl: squad.repoUrl,
75
- universe: squad.universe,
76
- autonomyTier: squad.autonomyTier,
77
- autonomyConfig: squad.autonomyConfig,
78
- status: squad.status,
79
- createdAt: squad.createdAt.toISOString(),
80
- },
81
- members: members.map((m) => ({
82
- id: m.id,
83
- displayName: m.displayName,
84
- role: m.roleName,
85
- persona: m.persona,
86
- veto: m.isVetoMember,
87
- tools: m.toolsAllowed,
88
- status: m.status,
89
- currentTask: currentTasks.get(m.roleName) ?? null,
90
- })),
91
- instances: instances.map((i) => ({
92
- id: i.id,
93
- status: i.status,
94
- issueRef: i.issueRef,
95
- branch: i.branch,
96
- taskCount: i.tasks.length,
97
- tasksComplete: i.tasks.filter((t) => t.status === 'done').length,
98
- })),
99
- });
100
- } catch (err) {
101
- res.status(500).json({ error: 'Failed to get squad' });
102
- }
103
- });
104
-
105
- /**
106
- * POST /api/squads/:name/run
107
- * Spawn a new instance for a squad.
108
- * Body: { objective: string, issueRef?: string }
109
- */
110
- router.post('/squads/:name/run', async (req, res) => {
111
- try {
112
- const squad = await getSquadByName(req.params.name);
113
- if (!squad) {
114
- res.status(404).json({ error: `Squad '${req.params.name}' not found` });
115
- return;
116
- }
117
-
118
- const { objective, issueRef } = req.body as {
119
- objective?: string;
120
- issueRef?: string;
121
- };
122
-
123
- if (!objective) {
124
- res.status(400).json({ error: 'objective is required' });
125
- return;
126
- }
127
-
128
- // Run asynchronously — return immediately with instance ID
129
- const instancePromise = runInstance({ squad, objective, issueRef });
130
-
131
- // We don't await — return accepted status
132
- // The client can poll /api/squads/:name for progress
133
- instancePromise.catch(() => {}); // prevent unhandled rejection
134
-
135
- res.status(202).json({
136
- message: `Instance starting for squad '${squad.name}'`,
137
- objective,
138
- });
139
- } catch (err) {
140
- res.status(500).json({ error: 'Failed to start instance' });
141
- }
142
- });
143
-
144
- return router;
145
- }
@@ -1,57 +0,0 @@
1
- import { Router } from 'express';
2
- import { getAllPricing, queryUsage, refreshPricing } from '../../models/index.js';
3
-
4
- export function usageRouter(): Router {
5
- const router = Router();
6
-
7
- /**
8
- * GET /api/usage
9
- * Query token usage with optional filters.
10
- * Query params: squadId, agentRole, model, since, until
11
- */
12
- router.get('/usage', async (req, res) => {
13
- try {
14
- const filters = {
15
- squadId: req.query.squadId as string | undefined,
16
- agentRole: req.query.agentRole as string | undefined,
17
- model: req.query.model as string | undefined,
18
- since: req.query.since as string | undefined,
19
- until: req.query.until as string | undefined,
20
- };
21
-
22
- const result = await queryUsage(filters);
23
- res.json(result);
24
- } catch (err) {
25
- res.status(500).json({ error: 'Failed to query usage' });
26
- }
27
- });
28
-
29
- /**
30
- * GET /api/usage/pricing
31
- * Get current model pricing.
32
- */
33
- router.get('/usage/pricing', async (_req, res) => {
34
- try {
35
- const pricing = await getAllPricing();
36
- res.json({ pricing });
37
- } catch (err) {
38
- res.status(500).json({ error: 'Failed to get pricing' });
39
- }
40
- });
41
-
42
- /**
43
- * POST /api/usage/pricing/refresh
44
- * Trigger a pricing refresh.
45
- */
46
- router.post('/usage/pricing/refresh', async (_req, res) => {
47
- try {
48
- await refreshPricing();
49
- const pricing = await getAllPricing();
50
- res.json({ message: 'Pricing refreshed', pricing });
51
- } catch (err) {
52
- res.status(500).json({ error: 'Failed to refresh pricing' });
53
- }
54
- });
55
-
56
- return router;
57
- }
@@ -1,49 +0,0 @@
1
- import { Router } from 'express';
2
- import { listWikiPages, readWikiPage, searchWiki, writeWikiPage } from '../../wiki/index.js';
3
-
4
- export const wikiRouter = Router();
5
-
6
- // List pages in a scope
7
- wikiRouter.get('/:scope', (req, res) => {
8
- const { scope } = req.params;
9
- const pages = listWikiPages(scope);
10
- res.json({ scope, pages });
11
- });
12
-
13
- // Read a specific page
14
- wikiRouter.get('/:scope/:page', (req, res) => {
15
- const { scope, page } = req.params;
16
- const result = readWikiPage(scope, page);
17
- if (!result) {
18
- res.status(404).json({ error: `Page '${page}' not found in '${scope}' wiki` });
19
- return;
20
- }
21
- res.json(result);
22
- });
23
-
24
- // Write (create/overwrite) a page
25
- wikiRouter.put('/:scope/:page', (req, res) => {
26
- const { scope, page } = req.params;
27
- const { content } = req.body;
28
- if (!content || typeof content !== 'string') {
29
- res.status(400).json({ error: 'Body must include "content" (string)' });
30
- return;
31
- }
32
- const result = writeWikiPage(scope, page, content);
33
- res.json(result);
34
- });
35
-
36
- // Search across scopes
37
- wikiRouter.get('/', (req, res) => {
38
- const keyword = req.query.q as string;
39
- const scopesParam = req.query.scopes as string | undefined;
40
-
41
- if (!keyword) {
42
- res.status(400).json({ error: 'Query parameter "q" is required' });
43
- return;
44
- }
45
-
46
- const scopes = scopesParam ? scopesParam.split(',') : ['io', 'shared'];
47
- const results = searchWiki(keyword, scopes);
48
- res.json({ keyword, results });
49
- });