borgmcp 4.1.0 → 4.2.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/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.map +1 -1
- package/dist/index.js +230 -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 +230 -42
- package/src/tool-manifest.ts +546 -1
package/dist/index.js
CHANGED
|
@@ -257,8 +257,15 @@ export async function main() {
|
|
|
257
257
|
isError: true,
|
|
258
258
|
};
|
|
259
259
|
}
|
|
260
|
+
const described = {
|
|
261
|
+
name: def.name,
|
|
262
|
+
description: def.description,
|
|
263
|
+
inputSchema: def.inputSchema,
|
|
264
|
+
outputSchema: def.outputSchema ?? null,
|
|
265
|
+
};
|
|
260
266
|
return {
|
|
261
|
-
content: [{ type: 'text', text: JSON.stringify(
|
|
267
|
+
content: [{ type: 'text', text: JSON.stringify(described, null, 2) }],
|
|
268
|
+
structuredContent: described,
|
|
262
269
|
};
|
|
263
270
|
}
|
|
264
271
|
// gh#899: borg_tool dispatcher — unwrap to the inner tool and fall through
|
|
@@ -306,6 +313,7 @@ export async function main() {
|
|
|
306
313
|
text: 'Not connected to a cube. Use `borg_assimilate cube_name="<name>"` to join one.',
|
|
307
314
|
},
|
|
308
315
|
],
|
|
316
|
+
structuredContent: { connected: false },
|
|
309
317
|
};
|
|
310
318
|
}
|
|
311
319
|
seedDisplayIdentity(active);
|
|
@@ -358,10 +366,12 @@ export async function main() {
|
|
|
358
366
|
: '';
|
|
359
367
|
// gh#285: version-mismatch nudge when on-disk package is newer.
|
|
360
368
|
let versionHeader = '';
|
|
369
|
+
let onDiskVersion = null;
|
|
361
370
|
try {
|
|
362
371
|
const running = getPackageVersion();
|
|
363
372
|
const onDisk = getOnDiskVersion();
|
|
364
373
|
if (running !== 'unknown' && onDisk !== 'unknown' && onDisk !== running) {
|
|
374
|
+
onDiskVersion = onDisk;
|
|
365
375
|
const [rMaj, rMin, rPat] = running.split('.').map(Number);
|
|
366
376
|
const [dMaj, dMin, dPat] = onDisk.split('.').map(Number);
|
|
367
377
|
const onDiskNewer = dMaj > rMaj || (dMaj === rMaj && dMin > rMin) || (dMaj === rMaj && dMin === rMin && dPat > rPat);
|
|
@@ -371,7 +381,21 @@ export async function main() {
|
|
|
371
381
|
}
|
|
372
382
|
}
|
|
373
383
|
catch { /* never break regen */ }
|
|
374
|
-
return {
|
|
384
|
+
return {
|
|
385
|
+
content: [{ type: 'text', text: versionHeader + prefix + formatRegenMarkdown(displayedResult, { mode }) }],
|
|
386
|
+
structuredContent: {
|
|
387
|
+
connected: true,
|
|
388
|
+
mode,
|
|
389
|
+
cube: displayedResult.cube,
|
|
390
|
+
drone: displayedResult.drone,
|
|
391
|
+
role: displayedResult.role,
|
|
392
|
+
behind_by: typeof displayedResult.behind_by === 'number' ? displayedResult.behind_by : null,
|
|
393
|
+
decision_topics: (displayedResult.decisions ?? []).map((d) => d.topic),
|
|
394
|
+
running_version: getPackageVersion(),
|
|
395
|
+
on_disk_version: onDiskVersion,
|
|
396
|
+
wake_path_healthy: inboxMonitorHealthy,
|
|
397
|
+
},
|
|
398
|
+
};
|
|
375
399
|
}
|
|
376
400
|
case 'borg_assimilate': {
|
|
377
401
|
const cubeName = args?.cube_name;
|
|
@@ -417,6 +441,11 @@ export async function main() {
|
|
|
417
441
|
].join('\n');
|
|
418
442
|
return {
|
|
419
443
|
content: [{ type: 'text', text: header + formatRegenMarkdown(displayedResult, { mode: 'full' }) }],
|
|
444
|
+
structuredContent: {
|
|
445
|
+
reattached: true,
|
|
446
|
+
cube_name: displayIdentity.cubeName,
|
|
447
|
+
drone_label: displayIdentity.droneLabel,
|
|
448
|
+
},
|
|
420
449
|
};
|
|
421
450
|
}
|
|
422
451
|
catch (err) {
|
|
@@ -426,7 +455,10 @@ export async function main() {
|
|
|
426
455
|
}
|
|
427
456
|
}
|
|
428
457
|
case 'borg_version': {
|
|
429
|
-
return {
|
|
458
|
+
return {
|
|
459
|
+
content: [{ type: 'text', text: `borgmcp ${getPackageVersion()}` }],
|
|
460
|
+
structuredContent: { version: getPackageVersion() },
|
|
461
|
+
};
|
|
430
462
|
}
|
|
431
463
|
case 'borg_playbook': {
|
|
432
464
|
// gh#912: serve the on-demand operating-playbook chapter (static
|
|
@@ -446,7 +478,14 @@ export async function main() {
|
|
|
446
478
|
: topic
|
|
447
479
|
? `No exact match for "${topic}". Full Borg MCP docs index — WebFetch the URL you need:`
|
|
448
480
|
: `Borg MCP docs index — WebFetch the URL of the section you need:`;
|
|
449
|
-
return {
|
|
481
|
+
return {
|
|
482
|
+
content: [{ type: 'text', text: `${header}\n\n${formatDocsIndex(sections)}` }],
|
|
483
|
+
structuredContent: {
|
|
484
|
+
topic: topic || null,
|
|
485
|
+
matched: matched.length > 0,
|
|
486
|
+
sections: sections.map((s) => ({ slug: s.slug, title: s.title, url: s.url, summary: s.summary })),
|
|
487
|
+
},
|
|
488
|
+
};
|
|
450
489
|
}
|
|
451
490
|
case 'borg_whoami': {
|
|
452
491
|
const active = await requireActiveCube();
|
|
@@ -476,7 +515,10 @@ export async function main() {
|
|
|
476
515
|
// The invocation-local server truth remains authoritative even if
|
|
477
516
|
// the display-only persistence refresh cannot be written.
|
|
478
517
|
}
|
|
479
|
-
return {
|
|
518
|
+
return {
|
|
519
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
520
|
+
structuredContent: { ...result },
|
|
521
|
+
};
|
|
480
522
|
}
|
|
481
523
|
case 'borg_cube': {
|
|
482
524
|
// No-cache invariant (T1.2 — 0.7.0): both `getCubeInfo` and
|
|
@@ -529,7 +571,10 @@ export async function main() {
|
|
|
529
571
|
}
|
|
530
572
|
lines.push('');
|
|
531
573
|
lines.push(getDronePlaybook());
|
|
532
|
-
return {
|
|
574
|
+
return {
|
|
575
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
576
|
+
structuredContent: { cube, roles },
|
|
577
|
+
};
|
|
533
578
|
}
|
|
534
579
|
case 'borg_role': {
|
|
535
580
|
// No-cache invariant (T1.2 — 0.7.0): role reads MUST fetch
|
|
@@ -544,7 +589,7 @@ export async function main() {
|
|
|
544
589
|
``,
|
|
545
590
|
role.detailed_description || '_(no detailed description set)_',
|
|
546
591
|
].join('\n');
|
|
547
|
-
return { content: [{ type: 'text', text }] };
|
|
592
|
+
return { content: [{ type: 'text', text }], structuredContent: { role } };
|
|
548
593
|
}
|
|
549
594
|
const { role } = await getRoleInfo(active.sessionToken, active.apiUrl, active.serverTrustIdentity);
|
|
550
595
|
const text = [
|
|
@@ -552,7 +597,7 @@ export async function main() {
|
|
|
552
597
|
``,
|
|
553
598
|
role.detailed_description || '_(no detailed description set)_',
|
|
554
599
|
].join('\n');
|
|
555
|
-
return { content: [{ type: 'text', text }] };
|
|
600
|
+
return { content: [{ type: 'text', text }], structuredContent: { role } };
|
|
556
601
|
}
|
|
557
602
|
case 'borg_role-rationale': {
|
|
558
603
|
const active = await requireActiveCube();
|
|
@@ -564,7 +609,10 @@ export async function main() {
|
|
|
564
609
|
'',
|
|
565
610
|
result.body || '_(empty)_',
|
|
566
611
|
].join('\n');
|
|
567
|
-
return {
|
|
612
|
+
return {
|
|
613
|
+
content: [{ type: 'text', text }],
|
|
614
|
+
structuredContent: { role: result.role, section: result.section, body: result.body },
|
|
615
|
+
};
|
|
568
616
|
}
|
|
569
617
|
case 'borg_roster': {
|
|
570
618
|
const active = await requireActiveCube();
|
|
@@ -577,7 +625,10 @@ export async function main() {
|
|
|
577
625
|
resolvedSince: resolvedSince ?? null,
|
|
578
626
|
humanAgo,
|
|
579
627
|
});
|
|
580
|
-
return {
|
|
628
|
+
return {
|
|
629
|
+
content: [{ type: 'text', text }],
|
|
630
|
+
structuredContent: { cube_name: active.name, drones, roles, since: resolvedSince ?? null },
|
|
631
|
+
};
|
|
581
632
|
}
|
|
582
633
|
case 'borg_stream-status': {
|
|
583
634
|
// Probe the in-process SSE consumer state. Does NOT require
|
|
@@ -616,7 +667,18 @@ export async function main() {
|
|
|
616
667
|
cubeName: active?.name ?? null,
|
|
617
668
|
humanAgo,
|
|
618
669
|
});
|
|
619
|
-
return {
|
|
670
|
+
return {
|
|
671
|
+
content: [{ type: 'text', text: silentInertWarning + text }],
|
|
672
|
+
structuredContent: {
|
|
673
|
+
status,
|
|
674
|
+
wake_path: wakePath,
|
|
675
|
+
inbox_monitor_healthy: inboxMonitorHealthy,
|
|
676
|
+
inbox_path: inboxPath,
|
|
677
|
+
monitor_state_root: monitorStateRoot,
|
|
678
|
+
drone_label: active?.droneLabel ?? null,
|
|
679
|
+
cube_name: active?.name ?? null,
|
|
680
|
+
},
|
|
681
|
+
};
|
|
620
682
|
}
|
|
621
683
|
case 'borg_read-log': {
|
|
622
684
|
const active = await requireActiveCube();
|
|
@@ -658,7 +720,16 @@ export async function main() {
|
|
|
658
720
|
lines.push('');
|
|
659
721
|
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
722
|
}
|
|
661
|
-
return {
|
|
723
|
+
return {
|
|
724
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
725
|
+
structuredContent: {
|
|
726
|
+
entries,
|
|
727
|
+
drones,
|
|
728
|
+
roles,
|
|
729
|
+
behind_by: typeof behind_by === 'number' ? behind_by : null,
|
|
730
|
+
has_more: has_more === true,
|
|
731
|
+
},
|
|
732
|
+
};
|
|
662
733
|
}
|
|
663
734
|
case 'borg_read-entry': {
|
|
664
735
|
const active = await requireActiveCube();
|
|
@@ -670,17 +741,26 @@ export async function main() {
|
|
|
670
741
|
'',
|
|
671
742
|
formatLogEntryMarkdown(entry, droneById, roleById),
|
|
672
743
|
].join('\n');
|
|
673
|
-
return {
|
|
744
|
+
return {
|
|
745
|
+
content: [{ type: 'text', text }],
|
|
746
|
+
structuredContent: { entry, drones, roles },
|
|
747
|
+
};
|
|
674
748
|
}
|
|
675
749
|
case 'borg_put-document': {
|
|
676
750
|
const active = await requireActiveCube();
|
|
677
751
|
const result = await putDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
678
|
-
return {
|
|
752
|
+
return {
|
|
753
|
+
content: [{ type: 'text', text: `Created cube document.\n\n${formatDocument(result.document)}` }],
|
|
754
|
+
structuredContent: { document: result.document },
|
|
755
|
+
};
|
|
679
756
|
}
|
|
680
757
|
case 'borg_get-document': {
|
|
681
758
|
const active = await requireActiveCube();
|
|
682
759
|
const result = await getDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
683
|
-
return {
|
|
760
|
+
return {
|
|
761
|
+
content: [{ type: 'text', text: formatDocument(result.document) }],
|
|
762
|
+
structuredContent: { document: result.document },
|
|
763
|
+
};
|
|
684
764
|
}
|
|
685
765
|
case 'borg_list-documents': {
|
|
686
766
|
const active = await requireActiveCube();
|
|
@@ -688,12 +768,18 @@ export async function main() {
|
|
|
688
768
|
const text = result.documents.length === 0
|
|
689
769
|
? `No active or superseded documents in cube "${active.name}".`
|
|
690
770
|
: result.documents.map(formatDocumentMetadata).join('\n\n');
|
|
691
|
-
return {
|
|
771
|
+
return {
|
|
772
|
+
content: [{ type: 'text', text }],
|
|
773
|
+
structuredContent: { documents: result.documents },
|
|
774
|
+
};
|
|
692
775
|
}
|
|
693
776
|
case 'borg_remove-document': {
|
|
694
777
|
const active = await requireActiveCube();
|
|
695
778
|
const result = await removeDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
696
|
-
return {
|
|
779
|
+
return {
|
|
780
|
+
content: [{ type: 'text', text: `Removed cube document.\n\n${formatDocumentMetadata(result.document)}` }],
|
|
781
|
+
structuredContent: { document: result.document },
|
|
782
|
+
};
|
|
697
783
|
}
|
|
698
784
|
case 'borg_log': {
|
|
699
785
|
const message = args?.message;
|
|
@@ -719,6 +805,13 @@ export async function main() {
|
|
|
719
805
|
text: `Suppressed duplicate ${decision.signal?.toUpperCase()} lifecycle log for ${displayIdentity.droneLabel}; recent cube log already contains this signal.`,
|
|
720
806
|
},
|
|
721
807
|
],
|
|
808
|
+
structuredContent: {
|
|
809
|
+
suppressed: true,
|
|
810
|
+
entry: null,
|
|
811
|
+
recipients: [],
|
|
812
|
+
unreachable_recipients: [],
|
|
813
|
+
advisory: null,
|
|
814
|
+
},
|
|
722
815
|
};
|
|
723
816
|
}
|
|
724
817
|
}
|
|
@@ -765,7 +858,16 @@ export async function main() {
|
|
|
765
858
|
? `\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
859
|
: '';
|
|
767
860
|
const text = `Logged to cube "${displayIdentity.cubeName}" as ${displayIdentity.droneLabel}. (entry id: ${result.entry.id})${routed}${unreachable}${citations}${advisory}`;
|
|
768
|
-
return {
|
|
861
|
+
return {
|
|
862
|
+
content: [{ type: 'text', text }],
|
|
863
|
+
structuredContent: {
|
|
864
|
+
suppressed: false,
|
|
865
|
+
entry: result.entry,
|
|
866
|
+
recipients: routedRecipients,
|
|
867
|
+
unreachable_recipients: result.unreachableRecipients ?? [],
|
|
868
|
+
advisory: result.advisory ?? null,
|
|
869
|
+
},
|
|
870
|
+
};
|
|
769
871
|
}
|
|
770
872
|
case 'borg_ack': {
|
|
771
873
|
const entryId = args?.entry_id;
|
|
@@ -787,12 +889,16 @@ export async function main() {
|
|
|
787
889
|
: `Acked entry ${entryId} in cube "${active.name}".`,
|
|
788
890
|
},
|
|
789
891
|
],
|
|
892
|
+
structuredContent: { entry_id: entryId, kind, cube_name: active.name },
|
|
790
893
|
};
|
|
791
894
|
}
|
|
792
895
|
case 'borg_ack-status': {
|
|
793
896
|
const active = await requireActiveCube();
|
|
794
897
|
const result = await getAckStatus(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
795
|
-
return {
|
|
898
|
+
return {
|
|
899
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
900
|
+
structuredContent: { ...result },
|
|
901
|
+
};
|
|
796
902
|
}
|
|
797
903
|
case 'borg_decide': {
|
|
798
904
|
const topic = args?.topic;
|
|
@@ -816,6 +922,7 @@ export async function main() {
|
|
|
816
922
|
text: `Recorded ratified decision on "${topic}" in cube "${active.name}"${superseded}. Cite it via borg_decisions; it surfaces in borg_regen.`,
|
|
817
923
|
},
|
|
818
924
|
],
|
|
925
|
+
structuredContent: { decision: row, superseded: Boolean(row?.supersedes), cube_name: active.name },
|
|
819
926
|
};
|
|
820
927
|
}
|
|
821
928
|
case 'borg_decisions': {
|
|
@@ -829,7 +936,10 @@ export async function main() {
|
|
|
829
936
|
: decisions
|
|
830
937
|
.map((d) => `**${d.topic}:** ${d.decision}${d.rationale ? ` — ${d.rationale}` : ''}`)
|
|
831
938
|
.join('\n');
|
|
832
|
-
return {
|
|
939
|
+
return {
|
|
940
|
+
content: [{ type: 'text', text }],
|
|
941
|
+
structuredContent: { decisions },
|
|
942
|
+
};
|
|
833
943
|
}
|
|
834
944
|
case 'borg_remove-decision': {
|
|
835
945
|
const topic = typeof args?.topic === 'string' ? args.topic : undefined;
|
|
@@ -845,15 +955,22 @@ export async function main() {
|
|
|
845
955
|
type: 'text',
|
|
846
956
|
text: `Removed the active ratified decision on "${decision.topic}" from cube "${active.name}".`,
|
|
847
957
|
}],
|
|
958
|
+
structuredContent: { decision, cube_name: active.name },
|
|
848
959
|
};
|
|
849
960
|
}
|
|
850
961
|
case 'borg_list-cubes': {
|
|
851
962
|
const { cubes } = await listCubes();
|
|
852
963
|
if (!cubes.length) {
|
|
853
|
-
return {
|
|
964
|
+
return {
|
|
965
|
+
content: [{ type: 'text', text: 'No cubes yet. Use borg_create-cube to make your first one.' }],
|
|
966
|
+
structuredContent: { cubes: [] },
|
|
967
|
+
};
|
|
854
968
|
}
|
|
855
969
|
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 {
|
|
970
|
+
return {
|
|
971
|
+
content: [{ type: 'text', text: `Your cubes (${cubes.length}):\n\n${lines.join('\n\n')}` }],
|
|
972
|
+
structuredContent: { cubes },
|
|
973
|
+
};
|
|
857
974
|
}
|
|
858
975
|
case 'borg_create-cube': {
|
|
859
976
|
const name = args?.name;
|
|
@@ -892,10 +1009,21 @@ export async function main() {
|
|
|
892
1009
|
? ' Template cube directive applied (operator passed empty).'
|
|
893
1010
|
: '';
|
|
894
1011
|
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 {
|
|
1012
|
+
return {
|
|
1013
|
+
content: [{ type: 'text', text }],
|
|
1014
|
+
structuredContent: {
|
|
1015
|
+
cube,
|
|
1016
|
+
template: templateName,
|
|
1017
|
+
roles_created: summary.created,
|
|
1018
|
+
roles_updated: summary.updated,
|
|
1019
|
+
},
|
|
1020
|
+
};
|
|
896
1021
|
}
|
|
897
1022
|
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 {
|
|
1023
|
+
return {
|
|
1024
|
+
content: [{ type: 'text', text }],
|
|
1025
|
+
structuredContent: { cube, template: null, roles_created: null, roles_updated: null },
|
|
1026
|
+
};
|
|
899
1027
|
}
|
|
900
1028
|
case 'borg_update-cube': {
|
|
901
1029
|
const cubeId = args?.cube_id;
|
|
@@ -911,7 +1039,10 @@ export async function main() {
|
|
|
911
1039
|
if (Object.keys(updates).length === 0)
|
|
912
1040
|
throw new Error('Pass at least one of: cube_directive, message_taxonomy.');
|
|
913
1041
|
const { cube, advisory } = await updateCube(cubeId, updates);
|
|
914
|
-
return {
|
|
1042
|
+
return {
|
|
1043
|
+
content: [{ type: 'text', text: formatUpdatedCubeResult(cube, advisory) }],
|
|
1044
|
+
structuredContent: { cube, advisory: advisory ?? null },
|
|
1045
|
+
};
|
|
915
1046
|
}
|
|
916
1047
|
case 'borg_patch-taxonomy-class': {
|
|
917
1048
|
const cubeId = args?.cube_id;
|
|
@@ -939,7 +1070,10 @@ export async function main() {
|
|
|
939
1070
|
label = String(classDef.class ?? '');
|
|
940
1071
|
}
|
|
941
1072
|
const verb = action === 'add' ? 'Added' : action === 'replace' ? 'Replaced' : 'Removed';
|
|
942
|
-
return {
|
|
1073
|
+
return {
|
|
1074
|
+
content: [{ type: 'text', text: `${verb} taxonomy class **${label}** in cube **${cube.name}** (id: ${cube.id}).` }],
|
|
1075
|
+
structuredContent: { action, class: label, cube },
|
|
1076
|
+
};
|
|
943
1077
|
}
|
|
944
1078
|
case 'borg_delete-cube': {
|
|
945
1079
|
const cubeId = args?.cube_id;
|
|
@@ -950,7 +1084,10 @@ export async function main() {
|
|
|
950
1084
|
throw new CubeDeletionConfirmationError(cubeId, confirmCubeId);
|
|
951
1085
|
}
|
|
952
1086
|
await deleteCube(cubeId, confirmCubeId);
|
|
953
|
-
return {
|
|
1087
|
+
return {
|
|
1088
|
+
content: [{ type: 'text', text: `Deleted cube ${cubeId} (and all its roles, drones, log entries).` }],
|
|
1089
|
+
structuredContent: { cube_id: cubeId, deleted: true },
|
|
1090
|
+
};
|
|
954
1091
|
}
|
|
955
1092
|
case 'borg_create-role': {
|
|
956
1093
|
const cubeId = args?.cube_id;
|
|
@@ -988,7 +1125,10 @@ export async function main() {
|
|
|
988
1125
|
role.is_mandatory ? 'mandatory' : null,
|
|
989
1126
|
].filter(Boolean).join(', ');
|
|
990
1127
|
const tag = tags ? ` (${tags})` : '';
|
|
991
|
-
return {
|
|
1128
|
+
return {
|
|
1129
|
+
content: [{ type: 'text', text: `Created role **${role.name}**${tag} (id: ${role.id}) in cube ${cubeId}.` }],
|
|
1130
|
+
structuredContent: { role, cube_id: cubeId },
|
|
1131
|
+
};
|
|
992
1132
|
}
|
|
993
1133
|
case 'borg_update-role': {
|
|
994
1134
|
const roleId = args?.role_id;
|
|
@@ -1016,7 +1156,10 @@ export async function main() {
|
|
|
1016
1156
|
if (Object.keys(updates).length === 0)
|
|
1017
1157
|
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
1158
|
const { role, advisory } = await updateRole(roleId, updates);
|
|
1019
|
-
return {
|
|
1159
|
+
return {
|
|
1160
|
+
content: [{ type: 'text', text: formatUpdatedRoleResult(role, advisory) }],
|
|
1161
|
+
structuredContent: { role, advisory: advisory ?? null },
|
|
1162
|
+
};
|
|
1020
1163
|
}
|
|
1021
1164
|
case 'borg_patch-role-section': {
|
|
1022
1165
|
const roleId = args?.role_id;
|
|
@@ -1047,26 +1190,45 @@ export async function main() {
|
|
|
1047
1190
|
({ role, advisory } = await patchRoleSection(roleId, { action, heading, body }));
|
|
1048
1191
|
}
|
|
1049
1192
|
}
|
|
1050
|
-
return {
|
|
1193
|
+
return {
|
|
1194
|
+
content: [{ type: 'text', text: formatPatchedRoleSectionResult(action, heading, role, advisory) }],
|
|
1195
|
+
structuredContent: { action, heading, role, advisory: advisory ?? null },
|
|
1196
|
+
};
|
|
1051
1197
|
}
|
|
1052
1198
|
case 'borg_delete-role': {
|
|
1053
1199
|
const roleId = args?.role_id;
|
|
1054
1200
|
if (!roleId)
|
|
1055
1201
|
throw new Error('role_id is required');
|
|
1056
1202
|
await deleteRole(roleId);
|
|
1057
|
-
return {
|
|
1203
|
+
return {
|
|
1204
|
+
content: [{ type: 'text', text: `Deleted role ${roleId}.` }],
|
|
1205
|
+
structuredContent: { role_id: roleId, deleted: true },
|
|
1206
|
+
};
|
|
1058
1207
|
}
|
|
1059
1208
|
case 'borg_reassign-drone': {
|
|
1209
|
+
const reassigned = await runReassignDroneTool({
|
|
1210
|
+
droneId: args?.drone_id,
|
|
1211
|
+
roleId: args?.role_id,
|
|
1212
|
+
});
|
|
1060
1213
|
return {
|
|
1061
|
-
content: [{ type: 'text', text:
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1214
|
+
content: [{ type: 'text', text: reassigned.text }],
|
|
1215
|
+
structuredContent: {
|
|
1216
|
+
drone: reassigned.drone,
|
|
1217
|
+
role_name: reassigned.roleName,
|
|
1218
|
+
cube_name: reassigned.cubeName,
|
|
1219
|
+
},
|
|
1065
1220
|
};
|
|
1066
1221
|
}
|
|
1067
1222
|
case 'borg_evict-drone': {
|
|
1223
|
+
const evicted = await runEvictDroneTool(args);
|
|
1068
1224
|
return {
|
|
1069
|
-
content: [{ type: 'text', text:
|
|
1225
|
+
content: [{ type: 'text', text: evicted.text }],
|
|
1226
|
+
structuredContent: {
|
|
1227
|
+
drone_id: evicted.droneId,
|
|
1228
|
+
label: evicted.label,
|
|
1229
|
+
cube_name: evicted.cubeName,
|
|
1230
|
+
evicted: true,
|
|
1231
|
+
},
|
|
1070
1232
|
};
|
|
1071
1233
|
}
|
|
1072
1234
|
case 'borg_list-drones': {
|
|
@@ -1075,7 +1237,10 @@ export async function main() {
|
|
|
1075
1237
|
throw new Error('cube_id is required');
|
|
1076
1238
|
const { drones, roles } = await getCube(cubeId);
|
|
1077
1239
|
if (!drones.length) {
|
|
1078
|
-
return {
|
|
1240
|
+
return {
|
|
1241
|
+
content: [{ type: 'text', text: 'No drones in this cube yet.' }],
|
|
1242
|
+
structuredContent: { cube_id: cubeId, drones: [], roles },
|
|
1243
|
+
};
|
|
1079
1244
|
}
|
|
1080
1245
|
const rolesById = new Map(roles.map((r) => [r.id, r]));
|
|
1081
1246
|
const lines = drones.map((d) => {
|
|
@@ -1088,7 +1253,10 @@ export async function main() {
|
|
|
1088
1253
|
...renderRuntimeMetadataLines(d),
|
|
1089
1254
|
].join('\n');
|
|
1090
1255
|
});
|
|
1091
|
-
return {
|
|
1256
|
+
return {
|
|
1257
|
+
content: [{ type: 'text', text: `Drones in cube ${cubeId} (${drones.length}):\n\n_${RUNTIME_METADATA_ADVISORY}_\n\n${lines.join('\n')}` }],
|
|
1258
|
+
structuredContent: { cube_id: cubeId, drones, roles },
|
|
1259
|
+
};
|
|
1092
1260
|
}
|
|
1093
1261
|
case 'borg_list-roles': {
|
|
1094
1262
|
// Sprint 6 / gh#153: surface role IDs to Coordinator-class drones
|
|
@@ -1103,7 +1271,10 @@ export async function main() {
|
|
|
1103
1271
|
if (!cubeId)
|
|
1104
1272
|
throw new Error('cube_id is required');
|
|
1105
1273
|
const roles = await listRoles(cubeId);
|
|
1106
|
-
return {
|
|
1274
|
+
return {
|
|
1275
|
+
content: [{ type: 'text', text: renderRoleList(roles, cubeId) }],
|
|
1276
|
+
structuredContent: { cube_id: cubeId, roles },
|
|
1277
|
+
};
|
|
1107
1278
|
}
|
|
1108
1279
|
case 'borg_list-templates': {
|
|
1109
1280
|
const names = listTemplateNames();
|
|
@@ -1111,7 +1282,12 @@ export async function main() {
|
|
|
1111
1282
|
const t = getTemplate(n);
|
|
1112
1283
|
return `- **${n}**: ${t.description}`;
|
|
1113
1284
|
});
|
|
1114
|
-
return {
|
|
1285
|
+
return {
|
|
1286
|
+
content: [{ type: 'text', text: `Available templates:\n\n${lines.join('\n')}` }],
|
|
1287
|
+
structuredContent: {
|
|
1288
|
+
templates: names.map((n) => ({ name: n, description: getTemplate(n).description })),
|
|
1289
|
+
},
|
|
1290
|
+
};
|
|
1115
1291
|
}
|
|
1116
1292
|
case 'borg_sync-roles': {
|
|
1117
1293
|
const cubeId = args?.cube_id;
|
|
@@ -1127,7 +1303,10 @@ export async function main() {
|
|
|
1127
1303
|
if (!cubeId)
|
|
1128
1304
|
throw new Error('cube_id is required');
|
|
1129
1305
|
const result = await syncRoles(cubeId, templateName, apply, decisions);
|
|
1130
|
-
return {
|
|
1306
|
+
return {
|
|
1307
|
+
content: [{ type: 'text', text: renderSyncRolesResult(result, templateName) }],
|
|
1308
|
+
structuredContent: { cube_id: cubeId, template: templateName, apply, result },
|
|
1309
|
+
};
|
|
1131
1310
|
}
|
|
1132
1311
|
case 'borg_apply-template': {
|
|
1133
1312
|
const cubeId = args?.cube_id;
|
|
@@ -1147,7 +1326,16 @@ export async function main() {
|
|
|
1147
1326
|
noMutation: 'No template fragments were changed.',
|
|
1148
1327
|
});
|
|
1149
1328
|
const { summary, cubeDirectiveNote } = await runApplyTemplateTool(cubeId, template, authority);
|
|
1150
|
-
return {
|
|
1329
|
+
return {
|
|
1330
|
+
content: [{ type: 'text', text: `Applied template **${templateName}** to cube ${cubeId} — ${summary.created} role(s) created, ${summary.updated} updated.${cubeDirectiveNote}` }],
|
|
1331
|
+
structuredContent: {
|
|
1332
|
+
cube_id: cubeId,
|
|
1333
|
+
template: templateName,
|
|
1334
|
+
roles_created: summary.created,
|
|
1335
|
+
roles_updated: summary.updated,
|
|
1336
|
+
cube_directive_applied: cubeDirectiveNote !== '',
|
|
1337
|
+
},
|
|
1338
|
+
};
|
|
1151
1339
|
}
|
|
1152
1340
|
default:
|
|
1153
1341
|
throw new Error(`Unknown tool: ${name}`);
|