opencode-swarm-plugin 0.4.0 → 0.6.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/.beads/issues.jsonl +487 -0
- package/README.md +107 -12
- package/dist/index.js +38 -38
- package/dist/plugin.js +38 -38
- package/examples/agents/swarm-planner.md +138 -0
- package/examples/commands/swarm.md +277 -0
- package/package.json +1 -1
- package/src/index.ts +12 -0
- package/src/learning.ts +13 -0
- package/src/swarm.integration.test.ts +315 -42
- package/src/swarm.ts +528 -52
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
swarm_complete,
|
|
17
17
|
swarm_subtask_prompt,
|
|
18
18
|
swarm_evaluation_prompt,
|
|
19
|
+
swarm_select_strategy,
|
|
20
|
+
swarm_plan_prompt,
|
|
19
21
|
formatSubtaskPromptV2,
|
|
20
22
|
SUBTASK_PROMPT_V2,
|
|
21
23
|
} from "./swarm";
|
|
@@ -119,6 +121,288 @@ describe("swarm_decompose", () => {
|
|
|
119
121
|
});
|
|
120
122
|
});
|
|
121
123
|
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Strategy Selection Tests
|
|
126
|
+
// ============================================================================
|
|
127
|
+
|
|
128
|
+
describe("swarm_select_strategy", () => {
|
|
129
|
+
it("selects feature-based for 'add' tasks", async () => {
|
|
130
|
+
const result = await swarm_select_strategy.execute(
|
|
131
|
+
{
|
|
132
|
+
task: "Add user authentication with OAuth",
|
|
133
|
+
},
|
|
134
|
+
mockContext,
|
|
135
|
+
);
|
|
136
|
+
const parsed = JSON.parse(result);
|
|
137
|
+
|
|
138
|
+
expect(parsed.strategy).toBe("feature-based");
|
|
139
|
+
expect(parsed.confidence).toBeGreaterThan(0.5);
|
|
140
|
+
expect(parsed.reasoning).toContain("add");
|
|
141
|
+
expect(parsed.guidelines).toBeInstanceOf(Array);
|
|
142
|
+
expect(parsed.anti_patterns).toBeInstanceOf(Array);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("selects file-based for 'refactor' tasks", async () => {
|
|
146
|
+
const result = await swarm_select_strategy.execute(
|
|
147
|
+
{
|
|
148
|
+
task: "Refactor all components to use new API",
|
|
149
|
+
},
|
|
150
|
+
mockContext,
|
|
151
|
+
);
|
|
152
|
+
const parsed = JSON.parse(result);
|
|
153
|
+
|
|
154
|
+
expect(parsed.strategy).toBe("file-based");
|
|
155
|
+
expect(parsed.confidence).toBeGreaterThanOrEqual(0.5);
|
|
156
|
+
expect(parsed.reasoning).toContain("refactor");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("selects risk-based for 'fix security' tasks", async () => {
|
|
160
|
+
const result = await swarm_select_strategy.execute(
|
|
161
|
+
{
|
|
162
|
+
task: "Fix security vulnerability in authentication",
|
|
163
|
+
},
|
|
164
|
+
mockContext,
|
|
165
|
+
);
|
|
166
|
+
const parsed = JSON.parse(result);
|
|
167
|
+
|
|
168
|
+
expect(parsed.strategy).toBe("risk-based");
|
|
169
|
+
expect(parsed.confidence).toBeGreaterThan(0.5);
|
|
170
|
+
// Should match either 'fix' or 'security'
|
|
171
|
+
expect(
|
|
172
|
+
parsed.reasoning.includes("fix") || parsed.reasoning.includes("security"),
|
|
173
|
+
).toBe(true);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("defaults to feature-based when no keywords match", async () => {
|
|
177
|
+
const result = await swarm_select_strategy.execute(
|
|
178
|
+
{
|
|
179
|
+
task: "Something completely unrelated without keywords",
|
|
180
|
+
},
|
|
181
|
+
mockContext,
|
|
182
|
+
);
|
|
183
|
+
const parsed = JSON.parse(result);
|
|
184
|
+
|
|
185
|
+
expect(parsed.strategy).toBe("feature-based");
|
|
186
|
+
// Confidence should be lower without keyword matches
|
|
187
|
+
expect(parsed.confidence).toBeLessThanOrEqual(0.6);
|
|
188
|
+
expect(parsed.reasoning).toContain("Defaulting to feature-based");
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("includes confidence score and reasoning", async () => {
|
|
192
|
+
const result = await swarm_select_strategy.execute(
|
|
193
|
+
{
|
|
194
|
+
task: "Implement new dashboard feature",
|
|
195
|
+
},
|
|
196
|
+
mockContext,
|
|
197
|
+
);
|
|
198
|
+
const parsed = JSON.parse(result);
|
|
199
|
+
|
|
200
|
+
expect(parsed).toHaveProperty("strategy");
|
|
201
|
+
expect(parsed).toHaveProperty("confidence");
|
|
202
|
+
expect(parsed).toHaveProperty("reasoning");
|
|
203
|
+
expect(parsed).toHaveProperty("description");
|
|
204
|
+
expect(typeof parsed.confidence).toBe("number");
|
|
205
|
+
expect(parsed.confidence).toBeGreaterThanOrEqual(0);
|
|
206
|
+
expect(parsed.confidence).toBeLessThanOrEqual(1);
|
|
207
|
+
expect(typeof parsed.reasoning).toBe("string");
|
|
208
|
+
expect(parsed.reasoning.length).toBeGreaterThan(0);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("includes alternative strategies with scores", async () => {
|
|
212
|
+
const result = await swarm_select_strategy.execute(
|
|
213
|
+
{
|
|
214
|
+
task: "Build new payment processing module",
|
|
215
|
+
},
|
|
216
|
+
mockContext,
|
|
217
|
+
);
|
|
218
|
+
const parsed = JSON.parse(result);
|
|
219
|
+
|
|
220
|
+
expect(parsed).toHaveProperty("alternatives");
|
|
221
|
+
expect(parsed.alternatives).toBeInstanceOf(Array);
|
|
222
|
+
expect(parsed.alternatives.length).toBe(2); // 3 strategies - 1 selected = 2 alternatives
|
|
223
|
+
|
|
224
|
+
for (const alt of parsed.alternatives) {
|
|
225
|
+
expect(alt).toHaveProperty("strategy");
|
|
226
|
+
expect(alt).toHaveProperty("description");
|
|
227
|
+
expect(alt).toHaveProperty("score");
|
|
228
|
+
expect(["file-based", "feature-based", "risk-based"]).toContain(
|
|
229
|
+
alt.strategy,
|
|
230
|
+
);
|
|
231
|
+
expect(typeof alt.score).toBe("number");
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it("includes codebase context in reasoning when provided", async () => {
|
|
236
|
+
const result = await swarm_select_strategy.execute(
|
|
237
|
+
{
|
|
238
|
+
task: "Add new API endpoint",
|
|
239
|
+
codebase_context: "Using Express.js with TypeScript and PostgreSQL",
|
|
240
|
+
},
|
|
241
|
+
mockContext,
|
|
242
|
+
);
|
|
243
|
+
const parsed = JSON.parse(result);
|
|
244
|
+
|
|
245
|
+
expect(parsed.reasoning).toContain("Express.js");
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// ============================================================================
|
|
250
|
+
// Planning Prompt Tests
|
|
251
|
+
// ============================================================================
|
|
252
|
+
|
|
253
|
+
describe("swarm_plan_prompt", () => {
|
|
254
|
+
it("auto-selects strategy when not specified", async () => {
|
|
255
|
+
const result = await swarm_plan_prompt.execute(
|
|
256
|
+
{
|
|
257
|
+
task: "Add user settings page",
|
|
258
|
+
max_subtasks: 3,
|
|
259
|
+
query_cass: false, // Disable CASS to isolate test
|
|
260
|
+
},
|
|
261
|
+
mockContext,
|
|
262
|
+
);
|
|
263
|
+
const parsed = JSON.parse(result);
|
|
264
|
+
|
|
265
|
+
expect(parsed).toHaveProperty("prompt");
|
|
266
|
+
expect(parsed).toHaveProperty("strategy");
|
|
267
|
+
expect(parsed.strategy).toHaveProperty("selected");
|
|
268
|
+
expect(parsed.strategy).toHaveProperty("reasoning");
|
|
269
|
+
expect(parsed.strategy.selected).toBe("feature-based"); // 'add' keyword
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("uses explicit strategy when provided", async () => {
|
|
273
|
+
const result = await swarm_plan_prompt.execute(
|
|
274
|
+
{
|
|
275
|
+
task: "Do something",
|
|
276
|
+
strategy: "risk-based",
|
|
277
|
+
max_subtasks: 3,
|
|
278
|
+
query_cass: false,
|
|
279
|
+
},
|
|
280
|
+
mockContext,
|
|
281
|
+
);
|
|
282
|
+
const parsed = JSON.parse(result);
|
|
283
|
+
|
|
284
|
+
expect(parsed.strategy.selected).toBe("risk-based");
|
|
285
|
+
expect(parsed.strategy.reasoning).toContain("User-specified strategy");
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("includes strategy guidelines in prompt", async () => {
|
|
289
|
+
const result = await swarm_plan_prompt.execute(
|
|
290
|
+
{
|
|
291
|
+
task: "Refactor the codebase",
|
|
292
|
+
max_subtasks: 4,
|
|
293
|
+
query_cass: false,
|
|
294
|
+
},
|
|
295
|
+
mockContext,
|
|
296
|
+
);
|
|
297
|
+
const parsed = JSON.parse(result);
|
|
298
|
+
|
|
299
|
+
// Prompt should contain strategy-specific guidelines
|
|
300
|
+
expect(parsed.prompt).toContain("## Strategy:");
|
|
301
|
+
expect(parsed.prompt).toContain("### Guidelines");
|
|
302
|
+
expect(parsed.prompt).toContain("### Anti-Patterns");
|
|
303
|
+
expect(parsed.prompt).toContain("### Examples");
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it("includes anti-patterns in output", async () => {
|
|
307
|
+
const result = await swarm_plan_prompt.execute(
|
|
308
|
+
{
|
|
309
|
+
task: "Build new feature",
|
|
310
|
+
max_subtasks: 3,
|
|
311
|
+
query_cass: false,
|
|
312
|
+
},
|
|
313
|
+
mockContext,
|
|
314
|
+
);
|
|
315
|
+
const parsed = JSON.parse(result);
|
|
316
|
+
|
|
317
|
+
expect(parsed.strategy).toHaveProperty("anti_patterns");
|
|
318
|
+
expect(parsed.strategy.anti_patterns).toBeInstanceOf(Array);
|
|
319
|
+
expect(parsed.strategy.anti_patterns.length).toBeGreaterThan(0);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("returns expected_schema and validation_note", async () => {
|
|
323
|
+
const result = await swarm_plan_prompt.execute(
|
|
324
|
+
{
|
|
325
|
+
task: "Some task",
|
|
326
|
+
max_subtasks: 5,
|
|
327
|
+
query_cass: false,
|
|
328
|
+
},
|
|
329
|
+
mockContext,
|
|
330
|
+
);
|
|
331
|
+
const parsed = JSON.parse(result);
|
|
332
|
+
|
|
333
|
+
expect(parsed).toHaveProperty("expected_schema", "BeadTree");
|
|
334
|
+
expect(parsed).toHaveProperty("validation_note");
|
|
335
|
+
expect(parsed.validation_note).toContain("swarm_validate_decomposition");
|
|
336
|
+
expect(parsed).toHaveProperty("schema_hint");
|
|
337
|
+
expect(parsed.schema_hint).toHaveProperty("epic");
|
|
338
|
+
expect(parsed.schema_hint).toHaveProperty("subtasks");
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it("reports CASS status in output (queried flag)", async () => {
|
|
342
|
+
// Test with CASS disabled
|
|
343
|
+
const resultDisabled = await swarm_plan_prompt.execute(
|
|
344
|
+
{
|
|
345
|
+
task: "Add feature",
|
|
346
|
+
max_subtasks: 3,
|
|
347
|
+
query_cass: false,
|
|
348
|
+
},
|
|
349
|
+
mockContext,
|
|
350
|
+
);
|
|
351
|
+
const parsedDisabled = JSON.parse(resultDisabled);
|
|
352
|
+
|
|
353
|
+
expect(parsedDisabled).toHaveProperty("cass_history");
|
|
354
|
+
expect(parsedDisabled.cass_history.queried).toBe(false);
|
|
355
|
+
|
|
356
|
+
// Test with CASS enabled (may or may not be available)
|
|
357
|
+
const resultEnabled = await swarm_plan_prompt.execute(
|
|
358
|
+
{
|
|
359
|
+
task: "Add feature",
|
|
360
|
+
max_subtasks: 3,
|
|
361
|
+
query_cass: true,
|
|
362
|
+
},
|
|
363
|
+
mockContext,
|
|
364
|
+
);
|
|
365
|
+
const parsedEnabled = JSON.parse(resultEnabled);
|
|
366
|
+
|
|
367
|
+
expect(parsedEnabled).toHaveProperty("cass_history");
|
|
368
|
+
expect(parsedEnabled.cass_history).toHaveProperty("queried");
|
|
369
|
+
// If CASS is unavailable, queried will be false with reason
|
|
370
|
+
if (!parsedEnabled.cass_history.queried) {
|
|
371
|
+
expect(parsedEnabled.cass_history).toHaveProperty("reason");
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it("includes context in prompt when provided", async () => {
|
|
376
|
+
const result = await swarm_plan_prompt.execute(
|
|
377
|
+
{
|
|
378
|
+
task: "Add user profile",
|
|
379
|
+
max_subtasks: 3,
|
|
380
|
+
context: "We use Next.js App Router with server components",
|
|
381
|
+
query_cass: false,
|
|
382
|
+
},
|
|
383
|
+
mockContext,
|
|
384
|
+
);
|
|
385
|
+
const parsed = JSON.parse(result);
|
|
386
|
+
|
|
387
|
+
expect(parsed.prompt).toContain("Next.js App Router");
|
|
388
|
+
expect(parsed.prompt).toContain("server components");
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it("includes max_subtasks in prompt", async () => {
|
|
392
|
+
const result = await swarm_plan_prompt.execute(
|
|
393
|
+
{
|
|
394
|
+
task: "Build something",
|
|
395
|
+
max_subtasks: 7,
|
|
396
|
+
query_cass: false,
|
|
397
|
+
},
|
|
398
|
+
mockContext,
|
|
399
|
+
);
|
|
400
|
+
const parsed = JSON.parse(result);
|
|
401
|
+
|
|
402
|
+
expect(parsed.prompt).toContain("2-7 independent subtasks");
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
|
|
122
406
|
describe("swarm_validate_decomposition", () => {
|
|
123
407
|
it("validates correct BeadTree", async () => {
|
|
124
408
|
const validBeadTree = JSON.stringify({
|
|
@@ -959,10 +1243,12 @@ describe("Graceful Degradation", () => {
|
|
|
959
1243
|
// Coordinator-Centric Swarm Tools (V2)
|
|
960
1244
|
// ============================================================================
|
|
961
1245
|
|
|
962
|
-
describe("
|
|
1246
|
+
describe("Swarm Prompt V2 (with Agent Mail/Beads)", () => {
|
|
963
1247
|
describe("formatSubtaskPromptV2", () => {
|
|
964
1248
|
it("generates correct prompt with all fields", () => {
|
|
965
1249
|
const result = formatSubtaskPromptV2({
|
|
1250
|
+
bead_id: "bd-123.1",
|
|
1251
|
+
epic_id: "bd-123",
|
|
966
1252
|
subtask_title: "Add OAuth provider",
|
|
967
1253
|
subtask_description: "Configure Google OAuth in the auth config",
|
|
968
1254
|
files: ["src/auth/google.ts", "src/auth/config.ts"],
|
|
@@ -982,16 +1268,15 @@ describe("Coordinator-Centric Swarm Tools", () => {
|
|
|
982
1268
|
// Check shared context is included
|
|
983
1269
|
expect(result).toContain("We are using NextAuth.js v5");
|
|
984
1270
|
|
|
985
|
-
// Check
|
|
986
|
-
expect(result).toContain("
|
|
987
|
-
expect(result).toContain("
|
|
988
|
-
expect(result).toContain("## Context");
|
|
989
|
-
expect(result).toContain("## Instructions");
|
|
990
|
-
expect(result).toContain("## When Complete");
|
|
1271
|
+
// Check bead/epic IDs are substituted
|
|
1272
|
+
expect(result).toContain("bd-123.1");
|
|
1273
|
+
expect(result).toContain("bd-123");
|
|
991
1274
|
});
|
|
992
1275
|
|
|
993
1276
|
it("handles missing optional fields", () => {
|
|
994
1277
|
const result = formatSubtaskPromptV2({
|
|
1278
|
+
bead_id: "bd-456.1",
|
|
1279
|
+
epic_id: "bd-456",
|
|
995
1280
|
subtask_title: "Simple task",
|
|
996
1281
|
subtask_description: "",
|
|
997
1282
|
files: [],
|
|
@@ -1004,16 +1289,16 @@ describe("Coordinator-Centric Swarm Tools", () => {
|
|
|
1004
1289
|
expect(result).toContain("(see title)");
|
|
1005
1290
|
|
|
1006
1291
|
// Check fallback for empty files
|
|
1007
|
-
expect(result).toContain(
|
|
1008
|
-
"(no specific files assigned - use your judgment)",
|
|
1009
|
-
);
|
|
1292
|
+
expect(result).toContain("(no specific files - use judgment)");
|
|
1010
1293
|
|
|
1011
1294
|
// Check fallback for missing context
|
|
1012
|
-
expect(result).toContain("(none
|
|
1295
|
+
expect(result).toContain("(none)");
|
|
1013
1296
|
});
|
|
1014
1297
|
|
|
1015
1298
|
it("handles files with special characters", () => {
|
|
1016
1299
|
const result = formatSubtaskPromptV2({
|
|
1300
|
+
bead_id: "bd-789.1",
|
|
1301
|
+
epic_id: "bd-789",
|
|
1017
1302
|
subtask_title: "Handle paths",
|
|
1018
1303
|
subtask_description: "Test file paths",
|
|
1019
1304
|
files: [
|
|
@@ -1030,51 +1315,39 @@ describe("Coordinator-Centric Swarm Tools", () => {
|
|
|
1030
1315
|
describe("SUBTASK_PROMPT_V2", () => {
|
|
1031
1316
|
it("contains expected sections", () => {
|
|
1032
1317
|
// Check all main sections are present in the template
|
|
1033
|
-
expect(SUBTASK_PROMPT_V2).toContain("##
|
|
1318
|
+
expect(SUBTASK_PROMPT_V2).toContain("## Task");
|
|
1034
1319
|
expect(SUBTASK_PROMPT_V2).toContain("{subtask_title}");
|
|
1035
1320
|
expect(SUBTASK_PROMPT_V2).toContain("{subtask_description}");
|
|
1036
1321
|
|
|
1037
|
-
expect(SUBTASK_PROMPT_V2).toContain("## Files
|
|
1322
|
+
expect(SUBTASK_PROMPT_V2).toContain("## Files");
|
|
1038
1323
|
expect(SUBTASK_PROMPT_V2).toContain("{file_list}");
|
|
1039
1324
|
|
|
1040
1325
|
expect(SUBTASK_PROMPT_V2).toContain("## Context");
|
|
1041
1326
|
expect(SUBTASK_PROMPT_V2).toContain("{shared_context}");
|
|
1042
1327
|
|
|
1043
|
-
expect(SUBTASK_PROMPT_V2).toContain("##
|
|
1044
|
-
expect(SUBTASK_PROMPT_V2).toContain("Read first");
|
|
1045
|
-
expect(SUBTASK_PROMPT_V2).toContain("Plan your approach");
|
|
1046
|
-
expect(SUBTASK_PROMPT_V2).toContain("Make the changes");
|
|
1047
|
-
expect(SUBTASK_PROMPT_V2).toContain("Verify");
|
|
1048
|
-
|
|
1049
|
-
expect(SUBTASK_PROMPT_V2).toContain("## When Complete");
|
|
1050
|
-
expect(SUBTASK_PROMPT_V2).toContain('"success"');
|
|
1051
|
-
expect(SUBTASK_PROMPT_V2).toContain('"summary"');
|
|
1052
|
-
expect(SUBTASK_PROMPT_V2).toContain('"files_modified"');
|
|
1328
|
+
expect(SUBTASK_PROMPT_V2).toContain("## Workflow");
|
|
1053
1329
|
});
|
|
1054
1330
|
|
|
1055
|
-
it("
|
|
1056
|
-
// V2 prompt
|
|
1057
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1058
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1059
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1060
|
-
expect(SUBTASK_PROMPT_V2).not.toContain("send_message");
|
|
1331
|
+
it("DOES contain Agent Mail instructions", () => {
|
|
1332
|
+
// V2 prompt tells agents to USE Agent Mail
|
|
1333
|
+
expect(SUBTASK_PROMPT_V2).toContain("Agent Mail");
|
|
1334
|
+
expect(SUBTASK_PROMPT_V2).toContain("agentmail_send");
|
|
1335
|
+
expect(SUBTASK_PROMPT_V2).toContain("thread_id");
|
|
1061
1336
|
});
|
|
1062
1337
|
|
|
1063
|
-
it("
|
|
1064
|
-
// V2 prompt
|
|
1065
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1066
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1067
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1068
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1069
|
-
expect(SUBTASK_PROMPT_V2).
|
|
1070
|
-
expect(SUBTASK_PROMPT_V2).not.toContain("swarm_complete");
|
|
1338
|
+
it("DOES contain beads instructions", () => {
|
|
1339
|
+
// V2 prompt tells agents to USE beads
|
|
1340
|
+
expect(SUBTASK_PROMPT_V2).toContain("{bead_id}");
|
|
1341
|
+
expect(SUBTASK_PROMPT_V2).toContain("{epic_id}");
|
|
1342
|
+
expect(SUBTASK_PROMPT_V2).toContain("beads_update");
|
|
1343
|
+
expect(SUBTASK_PROMPT_V2).toContain("beads_create");
|
|
1344
|
+
expect(SUBTASK_PROMPT_V2).toContain("swarm_complete");
|
|
1071
1345
|
});
|
|
1072
1346
|
|
|
1073
|
-
it("
|
|
1074
|
-
|
|
1075
|
-
expect(SUBTASK_PROMPT_V2).toContain("
|
|
1076
|
-
expect(SUBTASK_PROMPT_V2).toContain(
|
|
1077
|
-
expect(SUBTASK_PROMPT_V2).toContain('"blocker"');
|
|
1347
|
+
it("instructs agents to communicate", () => {
|
|
1348
|
+
expect(SUBTASK_PROMPT_V2).toContain("Never work silently");
|
|
1349
|
+
expect(SUBTASK_PROMPT_V2).toContain("Report progress");
|
|
1350
|
+
expect(SUBTASK_PROMPT_V2).toContain("coordinator");
|
|
1078
1351
|
});
|
|
1079
1352
|
});
|
|
1080
1353
|
});
|