@clinebot/agents 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -0
- package/dist/agent-input.d.ts +2 -0
- package/dist/agent.d.ts +56 -0
- package/dist/extensions.d.ts +21 -0
- package/dist/hooks/engine.d.ts +42 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/lifecycle.d.ts +5 -0
- package/dist/hooks/node.d.ts +2 -0
- package/dist/hooks/subprocess-runner.d.ts +16 -0
- package/dist/hooks/subprocess.d.ts +268 -0
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +49 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +49 -0
- package/dist/index.node.d.ts +5 -0
- package/dist/index.node.js +49 -0
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/policies.d.ts +14 -0
- package/dist/mcp/tools.d.ts +9 -0
- package/dist/mcp/types.d.ts +35 -0
- package/dist/message-builder.d.ts +31 -0
- package/dist/prompts/cline.d.ts +1 -0
- package/dist/prompts/index.d.ts +1 -0
- package/dist/runtime/agent-runtime-bus.d.ts +13 -0
- package/dist/runtime/conversation-store.d.ts +16 -0
- package/dist/runtime/lifecycle-orchestrator.d.ts +28 -0
- package/dist/runtime/tool-orchestrator.d.ts +39 -0
- package/dist/runtime/turn-processor.d.ts +21 -0
- package/dist/teams/index.d.ts +3 -0
- package/dist/teams/multi-agent.d.ts +566 -0
- package/dist/teams/spawn-agent-tool.d.ts +85 -0
- package/dist/teams/team-tools.d.ts +51 -0
- package/dist/tools/ask-question.d.ts +12 -0
- package/dist/tools/create.d.ts +59 -0
- package/dist/tools/execution.d.ts +61 -0
- package/dist/tools/formatting.d.ts +20 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/registry.d.ts +26 -0
- package/dist/tools/validation.d.ts +27 -0
- package/dist/types.d.ts +826 -0
- package/package.json +54 -0
- package/src/agent-input.ts +116 -0
- package/src/agent.test.ts +931 -0
- package/src/agent.ts +1050 -0
- package/src/example.test.ts +564 -0
- package/src/extensions.ts +337 -0
- package/src/hooks/engine.test.ts +163 -0
- package/src/hooks/engine.ts +537 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/lifecycle.ts +239 -0
- package/src/hooks/node.ts +18 -0
- package/src/hooks/subprocess-runner.ts +140 -0
- package/src/hooks/subprocess.test.ts +180 -0
- package/src/hooks/subprocess.ts +620 -0
- package/src/index.browser.ts +1 -0
- package/src/index.node.ts +21 -0
- package/src/index.ts +133 -0
- package/src/mcp/index.ts +17 -0
- package/src/mcp/policies.test.ts +51 -0
- package/src/mcp/policies.ts +53 -0
- package/src/mcp/tools.test.ts +76 -0
- package/src/mcp/tools.ts +60 -0
- package/src/mcp/types.ts +41 -0
- package/src/message-builder.test.ts +175 -0
- package/src/message-builder.ts +429 -0
- package/src/prompts/cline.ts +49 -0
- package/src/prompts/index.ts +1 -0
- package/src/runtime/agent-runtime-bus.ts +53 -0
- package/src/runtime/conversation-store.ts +61 -0
- package/src/runtime/lifecycle-orchestrator.ts +90 -0
- package/src/runtime/tool-orchestrator.ts +177 -0
- package/src/runtime/turn-processor.ts +250 -0
- package/src/streaming.test.ts +197 -0
- package/src/streaming.ts +307 -0
- package/src/teams/index.ts +63 -0
- package/src/teams/multi-agent.lifecycle.test.ts +48 -0
- package/src/teams/multi-agent.ts +1866 -0
- package/src/teams/spawn-agent-tool.test.ts +172 -0
- package/src/teams/spawn-agent-tool.ts +223 -0
- package/src/teams/team-tools.test.ts +448 -0
- package/src/teams/team-tools.ts +929 -0
- package/src/tools/ask-question.ts +78 -0
- package/src/tools/create.ts +104 -0
- package/src/tools/execution.ts +311 -0
- package/src/tools/formatting.ts +73 -0
- package/src/tools/index.ts +45 -0
- package/src/tools/registry.ts +52 -0
- package/src/tools/tools.test.ts +292 -0
- package/src/tools/validation.ts +73 -0
- package/src/types.ts +966 -0
|
@@ -0,0 +1,929 @@
|
|
|
1
|
+
import { basename, resolve } from "node:path";
|
|
2
|
+
import type { providers as LlmsProviders } from "@clinebot/llms";
|
|
3
|
+
import { type Tool, validateWithZod, zodToJsonSchema } from "@clinebot/shared";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { getClineDefaultSystemPrompt } from "../prompts/cline.js";
|
|
6
|
+
import { createTool } from "../tools/create.js";
|
|
7
|
+
import type { AgentConfig, AgentHooks, BasicLogger } from "../types.js";
|
|
8
|
+
import type { AgentTeamsRuntime, TeamRuntimeState } from "./multi-agent.js";
|
|
9
|
+
|
|
10
|
+
export interface TeamTeammateSpec {
|
|
11
|
+
agentId: string;
|
|
12
|
+
rolePrompt: string;
|
|
13
|
+
modelId?: string;
|
|
14
|
+
maxIterations?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const TeamSpawnTeammateInputSchema = z
|
|
18
|
+
.object({
|
|
19
|
+
agentId: z.string().min(1).describe("Teammate identifier"),
|
|
20
|
+
rolePrompt: z
|
|
21
|
+
.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.describe("System prompt describing teammate role"),
|
|
24
|
+
maxIterations: z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(1)
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Max iterations per teammate run for spawn"),
|
|
30
|
+
})
|
|
31
|
+
.strict();
|
|
32
|
+
|
|
33
|
+
const TeamShutdownTeammateInputSchema = z.object({
|
|
34
|
+
agentId: z.string().min(1).describe("Teammate identifier"),
|
|
35
|
+
reason: z.string().min(1).optional().describe("Optional shutdown reason"),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const TeamStatusInputSchema = z.object({});
|
|
39
|
+
|
|
40
|
+
const TeamCreateTaskInputSchema = z.object({
|
|
41
|
+
title: z.string().min(1).describe("Task title"),
|
|
42
|
+
description: z.string().min(1).describe("Task details"),
|
|
43
|
+
dependsOn: z.array(z.string()).optional().describe("Dependency task IDs"),
|
|
44
|
+
assignee: z.string().min(1).optional().describe("Optional assignee"),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const TeamClaimTaskInputSchema = z.object({
|
|
48
|
+
taskId: z.string().describe("Task ID"),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const TeamCompleteTaskInputSchema = z.object({
|
|
52
|
+
taskId: z.string().describe("Task ID"),
|
|
53
|
+
summary: z.string().min(1).describe("Completion summary"),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const TeamBlockTaskInputSchema = z.object({
|
|
57
|
+
taskId: z.string().describe("Task ID"),
|
|
58
|
+
reason: z.string().min(1).describe("Blocking reason"),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const TeamRunTaskInputSchema = z.object({
|
|
62
|
+
agentId: z.string().describe("Teammate agent ID"),
|
|
63
|
+
task: z.string().min(1).describe("Task instructions for the teammate"),
|
|
64
|
+
taskId: z.string().optional().describe("Optional shared task list ID"),
|
|
65
|
+
runMode: z
|
|
66
|
+
.enum(["sync", "async"])
|
|
67
|
+
.optional()
|
|
68
|
+
.describe(
|
|
69
|
+
"Execution mode: sync waits for result; async returns a runId immediately",
|
|
70
|
+
),
|
|
71
|
+
continueConversation: z
|
|
72
|
+
.boolean()
|
|
73
|
+
.optional()
|
|
74
|
+
.describe(
|
|
75
|
+
"If true, continue the teammate conversation; otherwise start fresh",
|
|
76
|
+
),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const TeamListRunsInputSchema = z.object({
|
|
80
|
+
status: z
|
|
81
|
+
.enum([
|
|
82
|
+
"queued",
|
|
83
|
+
"running",
|
|
84
|
+
"completed",
|
|
85
|
+
"failed",
|
|
86
|
+
"cancelled",
|
|
87
|
+
"interrupted",
|
|
88
|
+
])
|
|
89
|
+
.optional(),
|
|
90
|
+
agentId: z.string().min(1).optional().describe("Filter by teammate ID"),
|
|
91
|
+
includeCompleted: z
|
|
92
|
+
.boolean()
|
|
93
|
+
.optional()
|
|
94
|
+
.describe("Include completed/failed runs (default true)"),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const TeamCancelRunInputSchema = z.object({
|
|
98
|
+
runId: z.string().min(1).describe("Run ID"),
|
|
99
|
+
reason: z.string().min(1).optional().describe("Optional cancellation reason"),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const TeamAwaitRunInputSchema = z.object({
|
|
103
|
+
runId: z.string().min(1).describe("Async run ID to await"),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const TeamAwaitAllRunsInputSchema = z.object({});
|
|
107
|
+
|
|
108
|
+
const TeamSendMessageInputSchema = z.object({
|
|
109
|
+
toAgentId: z.string().min(1).describe("Recipient agent ID"),
|
|
110
|
+
subject: z.string().min(1).describe("Message subject"),
|
|
111
|
+
body: z.string().min(1).describe("Message body"),
|
|
112
|
+
taskId: z.string().min(1).optional().describe("Optional task ID context"),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const TeamBroadcastInputSchema = z.object({
|
|
116
|
+
subject: z.string().min(1).describe("Message subject"),
|
|
117
|
+
body: z.string().min(1).describe("Message body"),
|
|
118
|
+
taskId: z.string().min(1).optional().describe("Optional task ID context"),
|
|
119
|
+
includeLead: z
|
|
120
|
+
.boolean()
|
|
121
|
+
.optional()
|
|
122
|
+
.describe("Include the lead agent in broadcast recipients"),
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const TeamReadMailboxInputSchema = z.object({
|
|
126
|
+
unreadOnly: z
|
|
127
|
+
.boolean()
|
|
128
|
+
.optional()
|
|
129
|
+
.describe("Only unread messages for read action (default true)"),
|
|
130
|
+
limit: z
|
|
131
|
+
.number()
|
|
132
|
+
.int()
|
|
133
|
+
.min(1)
|
|
134
|
+
.max(100)
|
|
135
|
+
.optional()
|
|
136
|
+
.describe("Optional max number of messages for read action"),
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const TeamLogUpdateInputSchema = z.object({
|
|
140
|
+
kind: z.enum(["progress", "handoff", "blocked", "decision", "done", "error"]),
|
|
141
|
+
summary: z.string().min(1).describe("Update summary"),
|
|
142
|
+
taskId: z.string().min(1).optional().describe("Optional task ID context"),
|
|
143
|
+
evidence: z
|
|
144
|
+
.array(z.string().min(1))
|
|
145
|
+
.optional()
|
|
146
|
+
.describe("Optional evidence links/snippets"),
|
|
147
|
+
nextAction: z.string().min(1).optional().describe("Planned next step"),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const TeamCleanupInputSchema = z.object({});
|
|
151
|
+
|
|
152
|
+
const DEFAULT_OUTCOME_REQUIRED_SECTIONS = [
|
|
153
|
+
"current_state",
|
|
154
|
+
"boundary_analysis",
|
|
155
|
+
"interface_proposal",
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
const TeamCreateOutcomeInputSchema = z.object({
|
|
159
|
+
title: z.string().describe("Outcome title"),
|
|
160
|
+
requiredSections: z
|
|
161
|
+
.array(z.string())
|
|
162
|
+
.default(DEFAULT_OUTCOME_REQUIRED_SECTIONS)
|
|
163
|
+
.describe(
|
|
164
|
+
"Required sections for finalization gate (defaults to current_state,boundary_analysis,interface_proposal)",
|
|
165
|
+
),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const TeamAttachOutcomeFragmentInputSchema = z.object({
|
|
169
|
+
outcomeId: z.string().describe("Outcome ID"),
|
|
170
|
+
section: z.string().describe("Section name"),
|
|
171
|
+
sourceRunId: z.string().optional().describe("Optional source run ID"),
|
|
172
|
+
content: z.string().describe("Section fragment content"),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const TeamReviewOutcomeFragmentInputSchema = z.object({
|
|
176
|
+
fragmentId: z.string().describe("Fragment ID"),
|
|
177
|
+
approved: z.boolean().describe("Review decision"),
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const TeamFinalizeOutcomeInputSchema = z.object({
|
|
181
|
+
outcomeId: z.string().describe("Outcome ID"),
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const TeamListOutcomesInputSchema = z.object({});
|
|
185
|
+
|
|
186
|
+
type TeamSpawnTeammateInput = z.infer<typeof TeamSpawnTeammateInputSchema>;
|
|
187
|
+
type TeamShutdownTeammateInput = z.infer<
|
|
188
|
+
typeof TeamShutdownTeammateInputSchema
|
|
189
|
+
>;
|
|
190
|
+
type TeamStatusInput = z.infer<typeof TeamStatusInputSchema>;
|
|
191
|
+
type TeamCreateTaskInput = z.infer<typeof TeamCreateTaskInputSchema>;
|
|
192
|
+
type TeamClaimTaskInput = z.infer<typeof TeamClaimTaskInputSchema>;
|
|
193
|
+
type TeamCompleteTaskInput = z.infer<typeof TeamCompleteTaskInputSchema>;
|
|
194
|
+
type TeamBlockTaskInput = z.infer<typeof TeamBlockTaskInputSchema>;
|
|
195
|
+
type TeamRunTaskInput = z.infer<typeof TeamRunTaskInputSchema>;
|
|
196
|
+
type TeamListRunsInput = z.infer<typeof TeamListRunsInputSchema>;
|
|
197
|
+
type TeamCancelRunInput = z.infer<typeof TeamCancelRunInputSchema>;
|
|
198
|
+
type TeamAwaitRunInput = z.infer<typeof TeamAwaitRunInputSchema>;
|
|
199
|
+
type TeamAwaitAllRunsInput = z.infer<typeof TeamAwaitAllRunsInputSchema>;
|
|
200
|
+
type TeamSendMessageInput = z.infer<typeof TeamSendMessageInputSchema>;
|
|
201
|
+
type TeamBroadcastInput = z.infer<typeof TeamBroadcastInputSchema>;
|
|
202
|
+
type TeamReadMailboxInput = z.infer<typeof TeamReadMailboxInputSchema>;
|
|
203
|
+
type TeamLogUpdateInput = z.infer<typeof TeamLogUpdateInputSchema>;
|
|
204
|
+
type TeamCleanupInput = z.infer<typeof TeamCleanupInputSchema>;
|
|
205
|
+
type TeamCreateOutcomeInput = z.infer<typeof TeamCreateOutcomeInputSchema>;
|
|
206
|
+
type TeamAttachOutcomeFragmentInput = z.infer<
|
|
207
|
+
typeof TeamAttachOutcomeFragmentInputSchema
|
|
208
|
+
>;
|
|
209
|
+
type TeamReviewOutcomeFragmentInput = z.infer<
|
|
210
|
+
typeof TeamReviewOutcomeFragmentInputSchema
|
|
211
|
+
>;
|
|
212
|
+
type TeamFinalizeOutcomeInput = z.infer<typeof TeamFinalizeOutcomeInputSchema>;
|
|
213
|
+
type TeamListOutcomesInput = z.infer<typeof TeamListOutcomesInputSchema>;
|
|
214
|
+
|
|
215
|
+
export interface TeamTeammateRuntimeConfig {
|
|
216
|
+
providerId: string;
|
|
217
|
+
modelId: string;
|
|
218
|
+
cwd?: string;
|
|
219
|
+
apiKey?: string;
|
|
220
|
+
baseUrl?: string;
|
|
221
|
+
headers?: Record<string, string>;
|
|
222
|
+
providerConfig?: LlmsProviders.ProviderConfig;
|
|
223
|
+
knownModels?: Record<string, LlmsProviders.ModelInfo>;
|
|
224
|
+
thinking?: boolean;
|
|
225
|
+
clineWorkspaceMetadata?: string;
|
|
226
|
+
clineIdeName?: string;
|
|
227
|
+
maxIterations?: number;
|
|
228
|
+
hooks?: AgentHooks;
|
|
229
|
+
extensions?: AgentConfig["extensions"];
|
|
230
|
+
logger?: BasicLogger;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface CreateAgentTeamsToolsOptions {
|
|
234
|
+
runtime: AgentTeamsRuntime;
|
|
235
|
+
requesterId: string;
|
|
236
|
+
teammateRuntime: TeamTeammateRuntimeConfig;
|
|
237
|
+
createBaseTools?: () => Tool[];
|
|
238
|
+
allowSpawn?: boolean;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface BootstrapAgentTeamsOptions {
|
|
242
|
+
runtime: AgentTeamsRuntime;
|
|
243
|
+
teammateRuntime: TeamTeammateRuntimeConfig;
|
|
244
|
+
createBaseTools?: () => Tool[];
|
|
245
|
+
leadAgentId?: string;
|
|
246
|
+
restoredTeammates?: TeamTeammateSpec[];
|
|
247
|
+
restoredFromPersistence?: boolean;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export interface BootstrapAgentTeamsResult {
|
|
251
|
+
tools: Tool[];
|
|
252
|
+
restoredFromPersistence: boolean;
|
|
253
|
+
restoredTeammates: string[];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function buildFallbackWorkspaceMetadata(cwd: string): string {
|
|
257
|
+
const rootPath = resolve(cwd);
|
|
258
|
+
return `# Workspace Configuration\n${JSON.stringify(
|
|
259
|
+
{
|
|
260
|
+
workspaces: {
|
|
261
|
+
[rootPath]: {
|
|
262
|
+
hint: basename(rootPath),
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
null,
|
|
267
|
+
2,
|
|
268
|
+
)}`;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function buildTeammateSystemPrompt(
|
|
272
|
+
spec: TeamTeammateSpec,
|
|
273
|
+
teammateRuntime: TeamTeammateRuntimeConfig,
|
|
274
|
+
): string {
|
|
275
|
+
if (teammateRuntime.providerId !== "cline") {
|
|
276
|
+
return spec.rolePrompt;
|
|
277
|
+
}
|
|
278
|
+
const cwd = teammateRuntime.cwd?.trim() || process.cwd();
|
|
279
|
+
const metadata =
|
|
280
|
+
teammateRuntime.clineWorkspaceMetadata?.trim() ||
|
|
281
|
+
buildFallbackWorkspaceMetadata(cwd);
|
|
282
|
+
const rolePrompt = spec.rolePrompt.trim();
|
|
283
|
+
const teammateRules = rolePrompt ? `# Team Teammate Role\n${rolePrompt}` : "";
|
|
284
|
+
return getClineDefaultSystemPrompt(
|
|
285
|
+
teammateRuntime.clineIdeName?.trim() || "Terminal Shell",
|
|
286
|
+
cwd,
|
|
287
|
+
metadata,
|
|
288
|
+
teammateRules,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function spawnTeamTeammate(
|
|
293
|
+
options: Omit<CreateAgentTeamsToolsOptions, "requesterId" | "allowSpawn"> & {
|
|
294
|
+
requesterId: string;
|
|
295
|
+
spec: TeamTeammateSpec;
|
|
296
|
+
},
|
|
297
|
+
): void {
|
|
298
|
+
const teammateTools: Tool[] = [];
|
|
299
|
+
if (options.createBaseTools) {
|
|
300
|
+
teammateTools.push(...options.createBaseTools());
|
|
301
|
+
}
|
|
302
|
+
teammateTools.push(
|
|
303
|
+
...createAgentTeamsTools({
|
|
304
|
+
runtime: options.runtime,
|
|
305
|
+
requesterId: options.spec.agentId,
|
|
306
|
+
teammateRuntime: options.teammateRuntime,
|
|
307
|
+
createBaseTools: options.createBaseTools,
|
|
308
|
+
allowSpawn: false,
|
|
309
|
+
}),
|
|
310
|
+
);
|
|
311
|
+
options.runtime.spawnTeammate({
|
|
312
|
+
agentId: options.spec.agentId,
|
|
313
|
+
config: {
|
|
314
|
+
providerId: options.teammateRuntime.providerId,
|
|
315
|
+
modelId: options.spec.modelId ?? options.teammateRuntime.modelId,
|
|
316
|
+
apiKey: options.teammateRuntime.apiKey,
|
|
317
|
+
baseUrl: options.teammateRuntime.baseUrl,
|
|
318
|
+
headers: options.teammateRuntime.headers,
|
|
319
|
+
providerConfig: options.teammateRuntime.providerConfig,
|
|
320
|
+
knownModels: options.teammateRuntime.knownModels,
|
|
321
|
+
thinking: options.teammateRuntime.thinking,
|
|
322
|
+
systemPrompt: buildTeammateSystemPrompt(
|
|
323
|
+
options.spec,
|
|
324
|
+
options.teammateRuntime,
|
|
325
|
+
),
|
|
326
|
+
maxIterations:
|
|
327
|
+
options.spec.maxIterations ?? options.teammateRuntime.maxIterations,
|
|
328
|
+
tools: teammateTools,
|
|
329
|
+
hooks: options.teammateRuntime.hooks,
|
|
330
|
+
extensions: options.teammateRuntime.extensions,
|
|
331
|
+
logger: options.teammateRuntime.logger,
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export function bootstrapAgentTeams(
|
|
337
|
+
options: BootstrapAgentTeamsOptions,
|
|
338
|
+
): BootstrapAgentTeamsResult {
|
|
339
|
+
const leadAgentId = options.leadAgentId ?? "lead";
|
|
340
|
+
const restoredFromPersistence = options.restoredFromPersistence === true;
|
|
341
|
+
|
|
342
|
+
const tools = createAgentTeamsTools({
|
|
343
|
+
runtime: options.runtime,
|
|
344
|
+
requesterId: leadAgentId,
|
|
345
|
+
teammateRuntime: options.teammateRuntime,
|
|
346
|
+
createBaseTools: options.createBaseTools,
|
|
347
|
+
allowSpawn: true,
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
const restoredTeammates: string[] = [];
|
|
351
|
+
for (const spec of options.restoredTeammates ?? []) {
|
|
352
|
+
if (options.runtime.isTeammateActive(spec.agentId)) {
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
spawnTeamTeammate({
|
|
356
|
+
runtime: options.runtime,
|
|
357
|
+
requesterId: leadAgentId,
|
|
358
|
+
teammateRuntime: options.teammateRuntime,
|
|
359
|
+
createBaseTools: options.createBaseTools,
|
|
360
|
+
spec,
|
|
361
|
+
});
|
|
362
|
+
restoredTeammates.push(spec.agentId);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
tools,
|
|
367
|
+
restoredFromPersistence,
|
|
368
|
+
restoredTeammates,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export function createAgentTeamsTools(
|
|
373
|
+
options: CreateAgentTeamsToolsOptions,
|
|
374
|
+
): Tool[] {
|
|
375
|
+
const allowSpawn = options.allowSpawn ?? true;
|
|
376
|
+
const tools: Tool[] = [];
|
|
377
|
+
|
|
378
|
+
tools.push(
|
|
379
|
+
createTool<TeamSpawnTeammateInput, { agentId: string; status: string }>({
|
|
380
|
+
name: "team_spawn_teammate",
|
|
381
|
+
description: "Spawn a teammate with a required agentId and rolePrompt.",
|
|
382
|
+
inputSchema: zodToJsonSchema(TeamSpawnTeammateInputSchema),
|
|
383
|
+
execute: async (input) => {
|
|
384
|
+
const validatedInput = validateWithZod(
|
|
385
|
+
TeamSpawnTeammateInputSchema,
|
|
386
|
+
input,
|
|
387
|
+
);
|
|
388
|
+
if (options.runtime.getMemberRole(options.requesterId) !== "lead") {
|
|
389
|
+
throw new Error("Only the lead agent can manage teammates.");
|
|
390
|
+
}
|
|
391
|
+
if (!allowSpawn) {
|
|
392
|
+
throw new Error("Spawning teammates is disabled in this context.");
|
|
393
|
+
}
|
|
394
|
+
const spec: TeamTeammateSpec = {
|
|
395
|
+
agentId: validatedInput.agentId,
|
|
396
|
+
rolePrompt: validatedInput.rolePrompt,
|
|
397
|
+
maxIterations: validatedInput.maxIterations,
|
|
398
|
+
};
|
|
399
|
+
spawnTeamTeammate({
|
|
400
|
+
runtime: options.runtime,
|
|
401
|
+
requesterId: options.requesterId,
|
|
402
|
+
teammateRuntime: options.teammateRuntime,
|
|
403
|
+
createBaseTools: options.createBaseTools,
|
|
404
|
+
spec,
|
|
405
|
+
});
|
|
406
|
+
return { agentId: validatedInput.agentId, status: "spawned" };
|
|
407
|
+
},
|
|
408
|
+
}) as Tool,
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
tools.push(
|
|
412
|
+
createTool<TeamShutdownTeammateInput, { agentId: string; status: string }>({
|
|
413
|
+
name: "team_shutdown_teammate",
|
|
414
|
+
description: "Shutdown a teammate by agentId.",
|
|
415
|
+
inputSchema: zodToJsonSchema(TeamShutdownTeammateInputSchema),
|
|
416
|
+
execute: async (input) => {
|
|
417
|
+
const validatedInput = validateWithZod(
|
|
418
|
+
TeamShutdownTeammateInputSchema,
|
|
419
|
+
input,
|
|
420
|
+
);
|
|
421
|
+
if (options.runtime.getMemberRole(options.requesterId) !== "lead") {
|
|
422
|
+
throw new Error("Only the lead agent can manage teammates.");
|
|
423
|
+
}
|
|
424
|
+
options.runtime.shutdownTeammate(
|
|
425
|
+
validatedInput.agentId,
|
|
426
|
+
validatedInput.reason,
|
|
427
|
+
);
|
|
428
|
+
return { agentId: validatedInput.agentId, status: "stopped" };
|
|
429
|
+
},
|
|
430
|
+
}) as Tool,
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
tools.push(
|
|
434
|
+
createTool<TeamStatusInput, ReturnType<AgentTeamsRuntime["getSnapshot"]>>({
|
|
435
|
+
name: "team_status",
|
|
436
|
+
description:
|
|
437
|
+
"Return a snapshot of team members, task counts, mailbox, and mission log stats.",
|
|
438
|
+
inputSchema: zodToJsonSchema(TeamStatusInputSchema),
|
|
439
|
+
execute: async (input) => {
|
|
440
|
+
validateWithZod(TeamStatusInputSchema, input);
|
|
441
|
+
return options.runtime.getSnapshot();
|
|
442
|
+
},
|
|
443
|
+
}) as Tool,
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
tools.push(
|
|
447
|
+
createTool<TeamCreateTaskInput, { taskId: string; status: string }>({
|
|
448
|
+
name: "team_create_task",
|
|
449
|
+
description: "Create a shared team task with title and description.",
|
|
450
|
+
inputSchema: zodToJsonSchema(TeamCreateTaskInputSchema),
|
|
451
|
+
execute: async (input) => {
|
|
452
|
+
const validatedInput = validateWithZod(
|
|
453
|
+
TeamCreateTaskInputSchema,
|
|
454
|
+
input,
|
|
455
|
+
);
|
|
456
|
+
const task = options.runtime.createTask({
|
|
457
|
+
title: validatedInput.title,
|
|
458
|
+
description: validatedInput.description,
|
|
459
|
+
dependsOn: validatedInput.dependsOn,
|
|
460
|
+
assignee: validatedInput.assignee,
|
|
461
|
+
createdBy: options.requesterId,
|
|
462
|
+
});
|
|
463
|
+
return { taskId: task.id, status: task.status };
|
|
464
|
+
},
|
|
465
|
+
}) as Tool,
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
tools.push(
|
|
469
|
+
createTool<
|
|
470
|
+
TeamClaimTaskInput,
|
|
471
|
+
{ taskId: string; status: string; nextStep: string }
|
|
472
|
+
>({
|
|
473
|
+
name: "team_claim_task",
|
|
474
|
+
description: "Claim a task by taskId.",
|
|
475
|
+
inputSchema: zodToJsonSchema(TeamClaimTaskInputSchema),
|
|
476
|
+
execute: async (input) => {
|
|
477
|
+
const validatedInput = validateWithZod(TeamClaimTaskInputSchema, input);
|
|
478
|
+
const task = options.runtime.claimTask(
|
|
479
|
+
validatedInput.taskId,
|
|
480
|
+
options.requesterId,
|
|
481
|
+
);
|
|
482
|
+
return {
|
|
483
|
+
taskId: task.id,
|
|
484
|
+
status: task.status,
|
|
485
|
+
nextStep:
|
|
486
|
+
"Task is now in_progress. Execute the work using team_run_task or your own tools, then call team_complete_task when done.",
|
|
487
|
+
};
|
|
488
|
+
},
|
|
489
|
+
}) as Tool,
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
tools.push(
|
|
493
|
+
createTool<TeamCompleteTaskInput, { taskId: string; status: string }>({
|
|
494
|
+
name: "team_complete_task",
|
|
495
|
+
description: "Complete a task by taskId and provide a summary.",
|
|
496
|
+
inputSchema: zodToJsonSchema(TeamCompleteTaskInputSchema),
|
|
497
|
+
execute: async (input) => {
|
|
498
|
+
const validatedInput = validateWithZod(
|
|
499
|
+
TeamCompleteTaskInputSchema,
|
|
500
|
+
input,
|
|
501
|
+
);
|
|
502
|
+
const task = options.runtime.completeTask(
|
|
503
|
+
validatedInput.taskId,
|
|
504
|
+
options.requesterId,
|
|
505
|
+
validatedInput.summary,
|
|
506
|
+
);
|
|
507
|
+
return { taskId: task.id, status: task.status };
|
|
508
|
+
},
|
|
509
|
+
}) as Tool,
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
tools.push(
|
|
513
|
+
createTool<TeamBlockTaskInput, { taskId: string; status: string }>({
|
|
514
|
+
name: "team_block_task",
|
|
515
|
+
description: "Block a task by taskId with a reason.",
|
|
516
|
+
inputSchema: zodToJsonSchema(TeamBlockTaskInputSchema),
|
|
517
|
+
execute: async (input) => {
|
|
518
|
+
const validatedInput = validateWithZod(TeamBlockTaskInputSchema, input);
|
|
519
|
+
const task = options.runtime.blockTask(
|
|
520
|
+
validatedInput.taskId,
|
|
521
|
+
options.requesterId,
|
|
522
|
+
validatedInput.reason,
|
|
523
|
+
);
|
|
524
|
+
return { taskId: task.id, status: task.status };
|
|
525
|
+
},
|
|
526
|
+
}) as Tool,
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
tools.push(
|
|
530
|
+
createTool<
|
|
531
|
+
TeamRunTaskInput,
|
|
532
|
+
{
|
|
533
|
+
agentId: string;
|
|
534
|
+
mode: "sync" | "async";
|
|
535
|
+
runId?: string;
|
|
536
|
+
text?: string;
|
|
537
|
+
iterations?: number;
|
|
538
|
+
}
|
|
539
|
+
>({
|
|
540
|
+
name: "team_run_task",
|
|
541
|
+
description:
|
|
542
|
+
"Route a delegated task to a teammate. Choose sync (wait) or async (run in background).",
|
|
543
|
+
inputSchema: zodToJsonSchema(TeamRunTaskInputSchema),
|
|
544
|
+
execute: async (input) => {
|
|
545
|
+
const validatedInput = validateWithZod(TeamRunTaskInputSchema, input);
|
|
546
|
+
if (validatedInput.runMode === "async") {
|
|
547
|
+
const run = options.runtime.startTeammateRun(
|
|
548
|
+
validatedInput.agentId,
|
|
549
|
+
validatedInput.task,
|
|
550
|
+
{
|
|
551
|
+
taskId: validatedInput.taskId,
|
|
552
|
+
fromAgentId: options.requesterId,
|
|
553
|
+
continueConversation: validatedInput.continueConversation,
|
|
554
|
+
},
|
|
555
|
+
);
|
|
556
|
+
return {
|
|
557
|
+
agentId: validatedInput.agentId,
|
|
558
|
+
mode: "async",
|
|
559
|
+
runId: run.id,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
const result = await options.runtime.routeToTeammate(
|
|
563
|
+
validatedInput.agentId,
|
|
564
|
+
validatedInput.task,
|
|
565
|
+
{
|
|
566
|
+
taskId: validatedInput.taskId,
|
|
567
|
+
fromAgentId: options.requesterId,
|
|
568
|
+
continueConversation: validatedInput.continueConversation,
|
|
569
|
+
},
|
|
570
|
+
);
|
|
571
|
+
return {
|
|
572
|
+
agentId: validatedInput.agentId,
|
|
573
|
+
mode: "sync",
|
|
574
|
+
text: result.text,
|
|
575
|
+
iterations: result.iterations,
|
|
576
|
+
};
|
|
577
|
+
},
|
|
578
|
+
}) as Tool,
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
tools.push(
|
|
582
|
+
createTool<TeamCancelRunInput, { runId: string; status: string }>({
|
|
583
|
+
name: "team_cancel_run",
|
|
584
|
+
description: "Cancel one async teammate run.",
|
|
585
|
+
inputSchema: zodToJsonSchema(TeamCancelRunInputSchema),
|
|
586
|
+
execute: async (input) => {
|
|
587
|
+
const validatedInput = validateWithZod(TeamCancelRunInputSchema, input);
|
|
588
|
+
const run = options.runtime.cancelRun(
|
|
589
|
+
validatedInput.runId,
|
|
590
|
+
validatedInput.reason,
|
|
591
|
+
);
|
|
592
|
+
return { runId: run.id, status: run.status };
|
|
593
|
+
},
|
|
594
|
+
}) as Tool,
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
tools.push(
|
|
598
|
+
createTool<TeamListRunsInput, ReturnType<AgentTeamsRuntime["listRuns"]>>({
|
|
599
|
+
name: "team_list_runs",
|
|
600
|
+
description:
|
|
601
|
+
"List teammate runs started with team_run_task in async mode.",
|
|
602
|
+
inputSchema: zodToJsonSchema(TeamListRunsInputSchema),
|
|
603
|
+
execute: async (input) =>
|
|
604
|
+
options.runtime.listRuns(
|
|
605
|
+
validateWithZod(TeamListRunsInputSchema, input),
|
|
606
|
+
),
|
|
607
|
+
}) as Tool,
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
tools.push(
|
|
611
|
+
createTool<
|
|
612
|
+
TeamAwaitRunInput,
|
|
613
|
+
Awaited<ReturnType<AgentTeamsRuntime["awaitRun"]>>
|
|
614
|
+
>({
|
|
615
|
+
name: "team_await_run",
|
|
616
|
+
description: "Wait for one async run by runId.",
|
|
617
|
+
inputSchema: zodToJsonSchema(TeamAwaitRunInputSchema),
|
|
618
|
+
execute: async (input) => {
|
|
619
|
+
const validatedInput = validateWithZod(TeamAwaitRunInputSchema, input);
|
|
620
|
+
const run = await options.runtime.awaitRun(validatedInput.runId);
|
|
621
|
+
if (run.status === "failed") {
|
|
622
|
+
throw new Error(
|
|
623
|
+
`Run "${run.id}" failed${run.error ? `: ${run.error}` : ""}`,
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
if (run.status === "cancelled") {
|
|
627
|
+
throw new Error(
|
|
628
|
+
`Run "${run.id}" was cancelled${run.error ? `: ${run.error}` : ""}`,
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
if (run.status === "interrupted") {
|
|
632
|
+
throw new Error(
|
|
633
|
+
`Run "${run.id}" was interrupted${run.error ? `: ${run.error}` : ""}`,
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
return run;
|
|
637
|
+
},
|
|
638
|
+
}) as Tool,
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
tools.push(
|
|
642
|
+
createTool<
|
|
643
|
+
TeamAwaitAllRunsInput,
|
|
644
|
+
Awaited<ReturnType<AgentTeamsRuntime["awaitAllRuns"]>>
|
|
645
|
+
>({
|
|
646
|
+
name: "team_await_all_runs",
|
|
647
|
+
description: "Wait for all active async runs to complete.",
|
|
648
|
+
inputSchema: zodToJsonSchema(TeamAwaitAllRunsInputSchema),
|
|
649
|
+
execute: async (input) => {
|
|
650
|
+
validateWithZod(TeamAwaitAllRunsInputSchema, input);
|
|
651
|
+
const runs = await options.runtime.awaitAllRuns();
|
|
652
|
+
const failedRuns = runs.filter((run) =>
|
|
653
|
+
["failed", "cancelled", "interrupted"].includes(run.status),
|
|
654
|
+
);
|
|
655
|
+
if (failedRuns.length > 0) {
|
|
656
|
+
const details = failedRuns
|
|
657
|
+
.map(
|
|
658
|
+
(run) =>
|
|
659
|
+
`${run.id}:${run.status}${run.error ? `(${run.error})` : ""}`,
|
|
660
|
+
)
|
|
661
|
+
.join(", ");
|
|
662
|
+
throw new Error(
|
|
663
|
+
`One or more runs did not complete successfully: ${details}`,
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
return runs;
|
|
667
|
+
},
|
|
668
|
+
}) as Tool,
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
tools.push(
|
|
672
|
+
createTool<TeamSendMessageInput, { id: string; toAgentId: string }>({
|
|
673
|
+
name: "team_send_message",
|
|
674
|
+
description: "Send a direct mailbox message to one teammate.",
|
|
675
|
+
inputSchema: zodToJsonSchema(TeamSendMessageInputSchema),
|
|
676
|
+
execute: async (input) => {
|
|
677
|
+
const validatedInput = validateWithZod(
|
|
678
|
+
TeamSendMessageInputSchema,
|
|
679
|
+
input,
|
|
680
|
+
);
|
|
681
|
+
const message = options.runtime.sendMessage(
|
|
682
|
+
options.requesterId,
|
|
683
|
+
validatedInput.toAgentId,
|
|
684
|
+
validatedInput.subject,
|
|
685
|
+
validatedInput.body,
|
|
686
|
+
validatedInput.taskId,
|
|
687
|
+
);
|
|
688
|
+
return { id: message.id, toAgentId: message.toAgentId };
|
|
689
|
+
},
|
|
690
|
+
}) as Tool,
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
tools.push(
|
|
694
|
+
createTool<TeamBroadcastInput, { delivered: number }>({
|
|
695
|
+
name: "team_broadcast",
|
|
696
|
+
description: "Broadcast a mailbox message to all teammates.",
|
|
697
|
+
inputSchema: zodToJsonSchema(TeamBroadcastInputSchema),
|
|
698
|
+
execute: async (input) => {
|
|
699
|
+
const validatedInput = validateWithZod(TeamBroadcastInputSchema, input);
|
|
700
|
+
const messages = options.runtime.broadcast(
|
|
701
|
+
options.requesterId,
|
|
702
|
+
validatedInput.subject,
|
|
703
|
+
validatedInput.body,
|
|
704
|
+
{
|
|
705
|
+
taskId: validatedInput.taskId,
|
|
706
|
+
includeLead: validatedInput.includeLead,
|
|
707
|
+
},
|
|
708
|
+
);
|
|
709
|
+
return { delivered: messages.length };
|
|
710
|
+
},
|
|
711
|
+
}) as Tool,
|
|
712
|
+
);
|
|
713
|
+
|
|
714
|
+
tools.push(
|
|
715
|
+
createTool<
|
|
716
|
+
TeamReadMailboxInput,
|
|
717
|
+
ReturnType<AgentTeamsRuntime["listMailbox"]>
|
|
718
|
+
>({
|
|
719
|
+
name: "team_read_mailbox",
|
|
720
|
+
description: "Read the current agent mailbox.",
|
|
721
|
+
inputSchema: zodToJsonSchema(TeamReadMailboxInputSchema),
|
|
722
|
+
execute: async (input) => {
|
|
723
|
+
const validatedInput = validateWithZod(
|
|
724
|
+
TeamReadMailboxInputSchema,
|
|
725
|
+
input,
|
|
726
|
+
);
|
|
727
|
+
return options.runtime.listMailbox(options.requesterId, {
|
|
728
|
+
unreadOnly: validatedInput.unreadOnly,
|
|
729
|
+
limit: validatedInput.limit,
|
|
730
|
+
markRead: true,
|
|
731
|
+
});
|
|
732
|
+
},
|
|
733
|
+
}) as Tool,
|
|
734
|
+
);
|
|
735
|
+
|
|
736
|
+
tools.push(
|
|
737
|
+
createTool<TeamLogUpdateInput, { id: string }>({
|
|
738
|
+
name: "team_log_update",
|
|
739
|
+
description: "Append a mission log update for this agent.",
|
|
740
|
+
inputSchema: zodToJsonSchema(TeamLogUpdateInputSchema),
|
|
741
|
+
execute: async (input) => {
|
|
742
|
+
const validatedInput = validateWithZod(TeamLogUpdateInputSchema, input);
|
|
743
|
+
const entry = options.runtime.appendMissionLog({
|
|
744
|
+
agentId: options.requesterId,
|
|
745
|
+
taskId: validatedInput.taskId,
|
|
746
|
+
kind: validatedInput.kind,
|
|
747
|
+
summary: validatedInput.summary,
|
|
748
|
+
evidence: validatedInput.evidence,
|
|
749
|
+
nextAction: validatedInput.nextAction,
|
|
750
|
+
});
|
|
751
|
+
return { id: entry.id };
|
|
752
|
+
},
|
|
753
|
+
}) as Tool,
|
|
754
|
+
);
|
|
755
|
+
|
|
756
|
+
tools.push(
|
|
757
|
+
createTool<TeamCleanupInput, { status: string }>({
|
|
758
|
+
name: "team_cleanup",
|
|
759
|
+
description:
|
|
760
|
+
"Clean up the team runtime. Fails if teammates are still running.",
|
|
761
|
+
inputSchema: zodToJsonSchema(TeamCleanupInputSchema),
|
|
762
|
+
execute: async (input) => {
|
|
763
|
+
validateWithZod(TeamCleanupInputSchema, input);
|
|
764
|
+
if (options.runtime.getMemberRole(options.requesterId) !== "lead") {
|
|
765
|
+
throw new Error("Only the lead agent can run cleanup.");
|
|
766
|
+
}
|
|
767
|
+
options.runtime.cleanup();
|
|
768
|
+
return { status: "cleaned" };
|
|
769
|
+
},
|
|
770
|
+
}) as Tool,
|
|
771
|
+
);
|
|
772
|
+
|
|
773
|
+
tools.push(
|
|
774
|
+
createTool<TeamCreateOutcomeInput, { outcomeId: string; status: string }>({
|
|
775
|
+
name: "team_create_outcome",
|
|
776
|
+
description: "Create a converged team outcome.",
|
|
777
|
+
inputSchema: zodToJsonSchema(TeamCreateOutcomeInputSchema),
|
|
778
|
+
execute: async (input) => {
|
|
779
|
+
const validatedInput = validateWithZod(
|
|
780
|
+
TeamCreateOutcomeInputSchema,
|
|
781
|
+
input,
|
|
782
|
+
);
|
|
783
|
+
const outcome = options.runtime.createOutcome({
|
|
784
|
+
title: validatedInput.title,
|
|
785
|
+
requiredSections: validatedInput.requiredSections,
|
|
786
|
+
createdBy: options.requesterId,
|
|
787
|
+
});
|
|
788
|
+
return { outcomeId: outcome.id, status: outcome.status };
|
|
789
|
+
},
|
|
790
|
+
}) as Tool,
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
tools.push(
|
|
794
|
+
createTool<
|
|
795
|
+
TeamAttachOutcomeFragmentInput,
|
|
796
|
+
{ fragmentId: string; status: string }
|
|
797
|
+
>({
|
|
798
|
+
name: "team_attach_outcome_fragment",
|
|
799
|
+
description: "Attach a fragment to an outcome section.",
|
|
800
|
+
inputSchema: zodToJsonSchema(TeamAttachOutcomeFragmentInputSchema),
|
|
801
|
+
execute: async (input) => {
|
|
802
|
+
const validatedInput = validateWithZod(
|
|
803
|
+
TeamAttachOutcomeFragmentInputSchema,
|
|
804
|
+
input,
|
|
805
|
+
);
|
|
806
|
+
const fragment = options.runtime.attachOutcomeFragment({
|
|
807
|
+
outcomeId: validatedInput.outcomeId,
|
|
808
|
+
section: validatedInput.section,
|
|
809
|
+
sourceAgentId: options.requesterId,
|
|
810
|
+
sourceRunId: validatedInput.sourceRunId,
|
|
811
|
+
content: validatedInput.content,
|
|
812
|
+
});
|
|
813
|
+
return { fragmentId: fragment.id, status: fragment.status };
|
|
814
|
+
},
|
|
815
|
+
}) as Tool,
|
|
816
|
+
);
|
|
817
|
+
|
|
818
|
+
tools.push(
|
|
819
|
+
createTool<
|
|
820
|
+
TeamReviewOutcomeFragmentInput,
|
|
821
|
+
{ fragmentId: string; status: string }
|
|
822
|
+
>({
|
|
823
|
+
name: "team_review_outcome_fragment",
|
|
824
|
+
description: "Review one outcome fragment.",
|
|
825
|
+
inputSchema: zodToJsonSchema(TeamReviewOutcomeFragmentInputSchema),
|
|
826
|
+
execute: async (input) => {
|
|
827
|
+
const validatedInput = validateWithZod(
|
|
828
|
+
TeamReviewOutcomeFragmentInputSchema,
|
|
829
|
+
input,
|
|
830
|
+
);
|
|
831
|
+
const fragment = options.runtime.reviewOutcomeFragment({
|
|
832
|
+
fragmentId: validatedInput.fragmentId,
|
|
833
|
+
reviewedBy: options.requesterId,
|
|
834
|
+
approved: validatedInput.approved,
|
|
835
|
+
});
|
|
836
|
+
return { fragmentId: fragment.id, status: fragment.status };
|
|
837
|
+
},
|
|
838
|
+
}) as Tool,
|
|
839
|
+
);
|
|
840
|
+
|
|
841
|
+
tools.push(
|
|
842
|
+
createTool<TeamFinalizeOutcomeInput, { outcomeId: string; status: string }>(
|
|
843
|
+
{
|
|
844
|
+
name: "team_finalize_outcome",
|
|
845
|
+
description: "Finalize one outcome.",
|
|
846
|
+
inputSchema: zodToJsonSchema(TeamFinalizeOutcomeInputSchema),
|
|
847
|
+
execute: async (input) => {
|
|
848
|
+
const validatedInput = validateWithZod(
|
|
849
|
+
TeamFinalizeOutcomeInputSchema,
|
|
850
|
+
input,
|
|
851
|
+
);
|
|
852
|
+
const outcome = options.runtime.finalizeOutcome(
|
|
853
|
+
validatedInput.outcomeId,
|
|
854
|
+
);
|
|
855
|
+
return { outcomeId: outcome.id, status: outcome.status };
|
|
856
|
+
},
|
|
857
|
+
},
|
|
858
|
+
) as Tool,
|
|
859
|
+
);
|
|
860
|
+
|
|
861
|
+
tools.push(
|
|
862
|
+
createTool<
|
|
863
|
+
TeamListOutcomesInput,
|
|
864
|
+
ReturnType<AgentTeamsRuntime["listOutcomes"]>
|
|
865
|
+
>({
|
|
866
|
+
name: "team_list_outcomes",
|
|
867
|
+
description: "List team outcomes.",
|
|
868
|
+
inputSchema: zodToJsonSchema(TeamListOutcomesInputSchema),
|
|
869
|
+
execute: async (input) => {
|
|
870
|
+
validateWithZod(TeamListOutcomesInputSchema, input);
|
|
871
|
+
return options.runtime.listOutcomes();
|
|
872
|
+
},
|
|
873
|
+
}) as Tool,
|
|
874
|
+
);
|
|
875
|
+
|
|
876
|
+
return tools;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
export function reviveTeamStateDates(
|
|
880
|
+
state: TeamRuntimeState,
|
|
881
|
+
): TeamRuntimeState {
|
|
882
|
+
return {
|
|
883
|
+
...state,
|
|
884
|
+
tasks: state.tasks.map((task) => ({
|
|
885
|
+
...task,
|
|
886
|
+
createdAt: new Date(task.createdAt),
|
|
887
|
+
updatedAt: new Date(task.updatedAt),
|
|
888
|
+
})),
|
|
889
|
+
mailbox: state.mailbox.map((message) => ({
|
|
890
|
+
...message,
|
|
891
|
+
sentAt: new Date(message.sentAt),
|
|
892
|
+
readAt: message.readAt ? new Date(message.readAt) : undefined,
|
|
893
|
+
})),
|
|
894
|
+
missionLog: state.missionLog.map((entry) => ({
|
|
895
|
+
...entry,
|
|
896
|
+
ts: new Date(entry.ts),
|
|
897
|
+
})),
|
|
898
|
+
runs: (state.runs ?? []).map((run) => ({
|
|
899
|
+
...run,
|
|
900
|
+
startedAt: new Date(run.startedAt),
|
|
901
|
+
endedAt: run.endedAt ? new Date(run.endedAt) : undefined,
|
|
902
|
+
nextAttemptAt: run.nextAttemptAt
|
|
903
|
+
? new Date(run.nextAttemptAt)
|
|
904
|
+
: undefined,
|
|
905
|
+
heartbeatAt: run.heartbeatAt ? new Date(run.heartbeatAt) : undefined,
|
|
906
|
+
})),
|
|
907
|
+
outcomes: (state.outcomes ?? []).map((outcome) => ({
|
|
908
|
+
...outcome,
|
|
909
|
+
createdAt: new Date(outcome.createdAt),
|
|
910
|
+
finalizedAt: outcome.finalizedAt
|
|
911
|
+
? new Date(outcome.finalizedAt)
|
|
912
|
+
: undefined,
|
|
913
|
+
})),
|
|
914
|
+
outcomeFragments: (state.outcomeFragments ?? []).map((fragment) => ({
|
|
915
|
+
...fragment,
|
|
916
|
+
createdAt: new Date(fragment.createdAt),
|
|
917
|
+
reviewedAt: fragment.reviewedAt
|
|
918
|
+
? new Date(fragment.reviewedAt)
|
|
919
|
+
: undefined,
|
|
920
|
+
})),
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
export function sanitizeTeamName(name: string): string {
|
|
925
|
+
return name
|
|
926
|
+
.toLowerCase()
|
|
927
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
928
|
+
.replace(/^-+|-+$/g, "");
|
|
929
|
+
}
|