borgmcp 4.1.0 → 4.2.1
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/dist/direct-log.d.ts +1 -1
- package/dist/direct-log.d.ts.map +1 -1
- package/dist/direct-log.js +18 -2
- package/dist/direct-log.js.map +1 -1
- package/dist/drone-management.d.ts +19 -2
- package/dist/drone-management.d.ts.map +1 -1
- package/dist/drone-management.js +17 -7
- package/dist/drone-management.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +235 -42
- package/dist/index.js.map +1 -1
- package/dist/tool-manifest.d.ts +14 -0
- package/dist/tool-manifest.d.ts.map +1 -1
- package/dist/tool-manifest.js +520 -1
- package/dist/tool-manifest.js.map +1 -1
- package/package.json +1 -1
- package/src/direct-log.ts +17 -2
- package/src/drone-management.ts +35 -9
- package/src/index.ts +240 -42
- package/src/tool-manifest.ts +546 -1
package/dist/index.js
CHANGED
|
@@ -112,6 +112,17 @@ export function formatUpdatedRoleResult(role, advisory) {
|
|
|
112
112
|
const tag = tags ? ` (${tags})` : '';
|
|
113
113
|
return appendServerAdvisory(`Updated role **${role.name}**${tag} (id: ${role.id}).`, advisory);
|
|
114
114
|
}
|
|
115
|
+
// gh#496: the unread drain runs on every wake, so its structured payload must
|
|
116
|
+
// stay proportional to the entries it returns. Rosters are deliberately NOT
|
|
117
|
+
// included — entries already carry drone_label/role_name, and borg_roster
|
|
118
|
+
// serves identity mapping when a consumer needs it.
|
|
119
|
+
export function buildReadLogStructuredContent(input) {
|
|
120
|
+
return {
|
|
121
|
+
entries: input.entries,
|
|
122
|
+
behind_by: typeof input.behind_by === 'number' ? input.behind_by : null,
|
|
123
|
+
has_more: input.has_more === true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
115
126
|
export function formatPatchedRoleSectionResult(action, heading, role, advisory) {
|
|
116
127
|
const verb = action === 'replace' ? 'Replaced' : action === 'insert' ? 'Inserted' : 'Deleted';
|
|
117
128
|
return appendServerAdvisory(`${verb} section **${heading}** in role **${role.name}** (id: ${role.id}).`, advisory);
|
|
@@ -257,8 +268,15 @@ export async function main() {
|
|
|
257
268
|
isError: true,
|
|
258
269
|
};
|
|
259
270
|
}
|
|
271
|
+
const described = {
|
|
272
|
+
name: def.name,
|
|
273
|
+
description: def.description,
|
|
274
|
+
inputSchema: def.inputSchema,
|
|
275
|
+
outputSchema: def.outputSchema ?? null,
|
|
276
|
+
};
|
|
260
277
|
return {
|
|
261
|
-
content: [{ type: 'text', text: JSON.stringify(
|
|
278
|
+
content: [{ type: 'text', text: JSON.stringify(described, null, 2) }],
|
|
279
|
+
structuredContent: described,
|
|
262
280
|
};
|
|
263
281
|
}
|
|
264
282
|
// gh#899: borg_tool dispatcher — unwrap to the inner tool and fall through
|
|
@@ -306,6 +324,7 @@ export async function main() {
|
|
|
306
324
|
text: 'Not connected to a cube. Use `borg_assimilate cube_name="<name>"` to join one.',
|
|
307
325
|
},
|
|
308
326
|
],
|
|
327
|
+
structuredContent: { connected: false },
|
|
309
328
|
};
|
|
310
329
|
}
|
|
311
330
|
seedDisplayIdentity(active);
|
|
@@ -358,10 +377,12 @@ export async function main() {
|
|
|
358
377
|
: '';
|
|
359
378
|
// gh#285: version-mismatch nudge when on-disk package is newer.
|
|
360
379
|
let versionHeader = '';
|
|
380
|
+
let onDiskVersion = null;
|
|
361
381
|
try {
|
|
362
382
|
const running = getPackageVersion();
|
|
363
383
|
const onDisk = getOnDiskVersion();
|
|
364
384
|
if (running !== 'unknown' && onDisk !== 'unknown' && onDisk !== running) {
|
|
385
|
+
onDiskVersion = onDisk;
|
|
365
386
|
const [rMaj, rMin, rPat] = running.split('.').map(Number);
|
|
366
387
|
const [dMaj, dMin, dPat] = onDisk.split('.').map(Number);
|
|
367
388
|
const onDiskNewer = dMaj > rMaj || (dMaj === rMaj && dMin > rMin) || (dMaj === rMaj && dMin === rMin && dPat > rPat);
|
|
@@ -371,7 +392,21 @@ export async function main() {
|
|
|
371
392
|
}
|
|
372
393
|
}
|
|
373
394
|
catch { /* never break regen */ }
|
|
374
|
-
return {
|
|
395
|
+
return {
|
|
396
|
+
content: [{ type: 'text', text: versionHeader + prefix + formatRegenMarkdown(displayedResult, { mode }) }],
|
|
397
|
+
structuredContent: {
|
|
398
|
+
connected: true,
|
|
399
|
+
mode,
|
|
400
|
+
cube: displayedResult.cube,
|
|
401
|
+
drone: displayedResult.drone,
|
|
402
|
+
role: displayedResult.role,
|
|
403
|
+
behind_by: typeof displayedResult.behind_by === 'number' ? displayedResult.behind_by : null,
|
|
404
|
+
decision_topics: (displayedResult.decisions ?? []).map((d) => d.topic),
|
|
405
|
+
running_version: getPackageVersion(),
|
|
406
|
+
on_disk_version: onDiskVersion,
|
|
407
|
+
wake_path_healthy: inboxMonitorHealthy,
|
|
408
|
+
},
|
|
409
|
+
};
|
|
375
410
|
}
|
|
376
411
|
case 'borg_assimilate': {
|
|
377
412
|
const cubeName = args?.cube_name;
|
|
@@ -417,6 +452,11 @@ export async function main() {
|
|
|
417
452
|
].join('\n');
|
|
418
453
|
return {
|
|
419
454
|
content: [{ type: 'text', text: header + formatRegenMarkdown(displayedResult, { mode: 'full' }) }],
|
|
455
|
+
structuredContent: {
|
|
456
|
+
reattached: true,
|
|
457
|
+
cube_name: displayIdentity.cubeName,
|
|
458
|
+
drone_label: displayIdentity.droneLabel,
|
|
459
|
+
},
|
|
420
460
|
};
|
|
421
461
|
}
|
|
422
462
|
catch (err) {
|
|
@@ -426,7 +466,10 @@ export async function main() {
|
|
|
426
466
|
}
|
|
427
467
|
}
|
|
428
468
|
case 'borg_version': {
|
|
429
|
-
return {
|
|
469
|
+
return {
|
|
470
|
+
content: [{ type: 'text', text: `borgmcp ${getPackageVersion()}` }],
|
|
471
|
+
structuredContent: { version: getPackageVersion() },
|
|
472
|
+
};
|
|
430
473
|
}
|
|
431
474
|
case 'borg_playbook': {
|
|
432
475
|
// gh#912: serve the on-demand operating-playbook chapter (static
|
|
@@ -446,7 +489,14 @@ export async function main() {
|
|
|
446
489
|
: topic
|
|
447
490
|
? `No exact match for "${topic}". Full Borg MCP docs index — WebFetch the URL you need:`
|
|
448
491
|
: `Borg MCP docs index — WebFetch the URL of the section you need:`;
|
|
449
|
-
return {
|
|
492
|
+
return {
|
|
493
|
+
content: [{ type: 'text', text: `${header}\n\n${formatDocsIndex(sections)}` }],
|
|
494
|
+
structuredContent: {
|
|
495
|
+
topic: topic || null,
|
|
496
|
+
matched: matched.length > 0,
|
|
497
|
+
sections: sections.map((s) => ({ slug: s.slug, title: s.title, url: s.url, summary: s.summary })),
|
|
498
|
+
},
|
|
499
|
+
};
|
|
450
500
|
}
|
|
451
501
|
case 'borg_whoami': {
|
|
452
502
|
const active = await requireActiveCube();
|
|
@@ -476,7 +526,10 @@ export async function main() {
|
|
|
476
526
|
// The invocation-local server truth remains authoritative even if
|
|
477
527
|
// the display-only persistence refresh cannot be written.
|
|
478
528
|
}
|
|
479
|
-
return {
|
|
529
|
+
return {
|
|
530
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
531
|
+
structuredContent: { ...result },
|
|
532
|
+
};
|
|
480
533
|
}
|
|
481
534
|
case 'borg_cube': {
|
|
482
535
|
// No-cache invariant (T1.2 — 0.7.0): both `getCubeInfo` and
|
|
@@ -529,7 +582,10 @@ export async function main() {
|
|
|
529
582
|
}
|
|
530
583
|
lines.push('');
|
|
531
584
|
lines.push(getDronePlaybook());
|
|
532
|
-
return {
|
|
585
|
+
return {
|
|
586
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
587
|
+
structuredContent: { cube, roles },
|
|
588
|
+
};
|
|
533
589
|
}
|
|
534
590
|
case 'borg_role': {
|
|
535
591
|
// No-cache invariant (T1.2 — 0.7.0): role reads MUST fetch
|
|
@@ -544,7 +600,7 @@ export async function main() {
|
|
|
544
600
|
``,
|
|
545
601
|
role.detailed_description || '_(no detailed description set)_',
|
|
546
602
|
].join('\n');
|
|
547
|
-
return { content: [{ type: 'text', text }] };
|
|
603
|
+
return { content: [{ type: 'text', text }], structuredContent: { role } };
|
|
548
604
|
}
|
|
549
605
|
const { role } = await getRoleInfo(active.sessionToken, active.apiUrl, active.serverTrustIdentity);
|
|
550
606
|
const text = [
|
|
@@ -552,7 +608,7 @@ export async function main() {
|
|
|
552
608
|
``,
|
|
553
609
|
role.detailed_description || '_(no detailed description set)_',
|
|
554
610
|
].join('\n');
|
|
555
|
-
return { content: [{ type: 'text', text }] };
|
|
611
|
+
return { content: [{ type: 'text', text }], structuredContent: { role } };
|
|
556
612
|
}
|
|
557
613
|
case 'borg_role-rationale': {
|
|
558
614
|
const active = await requireActiveCube();
|
|
@@ -564,7 +620,10 @@ export async function main() {
|
|
|
564
620
|
'',
|
|
565
621
|
result.body || '_(empty)_',
|
|
566
622
|
].join('\n');
|
|
567
|
-
return {
|
|
623
|
+
return {
|
|
624
|
+
content: [{ type: 'text', text }],
|
|
625
|
+
structuredContent: { role: result.role, section: result.section, body: result.body },
|
|
626
|
+
};
|
|
568
627
|
}
|
|
569
628
|
case 'borg_roster': {
|
|
570
629
|
const active = await requireActiveCube();
|
|
@@ -577,7 +636,10 @@ export async function main() {
|
|
|
577
636
|
resolvedSince: resolvedSince ?? null,
|
|
578
637
|
humanAgo,
|
|
579
638
|
});
|
|
580
|
-
return {
|
|
639
|
+
return {
|
|
640
|
+
content: [{ type: 'text', text }],
|
|
641
|
+
structuredContent: { cube_name: active.name, drones, roles, since: resolvedSince ?? null },
|
|
642
|
+
};
|
|
581
643
|
}
|
|
582
644
|
case 'borg_stream-status': {
|
|
583
645
|
// Probe the in-process SSE consumer state. Does NOT require
|
|
@@ -616,7 +678,18 @@ export async function main() {
|
|
|
616
678
|
cubeName: active?.name ?? null,
|
|
617
679
|
humanAgo,
|
|
618
680
|
});
|
|
619
|
-
return {
|
|
681
|
+
return {
|
|
682
|
+
content: [{ type: 'text', text: silentInertWarning + text }],
|
|
683
|
+
structuredContent: {
|
|
684
|
+
status,
|
|
685
|
+
wake_path: wakePath,
|
|
686
|
+
inbox_monitor_healthy: inboxMonitorHealthy,
|
|
687
|
+
inbox_path: inboxPath,
|
|
688
|
+
monitor_state_root: monitorStateRoot,
|
|
689
|
+
drone_label: active?.droneLabel ?? null,
|
|
690
|
+
cube_name: active?.name ?? null,
|
|
691
|
+
},
|
|
692
|
+
};
|
|
620
693
|
}
|
|
621
694
|
case 'borg_read-log': {
|
|
622
695
|
const active = await requireActiveCube();
|
|
@@ -658,7 +731,10 @@ export async function main() {
|
|
|
658
731
|
lines.push('');
|
|
659
732
|
lines.push(`⚠ behind_by: ${behind_by} more unread ${behind_by === 1 ? 'entry' : 'entries'} addressed to you — call \`borg_read-log unread_only=true\` again until behind_by=0 so you don't skip messages.`);
|
|
660
733
|
}
|
|
661
|
-
return {
|
|
734
|
+
return {
|
|
735
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
736
|
+
structuredContent: buildReadLogStructuredContent({ entries, behind_by, has_more }),
|
|
737
|
+
};
|
|
662
738
|
}
|
|
663
739
|
case 'borg_read-entry': {
|
|
664
740
|
const active = await requireActiveCube();
|
|
@@ -670,17 +746,26 @@ export async function main() {
|
|
|
670
746
|
'',
|
|
671
747
|
formatLogEntryMarkdown(entry, droneById, roleById),
|
|
672
748
|
].join('\n');
|
|
673
|
-
return {
|
|
749
|
+
return {
|
|
750
|
+
content: [{ type: 'text', text }],
|
|
751
|
+
structuredContent: { entry, drones, roles },
|
|
752
|
+
};
|
|
674
753
|
}
|
|
675
754
|
case 'borg_put-document': {
|
|
676
755
|
const active = await requireActiveCube();
|
|
677
756
|
const result = await putDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
678
|
-
return {
|
|
757
|
+
return {
|
|
758
|
+
content: [{ type: 'text', text: `Created cube document.\n\n${formatDocument(result.document)}` }],
|
|
759
|
+
structuredContent: { document: result.document },
|
|
760
|
+
};
|
|
679
761
|
}
|
|
680
762
|
case 'borg_get-document': {
|
|
681
763
|
const active = await requireActiveCube();
|
|
682
764
|
const result = await getDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
683
|
-
return {
|
|
765
|
+
return {
|
|
766
|
+
content: [{ type: 'text', text: formatDocument(result.document) }],
|
|
767
|
+
structuredContent: { document: result.document },
|
|
768
|
+
};
|
|
684
769
|
}
|
|
685
770
|
case 'borg_list-documents': {
|
|
686
771
|
const active = await requireActiveCube();
|
|
@@ -688,12 +773,18 @@ export async function main() {
|
|
|
688
773
|
const text = result.documents.length === 0
|
|
689
774
|
? `No active or superseded documents in cube "${active.name}".`
|
|
690
775
|
: result.documents.map(formatDocumentMetadata).join('\n\n');
|
|
691
|
-
return {
|
|
776
|
+
return {
|
|
777
|
+
content: [{ type: 'text', text }],
|
|
778
|
+
structuredContent: { documents: result.documents },
|
|
779
|
+
};
|
|
692
780
|
}
|
|
693
781
|
case 'borg_remove-document': {
|
|
694
782
|
const active = await requireActiveCube();
|
|
695
783
|
const result = await removeDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
696
|
-
return {
|
|
784
|
+
return {
|
|
785
|
+
content: [{ type: 'text', text: `Removed cube document.\n\n${formatDocumentMetadata(result.document)}` }],
|
|
786
|
+
structuredContent: { document: result.document },
|
|
787
|
+
};
|
|
697
788
|
}
|
|
698
789
|
case 'borg_log': {
|
|
699
790
|
const message = args?.message;
|
|
@@ -719,6 +810,13 @@ export async function main() {
|
|
|
719
810
|
text: `Suppressed duplicate ${decision.signal?.toUpperCase()} lifecycle log for ${displayIdentity.droneLabel}; recent cube log already contains this signal.`,
|
|
720
811
|
},
|
|
721
812
|
],
|
|
813
|
+
structuredContent: {
|
|
814
|
+
suppressed: true,
|
|
815
|
+
entry: null,
|
|
816
|
+
recipients: [],
|
|
817
|
+
unreachable_recipients: [],
|
|
818
|
+
advisory: null,
|
|
819
|
+
},
|
|
722
820
|
};
|
|
723
821
|
}
|
|
724
822
|
}
|
|
@@ -765,7 +863,16 @@ export async function main() {
|
|
|
765
863
|
? `\nAdvisory: this message exceeded ${result.advisory.threshold_bytes} UTF-8 bytes. Store durable detail with borg_put-document, then cite its full id in borg_log.documents with an explicit borg_log.to audience.`
|
|
766
864
|
: '';
|
|
767
865
|
const text = `Logged to cube "${displayIdentity.cubeName}" as ${displayIdentity.droneLabel}. (entry id: ${result.entry.id})${routed}${unreachable}${citations}${advisory}`;
|
|
768
|
-
return {
|
|
866
|
+
return {
|
|
867
|
+
content: [{ type: 'text', text }],
|
|
868
|
+
structuredContent: {
|
|
869
|
+
suppressed: false,
|
|
870
|
+
entry: result.entry,
|
|
871
|
+
recipients: routedRecipients,
|
|
872
|
+
unreachable_recipients: result.unreachableRecipients ?? [],
|
|
873
|
+
advisory: result.advisory ?? null,
|
|
874
|
+
},
|
|
875
|
+
};
|
|
769
876
|
}
|
|
770
877
|
case 'borg_ack': {
|
|
771
878
|
const entryId = args?.entry_id;
|
|
@@ -787,12 +894,16 @@ export async function main() {
|
|
|
787
894
|
: `Acked entry ${entryId} in cube "${active.name}".`,
|
|
788
895
|
},
|
|
789
896
|
],
|
|
897
|
+
structuredContent: { entry_id: entryId, kind, cube_name: active.name },
|
|
790
898
|
};
|
|
791
899
|
}
|
|
792
900
|
case 'borg_ack-status': {
|
|
793
901
|
const active = await requireActiveCube();
|
|
794
902
|
const result = await getAckStatus(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
795
|
-
return {
|
|
903
|
+
return {
|
|
904
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
905
|
+
structuredContent: { ...result },
|
|
906
|
+
};
|
|
796
907
|
}
|
|
797
908
|
case 'borg_decide': {
|
|
798
909
|
const topic = args?.topic;
|
|
@@ -816,6 +927,7 @@ export async function main() {
|
|
|
816
927
|
text: `Recorded ratified decision on "${topic}" in cube "${active.name}"${superseded}. Cite it via borg_decisions; it surfaces in borg_regen.`,
|
|
817
928
|
},
|
|
818
929
|
],
|
|
930
|
+
structuredContent: { decision: row, superseded: Boolean(row?.supersedes), cube_name: active.name },
|
|
819
931
|
};
|
|
820
932
|
}
|
|
821
933
|
case 'borg_decisions': {
|
|
@@ -829,7 +941,10 @@ export async function main() {
|
|
|
829
941
|
: decisions
|
|
830
942
|
.map((d) => `**${d.topic}:** ${d.decision}${d.rationale ? ` — ${d.rationale}` : ''}`)
|
|
831
943
|
.join('\n');
|
|
832
|
-
return {
|
|
944
|
+
return {
|
|
945
|
+
content: [{ type: 'text', text }],
|
|
946
|
+
structuredContent: { decisions },
|
|
947
|
+
};
|
|
833
948
|
}
|
|
834
949
|
case 'borg_remove-decision': {
|
|
835
950
|
const topic = typeof args?.topic === 'string' ? args.topic : undefined;
|
|
@@ -845,15 +960,22 @@ export async function main() {
|
|
|
845
960
|
type: 'text',
|
|
846
961
|
text: `Removed the active ratified decision on "${decision.topic}" from cube "${active.name}".`,
|
|
847
962
|
}],
|
|
963
|
+
structuredContent: { decision, cube_name: active.name },
|
|
848
964
|
};
|
|
849
965
|
}
|
|
850
966
|
case 'borg_list-cubes': {
|
|
851
967
|
const { cubes } = await listCubes();
|
|
852
968
|
if (!cubes.length) {
|
|
853
|
-
return {
|
|
969
|
+
return {
|
|
970
|
+
content: [{ type: 'text', text: 'No cubes yet. Use borg_create-cube to make your first one.' }],
|
|
971
|
+
structuredContent: { cubes: [] },
|
|
972
|
+
};
|
|
854
973
|
}
|
|
855
974
|
const lines = cubes.map((c) => `- **${c.name}** (id: ${c.id})\n ${(c.cube_directive || '_(no directive set)_').split('\n')[0].slice(0, 120)}`);
|
|
856
|
-
return {
|
|
975
|
+
return {
|
|
976
|
+
content: [{ type: 'text', text: `Your cubes (${cubes.length}):\n\n${lines.join('\n\n')}` }],
|
|
977
|
+
structuredContent: { cubes },
|
|
978
|
+
};
|
|
857
979
|
}
|
|
858
980
|
case 'borg_create-cube': {
|
|
859
981
|
const name = args?.name;
|
|
@@ -892,10 +1014,21 @@ export async function main() {
|
|
|
892
1014
|
? ' Template cube directive applied (operator passed empty).'
|
|
893
1015
|
: '';
|
|
894
1016
|
const text = `Created cube **${cube.name}** (id: ${cube.id}) with template **${templateName}** applied — ${summary.created} role(s) created, ${summary.updated} updated.${cubeDirectiveNote} Use borg_assimilate ${cube.name} to join as a drone.`;
|
|
895
|
-
return {
|
|
1017
|
+
return {
|
|
1018
|
+
content: [{ type: 'text', text }],
|
|
1019
|
+
structuredContent: {
|
|
1020
|
+
cube,
|
|
1021
|
+
template: templateName,
|
|
1022
|
+
roles_created: summary.created,
|
|
1023
|
+
roles_updated: summary.updated,
|
|
1024
|
+
},
|
|
1025
|
+
};
|
|
896
1026
|
}
|
|
897
1027
|
const text = `Created cube **${cube.name}** (id: ${cube.id}). A default "Drone" role was seeded — rename or replace it via borg_update-role / borg_create-role / borg_delete-role. Use borg_assimilate ${cube.name} to join as a drone.`;
|
|
898
|
-
return {
|
|
1028
|
+
return {
|
|
1029
|
+
content: [{ type: 'text', text }],
|
|
1030
|
+
structuredContent: { cube, template: null, roles_created: null, roles_updated: null },
|
|
1031
|
+
};
|
|
899
1032
|
}
|
|
900
1033
|
case 'borg_update-cube': {
|
|
901
1034
|
const cubeId = args?.cube_id;
|
|
@@ -911,7 +1044,10 @@ export async function main() {
|
|
|
911
1044
|
if (Object.keys(updates).length === 0)
|
|
912
1045
|
throw new Error('Pass at least one of: cube_directive, message_taxonomy.');
|
|
913
1046
|
const { cube, advisory } = await updateCube(cubeId, updates);
|
|
914
|
-
return {
|
|
1047
|
+
return {
|
|
1048
|
+
content: [{ type: 'text', text: formatUpdatedCubeResult(cube, advisory) }],
|
|
1049
|
+
structuredContent: { cube, advisory: advisory ?? null },
|
|
1050
|
+
};
|
|
915
1051
|
}
|
|
916
1052
|
case 'borg_patch-taxonomy-class': {
|
|
917
1053
|
const cubeId = args?.cube_id;
|
|
@@ -939,7 +1075,10 @@ export async function main() {
|
|
|
939
1075
|
label = String(classDef.class ?? '');
|
|
940
1076
|
}
|
|
941
1077
|
const verb = action === 'add' ? 'Added' : action === 'replace' ? 'Replaced' : 'Removed';
|
|
942
|
-
return {
|
|
1078
|
+
return {
|
|
1079
|
+
content: [{ type: 'text', text: `${verb} taxonomy class **${label}** in cube **${cube.name}** (id: ${cube.id}).` }],
|
|
1080
|
+
structuredContent: { action, class: label, cube },
|
|
1081
|
+
};
|
|
943
1082
|
}
|
|
944
1083
|
case 'borg_delete-cube': {
|
|
945
1084
|
const cubeId = args?.cube_id;
|
|
@@ -950,7 +1089,10 @@ export async function main() {
|
|
|
950
1089
|
throw new CubeDeletionConfirmationError(cubeId, confirmCubeId);
|
|
951
1090
|
}
|
|
952
1091
|
await deleteCube(cubeId, confirmCubeId);
|
|
953
|
-
return {
|
|
1092
|
+
return {
|
|
1093
|
+
content: [{ type: 'text', text: `Deleted cube ${cubeId} (and all its roles, drones, log entries).` }],
|
|
1094
|
+
structuredContent: { cube_id: cubeId, deleted: true },
|
|
1095
|
+
};
|
|
954
1096
|
}
|
|
955
1097
|
case 'borg_create-role': {
|
|
956
1098
|
const cubeId = args?.cube_id;
|
|
@@ -988,7 +1130,10 @@ export async function main() {
|
|
|
988
1130
|
role.is_mandatory ? 'mandatory' : null,
|
|
989
1131
|
].filter(Boolean).join(', ');
|
|
990
1132
|
const tag = tags ? ` (${tags})` : '';
|
|
991
|
-
return {
|
|
1133
|
+
return {
|
|
1134
|
+
content: [{ type: 'text', text: `Created role **${role.name}**${tag} (id: ${role.id}) in cube ${cubeId}.` }],
|
|
1135
|
+
structuredContent: { role, cube_id: cubeId },
|
|
1136
|
+
};
|
|
992
1137
|
}
|
|
993
1138
|
case 'borg_update-role': {
|
|
994
1139
|
const roleId = args?.role_id;
|
|
@@ -1016,7 +1161,10 @@ export async function main() {
|
|
|
1016
1161
|
if (Object.keys(updates).length === 0)
|
|
1017
1162
|
throw new Error('Pass at least one of: name, short_description, detailed_description, is_default, is_mandatory, is_human_seat, can_broadcast, receives_all_direct.');
|
|
1018
1163
|
const { role, advisory } = await updateRole(roleId, updates);
|
|
1019
|
-
return {
|
|
1164
|
+
return {
|
|
1165
|
+
content: [{ type: 'text', text: formatUpdatedRoleResult(role, advisory) }],
|
|
1166
|
+
structuredContent: { role, advisory: advisory ?? null },
|
|
1167
|
+
};
|
|
1020
1168
|
}
|
|
1021
1169
|
case 'borg_patch-role-section': {
|
|
1022
1170
|
const roleId = args?.role_id;
|
|
@@ -1047,26 +1195,45 @@ export async function main() {
|
|
|
1047
1195
|
({ role, advisory } = await patchRoleSection(roleId, { action, heading, body }));
|
|
1048
1196
|
}
|
|
1049
1197
|
}
|
|
1050
|
-
return {
|
|
1198
|
+
return {
|
|
1199
|
+
content: [{ type: 'text', text: formatPatchedRoleSectionResult(action, heading, role, advisory) }],
|
|
1200
|
+
structuredContent: { action, heading, role, advisory: advisory ?? null },
|
|
1201
|
+
};
|
|
1051
1202
|
}
|
|
1052
1203
|
case 'borg_delete-role': {
|
|
1053
1204
|
const roleId = args?.role_id;
|
|
1054
1205
|
if (!roleId)
|
|
1055
1206
|
throw new Error('role_id is required');
|
|
1056
1207
|
await deleteRole(roleId);
|
|
1057
|
-
return {
|
|
1208
|
+
return {
|
|
1209
|
+
content: [{ type: 'text', text: `Deleted role ${roleId}.` }],
|
|
1210
|
+
structuredContent: { role_id: roleId, deleted: true },
|
|
1211
|
+
};
|
|
1058
1212
|
}
|
|
1059
1213
|
case 'borg_reassign-drone': {
|
|
1214
|
+
const reassigned = await runReassignDroneTool({
|
|
1215
|
+
droneId: args?.drone_id,
|
|
1216
|
+
roleId: args?.role_id,
|
|
1217
|
+
});
|
|
1060
1218
|
return {
|
|
1061
|
-
content: [{ type: 'text', text:
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1219
|
+
content: [{ type: 'text', text: reassigned.text }],
|
|
1220
|
+
structuredContent: {
|
|
1221
|
+
drone: reassigned.drone,
|
|
1222
|
+
role_name: reassigned.roleName,
|
|
1223
|
+
cube_name: reassigned.cubeName,
|
|
1224
|
+
},
|
|
1065
1225
|
};
|
|
1066
1226
|
}
|
|
1067
1227
|
case 'borg_evict-drone': {
|
|
1228
|
+
const evicted = await runEvictDroneTool(args);
|
|
1068
1229
|
return {
|
|
1069
|
-
content: [{ type: 'text', text:
|
|
1230
|
+
content: [{ type: 'text', text: evicted.text }],
|
|
1231
|
+
structuredContent: {
|
|
1232
|
+
drone_id: evicted.droneId,
|
|
1233
|
+
label: evicted.label,
|
|
1234
|
+
cube_name: evicted.cubeName,
|
|
1235
|
+
evicted: true,
|
|
1236
|
+
},
|
|
1070
1237
|
};
|
|
1071
1238
|
}
|
|
1072
1239
|
case 'borg_list-drones': {
|
|
@@ -1075,7 +1242,10 @@ export async function main() {
|
|
|
1075
1242
|
throw new Error('cube_id is required');
|
|
1076
1243
|
const { drones, roles } = await getCube(cubeId);
|
|
1077
1244
|
if (!drones.length) {
|
|
1078
|
-
return {
|
|
1245
|
+
return {
|
|
1246
|
+
content: [{ type: 'text', text: 'No drones in this cube yet.' }],
|
|
1247
|
+
structuredContent: { cube_id: cubeId, drones: [], roles },
|
|
1248
|
+
};
|
|
1079
1249
|
}
|
|
1080
1250
|
const rolesById = new Map(roles.map((r) => [r.id, r]));
|
|
1081
1251
|
const lines = drones.map((d) => {
|
|
@@ -1088,7 +1258,10 @@ export async function main() {
|
|
|
1088
1258
|
...renderRuntimeMetadataLines(d),
|
|
1089
1259
|
].join('\n');
|
|
1090
1260
|
});
|
|
1091
|
-
return {
|
|
1261
|
+
return {
|
|
1262
|
+
content: [{ type: 'text', text: `Drones in cube ${cubeId} (${drones.length}):\n\n_${RUNTIME_METADATA_ADVISORY}_\n\n${lines.join('\n')}` }],
|
|
1263
|
+
structuredContent: { cube_id: cubeId, drones, roles },
|
|
1264
|
+
};
|
|
1092
1265
|
}
|
|
1093
1266
|
case 'borg_list-roles': {
|
|
1094
1267
|
// Sprint 6 / gh#153: surface role IDs to Coordinator-class drones
|
|
@@ -1103,7 +1276,10 @@ export async function main() {
|
|
|
1103
1276
|
if (!cubeId)
|
|
1104
1277
|
throw new Error('cube_id is required');
|
|
1105
1278
|
const roles = await listRoles(cubeId);
|
|
1106
|
-
return {
|
|
1279
|
+
return {
|
|
1280
|
+
content: [{ type: 'text', text: renderRoleList(roles, cubeId) }],
|
|
1281
|
+
structuredContent: { cube_id: cubeId, roles },
|
|
1282
|
+
};
|
|
1107
1283
|
}
|
|
1108
1284
|
case 'borg_list-templates': {
|
|
1109
1285
|
const names = listTemplateNames();
|
|
@@ -1111,7 +1287,12 @@ export async function main() {
|
|
|
1111
1287
|
const t = getTemplate(n);
|
|
1112
1288
|
return `- **${n}**: ${t.description}`;
|
|
1113
1289
|
});
|
|
1114
|
-
return {
|
|
1290
|
+
return {
|
|
1291
|
+
content: [{ type: 'text', text: `Available templates:\n\n${lines.join('\n')}` }],
|
|
1292
|
+
structuredContent: {
|
|
1293
|
+
templates: names.map((n) => ({ name: n, description: getTemplate(n).description })),
|
|
1294
|
+
},
|
|
1295
|
+
};
|
|
1115
1296
|
}
|
|
1116
1297
|
case 'borg_sync-roles': {
|
|
1117
1298
|
const cubeId = args?.cube_id;
|
|
@@ -1127,7 +1308,10 @@ export async function main() {
|
|
|
1127
1308
|
if (!cubeId)
|
|
1128
1309
|
throw new Error('cube_id is required');
|
|
1129
1310
|
const result = await syncRoles(cubeId, templateName, apply, decisions);
|
|
1130
|
-
return {
|
|
1311
|
+
return {
|
|
1312
|
+
content: [{ type: 'text', text: renderSyncRolesResult(result, templateName) }],
|
|
1313
|
+
structuredContent: { cube_id: cubeId, template: templateName, apply, result },
|
|
1314
|
+
};
|
|
1131
1315
|
}
|
|
1132
1316
|
case 'borg_apply-template': {
|
|
1133
1317
|
const cubeId = args?.cube_id;
|
|
@@ -1147,7 +1331,16 @@ export async function main() {
|
|
|
1147
1331
|
noMutation: 'No template fragments were changed.',
|
|
1148
1332
|
});
|
|
1149
1333
|
const { summary, cubeDirectiveNote } = await runApplyTemplateTool(cubeId, template, authority);
|
|
1150
|
-
return {
|
|
1334
|
+
return {
|
|
1335
|
+
content: [{ type: 'text', text: `Applied template **${templateName}** to cube ${cubeId} — ${summary.created} role(s) created, ${summary.updated} updated.${cubeDirectiveNote}` }],
|
|
1336
|
+
structuredContent: {
|
|
1337
|
+
cube_id: cubeId,
|
|
1338
|
+
template: templateName,
|
|
1339
|
+
roles_created: summary.created,
|
|
1340
|
+
roles_updated: summary.updated,
|
|
1341
|
+
cube_directive_applied: cubeDirectiveNote !== '',
|
|
1342
|
+
},
|
|
1343
|
+
};
|
|
1151
1344
|
}
|
|
1152
1345
|
default:
|
|
1153
1346
|
throw new Error(`Unknown tool: ${name}`);
|