@geteigen/cli 0.0.0-stage → 3.1.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 (172) hide show
  1. package/README.md +154 -2
  2. package/dist/agent.d.ts +32 -0
  3. package/dist/agent.js +246 -0
  4. package/dist/auth.d.ts +5 -0
  5. package/dist/auth.js +33 -0
  6. package/dist/cli/src/agent.d.ts +24 -0
  7. package/dist/cli/src/agent.js +263 -0
  8. package/dist/cli/src/agentTools.d.ts +6 -0
  9. package/dist/cli/src/agentTools.js +104 -0
  10. package/dist/cli/src/auth.d.ts +5 -0
  11. package/dist/cli/src/auth.js +33 -0
  12. package/dist/cli/src/cliEnv.d.ts +6 -0
  13. package/dist/cli/src/cliEnv.js +26 -0
  14. package/dist/cli/src/config.d.ts +11 -0
  15. package/dist/cli/src/config.js +51 -0
  16. package/dist/cli/src/cursorAuth.d.ts +10 -0
  17. package/dist/cli/src/cursorAuth.js +92 -0
  18. package/dist/cli/src/gitAuthEnv.d.ts +5 -0
  19. package/dist/cli/src/gitAuthEnv.js +35 -0
  20. package/dist/cli/src/index.d.ts +2 -0
  21. package/dist/cli/src/index.js +244 -0
  22. package/dist/cli/src/listModels.d.ts +14 -0
  23. package/dist/cli/src/listModels.js +196 -0
  24. package/dist/cli/src/listSessions.d.ts +9 -0
  25. package/dist/cli/src/listSessions.js +37 -0
  26. package/dist/cli/src/machineConfig.d.ts +20 -0
  27. package/dist/cli/src/machineConfig.js +66 -0
  28. package/dist/cli/src/pickFolder.d.ts +5 -0
  29. package/dist/cli/src/pickFolder.js +65 -0
  30. package/dist/cli/src/proc.d.ts +31 -0
  31. package/dist/cli/src/proc.js +97 -0
  32. package/dist/cli/src/service.d.ts +17 -0
  33. package/dist/cli/src/service.js +255 -0
  34. package/dist/cli/src/workRoots.d.ts +30 -0
  35. package/dist/cli/src/workRoots.js +228 -0
  36. package/dist/cli/src/worker.d.ts +8 -0
  37. package/dist/cli/src/worker.js +51 -0
  38. package/dist/cli/src/workerCore.d.ts +47 -0
  39. package/dist/cli/src/workerCore.js +721 -0
  40. package/dist/cli/src/workspace.d.ts +10 -0
  41. package/dist/cli/src/workspace.js +329 -0
  42. package/dist/config.d.ts +11 -0
  43. package/dist/config.js +51 -0
  44. package/dist/cursorAuth.d.ts +10 -0
  45. package/dist/cursorAuth.js +95 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +108 -0
  48. package/dist/listModels.d.ts +6 -0
  49. package/dist/listModels.js +62 -0
  50. package/dist/listSessions.d.ts +9 -0
  51. package/dist/listSessions.js +37 -0
  52. package/dist/pickFolder.d.ts +5 -0
  53. package/dist/pickFolder.js +65 -0
  54. package/dist/shared/actionDrafts.d.ts +83 -0
  55. package/dist/shared/actionDrafts.js +169 -0
  56. package/dist/shared/agentArtifacts.d.ts +49 -0
  57. package/dist/shared/agentArtifacts.js +169 -0
  58. package/dist/shared/agentLabel.d.ts +18 -0
  59. package/dist/shared/agentLabel.js +22 -0
  60. package/dist/shared/agentMentions.d.ts +38 -0
  61. package/dist/shared/agentMentions.js +110 -0
  62. package/dist/shared/agentRepos.d.ts +28 -0
  63. package/dist/shared/agentRepos.js +60 -0
  64. package/dist/shared/agentRunStatus.d.ts +12 -0
  65. package/dist/shared/agentRunStatus.js +17 -0
  66. package/dist/shared/agentUsage.d.ts +24 -0
  67. package/dist/shared/agentUsage.js +139 -0
  68. package/dist/shared/approvals.d.ts +44 -0
  69. package/dist/shared/approvals.js +97 -0
  70. package/dist/shared/askEigen.d.ts +190 -0
  71. package/dist/shared/askEigen.js +76 -0
  72. package/dist/shared/attribution.d.ts +25 -0
  73. package/dist/shared/attribution.js +63 -0
  74. package/dist/shared/automations.d.ts +135 -0
  75. package/dist/shared/automations.js +553 -0
  76. package/dist/shared/backends/claudeCode.d.ts +44 -0
  77. package/dist/shared/backends/claudeCode.js +548 -0
  78. package/dist/shared/backends/codex.d.ts +15 -0
  79. package/dist/shared/backends/codex.js +287 -0
  80. package/dist/shared/backends/cursor.d.ts +111 -0
  81. package/dist/shared/backends/cursor.js +1216 -0
  82. package/dist/shared/backends/index.d.ts +18 -0
  83. package/dist/shared/backends/index.js +58 -0
  84. package/dist/shared/backends/opencode.d.ts +43 -0
  85. package/dist/shared/backends/opencode.js +415 -0
  86. package/dist/shared/backends/types.d.ts +171 -0
  87. package/dist/shared/backends/types.js +19 -0
  88. package/dist/shared/backends/usage.d.ts +8 -0
  89. package/dist/shared/backends/usage.js +71 -0
  90. package/dist/shared/billingPlans.d.ts +60 -0
  91. package/dist/shared/billingPlans.js +262 -0
  92. package/dist/shared/brain.d.ts +353 -0
  93. package/dist/shared/brain.js +487 -0
  94. package/dist/shared/clarifyingQuestions.d.ts +13 -0
  95. package/dist/shared/clarifyingQuestions.js +207 -0
  96. package/dist/shared/claudeModels.d.ts +10 -0
  97. package/dist/shared/claudeModels.js +52 -0
  98. package/dist/shared/cloudBackends.d.ts +21 -0
  99. package/dist/shared/cloudBackends.js +29 -0
  100. package/dist/shared/codexModels.d.ts +10 -0
  101. package/dist/shared/codexModels.js +28 -0
  102. package/dist/shared/contextWindows.d.ts +2 -0
  103. package/dist/shared/contextWindows.js +30 -0
  104. package/dist/shared/cursorMcpConfig.d.ts +14 -0
  105. package/dist/shared/cursorMcpConfig.js +43 -0
  106. package/dist/shared/cursorProjectMcp.d.ts +10 -0
  107. package/dist/shared/cursorProjectMcp.js +42 -0
  108. package/dist/shared/docs.d.ts +59 -0
  109. package/dist/shared/docs.js +87 -0
  110. package/dist/shared/events.d.ts +932 -0
  111. package/dist/shared/events.js +57 -0
  112. package/dist/shared/integrations.d.ts +266 -0
  113. package/dist/shared/integrations.js +449 -0
  114. package/dist/shared/issueTranscript.d.ts +64 -0
  115. package/dist/shared/issueTranscript.js +387 -0
  116. package/dist/shared/issues.d.ts +139 -0
  117. package/dist/shared/issues.js +217 -0
  118. package/dist/shared/machines.d.ts +119 -0
  119. package/dist/shared/machines.js +58 -0
  120. package/dist/shared/markdownMedia.d.ts +13 -0
  121. package/dist/shared/markdownMedia.js +41 -0
  122. package/dist/shared/notificationText.d.ts +6 -0
  123. package/dist/shared/notificationText.js +38 -0
  124. package/dist/shared/opencodeModels.d.ts +19 -0
  125. package/dist/shared/opencodeModels.js +62 -0
  126. package/dist/shared/opencodeSession.d.ts +7 -0
  127. package/dist/shared/opencodeSession.js +30 -0
  128. package/dist/shared/orchestration.d.ts +58 -0
  129. package/dist/shared/orchestration.js +12 -0
  130. package/dist/shared/orgs.d.ts +47 -0
  131. package/dist/shared/orgs.js +49 -0
  132. package/dist/shared/personalOrg.d.ts +5 -0
  133. package/dist/shared/personalOrg.js +12 -0
  134. package/dist/shared/plans.d.ts +3 -0
  135. package/dist/shared/plans.js +19 -0
  136. package/dist/shared/providerModels.d.ts +40 -0
  137. package/dist/shared/providerModels.js +503 -0
  138. package/dist/shared/roomAttention.d.ts +17 -0
  139. package/dist/shared/roomAttention.js +36 -0
  140. package/dist/shared/roomContext.d.ts +120 -0
  141. package/dist/shared/roomContext.js +133 -0
  142. package/dist/shared/roomPermissions.d.ts +56 -0
  143. package/dist/shared/roomPermissions.js +133 -0
  144. package/dist/shared/sessionSeats.d.ts +29 -0
  145. package/dist/shared/sessionSeats.js +57 -0
  146. package/dist/shared/slashCommands.d.ts +39 -0
  147. package/dist/shared/slashCommands.js +166 -0
  148. package/dist/shared/space.d.ts +33 -0
  149. package/dist/shared/space.js +54 -0
  150. package/dist/shared/spaceFeed.d.ts +78 -0
  151. package/dist/shared/spaceFeed.js +194 -0
  152. package/dist/shared/stringifyUnknown.d.ts +1 -0
  153. package/dist/shared/stringifyUnknown.js +1 -0
  154. package/dist/shared/swarm.d.ts +320 -0
  155. package/dist/shared/swarm.js +328 -0
  156. package/dist/shared/swarmVisual.d.ts +79 -0
  157. package/dist/shared/swarmVisual.js +212 -0
  158. package/dist/shared/terminalFilter.d.ts +13 -0
  159. package/dist/shared/terminalFilter.js +46 -0
  160. package/dist/shared/toolIntegration.d.ts +56 -0
  161. package/dist/shared/toolIntegration.js +180 -0
  162. package/dist/shared/typing.d.ts +9 -0
  163. package/dist/shared/typing.js +37 -0
  164. package/dist/shared/uploads.d.ts +31 -0
  165. package/dist/shared/uploads.js +65 -0
  166. package/dist/shared/voiceApprovals.d.ts +36 -0
  167. package/dist/shared/voiceApprovals.js +229 -0
  168. package/dist/shared/workspace.d.ts +49 -0
  169. package/dist/shared/workspace.js +53 -0
  170. package/dist/worker.d.ts +1 -0
  171. package/dist/worker.js +266 -0
  172. package/package.json +51 -4
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Space metadata carried on chat messages (`ChatMessage.space`).
3
+ *
4
+ * Stored as one JSON column so new Space features (reactions, pins, …) can
5
+ * add fields here without another schema migration. Keep this file free of
6
+ * runtime imports — the web bundler can't resolve "./x.js" between shared/
7
+ * files.
8
+ */
9
+ const ID_RE = /^[\w-]{1,64}$/;
10
+ function cleanId(value) {
11
+ return typeof value === "string" && ID_RE.test(value) ? value : undefined;
12
+ }
13
+ /** Validate untrusted client input; drops anything malformed. */
14
+ export function sanitizeSpaceMeta(input) {
15
+ if (!input || typeof input !== "object")
16
+ return undefined;
17
+ const raw = input;
18
+ const meta = {};
19
+ if (raw.origin === "space" || raw.origin === "agent")
20
+ meta.origin = raw.origin;
21
+ const threadId = cleanId(raw.threadId);
22
+ if (threadId)
23
+ meta.threadId = threadId;
24
+ if (raw.handoff && typeof raw.handoff === "object") {
25
+ const h = raw.handoff;
26
+ const agentId = cleanId(h.agentId);
27
+ const messageId = cleanId(h.messageId);
28
+ if (agentId && messageId)
29
+ meta.handoff = { agentId, messageId };
30
+ }
31
+ if (Array.isArray(raw.mentionUserIds)) {
32
+ const ids = raw.mentionUserIds
33
+ .map((id) => (typeof id === "string" && id.length <= 128 ? id : undefined))
34
+ .filter((id) => Boolean(id));
35
+ if (ids.length)
36
+ meta.mentionUserIds = [...new Set(ids)].slice(0, 25);
37
+ }
38
+ if (raw.offRecord === true)
39
+ meta.offRecord = true;
40
+ return Object.keys(meta).length ? meta : undefined;
41
+ }
42
+ export function parseSpaceMetaJson(raw) {
43
+ if (typeof raw !== "string" || !raw)
44
+ return undefined;
45
+ try {
46
+ return sanitizeSpaceMeta(JSON.parse(raw));
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ }
52
+ export function spaceMetaJson(meta) {
53
+ return meta && Object.keys(meta).length ? JSON.stringify(meta) : null;
54
+ }
@@ -0,0 +1,78 @@
1
+ import type { ChatAttachment, ChatMessage } from "./events.js";
2
+ import type { SpaceHandoffRef } from "./space.js";
3
+ /**
4
+ * The Space timeline: a Slack-style view across every agent in a room.
5
+ * Only people's messages and each agent's final reply per turn — no tool
6
+ * calls, and nothing from a turn that is still running. Thread replies are
7
+ * grouped under their root post.
8
+ */
9
+ export interface SpaceHumanEntry {
10
+ kind: "human";
11
+ key: string;
12
+ ts: number;
13
+ senderName: string;
14
+ senderColor?: string;
15
+ senderUserId?: string;
16
+ content: string;
17
+ /** Agents this message was sent to (one per @mention); empty = team chat. */
18
+ agentIds: string[];
19
+ attachments?: ChatAttachment[];
20
+ threadId?: string;
21
+ handoff?: SpaceHandoffRef;
22
+ mentionUserIds?: string[];
23
+ /** This post and its thread stay out of team memory. */
24
+ offRecord?: boolean;
25
+ }
26
+ /** What an agent's run changed — shown as a compact footer on its post. */
27
+ export interface SpaceRunStats {
28
+ /** Tool calls during the turn (hidden in the Space). */
29
+ steps: number;
30
+ filesChanged: number;
31
+ additions: number;
32
+ deletions: number;
33
+ /** Pull request links mentioned in the reply. */
34
+ prUrls: string[];
35
+ }
36
+ export interface SpaceAgentEntry {
37
+ kind: "agent";
38
+ key: string;
39
+ ts: number;
40
+ agentId: string;
41
+ content: string;
42
+ modelId?: string;
43
+ error: boolean;
44
+ stats: SpaceRunStats;
45
+ threadId?: string;
46
+ }
47
+ export type SpaceEntry = SpaceHumanEntry | SpaceAgentEntry;
48
+ export type SpaceReplier = {
49
+ kind: "human";
50
+ name: string;
51
+ userId?: string;
52
+ } | {
53
+ kind: "agent";
54
+ agentId: string;
55
+ };
56
+ export interface SpaceThreadSummary {
57
+ count: number;
58
+ lastTs: number;
59
+ /** Distinct repliers, most recent first. */
60
+ repliers: SpaceReplier[];
61
+ }
62
+ export interface SpaceTimeline {
63
+ /** Top-level posts (thread replies excluded). */
64
+ main: SpaceEntry[];
65
+ /** rootId → replies, oldest first. */
66
+ threads: Record<string, SpaceEntry[]>;
67
+ /** Running agents → thread their current turn belongs to (if any). */
68
+ activeThreadByAgent: Record<string, string | undefined>;
69
+ }
70
+ export declare function buildSpaceTimeline(messages: ChatMessage[], runningAgentIds: ReadonlySet<string>): SpaceTimeline;
71
+ export declare function summarizeThread(replies: SpaceEntry[] | undefined): SpaceThreadSummary | null;
72
+ /** Markdown → readable one-paragraph text for the collapsed preview. */
73
+ export declare function plainPreview(markdown: string): string;
74
+ export declare const SPACE_PREVIEW_CHARS = 200;
75
+ export declare function truncatePreview(text: string, limit?: number): {
76
+ text: string;
77
+ truncated: boolean;
78
+ };
@@ -0,0 +1,194 @@
1
+ // Type-only imports above: the web bundler can't resolve runtime "./x.js"
2
+ // imports between shared/ files, so mirror the constant here.
3
+ const SPACE_CHANNEL = "space";
4
+ /** Same message fanned out to several agents arrives as separate rows. */
5
+ const FANOUT_WINDOW_MS = 10_000;
6
+ const PR_URL_RE = /https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/pull\/\d+/g;
7
+ function newTurn(threadId, visibleInSpace = false) {
8
+ return { steps: 0, files: new Set(), additions: 0, deletions: 0, threadId, visibleInSpace };
9
+ }
10
+ function addDiff(turn, msg) {
11
+ const patch = msg.diffPatch;
12
+ if (!patch || msg.reverted)
13
+ return;
14
+ let sawHeader = false;
15
+ for (const line of patch.split("\n")) {
16
+ const header = /^\+\+\+ (?:b\/)?(.+)$/.exec(line);
17
+ if (header) {
18
+ if (header[1] !== "/dev/null")
19
+ turn.files.add(header[1].trim());
20
+ sawHeader = true;
21
+ continue;
22
+ }
23
+ if (/^(---|diff |index |@@)/.test(line))
24
+ continue;
25
+ if (line.startsWith("+"))
26
+ turn.additions += 1;
27
+ else if (line.startsWith("-"))
28
+ turn.deletions += 1;
29
+ }
30
+ if (!sawHeader)
31
+ turn.files.add(msg.id);
32
+ }
33
+ function humanEntry(msg, agentIds) {
34
+ return {
35
+ kind: "human",
36
+ key: msg.id,
37
+ ts: msg.ts,
38
+ senderName: msg.senderName || "Someone",
39
+ senderColor: msg.senderColor,
40
+ senderUserId: msg.senderUserId,
41
+ content: msg.content,
42
+ agentIds,
43
+ attachments: msg.attachments,
44
+ threadId: msg.space?.threadId,
45
+ handoff: msg.space?.handoff,
46
+ mentionUserIds: msg.space?.mentionUserIds,
47
+ offRecord: msg.space?.offRecord,
48
+ };
49
+ }
50
+ export function buildSpaceTimeline(messages, runningAgentIds) {
51
+ const entries = [];
52
+ const pending = new Map();
53
+ const flush = (agentId) => {
54
+ const turn = pending.get(agentId);
55
+ pending.delete(agentId);
56
+ const last = turn?.last;
57
+ if (!turn || !last || !turn.visibleInSpace)
58
+ return;
59
+ entries.push({
60
+ kind: "agent",
61
+ key: last.id,
62
+ ts: last.ts,
63
+ agentId,
64
+ content: last.content,
65
+ modelId: last.modelId,
66
+ error: last.status === "error",
67
+ threadId: turn.threadId,
68
+ stats: {
69
+ steps: turn.steps,
70
+ filesChanged: turn.files.size,
71
+ additions: turn.additions,
72
+ deletions: turn.deletions,
73
+ prUrls: [...new Set(last.content.match(PR_URL_RE) ?? [])],
74
+ },
75
+ });
76
+ };
77
+ for (const msg of messages) {
78
+ const agentId = msg.agentId;
79
+ if (agentId === SPACE_CHANNEL) {
80
+ if (msg.role === "user")
81
+ entries.push(humanEntry(msg, []));
82
+ else if ((msg.senderName === "Keel" || msg.senderName === "Eigen") && msg.content.trim()) {
83
+ entries.push({
84
+ kind: "agent",
85
+ key: msg.id,
86
+ ts: msg.ts,
87
+ agentId: "keel",
88
+ content: msg.content,
89
+ error: false,
90
+ threadId: msg.space?.threadId,
91
+ stats: { steps: 0, filesChanged: 0, additions: 0, deletions: 0, prUrls: [] },
92
+ });
93
+ }
94
+ continue;
95
+ }
96
+ if (msg.role === "user") {
97
+ const fromSpace = msg.space?.origin === "space";
98
+ if (agentId) {
99
+ flush(agentId);
100
+ pending.set(agentId, newTurn(msg.space?.threadId, fromSpace));
101
+ }
102
+ if (!fromSpace)
103
+ continue;
104
+ const prev = entries[entries.length - 1];
105
+ if (agentId &&
106
+ prev?.kind === "human" &&
107
+ prev.agentIds.length > 0 &&
108
+ prev.content === msg.content &&
109
+ prev.senderName === (msg.senderName || "Someone") &&
110
+ prev.senderUserId === msg.senderUserId &&
111
+ prev.threadId === msg.space?.threadId &&
112
+ msg.ts - prev.ts <= FANOUT_WINDOW_MS) {
113
+ if (!prev.agentIds.includes(agentId))
114
+ prev.agentIds.push(agentId);
115
+ continue;
116
+ }
117
+ entries.push(humanEntry(msg, agentId ? [agentId] : []));
118
+ continue;
119
+ }
120
+ if (!agentId)
121
+ continue;
122
+ const turn = pending.get(agentId) ?? newTurn();
123
+ pending.set(agentId, turn);
124
+ if (msg.role === "tool") {
125
+ turn.steps += 1;
126
+ addDiff(turn, msg);
127
+ }
128
+ else if (msg.role === "assistant" &&
129
+ msg.status !== "streaming" &&
130
+ msg.content.trim()) {
131
+ turn.last = msg;
132
+ }
133
+ }
134
+ const activeThreadByAgent = {};
135
+ for (const [agentId, turn] of [...pending]) {
136
+ // Still working — the reply lands in the Space once the turn ends.
137
+ if (runningAgentIds.has(agentId)) {
138
+ activeThreadByAgent[agentId] = turn.threadId;
139
+ continue;
140
+ }
141
+ flush(agentId);
142
+ }
143
+ entries.sort((a, b) => a.ts - b.ts);
144
+ const main = [];
145
+ const threads = {};
146
+ for (const entry of entries) {
147
+ if (entry.threadId)
148
+ (threads[entry.threadId] ??= []).push(entry);
149
+ else
150
+ main.push(entry);
151
+ }
152
+ return { main, threads, activeThreadByAgent };
153
+ }
154
+ export function summarizeThread(replies) {
155
+ if (!replies?.length)
156
+ return null;
157
+ const repliers = [];
158
+ const seen = new Set();
159
+ for (const r of [...replies].reverse()) {
160
+ const id = r.kind === "agent" ? `a:${r.agentId}` : `h:${r.senderUserId || r.senderName}`;
161
+ if (seen.has(id))
162
+ continue;
163
+ seen.add(id);
164
+ repliers.push(r.kind === "agent"
165
+ ? { kind: "agent", agentId: r.agentId }
166
+ : { kind: "human", name: r.senderName, userId: r.senderUserId });
167
+ }
168
+ return { count: replies.length, lastTs: replies[replies.length - 1].ts, repliers };
169
+ }
170
+ /** Markdown → readable one-paragraph text for the collapsed preview. */
171
+ export function plainPreview(markdown) {
172
+ return markdown
173
+ .replace(/```[\s\S]*?```/g, " [code] ")
174
+ .replace(/`([^`]+)`/g, "$1")
175
+ .replace(/!\[[^\]]*\]\([^)]*\)/g, "")
176
+ .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1")
177
+ .replace(/^\s{0,3}(#{1,6}|>|[-*+]|\d+\.)\s+/gm, "")
178
+ .replace(/(\*\*|__|~~)(.+?)\1/g, "$2")
179
+ .replace(/(^|\W)[*_](\S[^*_]*?)[*_](?=\W|$)/g, "$1$2")
180
+ .replace(/\|/g, " ")
181
+ .replace(/\s+/g, " ")
182
+ .trim();
183
+ }
184
+ export const SPACE_PREVIEW_CHARS = 200;
185
+ export function truncatePreview(text, limit = SPACE_PREVIEW_CHARS) {
186
+ if (text.length <= limit)
187
+ return { text, truncated: false };
188
+ const cut = text.slice(0, limit);
189
+ const space = cut.lastIndexOf(" ");
190
+ return {
191
+ text: `${(space > limit * 0.7 ? cut.slice(0, space) : cut).trimEnd()}…`,
192
+ truncated: true,
193
+ };
194
+ }
@@ -0,0 +1 @@
1
+ export { errorMessage, stringifyUnknown } from "./backends/cursor.js";
@@ -0,0 +1 @@
1
+ export { errorMessage, stringifyUnknown } from "./backends/cursor.js";
@@ -0,0 +1,320 @@
1
+ import type { AgentBackendKind } from "./backends/types.js";
2
+ export declare const SWARM_STATUSES: readonly ["draft", "planning", "researching", "awaiting_approval", "building", "paused", "stopped", "done", "failed"];
3
+ export type SwarmStatus = (typeof SWARM_STATUSES)[number];
4
+ /** Statuses where the runner schedules agent cycles. */
5
+ export declare const ACTIVE_SWARM_STATUSES: readonly ["planning", "researching", "building"];
6
+ export declare const TERMINAL_SWARM_STATUSES: readonly ["stopped", "done", "failed"];
7
+ export type SwarmPhase = "research" | "build";
8
+ export declare const SWARM_ROLES: readonly ["orchestrator", "researcher", "critic", "ranker", "synthesizer", "verifier", "engineer", "integrator"];
9
+ export type SwarmRole = (typeof SWARM_ROLES)[number];
10
+ /** Roles that write code and can only be spawned in the build phase. */
11
+ export declare const REPO_ROLES: readonly SwarmRole[];
12
+ export declare const WORKER_ROLES: readonly SwarmRole[];
13
+ export type SwarmAgentStatus = "idle" | "running" | "retired" | "error";
14
+ export declare const SWARM_TASK_STATUSES: readonly ["pending", "claimed", "done", "failed", "cancelled"];
15
+ export type SwarmTaskStatus = (typeof SWARM_TASK_STATUSES)[number];
16
+ export declare const SWARM_TASK_KINDS: readonly ["research", "critique", "rank", "synthesize", "verify", "build", "integrate"];
17
+ export type SwarmTaskKind = (typeof SWARM_TASK_KINDS)[number];
18
+ export declare const SWARM_POST_KINDS: readonly ["finding", "question", "answer", "proposal", "critique", "decision", "directive", "progress"];
19
+ export type SwarmPostKind = (typeof SWARM_POST_KINDS)[number];
20
+ export declare const SWARM_BASE_CHANNELS: readonly ["plan", "findings", "questions", "decisions"];
21
+ export type SwarmBaseChannel = (typeof SWARM_BASE_CHANNELS)[number];
22
+ export declare const SWARM_HYPOTHESIS_STATUSES: readonly ["proposed", "promoted", "rejected"];
23
+ export type SwarmHypothesisStatus = (typeof SWARM_HYPOTHESIS_STATUSES)[number];
24
+ export declare const SWARM_CRITIQUE_VERDICTS: readonly ["support", "refute", "needs_evidence"];
25
+ export type SwarmCritiqueVerdict = (typeof SWARM_CRITIQUE_VERDICTS)[number];
26
+ export declare const SWARM_ARTIFACT_KINDS: readonly ["report", "design", "notes", "benchmark", "data", "code_ref", "other"];
27
+ export type SwarmArtifactKind = (typeof SWARM_ARTIFACT_KINDS)[number];
28
+ export declare const DEFAULT_SWARM_BUDGET_USD = 25;
29
+ export declare const MAX_SWARM_BUDGET_USD = 2000;
30
+ export declare const DEFAULT_SWARM_DEADLINE_HOURS = 24;
31
+ export declare const MAX_SWARM_DEADLINE_HOURS: number;
32
+ export declare const DEFAULT_SWARM_MAX_WORKERS = 5;
33
+ export declare const MAX_SWARM_WORKERS = 8;
34
+ export declare const DEFAULT_SWARM_MAX_RUNNING = 3;
35
+ export declare const MAX_SWARM_RUNNING = 6;
36
+ export declare const DEFAULT_SWARM_MAX_CYCLES = 200;
37
+ export declare const MAX_SWARM_CYCLES = 2000;
38
+ export declare const SWARM_STALL_LIMIT = 2;
39
+ export declare const SWARM_IDLE_ORCHESTRATOR_LIMIT = 3;
40
+ export declare const SWARM_MIN_CRITIQUED_HYPOTHESES = 4;
41
+ export declare const SWARM_BUDGET_WARN_RATIO = 0.8;
42
+ export declare const MAX_SWARM_TITLE = 160;
43
+ export declare const MAX_SWARM_GOAL = 12000;
44
+ export declare const MAX_SWARM_POST = 8000;
45
+ export declare const MAX_SWARM_NOTES = 12000;
46
+ export declare const MAX_SWARM_TASK_SPEC = 4000;
47
+ export declare const MAX_SWARM_LEDGER_FIELD = 12000;
48
+ export declare const MAX_SWARM_ARTIFACT = 200000;
49
+ export declare const MAX_SWARM_BRIEF = 3000;
50
+ export declare const SWARM_ELO_START = 1200;
51
+ export declare const SWARM_ELO_K = 32;
52
+ export interface SwarmInfo {
53
+ id: string;
54
+ orgId: string | null;
55
+ creatorId: string;
56
+ creatorName?: string | null;
57
+ title: string;
58
+ goal: string;
59
+ status: SwarmStatus;
60
+ phase: SwarmPhase;
61
+ repoUrl: string | null;
62
+ startingRef: string;
63
+ /** Default agent for the swarm's workers. */
64
+ backend: AgentBackendKind;
65
+ /** Run workers on this Machine instead of the cloud (null = cloud). */
66
+ machineId?: string | null;
67
+ machineName?: string | null;
68
+ modelId: string;
69
+ budgetUsd: number;
70
+ spentUsd: number;
71
+ tokensUsed: number;
72
+ deadlineAt: number | null;
73
+ maxWorkers: number;
74
+ maxRunning: number;
75
+ maxCycles: number;
76
+ cyclesDone: number;
77
+ stallCount: number;
78
+ stopReason: string | null;
79
+ approvalNote: string | null;
80
+ createdAt: number;
81
+ updatedAt: number;
82
+ startedAt: number | null;
83
+ finishedAt: number | null;
84
+ runningAgents?: number;
85
+ totalAgents?: number;
86
+ }
87
+ export interface SwarmAgentInfo {
88
+ id: string;
89
+ swarmId: string;
90
+ role: SwarmRole;
91
+ label: string;
92
+ brief: string;
93
+ status: SwarmAgentStatus;
94
+ /** Agent this worker runs on (may differ per worker). */
95
+ backend: AgentBackendKind;
96
+ /** Machine override for this worker (null = the swarm's choice). */
97
+ machineId?: string | null;
98
+ machineName?: string | null;
99
+ modelId: string;
100
+ cursorAgentId: string | null;
101
+ hasRepo: boolean;
102
+ branch: string | null;
103
+ currentTaskId: string | null;
104
+ cycles: number;
105
+ spentUsd: number;
106
+ tokensUsed: number;
107
+ lastCycleAt: number | null;
108
+ lastBoardCallAt: number | null;
109
+ runStartedAt: number | null;
110
+ lastError: string | null;
111
+ createdAt: number;
112
+ /** Agent that spawned this worker. Null for the orchestrator. */
113
+ spawnedBy: string | null;
114
+ }
115
+ export interface SwarmTaskInfo {
116
+ id: string;
117
+ swarmId: string;
118
+ title: string;
119
+ spec: string;
120
+ kind: SwarmTaskKind;
121
+ status: SwarmTaskStatus;
122
+ ownerAgentId: string | null;
123
+ roleHint: SwarmRole | null;
124
+ blockedBy: string[];
125
+ priority: number;
126
+ resultMd: string | null;
127
+ attempts: number;
128
+ createdAt: number;
129
+ updatedAt: number;
130
+ completedAt: number | null;
131
+ }
132
+ export interface SwarmPostInfo {
133
+ id: string;
134
+ swarmId: string;
135
+ authorAgentId: string | null;
136
+ authorUserId: string | null;
137
+ authorLabel: string;
138
+ authorRole: SwarmRole | "human" | "system";
139
+ channel: string;
140
+ kind: SwarmPostKind;
141
+ bodyMd: string;
142
+ refs: string[];
143
+ mentions: string[];
144
+ createdAt: number;
145
+ }
146
+ export interface SwarmLedgerInfo {
147
+ swarmId: string;
148
+ revision: number;
149
+ factsMd: string;
150
+ guessesMd: string;
151
+ planMd: string;
152
+ openQuestionsMd: string;
153
+ progress: SwarmProgressEntry | null;
154
+ updatedBy: string | null;
155
+ updatedAt: number;
156
+ }
157
+ export interface SwarmProgressEntry {
158
+ isRequestSatisfied: boolean;
159
+ isProgressBeingMade: boolean;
160
+ isInLoop: boolean;
161
+ nextFocus: string;
162
+ reason: string;
163
+ }
164
+ export interface SwarmHypothesisInfo {
165
+ id: string;
166
+ swarmId: string;
167
+ title: string;
168
+ claimMd: string;
169
+ evidenceMd: string;
170
+ parentIds: string[];
171
+ elo: number;
172
+ matches: number;
173
+ wins: number;
174
+ critiques: number;
175
+ status: SwarmHypothesisStatus;
176
+ authorAgentId: string | null;
177
+ createdAt: number;
178
+ updatedAt: number;
179
+ }
180
+ export interface SwarmCritiqueInfo {
181
+ id: string;
182
+ hypothesisId: string;
183
+ authorAgentId: string | null;
184
+ verdict: SwarmCritiqueVerdict;
185
+ score: number;
186
+ bodyMd: string;
187
+ createdAt: number;
188
+ }
189
+ export interface SwarmArtifactInfo {
190
+ id: string;
191
+ swarmId: string;
192
+ agentId: string | null;
193
+ kind: SwarmArtifactKind;
194
+ name: string;
195
+ size: number;
196
+ createdAt: number;
197
+ updatedAt: number;
198
+ }
199
+ export interface SwarmEventInfo {
200
+ id: string;
201
+ swarmId: string;
202
+ agentId: string | null;
203
+ kind: string;
204
+ message: string;
205
+ createdAt: number;
206
+ }
207
+ export interface SwarmMessageInfo {
208
+ id: string;
209
+ agentId: string;
210
+ cycle: number;
211
+ role: "user" | "assistant" | "tool" | "error";
212
+ content: string;
213
+ toolName: string | null;
214
+ status: "running" | "done" | "error" | null;
215
+ ts: number;
216
+ }
217
+ export interface SwarmSnapshot {
218
+ swarm: SwarmInfo;
219
+ agents: SwarmAgentInfo[];
220
+ tasks: SwarmTaskInfo[];
221
+ posts: SwarmPostInfo[];
222
+ hypotheses: SwarmHypothesisInfo[];
223
+ critiques: SwarmCritiqueInfo[];
224
+ ledger: SwarmLedgerInfo | null;
225
+ artifacts: SwarmArtifactInfo[];
226
+ events: SwarmEventInfo[];
227
+ canEdit: boolean;
228
+ }
229
+ export declare const isSwarmStatus: (v: unknown) => v is SwarmStatus;
230
+ export declare const isSwarmRole: (v: unknown) => v is SwarmRole;
231
+ export declare const isSwarmTaskKind: (v: unknown) => v is SwarmTaskKind;
232
+ export declare const isSwarmTaskStatus: (v: unknown) => v is SwarmTaskStatus;
233
+ export declare const isSwarmPostKind: (v: unknown) => v is SwarmPostKind;
234
+ export declare const isSwarmArtifactKind: (v: unknown) => v is SwarmArtifactKind;
235
+ export declare const isSwarmCritiqueVerdict: (v: unknown) => v is SwarmCritiqueVerdict;
236
+ export declare const isSwarmHypothesisStatus: (v: unknown) => v is SwarmHypothesisStatus;
237
+ export declare function isActiveSwarmStatus(status: SwarmStatus): boolean;
238
+ export declare function isTerminalSwarmStatus(status: SwarmStatus): boolean;
239
+ export declare function canStartSwarm(status: SwarmStatus): boolean;
240
+ export declare function canPauseSwarm(status: SwarmStatus): boolean;
241
+ export declare function canResumeSwarm(status: SwarmStatus): boolean;
242
+ export declare function canStopSwarm(status: SwarmStatus): boolean;
243
+ export declare function isSwarmChannel(value: unknown): value is string;
244
+ export declare function roleNeedsRepo(role: SwarmRole): boolean;
245
+ /** When the human attached a repo, every agent gets a checkout so they can read it. */
246
+ export declare function swarmAgentUsesRepo(swarm: Pick<SwarmInfo, "repoUrl">, _role?: SwarmRole): boolean;
247
+ /** Engineers / integrators only exist once the research report is approved. */
248
+ export declare function roleAllowedInPhase(role: SwarmRole, phase: SwarmPhase): boolean;
249
+ export declare function canEditSwarm(swarm: {
250
+ creatorId: string;
251
+ orgId?: string | null;
252
+ }, actor: {
253
+ userId: string;
254
+ orgRole?: string | null;
255
+ }): boolean;
256
+ export declare function clampSwarmBudgetUsd(raw: unknown): number;
257
+ export declare function clampSwarmDeadlineHours(raw: unknown): number;
258
+ export declare function clampSwarmMaxWorkers(raw: unknown): number;
259
+ export declare function clampSwarmMaxRunning(raw: unknown): number;
260
+ export declare function clampSwarmMaxCycles(raw: unknown): number;
261
+ export type SwarmEloOutcome = "a" | "b" | "draw";
262
+ export declare function nextEloRatings(ratingA: number, ratingB: number, outcome: SwarmEloOutcome, k?: number): {
263
+ a: number;
264
+ b: number;
265
+ };
266
+ export interface SwarmLimitState {
267
+ status: SwarmStatus;
268
+ budgetUsd: number;
269
+ spentUsd: number;
270
+ deadlineAt: number | null;
271
+ maxCycles: number;
272
+ cyclesDone: number;
273
+ }
274
+ export type SwarmLimitVerdict = {
275
+ action: "continue";
276
+ } | {
277
+ action: "pause";
278
+ reason: "budget";
279
+ } | {
280
+ action: "stop";
281
+ reason: "deadline" | "max_cycles";
282
+ };
283
+ /** Hard limits the runner enforces before starting any cycle. */
284
+ export declare function evaluateSwarmLimits(state: SwarmLimitState, now: number): SwarmLimitVerdict;
285
+ export declare function shouldWarnBudget(spentUsd: number, budgetUsd: number): boolean;
286
+ export interface SwarmDoneGateInput {
287
+ phase: SwarmPhase;
288
+ hasReport: boolean;
289
+ critiquedHypotheses: number;
290
+ latestVerificationPassed: boolean | null;
291
+ openBuildTasks: number;
292
+ minCritiquedHypotheses?: number;
293
+ }
294
+ /** A swarm may only finish with a report, enough vetted ideas, and a passing verifier. */
295
+ export declare function evaluateDoneGate(input: SwarmDoneGateInput): {
296
+ ok: boolean;
297
+ missing: string[];
298
+ };
299
+ export declare function taskDependenciesMet(task: Pick<SwarmTaskInfo, "blockedBy">, byId: Map<string, Pick<SwarmTaskInfo, "status">>): boolean;
300
+ export declare function taskMatchesRole(task: Pick<SwarmTaskInfo, "roleHint" | "kind">, role: SwarmRole): boolean;
301
+ export declare function extractMentions(body: string): string[];
302
+ export declare function slugifySwarmLabel(raw: string, fallback?: string): string;
303
+ export declare function swarmTitleFromGoal(goal: string): string;
304
+ /** Compact label for a swarm's stored Cursor model id (no catalog required). */
305
+ export declare function formatSwarmModelLabel(modelId: string | null | undefined): string;
306
+ export interface SwarmDigestInput {
307
+ agentId: string;
308
+ agentLabel: string;
309
+ since: number;
310
+ posts: Pick<SwarmPostInfo, "id" | "authorLabel" | "authorRole" | "channel" | "kind" | "bodyMd" | "mentions" | "createdAt">[];
311
+ tasks: Pick<SwarmTaskInfo, "id" | "title" | "status" | "ownerAgentId" | "kind">[];
312
+ hypotheses: Pick<SwarmHypothesisInfo, "id" | "title" | "elo" | "critiques" | "status">[];
313
+ agents: Pick<SwarmAgentInfo, "id" | "label" | "role" | "status">[];
314
+ maxChars?: number;
315
+ }
316
+ /**
317
+ * Deterministic board digest injected into every cycle prompt. Agents get the
318
+ * decisions, directives, and anything addressed to them — not the whole board.
319
+ */
320
+ export declare function buildBoardDigest(input: SwarmDigestInput): string;