heyhank 0.1.0 → 0.2.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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -10
  3. package/bin/cli.ts +7 -7
  4. package/bin/ctl.ts +42 -42
  5. package/dist/assets/{AgentsPage-BPhirnCe.js → AgentsPage-B-AAmsMK.js} +3 -3
  6. package/dist/assets/AssistantPage-BV1Mfwdt.js +2 -0
  7. package/dist/assets/BusinessPage-tLpNEz19.js +1 -0
  8. package/dist/assets/{CronManager-DDbz-yiT.js → CronManager-B-K_n3Jg.js} +1 -1
  9. package/dist/assets/HelpPage-Bhf_j6Xr.js +1 -0
  10. package/dist/assets/{IntegrationsPage-CrOitCmJ.js → IntegrationsPage-DAMjs9tM.js} +1 -1
  11. package/dist/assets/JarvisHUD-C_TGXCCn.js +120 -0
  12. package/dist/assets/MediaPage-C48HTTrt.js +1 -0
  13. package/dist/assets/MemoryPage-JkC-qtgp.js +1 -0
  14. package/dist/assets/{PlatformDashboard-Do6F0O2p.js → PlatformDashboard-AUo7tNnE.js} +1 -1
  15. package/dist/assets/{Playground-Fc5cdc5p.js → Playground-AzNMsRBL.js} +1 -1
  16. package/dist/assets/{ProcessPanel-CslEiZkI.js → ProcessPanel-DpE_2sX3.js} +1 -1
  17. package/dist/assets/{PromptsPage-D2EhsdNO.js → PromptsPage-C2RQOs6p.js} +2 -2
  18. package/dist/assets/RunsPage-B9UOyO79.js +1 -0
  19. package/dist/assets/{SandboxManager-a1AVI5q2.js → SandboxManager-jHvYjwfh.js} +1 -1
  20. package/dist/assets/SettingsPage-BBJax6gt.js +51 -0
  21. package/dist/assets/SkillsMarketplace-IjmjfdjD.js +1 -0
  22. package/dist/assets/SocialMediaPage-DoPZHhr2.js +10 -0
  23. package/dist/assets/{TailscalePage-CHiFhZXF.js → TailscalePage-DDEY7ckO.js} +1 -1
  24. package/dist/assets/TelephonyPage-OPNBZYKt.js +9 -0
  25. package/dist/assets/{TerminalPage-Drwyrnfd.js → TerminalPage-BjMbHHW3.js} +1 -1
  26. package/dist/assets/{gemini-live-client-C7rqAW7G.js → gemini-live-client-C70FEtX2.js} +11 -8
  27. package/dist/assets/{index-CEqZnThB.js → index-BgYM4wXw.js} +94 -93
  28. package/dist/assets/index-BkjSoVgn.css +32 -0
  29. package/dist/assets/sw-register-C7NOHtIu.js +1 -0
  30. package/dist/assets/text-chat-client-BSbLJerZ.js +2 -0
  31. package/dist/index.html +2 -2
  32. package/dist/sw.js +1 -1
  33. package/package.json +6 -1
  34. package/server/agent-executor.ts +37 -2
  35. package/server/agent-store.ts +3 -3
  36. package/server/agent-types.ts +11 -0
  37. package/server/assistant-store.ts +232 -6
  38. package/server/auth-manager.ts +9 -0
  39. package/server/cache-headers.ts +1 -1
  40. package/server/calendar-service.ts +10 -0
  41. package/server/ceo/document-store.ts +129 -0
  42. package/server/ceo/finance-store.ts +343 -0
  43. package/server/ceo/kpi-store.ts +208 -0
  44. package/server/ceo/memory-import.ts +277 -0
  45. package/server/ceo/news-store.ts +208 -0
  46. package/server/ceo/template-store.ts +134 -0
  47. package/server/ceo/time-tracking-store.ts +227 -0
  48. package/server/claude-auth-monitor.ts +128 -0
  49. package/server/claude-code-worker.ts +86 -0
  50. package/server/claude-session-discovery.ts +74 -1
  51. package/server/cli-launcher.ts +32 -10
  52. package/server/codex-adapter.ts +2 -2
  53. package/server/codex-ws-proxy.cjs +1 -1
  54. package/server/container-manager.ts +4 -4
  55. package/server/content-intelligence/content-engine.ts +1112 -0
  56. package/server/content-intelligence/platform-knowledge.ts +870 -0
  57. package/server/cron-store.ts +3 -3
  58. package/server/embedding-service.ts +49 -0
  59. package/server/event-bus-types.ts +13 -0
  60. package/server/federation/node-store.ts +5 -4
  61. package/server/fs-utils.ts +28 -1
  62. package/server/hank-notifications-store.ts +91 -0
  63. package/server/hank-tool-executor.ts +1835 -0
  64. package/server/hank-tools.ts +2107 -0
  65. package/server/image-pull-manager.ts +2 -2
  66. package/server/index.ts +25 -2
  67. package/server/llm-providers-streaming.ts +541 -0
  68. package/server/llm-providers.ts +12 -0
  69. package/server/marketplace.ts +249 -0
  70. package/server/mcp-registry.ts +158 -0
  71. package/server/memory-service.ts +296 -0
  72. package/server/obsidian-sync.ts +184 -0
  73. package/server/provider-manager.ts +5 -2
  74. package/server/provider-registry.ts +12 -0
  75. package/server/reminder-scheduler.ts +37 -1
  76. package/server/routes/agent-routes.ts +2 -1
  77. package/server/routes/assistant-routes.ts +198 -5
  78. package/server/routes/ceo-finance-kpi-routes.ts +167 -0
  79. package/server/routes/ceo-news-time-routes.ts +137 -0
  80. package/server/routes/ceo-routes.ts +99 -0
  81. package/server/routes/content-routes.ts +116 -0
  82. package/server/routes/email-routes.ts +147 -0
  83. package/server/routes/env-routes.ts +3 -3
  84. package/server/routes/fs-routes.ts +12 -9
  85. package/server/routes/hank-chat-routes.ts +592 -0
  86. package/server/routes/llm-routes.ts +12 -0
  87. package/server/routes/marketplace-routes.ts +63 -0
  88. package/server/routes/media-routes.ts +1 -1
  89. package/server/routes/memory-routes.ts +127 -0
  90. package/server/routes/platform-routes.ts +14 -675
  91. package/server/routes/sandbox-routes.ts +1 -1
  92. package/server/routes/settings-routes.ts +51 -1
  93. package/server/routes/socialmedia-routes.ts +152 -2
  94. package/server/routes/system-routes.ts +2 -2
  95. package/server/routes/team-routes.ts +71 -0
  96. package/server/routes/telephony-routes.ts +98 -18
  97. package/server/routes.ts +36 -9
  98. package/server/session-creation-service.ts +2 -2
  99. package/server/session-orchestrator.ts +54 -2
  100. package/server/session-types.ts +2 -0
  101. package/server/settings-manager.ts +50 -2
  102. package/server/skill-discovery.ts +68 -0
  103. package/server/socialmedia/adapters/browser-adapter.ts +179 -0
  104. package/server/socialmedia/adapters/postiz-adapter.ts +291 -14
  105. package/server/socialmedia/manager.ts +234 -15
  106. package/server/socialmedia/store.ts +51 -1
  107. package/server/socialmedia/types.ts +35 -2
  108. package/server/socialview/browser-manager.ts +150 -0
  109. package/server/socialview/extractors.ts +1298 -0
  110. package/server/socialview/image-describe.ts +188 -0
  111. package/server/socialview/library.ts +119 -0
  112. package/server/socialview/poster.ts +276 -0
  113. package/server/socialview/routes.ts +371 -0
  114. package/server/socialview/style-analyzer.ts +187 -0
  115. package/server/socialview/style-profiles.ts +67 -0
  116. package/server/socialview/types.ts +166 -0
  117. package/server/socialview/vision.ts +127 -0
  118. package/server/socialview/vnc-manager.ts +110 -0
  119. package/server/style-injector.ts +135 -0
  120. package/server/team-service.ts +239 -0
  121. package/server/team-store.ts +75 -0
  122. package/server/team-types.ts +52 -0
  123. package/server/telephony/audio-bridge.ts +281 -35
  124. package/server/telephony/audio-recorder.ts +132 -0
  125. package/server/telephony/call-manager.ts +803 -104
  126. package/server/telephony/call-types.ts +67 -1
  127. package/server/telephony/esl-client.ts +319 -0
  128. package/server/telephony/freeswitch-sync.ts +155 -0
  129. package/server/telephony/phone-utils.ts +63 -0
  130. package/server/telephony/telephony-store.ts +9 -8
  131. package/server/url-validator.ts +82 -0
  132. package/server/vault-markdown.ts +317 -0
  133. package/server/vault-migration.ts +121 -0
  134. package/server/vault-store.ts +466 -0
  135. package/server/vault-watcher.ts +59 -0
  136. package/server/vector-store.ts +210 -0
  137. package/server/voice-pipeline/gemini-live-adapter.ts +97 -0
  138. package/server/voice-pipeline/greeting-cache.ts +200 -0
  139. package/server/voice-pipeline/manager.ts +249 -0
  140. package/server/voice-pipeline/pipeline.ts +335 -0
  141. package/server/voice-pipeline/providers/index.ts +47 -0
  142. package/server/voice-pipeline/providers/llm-internal.ts +527 -0
  143. package/server/voice-pipeline/providers/stt-google.ts +157 -0
  144. package/server/voice-pipeline/providers/tts-google.ts +126 -0
  145. package/server/voice-pipeline/types.ts +247 -0
  146. package/server/ws-bridge-types.ts +6 -1
  147. package/dist/assets/AssistantPage-DJ-cMQfb.js +0 -1
  148. package/dist/assets/HelpPage-DMfkzERp.js +0 -1
  149. package/dist/assets/MediaPage-CE5rdvkC.js +0 -1
  150. package/dist/assets/RunsPage-C5BZF5Rx.js +0 -1
  151. package/dist/assets/SettingsPage-DirhjQrJ.js +0 -51
  152. package/dist/assets/SocialMediaPage-DBuM28vD.js +0 -1
  153. package/dist/assets/TelephonyPage-x0VV0fOo.js +0 -1
  154. package/dist/assets/index-C8M_PUmX.css +0 -32
  155. package/dist/assets/sw-register-LSSpj6RU.js +0 -1
  156. package/server/socialmedia/adapters/ayrshare-adapter.ts +0 -169
@@ -0,0 +1,239 @@
1
+ import { randomUUID } from "crypto";
2
+ import * as teamStore from "./team-store.js";
3
+ import * as agentStore from "./agent-store.js";
4
+ import type { Team, TeamStatus, TeamState } from "./team-types.js";
5
+
6
+ const COORDINATOR_SYSTEM_PROMPT = `You are the Team Coordinator for HeyHank. You coordinate parallel agent teams to accomplish complex goals.
7
+
8
+ ## Your Goal
9
+ {{goal}}
10
+
11
+ ## Team Info
12
+ - Team ID: {{teamId}}
13
+ - Repo: {{repoRoot}}
14
+ - Base branch: {{baseBranch}}
15
+ - Team branch: {{teamBranch}}
16
+ - Suggested agents: {{suggestedAgents}}
17
+
18
+ ## Available Agents
19
+ {{availableAgents}}
20
+
21
+ ## API Reference
22
+ Base URL: {{apiBase}}
23
+ All requests need: Authorization: Bearer {{authToken}}
24
+
25
+ ### List agents
26
+ curl -s -H "Authorization: Bearer {{authToken}}" {{apiBase}}/api/agents | jq '.[] | {id, name, description}'
27
+
28
+ ### Create a new agent
29
+ curl -s -X POST -H "Authorization: Bearer {{authToken}}" -H "Content-Type: application/json" {{apiBase}}/api/agents -d '{
30
+ "name": "Agent Name",
31
+ "description": "What this agent does",
32
+ "backendType": "claude",
33
+ "model": "claude-sonnet-4-20250514",
34
+ "prompt": "Your system prompt here",
35
+ "cwd": "/path/to/worktree",
36
+ "permissionMode": "bypassPermissions"
37
+ }'
38
+
39
+ ### Run an agent (start a task)
40
+ curl -s -X POST -H "Authorization: Bearer {{authToken}}" -H "Content-Type: application/json" {{apiBase}}/api/agents/{agentId}/run -d '{
41
+ "input": "The task description",
42
+ "cwd": "/path/to/worktree"
43
+ }'
44
+ Response: { "sessionId": "..." }
45
+
46
+ ### Monitor an agent session
47
+ curl -s -H "Authorization: Bearer {{authToken}}" {{apiBase}}/api/sessions/{sessionId}/agent-status
48
+ Response: { "isCompleted": bool, "isWorking": bool, "needsInput": bool, "recentActivity": [...] }
49
+
50
+ ### Update team task status
51
+ curl -s -X PUT -H "Authorization: Bearer {{authToken}}" -H "Content-Type: application/json" {{apiBase}}/api/teams/{{teamId}}/tasks/{taskId} -d '{
52
+ "state": "running|completed|failed",
53
+ "sessionId": "...",
54
+ "agentId": "...",
55
+ "agentName": "..."
56
+ }'
57
+
58
+ ### Complete team
59
+ curl -s -X POST -H "Authorization: Bearer {{authToken}}" -H "Content-Type: application/json" {{apiBase}}/api/teams/{{teamId}}/complete -d '{
60
+ "result": "Summary of what was accomplished"
61
+ }'
62
+
63
+ ### Fail team
64
+ curl -s -X POST -H "Authorization: Bearer {{authToken}}" -H "Content-Type: application/json" {{apiBase}}/api/teams/{{teamId}}/fail -d '{
65
+ "error": "What went wrong"
66
+ }'
67
+
68
+ ## Your Workflow
69
+
70
+ ### Step 1: PLAN
71
+ Analyze the goal. Break it into independent, parallelizable tasks. Consider:
72
+ - What needs to be done?
73
+ - Which tasks can run in parallel vs which have dependencies?
74
+ - Which existing agent fits each task? If none fits, create a new specialized agent.
75
+
76
+ ### Step 2: PREPARE
77
+ For each task, create a git worktree for isolation:
78
+ \`\`\`bash
79
+ cd {{repoRoot}}
80
+ git worktree add -b task-{taskId} .worktrees/task-{taskId} {{baseBranch}}
81
+ \`\`\`
82
+
83
+ ### Step 3: ASSIGN & START
84
+ For each task:
85
+ 1. Choose or create an agent
86
+ 2. Start the agent with cwd set to the worktree path
87
+ 3. Update the task status via the API
88
+ 4. Record the sessionId
89
+
90
+ ### Step 4: MONITOR
91
+ Poll each running session every 10 seconds:
92
+ \`\`\`bash
93
+ curl -s -H "Authorization: Bearer {{authToken}}" {{apiBase}}/api/sessions/{sessionId}/agent-status
94
+ \`\`\`
95
+ - If \`needsInput\` is true: check what the agent needs, provide it via send_message
96
+ - If \`isCompleted\` is true: mark task as completed
97
+ - If there's an error: mark task as failed
98
+
99
+ ### Step 5: MERGE
100
+ When all tasks are completed:
101
+ \`\`\`bash
102
+ cd {{repoRoot}}
103
+ git checkout {{baseBranch}}
104
+ git checkout -b {{teamBranch}}
105
+ # Merge each task branch
106
+ git merge --no-ff task-{taskId1} -m "Merge task: {description}"
107
+ git merge --no-ff task-{taskId2} -m "Merge task: {description}"
108
+ # If merge conflict: attempt to resolve, or report in team failure
109
+ \`\`\`
110
+
111
+ ### Step 6: CLEANUP & REPORT
112
+ \`\`\`bash
113
+ # Remove worktrees
114
+ git worktree remove .worktrees/task-{taskId1}
115
+ git worktree remove .worktrees/task-{taskId2}
116
+ # Delete task branches
117
+ git branch -d task-{taskId1}
118
+ git branch -d task-{taskId2}
119
+ \`\`\`
120
+ Then call the complete endpoint with a summary of what was accomplished.
121
+
122
+ ## Important Rules
123
+ - Always use worktrees for isolation — never let two agents edit the same working directory
124
+ - Create new agents when no existing agent fits a task — don't force a mismatch
125
+ - Monitor agents actively — check every 10 seconds
126
+ - If an agent fails, try to recover (restart or reassign) before failing the team
127
+ - Keep the team status updated via the API so Hank can monitor progress
128
+ - After merging, verify the result compiles/builds if applicable
129
+ `;
130
+
131
+ export function createTeam(opts: {
132
+ goal: string;
133
+ repoRoot: string;
134
+ baseBranch?: string;
135
+ suggestedAgents?: string[];
136
+ }): Team {
137
+ const teamId = `team-${Date.now()}-${randomUUID().slice(0, 8)}`;
138
+ const team: Team = {
139
+ id: teamId,
140
+ goal: opts.goal,
141
+ state: "pending",
142
+ coordinatorSessionId: null,
143
+ tasks: [],
144
+ suggestedAgents: opts.suggestedAgents || [],
145
+ repoRoot: opts.repoRoot,
146
+ baseBranch: opts.baseBranch || "main",
147
+ teamBranch: `team/${teamId}`,
148
+ createdAt: Date.now(),
149
+ updatedAt: Date.now(),
150
+ };
151
+ teamStore.createTeam(team);
152
+ return team;
153
+ }
154
+
155
+ export function getTeam(teamId: string): Team | null {
156
+ return teamStore.getTeam(teamId);
157
+ }
158
+
159
+ export function listTeams(): Team[] {
160
+ return teamStore.listTeams();
161
+ }
162
+
163
+ export function deleteTeam(teamId: string): boolean {
164
+ return teamStore.deleteTeam(teamId);
165
+ }
166
+
167
+ export function getTeamStatus(teamId: string): TeamStatus | null {
168
+ const team = teamStore.getTeam(teamId);
169
+ if (!team) return null;
170
+ return {
171
+ id: team.id,
172
+ goal: team.goal,
173
+ state: team.state,
174
+ tasksTotal: team.tasks.length,
175
+ tasksCompleted: team.tasks.filter((t) => t.state === "completed").length,
176
+ tasksFailed: team.tasks.filter((t) => t.state === "failed").length,
177
+ tasksRunning: team.tasks.filter((t) => t.state === "running").length,
178
+ tasks: team.tasks.map((t) => ({
179
+ id: t.id,
180
+ description: t.description,
181
+ agentName: t.agentName,
182
+ state: t.state,
183
+ })),
184
+ result: team.result,
185
+ error: team.error,
186
+ };
187
+ }
188
+
189
+ export function updateTeamState(teamId: string, state: TeamState, extra?: Partial<Team>): Team | null {
190
+ return teamStore.updateTeam(teamId, { state, updatedAt: Date.now(), ...extra });
191
+ }
192
+
193
+ export function updateTask(teamId: string, taskId: string, updates: Record<string, unknown>): Team | null {
194
+ const team = teamStore.getTeam(teamId);
195
+ if (!team) return null;
196
+ const task = team.tasks.find((t) => t.id === taskId);
197
+ if (!task) return null;
198
+ Object.assign(task, updates);
199
+ team.updatedAt = Date.now();
200
+ return teamStore.updateTeam(teamId, { tasks: team.tasks, updatedAt: team.updatedAt });
201
+ }
202
+
203
+ export function buildCoordinatorPrompt(team: Team, apiBase: string, authToken: string): string {
204
+ const agents = agentStore.listAgents().filter((a) => a.enabled);
205
+ const agentList = agents
206
+ .map((a) => `- "${a.name}" (${a.backendType}): ${a.description || "no description"}`)
207
+ .join("\n");
208
+
209
+ return COORDINATOR_SYSTEM_PROMPT
210
+ .replace(/\{\{teamId\}\}/g, team.id)
211
+ .replace(/\{\{goal\}\}/g, team.goal)
212
+ .replace(/\{\{repoRoot\}\}/g, team.repoRoot)
213
+ .replace(/\{\{baseBranch\}\}/g, team.baseBranch)
214
+ .replace(/\{\{teamBranch\}\}/g, team.teamBranch)
215
+ .replace(/\{\{apiBase\}\}/g, apiBase)
216
+ .replace(/\{\{authToken\}\}/g, authToken)
217
+ .replace(/\{\{availableAgents\}\}/g, agentList)
218
+ .replace(/\{\{suggestedAgents\}\}/g, team.suggestedAgents.join(", ") || "none");
219
+ }
220
+
221
+ export function ensureCoordinatorAgent(): string {
222
+ const agents = agentStore.listAgents();
223
+ const existing = agents.find((a) => a.name === "Team Coordinator");
224
+ if (existing) return existing.id;
225
+
226
+ const config = {
227
+ name: "Team Coordinator",
228
+ description: "Coordinates parallel agent teams. Breaks goals into tasks, creates worktrees, assigns agents, monitors progress, and merges results.",
229
+ backendType: "claude" as const,
230
+ model: "claude-sonnet-4-20250514",
231
+ permissionMode: "bypassPermissions",
232
+ prompt: "System prompt is injected at runtime via team-service.buildCoordinatorPrompt()",
233
+ enabled: true,
234
+ cwd: "",
235
+ version: 1 as const,
236
+ };
237
+ const agent = agentStore.createAgent(config);
238
+ return agent.id;
239
+ }
@@ -0,0 +1,75 @@
1
+ import {
2
+ mkdirSync,
3
+ readdirSync,
4
+ readFileSync,
5
+ unlinkSync,
6
+ existsSync,
7
+ } from "node:fs";
8
+ import { join } from "node:path";
9
+ import { HEYHANK_HOME } from "./paths.js";
10
+ import { atomicWriteFileSync } from "./fs-utils.js";
11
+ import type { Team } from "./team-types.js";
12
+
13
+ const TEAMS_DIR = join(HEYHANK_HOME, "teams");
14
+
15
+ function ensureDir(): void {
16
+ mkdirSync(TEAMS_DIR, { recursive: true });
17
+ }
18
+
19
+ function filePath(id: string): string {
20
+ return join(TEAMS_DIR, `${id}.json`);
21
+ }
22
+
23
+ export function createTeam(team: Team): void {
24
+ ensureDir();
25
+ atomicWriteFileSync(filePath(team.id), JSON.stringify(team, null, 2));
26
+ }
27
+
28
+ export function getTeam(teamId: string): Team | null {
29
+ ensureDir();
30
+ try {
31
+ const raw = readFileSync(filePath(teamId), "utf-8");
32
+ return JSON.parse(raw) as Team;
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ export function updateTeam(teamId: string, updates: Partial<Team>): Team | null {
39
+ const existing = getTeam(teamId);
40
+ if (!existing) return null;
41
+ const updated = { ...existing, ...updates };
42
+ atomicWriteFileSync(filePath(teamId), JSON.stringify(updated, null, 2));
43
+ return updated;
44
+ }
45
+
46
+ export function listTeams(): Team[] {
47
+ ensureDir();
48
+ try {
49
+ const files = readdirSync(TEAMS_DIR).filter((f) => f.endsWith(".json"));
50
+ const teams: Team[] = [];
51
+ for (const file of files) {
52
+ try {
53
+ const raw = readFileSync(join(TEAMS_DIR, file), "utf-8");
54
+ teams.push(JSON.parse(raw));
55
+ } catch {
56
+ // Skip corrupt files
57
+ }
58
+ }
59
+ teams.sort((a, b) => b.createdAt - a.createdAt);
60
+ return teams;
61
+ } catch {
62
+ return [];
63
+ }
64
+ }
65
+
66
+ export function deleteTeam(teamId: string): boolean {
67
+ ensureDir();
68
+ if (!existsSync(filePath(teamId))) return false;
69
+ try {
70
+ unlinkSync(filePath(teamId));
71
+ return true;
72
+ } catch {
73
+ return false;
74
+ }
75
+ }
@@ -0,0 +1,52 @@
1
+ export type TeamState = "pending" | "planning" | "running" | "merging" | "completed" | "failed";
2
+ export type TaskState = "pending" | "assigned" | "running" | "completed" | "failed";
3
+
4
+ export interface TeamTask {
5
+ id: string;
6
+ description: string;
7
+ agentId: string | null;
8
+ agentName: string | null;
9
+ sessionId: string | null;
10
+ branch: string;
11
+ worktreePath: string | null;
12
+ state: TaskState;
13
+ dependsOn: string[];
14
+ startedAt?: number;
15
+ completedAt?: number;
16
+ error?: string;
17
+ }
18
+
19
+ export interface Team {
20
+ id: string;
21
+ goal: string;
22
+ state: TeamState;
23
+ coordinatorSessionId: string | null;
24
+ tasks: TeamTask[];
25
+ suggestedAgents: string[];
26
+ repoRoot: string;
27
+ baseBranch: string;
28
+ teamBranch: string;
29
+ createdAt: number;
30
+ updatedAt: number;
31
+ completedAt?: number;
32
+ result?: string;
33
+ error?: string;
34
+ }
35
+
36
+ export interface TeamStatus {
37
+ id: string;
38
+ goal: string;
39
+ state: TeamState;
40
+ tasksTotal: number;
41
+ tasksCompleted: number;
42
+ tasksFailed: number;
43
+ tasksRunning: number;
44
+ tasks: Array<{
45
+ id: string;
46
+ description: string;
47
+ agentName: string | null;
48
+ state: TaskState;
49
+ }>;
50
+ result?: string;
51
+ error?: string;
52
+ }