opencode-swarm-plugin 0.36.1 → 0.38.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/.hive/issues.jsonl +16 -0
- package/.hive/memories.jsonl +13 -1
- package/.turbo/turbo-build.log +4 -4
- package/.turbo/turbo-test.log +286 -286
- package/CHANGELOG.md +170 -0
- package/README.md +33 -0
- package/bin/swarm.test.ts +106 -0
- package/bin/swarm.ts +181 -208
- package/dist/hive.d.ts +59 -0
- package/dist/hive.d.ts.map +1 -1
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +453 -118
- package/dist/plugin.js +452 -118
- package/dist/swarm-decompose.d.ts +30 -0
- package/dist/swarm-decompose.d.ts.map +1 -1
- package/dist/swarm.d.ts +15 -0
- package/dist/swarm.d.ts.map +1 -1
- package/evals/README.md +27 -10
- package/examples/plugin-wrapper-template.ts +60 -8
- package/package.json +4 -1
- package/src/compaction-hook.test.ts +97 -2
- package/src/compaction-hook.ts +32 -2
- package/src/hive.integration.test.ts +148 -0
- package/src/hive.ts +89 -0
- package/src/swarm-decompose.test.ts +188 -0
- package/src/swarm-decompose.ts +52 -1
- package/src/swarm-orchestrate.test.ts +270 -7
- package/src/swarm-orchestrate.ts +98 -11
- package/src/swarm-prompts.test.ts +121 -0
- package/src/swarm-prompts.ts +295 -2
- package/src/swarm-research.integration.test.ts +157 -0
- package/src/swarm-review.integration.test.ts +24 -29
package/dist/plugin.js
CHANGED
|
@@ -22178,6 +22178,357 @@ Codebase context considered: ${args.codebase_context.slice(0, 200)}...`;
|
|
|
22178
22178
|
};
|
|
22179
22179
|
});
|
|
22180
22180
|
|
|
22181
|
+
// src/eval-capture.ts
|
|
22182
|
+
var exports_eval_capture = {};
|
|
22183
|
+
__export(exports_eval_capture, {
|
|
22184
|
+
updateEvalRecord: () => updateEvalRecord,
|
|
22185
|
+
saveSession: () => saveSession,
|
|
22186
|
+
readSessionEvents: () => readSessionEvents,
|
|
22187
|
+
readPartialRecords: () => readPartialRecords,
|
|
22188
|
+
readEvalRecords: () => readEvalRecords,
|
|
22189
|
+
getSessionPath: () => getSessionPath,
|
|
22190
|
+
getSessionDir: () => getSessionDir,
|
|
22191
|
+
getEvalDataStats: () => getEvalDataStats,
|
|
22192
|
+
getEvalDataPath: () => getEvalDataPath,
|
|
22193
|
+
finalizeEvalRecord: () => finalizeEvalRecord,
|
|
22194
|
+
exportForEvalite: () => exportForEvalite,
|
|
22195
|
+
ensureSessionDir: () => ensureSessionDir,
|
|
22196
|
+
ensureEvalDataDir: () => ensureEvalDataDir,
|
|
22197
|
+
captureSubtaskOutcome: () => captureSubtaskOutcome,
|
|
22198
|
+
captureHumanFeedback: () => captureHumanFeedback,
|
|
22199
|
+
captureDecomposition: () => captureDecomposition,
|
|
22200
|
+
captureCoordinatorEvent: () => captureCoordinatorEvent,
|
|
22201
|
+
appendEvalRecord: () => appendEvalRecord,
|
|
22202
|
+
SubtaskOutcomeSchema: () => SubtaskOutcomeSchema,
|
|
22203
|
+
EvalRecordSchema: () => EvalRecordSchema,
|
|
22204
|
+
DEFAULT_EVAL_DATA_PATH: () => DEFAULT_EVAL_DATA_PATH,
|
|
22205
|
+
CoordinatorSessionSchema: () => CoordinatorSessionSchema,
|
|
22206
|
+
CoordinatorEventSchema: () => CoordinatorEventSchema
|
|
22207
|
+
});
|
|
22208
|
+
import * as fs from "node:fs";
|
|
22209
|
+
import * as os from "node:os";
|
|
22210
|
+
import * as path from "node:path";
|
|
22211
|
+
function getEvalDataPath(projectPath) {
|
|
22212
|
+
return path.join(projectPath, DEFAULT_EVAL_DATA_PATH);
|
|
22213
|
+
}
|
|
22214
|
+
function ensureEvalDataDir(projectPath) {
|
|
22215
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22216
|
+
const dir = path.dirname(evalPath);
|
|
22217
|
+
if (!fs.existsSync(dir)) {
|
|
22218
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
22219
|
+
}
|
|
22220
|
+
}
|
|
22221
|
+
function appendEvalRecord(projectPath, record2) {
|
|
22222
|
+
ensureEvalDataDir(projectPath);
|
|
22223
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22224
|
+
const line = `${JSON.stringify(record2)}
|
|
22225
|
+
`;
|
|
22226
|
+
fs.appendFileSync(evalPath, line, "utf-8");
|
|
22227
|
+
}
|
|
22228
|
+
function readEvalRecords(projectPath) {
|
|
22229
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22230
|
+
if (!fs.existsSync(evalPath)) {
|
|
22231
|
+
return [];
|
|
22232
|
+
}
|
|
22233
|
+
const content = fs.readFileSync(evalPath, "utf-8");
|
|
22234
|
+
const lines = content.trim().split(`
|
|
22235
|
+
`).filter(Boolean);
|
|
22236
|
+
return lines.map((line) => {
|
|
22237
|
+
const parsed = JSON.parse(line);
|
|
22238
|
+
return EvalRecordSchema.parse(parsed);
|
|
22239
|
+
});
|
|
22240
|
+
}
|
|
22241
|
+
function readPartialRecords(projectPath) {
|
|
22242
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22243
|
+
if (!fs.existsSync(evalPath)) {
|
|
22244
|
+
return [];
|
|
22245
|
+
}
|
|
22246
|
+
const content = fs.readFileSync(evalPath, "utf-8");
|
|
22247
|
+
const lines = content.trim().split(`
|
|
22248
|
+
`).filter(Boolean);
|
|
22249
|
+
return lines.map((line) => JSON.parse(line));
|
|
22250
|
+
}
|
|
22251
|
+
function updateEvalRecord(projectPath, id, updates) {
|
|
22252
|
+
const records = readPartialRecords(projectPath);
|
|
22253
|
+
const index = records.findIndex((r) => r.id === id);
|
|
22254
|
+
if (index === -1) {
|
|
22255
|
+
return false;
|
|
22256
|
+
}
|
|
22257
|
+
records[index] = { ...records[index], ...updates };
|
|
22258
|
+
const evalPath = getEvalDataPath(projectPath);
|
|
22259
|
+
const content = `${records.map((r) => JSON.stringify(r)).join(`
|
|
22260
|
+
`)}
|
|
22261
|
+
`;
|
|
22262
|
+
fs.writeFileSync(evalPath, content, "utf-8");
|
|
22263
|
+
return true;
|
|
22264
|
+
}
|
|
22265
|
+
function captureDecomposition(params) {
|
|
22266
|
+
const record2 = {
|
|
22267
|
+
id: params.epicId,
|
|
22268
|
+
timestamp: new Date().toISOString(),
|
|
22269
|
+
project_path: params.projectPath,
|
|
22270
|
+
task: params.task,
|
|
22271
|
+
context: params.context,
|
|
22272
|
+
strategy: params.strategy,
|
|
22273
|
+
subtask_count: params.subtasks.length,
|
|
22274
|
+
epic_title: params.epicTitle,
|
|
22275
|
+
epic_description: params.epicDescription,
|
|
22276
|
+
subtasks: params.subtasks,
|
|
22277
|
+
outcomes: []
|
|
22278
|
+
};
|
|
22279
|
+
inProgressRecords.set(params.epicId, record2);
|
|
22280
|
+
appendEvalRecord(params.projectPath, record2);
|
|
22281
|
+
return record2;
|
|
22282
|
+
}
|
|
22283
|
+
function captureSubtaskOutcome(params) {
|
|
22284
|
+
const outcome = {
|
|
22285
|
+
bead_id: params.beadId,
|
|
22286
|
+
title: params.title,
|
|
22287
|
+
planned_files: params.plannedFiles,
|
|
22288
|
+
actual_files: params.actualFiles,
|
|
22289
|
+
duration_ms: params.durationMs,
|
|
22290
|
+
error_count: params.errorCount,
|
|
22291
|
+
retry_count: params.retryCount,
|
|
22292
|
+
success: params.success,
|
|
22293
|
+
failure_mode: params.failureMode
|
|
22294
|
+
};
|
|
22295
|
+
const record2 = inProgressRecords.get(params.epicId);
|
|
22296
|
+
if (record2) {
|
|
22297
|
+
record2.outcomes = record2.outcomes || [];
|
|
22298
|
+
record2.outcomes.push(outcome);
|
|
22299
|
+
}
|
|
22300
|
+
updateEvalRecord(params.projectPath, params.epicId, {
|
|
22301
|
+
outcomes: record2?.outcomes
|
|
22302
|
+
});
|
|
22303
|
+
}
|
|
22304
|
+
function finalizeEvalRecord(params) {
|
|
22305
|
+
const record2 = inProgressRecords.get(params.epicId);
|
|
22306
|
+
if (!record2 || !record2.outcomes || record2.outcomes.length === 0) {
|
|
22307
|
+
return null;
|
|
22308
|
+
}
|
|
22309
|
+
const outcomes = record2.outcomes;
|
|
22310
|
+
const overallSuccess = outcomes.every((o) => o.success);
|
|
22311
|
+
const totalDurationMs = outcomes.reduce((sum, o) => sum + o.duration_ms, 0);
|
|
22312
|
+
const totalErrors = outcomes.reduce((sum, o) => sum + o.error_count, 0);
|
|
22313
|
+
const allPlannedFiles = record2.subtasks?.flatMap((s) => s.files) || [];
|
|
22314
|
+
const fileOccurrences = new Map;
|
|
22315
|
+
for (const file2 of allPlannedFiles) {
|
|
22316
|
+
fileOccurrences.set(file2, (fileOccurrences.get(file2) || 0) + 1);
|
|
22317
|
+
}
|
|
22318
|
+
const fileOverlapCount = Array.from(fileOccurrences.values()).filter((count) => count > 1).length;
|
|
22319
|
+
const plannedFileSet = new Set(allPlannedFiles);
|
|
22320
|
+
const actualFileSet = new Set(outcomes.flatMap((o) => o.actual_files));
|
|
22321
|
+
const scopeAccuracy = plannedFileSet.size > 0 ? actualFileSet.size / plannedFileSet.size : 1;
|
|
22322
|
+
const durations = outcomes.map((o) => o.duration_ms).filter((d) => d > 0);
|
|
22323
|
+
const timeBalanceRatio = durations.length > 1 ? Math.max(...durations) / Math.min(...durations) : 1;
|
|
22324
|
+
const finalRecord = {
|
|
22325
|
+
...record2,
|
|
22326
|
+
overall_success: overallSuccess,
|
|
22327
|
+
total_duration_ms: totalDurationMs,
|
|
22328
|
+
total_errors: totalErrors,
|
|
22329
|
+
file_overlap_count: fileOverlapCount,
|
|
22330
|
+
scope_accuracy: scopeAccuracy,
|
|
22331
|
+
time_balance_ratio: timeBalanceRatio
|
|
22332
|
+
};
|
|
22333
|
+
updateEvalRecord(params.projectPath, params.epicId, finalRecord);
|
|
22334
|
+
inProgressRecords.delete(params.epicId);
|
|
22335
|
+
return finalRecord;
|
|
22336
|
+
}
|
|
22337
|
+
function captureHumanFeedback(params) {
|
|
22338
|
+
updateEvalRecord(params.projectPath, params.epicId, {
|
|
22339
|
+
human_accepted: params.accepted,
|
|
22340
|
+
human_modified: params.modified,
|
|
22341
|
+
human_notes: params.notes
|
|
22342
|
+
});
|
|
22343
|
+
}
|
|
22344
|
+
function exportForEvalite(projectPath) {
|
|
22345
|
+
const records = readEvalRecords(projectPath);
|
|
22346
|
+
return records.filter((r) => r.outcomes && r.outcomes.length > 0).map((record2) => ({
|
|
22347
|
+
input: {
|
|
22348
|
+
task: record2.task,
|
|
22349
|
+
context: record2.context
|
|
22350
|
+
},
|
|
22351
|
+
expected: {
|
|
22352
|
+
minSubtasks: 2,
|
|
22353
|
+
subtaskCount: record2.subtask_count,
|
|
22354
|
+
requiredFiles: record2.subtasks.flatMap((s) => s.files),
|
|
22355
|
+
overallSuccess: record2.overall_success
|
|
22356
|
+
},
|
|
22357
|
+
actual: record2
|
|
22358
|
+
}));
|
|
22359
|
+
}
|
|
22360
|
+
function getEvalDataStats(projectPath) {
|
|
22361
|
+
const records = readEvalRecords(projectPath);
|
|
22362
|
+
const complete = records.filter((r) => r.outcomes && r.outcomes.length > 0);
|
|
22363
|
+
if (complete.length === 0) {
|
|
22364
|
+
return {
|
|
22365
|
+
totalRecords: records.length,
|
|
22366
|
+
completeRecords: 0,
|
|
22367
|
+
successRate: 0,
|
|
22368
|
+
avgSubtasks: 0,
|
|
22369
|
+
avgDurationMs: 0,
|
|
22370
|
+
avgScopeAccuracy: 0,
|
|
22371
|
+
avgTimeBalance: 0
|
|
22372
|
+
};
|
|
22373
|
+
}
|
|
22374
|
+
const successCount = complete.filter((r) => r.overall_success).length;
|
|
22375
|
+
const avgSubtasks = complete.reduce((sum, r) => sum + (r.outcomes?.length || 0), 0) / complete.length;
|
|
22376
|
+
const avgDurationMs = complete.reduce((sum, r) => sum + (r.total_duration_ms || 0), 0) / complete.length;
|
|
22377
|
+
const avgScopeAccuracy = complete.reduce((sum, r) => sum + (r.scope_accuracy || 1), 0) / complete.length;
|
|
22378
|
+
const avgTimeBalance = complete.reduce((sum, r) => sum + (r.time_balance_ratio || 1), 0) / complete.length;
|
|
22379
|
+
return {
|
|
22380
|
+
totalRecords: records.length,
|
|
22381
|
+
completeRecords: complete.length,
|
|
22382
|
+
successRate: successCount / complete.length,
|
|
22383
|
+
avgSubtasks,
|
|
22384
|
+
avgDurationMs,
|
|
22385
|
+
avgScopeAccuracy,
|
|
22386
|
+
avgTimeBalance
|
|
22387
|
+
};
|
|
22388
|
+
}
|
|
22389
|
+
function getSessionDir() {
|
|
22390
|
+
return path.join(os.homedir(), ".config", "swarm-tools", "sessions");
|
|
22391
|
+
}
|
|
22392
|
+
function getSessionPath(sessionId) {
|
|
22393
|
+
return path.join(getSessionDir(), `${sessionId}.jsonl`);
|
|
22394
|
+
}
|
|
22395
|
+
function ensureSessionDir() {
|
|
22396
|
+
const sessionDir = getSessionDir();
|
|
22397
|
+
if (!fs.existsSync(sessionDir)) {
|
|
22398
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
22399
|
+
}
|
|
22400
|
+
}
|
|
22401
|
+
function captureCoordinatorEvent(event) {
|
|
22402
|
+
CoordinatorEventSchema.parse(event);
|
|
22403
|
+
ensureSessionDir();
|
|
22404
|
+
const sessionPath = getSessionPath(event.session_id);
|
|
22405
|
+
const line = `${JSON.stringify(event)}
|
|
22406
|
+
`;
|
|
22407
|
+
fs.appendFileSync(sessionPath, line, "utf-8");
|
|
22408
|
+
}
|
|
22409
|
+
function readSessionEvents(sessionId) {
|
|
22410
|
+
const sessionPath = getSessionPath(sessionId);
|
|
22411
|
+
if (!fs.existsSync(sessionPath)) {
|
|
22412
|
+
return [];
|
|
22413
|
+
}
|
|
22414
|
+
const content = fs.readFileSync(sessionPath, "utf-8");
|
|
22415
|
+
const lines = content.trim().split(`
|
|
22416
|
+
`).filter(Boolean);
|
|
22417
|
+
return lines.map((line) => {
|
|
22418
|
+
const parsed = JSON.parse(line);
|
|
22419
|
+
return CoordinatorEventSchema.parse(parsed);
|
|
22420
|
+
});
|
|
22421
|
+
}
|
|
22422
|
+
function saveSession(params) {
|
|
22423
|
+
const events = readSessionEvents(params.session_id);
|
|
22424
|
+
if (events.length === 0) {
|
|
22425
|
+
return null;
|
|
22426
|
+
}
|
|
22427
|
+
const timestamps = events.map((e) => new Date(e.timestamp).getTime());
|
|
22428
|
+
const startTime = new Date(Math.min(...timestamps)).toISOString();
|
|
22429
|
+
const endTime = new Date(Math.max(...timestamps)).toISOString();
|
|
22430
|
+
const session = {
|
|
22431
|
+
session_id: params.session_id,
|
|
22432
|
+
epic_id: params.epic_id,
|
|
22433
|
+
start_time: startTime,
|
|
22434
|
+
end_time: endTime,
|
|
22435
|
+
events
|
|
22436
|
+
};
|
|
22437
|
+
return session;
|
|
22438
|
+
}
|
|
22439
|
+
var SubtaskOutcomeSchema, EvalRecordSchema, CoordinatorEventSchema, CoordinatorSessionSchema, DEFAULT_EVAL_DATA_PATH = ".opencode/eval-data.jsonl", inProgressRecords;
|
|
22440
|
+
var init_eval_capture = __esm(() => {
|
|
22441
|
+
init_zod();
|
|
22442
|
+
SubtaskOutcomeSchema = exports_external.object({
|
|
22443
|
+
bead_id: exports_external.string(),
|
|
22444
|
+
title: exports_external.string(),
|
|
22445
|
+
planned_files: exports_external.array(exports_external.string()),
|
|
22446
|
+
actual_files: exports_external.array(exports_external.string()),
|
|
22447
|
+
duration_ms: exports_external.number().int().min(0),
|
|
22448
|
+
error_count: exports_external.number().int().min(0),
|
|
22449
|
+
retry_count: exports_external.number().int().min(0),
|
|
22450
|
+
success: exports_external.boolean(),
|
|
22451
|
+
failure_mode: exports_external.string().optional()
|
|
22452
|
+
});
|
|
22453
|
+
EvalRecordSchema = exports_external.object({
|
|
22454
|
+
id: exports_external.string(),
|
|
22455
|
+
timestamp: exports_external.string(),
|
|
22456
|
+
project_path: exports_external.string(),
|
|
22457
|
+
task: exports_external.string(),
|
|
22458
|
+
context: exports_external.string().optional(),
|
|
22459
|
+
strategy: exports_external.enum(["file-based", "feature-based", "risk-based", "auto"]),
|
|
22460
|
+
subtask_count: exports_external.number().int().min(1),
|
|
22461
|
+
epic_title: exports_external.string(),
|
|
22462
|
+
epic_description: exports_external.string().optional(),
|
|
22463
|
+
subtasks: exports_external.array(exports_external.object({
|
|
22464
|
+
title: exports_external.string(),
|
|
22465
|
+
description: exports_external.string().optional(),
|
|
22466
|
+
files: exports_external.array(exports_external.string()),
|
|
22467
|
+
dependencies: exports_external.array(exports_external.number()).optional(),
|
|
22468
|
+
estimated_complexity: exports_external.number().int().min(1).max(5).optional()
|
|
22469
|
+
})),
|
|
22470
|
+
outcomes: exports_external.array(SubtaskOutcomeSchema).optional(),
|
|
22471
|
+
overall_success: exports_external.boolean().optional(),
|
|
22472
|
+
total_duration_ms: exports_external.number().int().min(0).optional(),
|
|
22473
|
+
total_errors: exports_external.number().int().min(0).optional(),
|
|
22474
|
+
human_accepted: exports_external.boolean().optional(),
|
|
22475
|
+
human_modified: exports_external.boolean().optional(),
|
|
22476
|
+
human_notes: exports_external.string().optional(),
|
|
22477
|
+
file_overlap_count: exports_external.number().int().min(0).optional(),
|
|
22478
|
+
scope_accuracy: exports_external.number().min(0).max(2).optional(),
|
|
22479
|
+
time_balance_ratio: exports_external.number().min(1).optional()
|
|
22480
|
+
});
|
|
22481
|
+
CoordinatorEventSchema = exports_external.discriminatedUnion("event_type", [
|
|
22482
|
+
exports_external.object({
|
|
22483
|
+
session_id: exports_external.string(),
|
|
22484
|
+
epic_id: exports_external.string(),
|
|
22485
|
+
timestamp: exports_external.string(),
|
|
22486
|
+
event_type: exports_external.literal("DECISION"),
|
|
22487
|
+
decision_type: exports_external.enum([
|
|
22488
|
+
"strategy_selected",
|
|
22489
|
+
"worker_spawned",
|
|
22490
|
+
"review_completed",
|
|
22491
|
+
"decomposition_complete"
|
|
22492
|
+
]),
|
|
22493
|
+
payload: exports_external.any()
|
|
22494
|
+
}),
|
|
22495
|
+
exports_external.object({
|
|
22496
|
+
session_id: exports_external.string(),
|
|
22497
|
+
epic_id: exports_external.string(),
|
|
22498
|
+
timestamp: exports_external.string(),
|
|
22499
|
+
event_type: exports_external.literal("VIOLATION"),
|
|
22500
|
+
violation_type: exports_external.enum([
|
|
22501
|
+
"coordinator_edited_file",
|
|
22502
|
+
"coordinator_ran_tests",
|
|
22503
|
+
"coordinator_reserved_files",
|
|
22504
|
+
"no_worker_spawned"
|
|
22505
|
+
]),
|
|
22506
|
+
payload: exports_external.any()
|
|
22507
|
+
}),
|
|
22508
|
+
exports_external.object({
|
|
22509
|
+
session_id: exports_external.string(),
|
|
22510
|
+
epic_id: exports_external.string(),
|
|
22511
|
+
timestamp: exports_external.string(),
|
|
22512
|
+
event_type: exports_external.literal("OUTCOME"),
|
|
22513
|
+
outcome_type: exports_external.enum([
|
|
22514
|
+
"subtask_success",
|
|
22515
|
+
"subtask_retry",
|
|
22516
|
+
"subtask_failed",
|
|
22517
|
+
"epic_complete"
|
|
22518
|
+
]),
|
|
22519
|
+
payload: exports_external.any()
|
|
22520
|
+
})
|
|
22521
|
+
]);
|
|
22522
|
+
CoordinatorSessionSchema = exports_external.object({
|
|
22523
|
+
session_id: exports_external.string(),
|
|
22524
|
+
epic_id: exports_external.string(),
|
|
22525
|
+
start_time: exports_external.string(),
|
|
22526
|
+
end_time: exports_external.string().optional(),
|
|
22527
|
+
events: exports_external.array(CoordinatorEventSchema)
|
|
22528
|
+
});
|
|
22529
|
+
inProgressRecords = new Map;
|
|
22530
|
+
});
|
|
22531
|
+
|
|
22181
22532
|
// src/learning.ts
|
|
22182
22533
|
var exports_learning = {};
|
|
22183
22534
|
__export(exports_learning, {
|
|
@@ -39165,6 +39516,71 @@ var hive_ready = tool({
|
|
|
39165
39516
|
}
|
|
39166
39517
|
}
|
|
39167
39518
|
});
|
|
39519
|
+
var hive_cells = tool({
|
|
39520
|
+
description: `Query cells from the hive database with flexible filtering.
|
|
39521
|
+
|
|
39522
|
+
USE THIS TOOL TO:
|
|
39523
|
+
- List all open cells: hive_cells()
|
|
39524
|
+
- Find cells by status: hive_cells({ status: "in_progress" })
|
|
39525
|
+
- Find cells by type: hive_cells({ type: "bug" })
|
|
39526
|
+
- Get a specific cell by partial ID: hive_cells({ id: "mjkmd" })
|
|
39527
|
+
- Get the next ready (unblocked) cell: hive_cells({ ready: true })
|
|
39528
|
+
- Combine filters: hive_cells({ status: "open", type: "task" })
|
|
39529
|
+
|
|
39530
|
+
RETURNS: Array of cells with id, title, status, priority, type, parent_id, created_at, updated_at
|
|
39531
|
+
|
|
39532
|
+
PREFER THIS OVER hive_query when you need to:
|
|
39533
|
+
- See what work is available
|
|
39534
|
+
- Check status of multiple cells
|
|
39535
|
+
- Find cells matching criteria
|
|
39536
|
+
- Look up a cell by partial ID`,
|
|
39537
|
+
args: {
|
|
39538
|
+
id: tool.schema.string().optional().describe("Partial or full cell ID to look up"),
|
|
39539
|
+
status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("Filter by status"),
|
|
39540
|
+
type: tool.schema.enum(["task", "bug", "feature", "epic", "chore"]).optional().describe("Filter by type"),
|
|
39541
|
+
ready: tool.schema.boolean().optional().describe("If true, return only the next unblocked cell"),
|
|
39542
|
+
limit: tool.schema.number().optional().describe("Max cells to return (default 20)")
|
|
39543
|
+
},
|
|
39544
|
+
async execute(args, ctx) {
|
|
39545
|
+
const projectKey = getHiveWorkingDirectory();
|
|
39546
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
39547
|
+
try {
|
|
39548
|
+
if (args.id) {
|
|
39549
|
+
const fullId = await resolvePartialId(adapter, projectKey, args.id) || args.id;
|
|
39550
|
+
const cell = await adapter.getCell(projectKey, fullId);
|
|
39551
|
+
if (!cell) {
|
|
39552
|
+
throw new HiveError(`No cell found matching ID '${args.id}'`, "hive_cells");
|
|
39553
|
+
}
|
|
39554
|
+
const formatted2 = formatCellForOutput(cell);
|
|
39555
|
+
return JSON.stringify([formatted2], null, 2);
|
|
39556
|
+
}
|
|
39557
|
+
if (args.ready) {
|
|
39558
|
+
const ready = await adapter.getNextReadyCell(projectKey);
|
|
39559
|
+
if (!ready) {
|
|
39560
|
+
return JSON.stringify([], null, 2);
|
|
39561
|
+
}
|
|
39562
|
+
const formatted2 = formatCellForOutput(ready);
|
|
39563
|
+
return JSON.stringify([formatted2], null, 2);
|
|
39564
|
+
}
|
|
39565
|
+
const cells = await adapter.queryCells(projectKey, {
|
|
39566
|
+
status: args.status,
|
|
39567
|
+
type: args.type,
|
|
39568
|
+
limit: args.limit || 20
|
|
39569
|
+
});
|
|
39570
|
+
const formatted = cells.map((c) => formatCellForOutput(c));
|
|
39571
|
+
return JSON.stringify(formatted, null, 2);
|
|
39572
|
+
} catch (error45) {
|
|
39573
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
39574
|
+
if (message.includes("Ambiguous hash")) {
|
|
39575
|
+
throw new HiveError(`Ambiguous ID '${args.id}': multiple cells match. Please provide more characters.`, "hive_cells");
|
|
39576
|
+
}
|
|
39577
|
+
if (message.includes("Bead not found") || message.includes("Cell not found")) {
|
|
39578
|
+
throw new HiveError(`No cell found matching ID '${args.id || "unknown"}'`, "hive_cells");
|
|
39579
|
+
}
|
|
39580
|
+
throw new HiveError(`Failed to query cells: ${message}`, "hive_cells");
|
|
39581
|
+
}
|
|
39582
|
+
}
|
|
39583
|
+
});
|
|
39168
39584
|
var hive_sync = tool({
|
|
39169
39585
|
description: "Sync hive to git and push (MANDATORY at session end)",
|
|
39170
39586
|
args: {
|
|
@@ -39306,6 +39722,7 @@ var hiveTools = {
|
|
|
39306
39722
|
hive_close,
|
|
39307
39723
|
hive_start,
|
|
39308
39724
|
hive_ready,
|
|
39725
|
+
hive_cells,
|
|
39309
39726
|
hive_sync,
|
|
39310
39727
|
hive_link_thread
|
|
39311
39728
|
};
|
|
@@ -41464,122 +41881,7 @@ init_swarm_strategies();
|
|
|
41464
41881
|
init_dist();
|
|
41465
41882
|
init_zod();
|
|
41466
41883
|
init_swarm_strategies();
|
|
41467
|
-
|
|
41468
|
-
// src/eval-capture.ts
|
|
41469
|
-
init_zod();
|
|
41470
|
-
import * as fs from "node:fs";
|
|
41471
|
-
import * as os from "node:os";
|
|
41472
|
-
import * as path from "node:path";
|
|
41473
|
-
var SubtaskOutcomeSchema = exports_external.object({
|
|
41474
|
-
bead_id: exports_external.string(),
|
|
41475
|
-
title: exports_external.string(),
|
|
41476
|
-
planned_files: exports_external.array(exports_external.string()),
|
|
41477
|
-
actual_files: exports_external.array(exports_external.string()),
|
|
41478
|
-
duration_ms: exports_external.number().int().min(0),
|
|
41479
|
-
error_count: exports_external.number().int().min(0),
|
|
41480
|
-
retry_count: exports_external.number().int().min(0),
|
|
41481
|
-
success: exports_external.boolean(),
|
|
41482
|
-
failure_mode: exports_external.string().optional()
|
|
41483
|
-
});
|
|
41484
|
-
var EvalRecordSchema = exports_external.object({
|
|
41485
|
-
id: exports_external.string(),
|
|
41486
|
-
timestamp: exports_external.string(),
|
|
41487
|
-
project_path: exports_external.string(),
|
|
41488
|
-
task: exports_external.string(),
|
|
41489
|
-
context: exports_external.string().optional(),
|
|
41490
|
-
strategy: exports_external.enum(["file-based", "feature-based", "risk-based", "auto"]),
|
|
41491
|
-
subtask_count: exports_external.number().int().min(1),
|
|
41492
|
-
epic_title: exports_external.string(),
|
|
41493
|
-
epic_description: exports_external.string().optional(),
|
|
41494
|
-
subtasks: exports_external.array(exports_external.object({
|
|
41495
|
-
title: exports_external.string(),
|
|
41496
|
-
description: exports_external.string().optional(),
|
|
41497
|
-
files: exports_external.array(exports_external.string()),
|
|
41498
|
-
dependencies: exports_external.array(exports_external.number()).optional(),
|
|
41499
|
-
estimated_complexity: exports_external.number().int().min(1).max(5).optional()
|
|
41500
|
-
})),
|
|
41501
|
-
outcomes: exports_external.array(SubtaskOutcomeSchema).optional(),
|
|
41502
|
-
overall_success: exports_external.boolean().optional(),
|
|
41503
|
-
total_duration_ms: exports_external.number().int().min(0).optional(),
|
|
41504
|
-
total_errors: exports_external.number().int().min(0).optional(),
|
|
41505
|
-
human_accepted: exports_external.boolean().optional(),
|
|
41506
|
-
human_modified: exports_external.boolean().optional(),
|
|
41507
|
-
human_notes: exports_external.string().optional(),
|
|
41508
|
-
file_overlap_count: exports_external.number().int().min(0).optional(),
|
|
41509
|
-
scope_accuracy: exports_external.number().min(0).max(2).optional(),
|
|
41510
|
-
time_balance_ratio: exports_external.number().min(1).optional()
|
|
41511
|
-
});
|
|
41512
|
-
var CoordinatorEventSchema = exports_external.discriminatedUnion("event_type", [
|
|
41513
|
-
exports_external.object({
|
|
41514
|
-
session_id: exports_external.string(),
|
|
41515
|
-
epic_id: exports_external.string(),
|
|
41516
|
-
timestamp: exports_external.string(),
|
|
41517
|
-
event_type: exports_external.literal("DECISION"),
|
|
41518
|
-
decision_type: exports_external.enum([
|
|
41519
|
-
"strategy_selected",
|
|
41520
|
-
"worker_spawned",
|
|
41521
|
-
"review_completed",
|
|
41522
|
-
"decomposition_complete"
|
|
41523
|
-
]),
|
|
41524
|
-
payload: exports_external.any()
|
|
41525
|
-
}),
|
|
41526
|
-
exports_external.object({
|
|
41527
|
-
session_id: exports_external.string(),
|
|
41528
|
-
epic_id: exports_external.string(),
|
|
41529
|
-
timestamp: exports_external.string(),
|
|
41530
|
-
event_type: exports_external.literal("VIOLATION"),
|
|
41531
|
-
violation_type: exports_external.enum([
|
|
41532
|
-
"coordinator_edited_file",
|
|
41533
|
-
"coordinator_ran_tests",
|
|
41534
|
-
"coordinator_reserved_files",
|
|
41535
|
-
"no_worker_spawned"
|
|
41536
|
-
]),
|
|
41537
|
-
payload: exports_external.any()
|
|
41538
|
-
}),
|
|
41539
|
-
exports_external.object({
|
|
41540
|
-
session_id: exports_external.string(),
|
|
41541
|
-
epic_id: exports_external.string(),
|
|
41542
|
-
timestamp: exports_external.string(),
|
|
41543
|
-
event_type: exports_external.literal("OUTCOME"),
|
|
41544
|
-
outcome_type: exports_external.enum([
|
|
41545
|
-
"subtask_success",
|
|
41546
|
-
"subtask_retry",
|
|
41547
|
-
"subtask_failed",
|
|
41548
|
-
"epic_complete"
|
|
41549
|
-
]),
|
|
41550
|
-
payload: exports_external.any()
|
|
41551
|
-
})
|
|
41552
|
-
]);
|
|
41553
|
-
var CoordinatorSessionSchema = exports_external.object({
|
|
41554
|
-
session_id: exports_external.string(),
|
|
41555
|
-
epic_id: exports_external.string(),
|
|
41556
|
-
start_time: exports_external.string(),
|
|
41557
|
-
end_time: exports_external.string().optional(),
|
|
41558
|
-
events: exports_external.array(CoordinatorEventSchema)
|
|
41559
|
-
});
|
|
41560
|
-
var inProgressRecords = new Map;
|
|
41561
|
-
function getSessionDir() {
|
|
41562
|
-
return path.join(os.homedir(), ".config", "swarm-tools", "sessions");
|
|
41563
|
-
}
|
|
41564
|
-
function getSessionPath(sessionId) {
|
|
41565
|
-
return path.join(getSessionDir(), `${sessionId}.jsonl`);
|
|
41566
|
-
}
|
|
41567
|
-
function ensureSessionDir() {
|
|
41568
|
-
const sessionDir = getSessionDir();
|
|
41569
|
-
if (!fs.existsSync(sessionDir)) {
|
|
41570
|
-
fs.mkdirSync(sessionDir, { recursive: true });
|
|
41571
|
-
}
|
|
41572
|
-
}
|
|
41573
|
-
function captureCoordinatorEvent(event) {
|
|
41574
|
-
CoordinatorEventSchema.parse(event);
|
|
41575
|
-
ensureSessionDir();
|
|
41576
|
-
const sessionPath = getSessionPath(event.session_id);
|
|
41577
|
-
const line = `${JSON.stringify(event)}
|
|
41578
|
-
`;
|
|
41579
|
-
fs.appendFileSync(sessionPath, line, "utf-8");
|
|
41580
|
-
}
|
|
41581
|
-
|
|
41582
|
-
// src/swarm-decompose.ts
|
|
41884
|
+
init_eval_capture();
|
|
41583
41885
|
var DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
|
|
41584
41886
|
|
|
41585
41887
|
## Task
|
|
@@ -41897,9 +42199,14 @@ ${fullContext}` : `## Additional Context
|
|
|
41897
42199
|
}
|
|
41898
42200
|
});
|
|
41899
42201
|
var swarm_validate_decomposition = tool({
|
|
41900
|
-
description: "Validate a decomposition response against CellTreeSchema",
|
|
42202
|
+
description: "Validate a decomposition response against CellTreeSchema and capture for eval",
|
|
41901
42203
|
args: {
|
|
41902
|
-
response: tool.schema.string().describe("JSON response from agent (CellTree format)")
|
|
42204
|
+
response: tool.schema.string().describe("JSON response from agent (CellTree format)"),
|
|
42205
|
+
project_path: tool.schema.string().optional().describe("Project path for eval capture"),
|
|
42206
|
+
task: tool.schema.string().optional().describe("Original task description for eval capture"),
|
|
42207
|
+
context: tool.schema.string().optional().describe("Context provided for decomposition"),
|
|
42208
|
+
strategy: tool.schema.enum(["file-based", "feature-based", "risk-based", "auto"]).optional().describe("Decomposition strategy used"),
|
|
42209
|
+
epic_id: tool.schema.string().optional().describe("Epic ID for eval capture")
|
|
41903
42210
|
},
|
|
41904
42211
|
async execute(args) {
|
|
41905
42212
|
try {
|
|
@@ -41933,6 +42240,29 @@ var swarm_validate_decomposition = tool({
|
|
|
41933
42240
|
}
|
|
41934
42241
|
}
|
|
41935
42242
|
const instructionConflicts = detectInstructionConflicts(validated.subtasks);
|
|
42243
|
+
if (args.project_path && args.task && args.strategy && args.epic_id) {
|
|
42244
|
+
try {
|
|
42245
|
+
const { captureDecomposition: captureDecomposition2 } = await Promise.resolve().then(() => (init_eval_capture(), exports_eval_capture));
|
|
42246
|
+
captureDecomposition2({
|
|
42247
|
+
epicId: args.epic_id,
|
|
42248
|
+
projectPath: args.project_path,
|
|
42249
|
+
task: args.task,
|
|
42250
|
+
context: args.context,
|
|
42251
|
+
strategy: args.strategy,
|
|
42252
|
+
epicTitle: validated.epic.title,
|
|
42253
|
+
epicDescription: validated.epic.description,
|
|
42254
|
+
subtasks: validated.subtasks.map((s) => ({
|
|
42255
|
+
title: s.title,
|
|
42256
|
+
description: s.description,
|
|
42257
|
+
files: s.files,
|
|
42258
|
+
dependencies: s.dependencies,
|
|
42259
|
+
estimated_complexity: s.estimated_complexity
|
|
42260
|
+
}))
|
|
42261
|
+
});
|
|
42262
|
+
} catch (error45) {
|
|
42263
|
+
console.warn("[swarm_validate_decomposition] Failed to capture decomposition:", error45);
|
|
42264
|
+
}
|
|
42265
|
+
}
|
|
41936
42266
|
return JSON.stringify({
|
|
41937
42267
|
valid: true,
|
|
41938
42268
|
cell_tree: validated,
|
|
@@ -44080,6 +44410,7 @@ var worktreeTools = {
|
|
|
44080
44410
|
init_dist();
|
|
44081
44411
|
init_zod();
|
|
44082
44412
|
import { sendSwarmMessage as sendSwarmMessage2 } from "swarm-mail";
|
|
44413
|
+
init_eval_capture();
|
|
44083
44414
|
var ReviewIssueSchema = exports_external.object({
|
|
44084
44415
|
file: exports_external.string(),
|
|
44085
44416
|
line: exports_external.number().optional(),
|
|
@@ -44436,6 +44767,7 @@ var reviewTools = {
|
|
|
44436
44767
|
};
|
|
44437
44768
|
|
|
44438
44769
|
// src/swarm-orchestrate.ts
|
|
44770
|
+
init_eval_capture();
|
|
44439
44771
|
function generateWorkerHandoff(params) {
|
|
44440
44772
|
const handoff = {
|
|
44441
44773
|
contract: {
|
|
@@ -46024,6 +46356,7 @@ var orchestrateTools = {
|
|
|
46024
46356
|
};
|
|
46025
46357
|
|
|
46026
46358
|
// src/swarm-prompts.ts
|
|
46359
|
+
init_eval_capture();
|
|
46027
46360
|
var STRATEGY_DECOMPOSITION_PROMPT2 = `You are decomposing a task into parallelizable subtasks for a swarm of agents.
|
|
46028
46361
|
|
|
46029
46362
|
## Task
|
|
@@ -62712,6 +63045,7 @@ function guardrailOutput(toolName, output, config2 = DEFAULT_GUARDRAIL_CONFIG) {
|
|
|
62712
63045
|
}
|
|
62713
63046
|
|
|
62714
63047
|
// src/planning-guardrails.ts
|
|
63048
|
+
init_eval_capture();
|
|
62715
63049
|
var FILE_MODIFICATION_PATTERNS = [
|
|
62716
63050
|
/\bimplement\b/i,
|
|
62717
63051
|
/\bcreate\b.*\.(ts|js|tsx|jsx|py|rs|go|java|rb|swift|kt)/i,
|
|
@@ -78,9 +78,24 @@ export declare const swarm_validate_decomposition: {
|
|
|
78
78
|
description: string;
|
|
79
79
|
args: {
|
|
80
80
|
response: z.ZodString;
|
|
81
|
+
project_path: z.ZodOptional<z.ZodString>;
|
|
82
|
+
task: z.ZodOptional<z.ZodString>;
|
|
83
|
+
context: z.ZodOptional<z.ZodString>;
|
|
84
|
+
strategy: z.ZodOptional<z.ZodEnum<{
|
|
85
|
+
"file-based": "file-based";
|
|
86
|
+
"feature-based": "feature-based";
|
|
87
|
+
"risk-based": "risk-based";
|
|
88
|
+
auto: "auto";
|
|
89
|
+
}>>;
|
|
90
|
+
epic_id: z.ZodOptional<z.ZodString>;
|
|
81
91
|
};
|
|
82
92
|
execute(args: {
|
|
83
93
|
response: string;
|
|
94
|
+
project_path?: string | undefined;
|
|
95
|
+
task?: string | undefined;
|
|
96
|
+
context?: string | undefined;
|
|
97
|
+
strategy?: "file-based" | "feature-based" | "risk-based" | "auto" | undefined;
|
|
98
|
+
epic_id?: string | undefined;
|
|
84
99
|
}, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
85
100
|
};
|
|
86
101
|
/**
|
|
@@ -211,9 +226,24 @@ export declare const decomposeTools: {
|
|
|
211
226
|
description: string;
|
|
212
227
|
args: {
|
|
213
228
|
response: z.ZodString;
|
|
229
|
+
project_path: z.ZodOptional<z.ZodString>;
|
|
230
|
+
task: z.ZodOptional<z.ZodString>;
|
|
231
|
+
context: z.ZodOptional<z.ZodString>;
|
|
232
|
+
strategy: z.ZodOptional<z.ZodEnum<{
|
|
233
|
+
"file-based": "file-based";
|
|
234
|
+
"feature-based": "feature-based";
|
|
235
|
+
"risk-based": "risk-based";
|
|
236
|
+
auto: "auto";
|
|
237
|
+
}>>;
|
|
238
|
+
epic_id: z.ZodOptional<z.ZodString>;
|
|
214
239
|
};
|
|
215
240
|
execute(args: {
|
|
216
241
|
response: string;
|
|
242
|
+
project_path?: string | undefined;
|
|
243
|
+
task?: string | undefined;
|
|
244
|
+
context?: string | undefined;
|
|
245
|
+
strategy?: "file-based" | "feature-based" | "risk-based" | "auto" | undefined;
|
|
246
|
+
epic_id?: string | undefined;
|
|
217
247
|
}, context: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
218
248
|
};
|
|
219
249
|
swarm_delegate_planning: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swarm-decompose.d.ts","sourceRoot":"","sources":["../src/swarm-decompose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyJxB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,mBAAmB,GAAG,eAAe,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;CACrB;AA8CD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACvD,mBAAmB,EAAE,CAmDvB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,GACnC,MAAM,EAAE,CAgBV;AA+GD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;CAiG1B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,4BAA4B
|
|
1
|
+
{"version":3,"file":"swarm-decompose.d.ts","sourceRoot":"","sources":["../src/swarm-decompose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyJxB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,mBAAmB,GAAG,eAAe,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;CACrB;AA8CD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACvD,mBAAmB,EAAE,CAmDvB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,GACnC,MAAM,EAAE,CAgBV;AA+GD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;CAiG1B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;CAqKvC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;CAuMlC,CAAC;AAMH,qBAAa,UAAW,SAAQ,KAAK;aAGjB,SAAS,EAAE,MAAM;aACjB,OAAO,CAAC,EAAE,OAAO;gBAFjC,OAAO,EAAE,MAAM,EACC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,YAAA;CAKpC;AAED,qBAAa,kBAAmB,SAAQ,UAAU;aAG9B,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ;gBADrC,OAAO,EAAE,MAAM,EACC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,YAAA;CAIxC;AAkCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;CA0RjC,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAK1B,CAAC"}
|