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/src/drone-management.ts
CHANGED
|
@@ -63,10 +63,26 @@ async function requireActiveCube(deps: DroneManagementDeps): Promise<ActiveCube>
|
|
|
63
63
|
return active;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// gh#492: tool helpers return the mutation receipt data alongside the rendered
|
|
67
|
+
// text so the MCP handler can emit structuredContent from the same source.
|
|
68
|
+
export interface ReassignDroneToolResult {
|
|
69
|
+
text: string;
|
|
70
|
+
drone: { id: string; cube_id: string; role_id: string; label: string };
|
|
71
|
+
roleName: string;
|
|
72
|
+
cubeName: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface EvictDroneToolResult {
|
|
76
|
+
text: string;
|
|
77
|
+
droneId: string;
|
|
78
|
+
label: string;
|
|
79
|
+
cubeName: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
66
82
|
export async function runReassignDroneTool(
|
|
67
83
|
input: { droneId: unknown; roleId: unknown },
|
|
68
84
|
deps: DroneManagementDeps = defaultDeps,
|
|
69
|
-
): Promise<
|
|
85
|
+
): Promise<ReassignDroneToolResult> {
|
|
70
86
|
if (typeof input.droneId !== 'string' || input.droneId.length === 0) {
|
|
71
87
|
throw new Error('drone_id is required');
|
|
72
88
|
}
|
|
@@ -113,19 +129,24 @@ export async function runReassignDroneTool(
|
|
|
113
129
|
}
|
|
114
130
|
}
|
|
115
131
|
|
|
116
|
-
return
|
|
117
|
-
|
|
118
|
-
|
|
132
|
+
return {
|
|
133
|
+
text: formatReassignDroneSuccess({
|
|
134
|
+
droneLabel: drone.label,
|
|
135
|
+
cubeName: cube.name,
|
|
136
|
+
roleName: role.name,
|
|
137
|
+
droneId: drone.id,
|
|
138
|
+
roleId: drone.role_id,
|
|
139
|
+
}) + warning,
|
|
140
|
+
drone: { id: drone.id, cube_id: drone.cube_id, role_id: drone.role_id, label: drone.label },
|
|
119
141
|
roleName: role.name,
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}) + warning;
|
|
142
|
+
cubeName: cube.name,
|
|
143
|
+
};
|
|
123
144
|
}
|
|
124
145
|
|
|
125
146
|
export async function runEvictDroneTool(
|
|
126
147
|
args: Record<string, unknown> | undefined,
|
|
127
148
|
deps: DroneManagementDeps = defaultDeps,
|
|
128
|
-
): Promise<
|
|
149
|
+
): Promise<EvictDroneToolResult> {
|
|
129
150
|
const droneIdInput = typeof args?.drone_id === 'string' ? args.drone_id : undefined;
|
|
130
151
|
const labelInput = typeof args?.label === 'string' ? args.label.trim() : undefined;
|
|
131
152
|
const cubeIdInput = typeof args?.cube_id === 'string' ? args.cube_id : undefined;
|
|
@@ -164,5 +185,10 @@ export async function runEvictDroneTool(
|
|
|
164
185
|
'[LOCAL-MANAGE-COMMIT-UNCONFIRMED] The server returned a successful eviction response for an unexpected drone. The eviction may already be committed. Do not retry blindly; inspect the cube roster first.',
|
|
165
186
|
);
|
|
166
187
|
}
|
|
167
|
-
return
|
|
188
|
+
return {
|
|
189
|
+
text: formatEvictDroneSuccess(priorDrone.label, cube.name),
|
|
190
|
+
droneId: priorDrone.id,
|
|
191
|
+
label: priorDrone.label,
|
|
192
|
+
cubeName: cube.name,
|
|
193
|
+
};
|
|
168
194
|
}
|
package/src/index.ts
CHANGED
|
@@ -419,8 +419,15 @@ export async function main() {
|
|
|
419
419
|
isError: true,
|
|
420
420
|
};
|
|
421
421
|
}
|
|
422
|
+
const described = {
|
|
423
|
+
name: def.name,
|
|
424
|
+
description: def.description,
|
|
425
|
+
inputSchema: def.inputSchema,
|
|
426
|
+
outputSchema: def.outputSchema ?? null,
|
|
427
|
+
};
|
|
422
428
|
return {
|
|
423
|
-
content: [{ type: 'text', text: JSON.stringify(
|
|
429
|
+
content: [{ type: 'text', text: JSON.stringify(described, null, 2) }],
|
|
430
|
+
structuredContent: described,
|
|
424
431
|
};
|
|
425
432
|
}
|
|
426
433
|
|
|
@@ -471,6 +478,7 @@ export async function main() {
|
|
|
471
478
|
text: 'Not connected to a cube. Use `borg_assimilate cube_name="<name>"` to join one.',
|
|
472
479
|
},
|
|
473
480
|
],
|
|
481
|
+
structuredContent: { connected: false },
|
|
474
482
|
};
|
|
475
483
|
}
|
|
476
484
|
seedDisplayIdentity(active);
|
|
@@ -524,10 +532,12 @@ export async function main() {
|
|
|
524
532
|
|
|
525
533
|
// gh#285: version-mismatch nudge when on-disk package is newer.
|
|
526
534
|
let versionHeader = '';
|
|
535
|
+
let onDiskVersion: string | null = null;
|
|
527
536
|
try {
|
|
528
537
|
const running = getPackageVersion();
|
|
529
538
|
const onDisk = getOnDiskVersion();
|
|
530
539
|
if (running !== 'unknown' && onDisk !== 'unknown' && onDisk !== running) {
|
|
540
|
+
onDiskVersion = onDisk;
|
|
531
541
|
const [rMaj, rMin, rPat] = running.split('.').map(Number);
|
|
532
542
|
const [dMaj, dMin, dPat] = onDisk.split('.').map(Number);
|
|
533
543
|
const onDiskNewer = dMaj > rMaj || (dMaj === rMaj && dMin > rMin) || (dMaj === rMaj && dMin === rMin && dPat > rPat);
|
|
@@ -537,7 +547,21 @@ export async function main() {
|
|
|
537
547
|
}
|
|
538
548
|
} catch { /* never break regen */ }
|
|
539
549
|
|
|
540
|
-
return {
|
|
550
|
+
return {
|
|
551
|
+
content: [{ type: 'text', text: versionHeader + prefix + formatRegenMarkdown(displayedResult, { mode }) }],
|
|
552
|
+
structuredContent: {
|
|
553
|
+
connected: true,
|
|
554
|
+
mode,
|
|
555
|
+
cube: displayedResult.cube,
|
|
556
|
+
drone: displayedResult.drone,
|
|
557
|
+
role: displayedResult.role,
|
|
558
|
+
behind_by: typeof displayedResult.behind_by === 'number' ? displayedResult.behind_by : null,
|
|
559
|
+
decision_topics: (displayedResult.decisions ?? []).map((d: any) => d.topic),
|
|
560
|
+
running_version: getPackageVersion(),
|
|
561
|
+
on_disk_version: onDiskVersion,
|
|
562
|
+
wake_path_healthy: inboxMonitorHealthy,
|
|
563
|
+
},
|
|
564
|
+
};
|
|
541
565
|
}
|
|
542
566
|
|
|
543
567
|
case 'borg_assimilate': {
|
|
@@ -583,6 +607,11 @@ export async function main() {
|
|
|
583
607
|
].join('\n');
|
|
584
608
|
return {
|
|
585
609
|
content: [{ type: 'text', text: header + formatRegenMarkdown(displayedResult, { mode: 'full' }) }],
|
|
610
|
+
structuredContent: {
|
|
611
|
+
reattached: true,
|
|
612
|
+
cube_name: displayIdentity.cubeName,
|
|
613
|
+
drone_label: displayIdentity.droneLabel,
|
|
614
|
+
},
|
|
586
615
|
};
|
|
587
616
|
} catch (err: any) {
|
|
588
617
|
markDisplayIdentityReadFailed(active!);
|
|
@@ -592,7 +621,10 @@ export async function main() {
|
|
|
592
621
|
}
|
|
593
622
|
|
|
594
623
|
case 'borg_version': {
|
|
595
|
-
return {
|
|
624
|
+
return {
|
|
625
|
+
content: [{ type: 'text', text: `borgmcp ${getPackageVersion()}` }],
|
|
626
|
+
structuredContent: { version: getPackageVersion() },
|
|
627
|
+
};
|
|
596
628
|
}
|
|
597
629
|
|
|
598
630
|
case 'borg_playbook': {
|
|
@@ -615,7 +647,14 @@ export async function main() {
|
|
|
615
647
|
: topic
|
|
616
648
|
? `No exact match for "${topic}". Full Borg MCP docs index — WebFetch the URL you need:`
|
|
617
649
|
: `Borg MCP docs index — WebFetch the URL of the section you need:`;
|
|
618
|
-
return {
|
|
650
|
+
return {
|
|
651
|
+
content: [{ type: 'text', text: `${header}\n\n${formatDocsIndex(sections)}` }],
|
|
652
|
+
structuredContent: {
|
|
653
|
+
topic: topic || null,
|
|
654
|
+
matched: matched.length > 0,
|
|
655
|
+
sections: sections.map((s) => ({ slug: s.slug, title: s.title, url: s.url, summary: s.summary })),
|
|
656
|
+
},
|
|
657
|
+
};
|
|
619
658
|
}
|
|
620
659
|
|
|
621
660
|
case 'borg_whoami': {
|
|
@@ -644,7 +683,10 @@ export async function main() {
|
|
|
644
683
|
// The invocation-local server truth remains authoritative even if
|
|
645
684
|
// the display-only persistence refresh cannot be written.
|
|
646
685
|
}
|
|
647
|
-
return {
|
|
686
|
+
return {
|
|
687
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
688
|
+
structuredContent: { ...result },
|
|
689
|
+
};
|
|
648
690
|
}
|
|
649
691
|
|
|
650
692
|
case 'borg_cube': {
|
|
@@ -697,7 +739,10 @@ export async function main() {
|
|
|
697
739
|
}
|
|
698
740
|
lines.push('');
|
|
699
741
|
lines.push(getDronePlaybook());
|
|
700
|
-
return {
|
|
742
|
+
return {
|
|
743
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
744
|
+
structuredContent: { cube, roles },
|
|
745
|
+
};
|
|
701
746
|
}
|
|
702
747
|
|
|
703
748
|
case 'borg_role': {
|
|
@@ -718,7 +763,7 @@ export async function main() {
|
|
|
718
763
|
``,
|
|
719
764
|
role.detailed_description || '_(no detailed description set)_',
|
|
720
765
|
].join('\n');
|
|
721
|
-
return { content: [{ type: 'text', text }] };
|
|
766
|
+
return { content: [{ type: 'text', text }], structuredContent: { role } };
|
|
722
767
|
}
|
|
723
768
|
const { role } = await getRoleInfo(
|
|
724
769
|
active.sessionToken,
|
|
@@ -730,7 +775,7 @@ export async function main() {
|
|
|
730
775
|
``,
|
|
731
776
|
role.detailed_description || '_(no detailed description set)_',
|
|
732
777
|
].join('\n');
|
|
733
|
-
return { content: [{ type: 'text', text }] };
|
|
778
|
+
return { content: [{ type: 'text', text }], structuredContent: { role } };
|
|
734
779
|
}
|
|
735
780
|
|
|
736
781
|
case 'borg_role-rationale': {
|
|
@@ -749,7 +794,10 @@ export async function main() {
|
|
|
749
794
|
'',
|
|
750
795
|
result.body || '_(empty)_',
|
|
751
796
|
].join('\n');
|
|
752
|
-
return {
|
|
797
|
+
return {
|
|
798
|
+
content: [{ type: 'text', text }],
|
|
799
|
+
structuredContent: { role: result.role, section: result.section, body: result.body },
|
|
800
|
+
};
|
|
753
801
|
}
|
|
754
802
|
|
|
755
803
|
case 'borg_roster': {
|
|
@@ -763,7 +811,10 @@ export async function main() {
|
|
|
763
811
|
resolvedSince: resolvedSince ?? null,
|
|
764
812
|
humanAgo,
|
|
765
813
|
});
|
|
766
|
-
return {
|
|
814
|
+
return {
|
|
815
|
+
content: [{ type: 'text', text }],
|
|
816
|
+
structuredContent: { cube_name: active.name, drones, roles, since: resolvedSince ?? null },
|
|
817
|
+
};
|
|
767
818
|
}
|
|
768
819
|
|
|
769
820
|
case 'borg_stream-status': {
|
|
@@ -803,7 +854,18 @@ export async function main() {
|
|
|
803
854
|
cubeName: active?.name ?? null,
|
|
804
855
|
humanAgo,
|
|
805
856
|
});
|
|
806
|
-
return {
|
|
857
|
+
return {
|
|
858
|
+
content: [{ type: 'text', text: silentInertWarning + text }],
|
|
859
|
+
structuredContent: {
|
|
860
|
+
status,
|
|
861
|
+
wake_path: wakePath,
|
|
862
|
+
inbox_monitor_healthy: inboxMonitorHealthy,
|
|
863
|
+
inbox_path: inboxPath,
|
|
864
|
+
monitor_state_root: monitorStateRoot,
|
|
865
|
+
drone_label: active?.droneLabel ?? null,
|
|
866
|
+
cube_name: active?.name ?? null,
|
|
867
|
+
},
|
|
868
|
+
};
|
|
807
869
|
}
|
|
808
870
|
|
|
809
871
|
case 'borg_read-log': {
|
|
@@ -849,7 +911,16 @@ export async function main() {
|
|
|
849
911
|
`⚠ 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.`
|
|
850
912
|
);
|
|
851
913
|
}
|
|
852
|
-
return {
|
|
914
|
+
return {
|
|
915
|
+
content: [{ type: 'text', text: lines.join('\n') }],
|
|
916
|
+
structuredContent: {
|
|
917
|
+
entries,
|
|
918
|
+
drones,
|
|
919
|
+
roles,
|
|
920
|
+
behind_by: typeof behind_by === 'number' ? behind_by : null,
|
|
921
|
+
has_more: has_more === true,
|
|
922
|
+
},
|
|
923
|
+
};
|
|
853
924
|
}
|
|
854
925
|
|
|
855
926
|
case 'borg_read-entry': {
|
|
@@ -867,19 +938,28 @@ export async function main() {
|
|
|
867
938
|
'',
|
|
868
939
|
formatLogEntryMarkdown(entry, droneById, roleById),
|
|
869
940
|
].join('\n');
|
|
870
|
-
return {
|
|
941
|
+
return {
|
|
942
|
+
content: [{ type: 'text', text }],
|
|
943
|
+
structuredContent: { entry, drones, roles },
|
|
944
|
+
};
|
|
871
945
|
}
|
|
872
946
|
|
|
873
947
|
case 'borg_put-document': {
|
|
874
948
|
const active = await requireActiveCube();
|
|
875
949
|
const result = await putDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
876
|
-
return {
|
|
950
|
+
return {
|
|
951
|
+
content: [{ type: 'text', text: `Created cube document.\n\n${formatDocument(result.document)}` }],
|
|
952
|
+
structuredContent: { document: result.document },
|
|
953
|
+
};
|
|
877
954
|
}
|
|
878
955
|
|
|
879
956
|
case 'borg_get-document': {
|
|
880
957
|
const active = await requireActiveCube();
|
|
881
958
|
const result = await getDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
882
|
-
return {
|
|
959
|
+
return {
|
|
960
|
+
content: [{ type: 'text', text: formatDocument(result.document) }],
|
|
961
|
+
structuredContent: { document: result.document },
|
|
962
|
+
};
|
|
883
963
|
}
|
|
884
964
|
|
|
885
965
|
case 'borg_list-documents': {
|
|
@@ -888,13 +968,19 @@ export async function main() {
|
|
|
888
968
|
const text = result.documents.length === 0
|
|
889
969
|
? `No active or superseded documents in cube "${active.name}".`
|
|
890
970
|
: result.documents.map(formatDocumentMetadata).join('\n\n');
|
|
891
|
-
return {
|
|
971
|
+
return {
|
|
972
|
+
content: [{ type: 'text', text }],
|
|
973
|
+
structuredContent: { documents: result.documents },
|
|
974
|
+
};
|
|
892
975
|
}
|
|
893
976
|
|
|
894
977
|
case 'borg_remove-document': {
|
|
895
978
|
const active = await requireActiveCube();
|
|
896
979
|
const result = await removeDocument(active.sessionToken, active.apiUrl, args ?? {}, active.serverTrustIdentity);
|
|
897
|
-
return {
|
|
980
|
+
return {
|
|
981
|
+
content: [{ type: 'text', text: `Removed cube document.\n\n${formatDocumentMetadata(result.document)}` }],
|
|
982
|
+
structuredContent: { document: result.document },
|
|
983
|
+
};
|
|
898
984
|
}
|
|
899
985
|
|
|
900
986
|
case 'borg_log': {
|
|
@@ -918,6 +1004,13 @@ export async function main() {
|
|
|
918
1004
|
text: `Suppressed duplicate ${decision.signal?.toUpperCase()} lifecycle log for ${displayIdentity.droneLabel}; recent cube log already contains this signal.`,
|
|
919
1005
|
},
|
|
920
1006
|
],
|
|
1007
|
+
structuredContent: {
|
|
1008
|
+
suppressed: true,
|
|
1009
|
+
entry: null,
|
|
1010
|
+
recipients: [],
|
|
1011
|
+
unreachable_recipients: [],
|
|
1012
|
+
advisory: null,
|
|
1013
|
+
},
|
|
921
1014
|
};
|
|
922
1015
|
}
|
|
923
1016
|
}
|
|
@@ -962,7 +1055,16 @@ export async function main() {
|
|
|
962
1055
|
? `\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.`
|
|
963
1056
|
: '';
|
|
964
1057
|
const text = `Logged to cube "${displayIdentity.cubeName}" as ${displayIdentity.droneLabel}. (entry id: ${result.entry.id})${routed}${unreachable}${citations}${advisory}`;
|
|
965
|
-
return {
|
|
1058
|
+
return {
|
|
1059
|
+
content: [{ type: 'text', text }],
|
|
1060
|
+
structuredContent: {
|
|
1061
|
+
suppressed: false,
|
|
1062
|
+
entry: result.entry,
|
|
1063
|
+
recipients: routedRecipients,
|
|
1064
|
+
unreachable_recipients: result.unreachableRecipients ?? [],
|
|
1065
|
+
advisory: result.advisory ?? null,
|
|
1066
|
+
},
|
|
1067
|
+
};
|
|
966
1068
|
}
|
|
967
1069
|
|
|
968
1070
|
case 'borg_ack': {
|
|
@@ -992,6 +1094,7 @@ export async function main() {
|
|
|
992
1094
|
: `Acked entry ${entryId} in cube "${active.name}".`,
|
|
993
1095
|
},
|
|
994
1096
|
],
|
|
1097
|
+
structuredContent: { entry_id: entryId, kind, cube_name: active.name },
|
|
995
1098
|
};
|
|
996
1099
|
}
|
|
997
1100
|
|
|
@@ -1003,7 +1106,10 @@ export async function main() {
|
|
|
1003
1106
|
args ?? {},
|
|
1004
1107
|
active.serverTrustIdentity,
|
|
1005
1108
|
);
|
|
1006
|
-
return {
|
|
1109
|
+
return {
|
|
1110
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
1111
|
+
structuredContent: { ...result },
|
|
1112
|
+
};
|
|
1007
1113
|
}
|
|
1008
1114
|
|
|
1009
1115
|
case 'borg_decide': {
|
|
@@ -1031,6 +1137,7 @@ export async function main() {
|
|
|
1031
1137
|
text: `Recorded ratified decision on "${topic}" in cube "${active.name}"${superseded}. Cite it via borg_decisions; it surfaces in borg_regen.`,
|
|
1032
1138
|
},
|
|
1033
1139
|
],
|
|
1140
|
+
structuredContent: { decision: row, superseded: Boolean(row?.supersedes), cube_name: active.name },
|
|
1034
1141
|
};
|
|
1035
1142
|
}
|
|
1036
1143
|
|
|
@@ -1051,7 +1158,10 @@ export async function main() {
|
|
|
1051
1158
|
: decisions
|
|
1052
1159
|
.map((d: any) => `**${d.topic}:** ${d.decision}${d.rationale ? ` — ${d.rationale}` : ''}`)
|
|
1053
1160
|
.join('\n');
|
|
1054
|
-
return {
|
|
1161
|
+
return {
|
|
1162
|
+
content: [{ type: 'text', text }],
|
|
1163
|
+
structuredContent: { decisions },
|
|
1164
|
+
};
|
|
1055
1165
|
}
|
|
1056
1166
|
|
|
1057
1167
|
case 'borg_remove-decision': {
|
|
@@ -1073,18 +1183,25 @@ export async function main() {
|
|
|
1073
1183
|
type: 'text',
|
|
1074
1184
|
text: `Removed the active ratified decision on "${decision.topic}" from cube "${active.name}".`,
|
|
1075
1185
|
}],
|
|
1186
|
+
structuredContent: { decision, cube_name: active.name },
|
|
1076
1187
|
};
|
|
1077
1188
|
}
|
|
1078
1189
|
|
|
1079
1190
|
case 'borg_list-cubes': {
|
|
1080
1191
|
const { cubes } = await listCubes();
|
|
1081
1192
|
if (!cubes.length) {
|
|
1082
|
-
return {
|
|
1193
|
+
return {
|
|
1194
|
+
content: [{ type: 'text', text: 'No cubes yet. Use borg_create-cube to make your first one.' }],
|
|
1195
|
+
structuredContent: { cubes: [] },
|
|
1196
|
+
};
|
|
1083
1197
|
}
|
|
1084
1198
|
const lines = cubes.map((c: any) =>
|
|
1085
1199
|
`- **${c.name}** (id: ${c.id})\n ${(c.cube_directive || '_(no directive set)_').split('\n')[0].slice(0, 120)}`
|
|
1086
1200
|
);
|
|
1087
|
-
return {
|
|
1201
|
+
return {
|
|
1202
|
+
content: [{ type: 'text', text: `Your cubes (${cubes.length}):\n\n${lines.join('\n\n')}` }],
|
|
1203
|
+
structuredContent: { cubes },
|
|
1204
|
+
};
|
|
1088
1205
|
}
|
|
1089
1206
|
|
|
1090
1207
|
case 'borg_create-cube': {
|
|
@@ -1126,10 +1243,21 @@ export async function main() {
|
|
|
1126
1243
|
? ' Template cube directive applied (operator passed empty).'
|
|
1127
1244
|
: '';
|
|
1128
1245
|
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.`;
|
|
1129
|
-
return {
|
|
1246
|
+
return {
|
|
1247
|
+
content: [{ type: 'text', text }],
|
|
1248
|
+
structuredContent: {
|
|
1249
|
+
cube,
|
|
1250
|
+
template: templateName,
|
|
1251
|
+
roles_created: summary.created,
|
|
1252
|
+
roles_updated: summary.updated,
|
|
1253
|
+
},
|
|
1254
|
+
};
|
|
1130
1255
|
}
|
|
1131
1256
|
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.`;
|
|
1132
|
-
return {
|
|
1257
|
+
return {
|
|
1258
|
+
content: [{ type: 'text', text }],
|
|
1259
|
+
structuredContent: { cube, template: null, roles_created: null, roles_updated: null },
|
|
1260
|
+
};
|
|
1133
1261
|
}
|
|
1134
1262
|
|
|
1135
1263
|
case 'borg_update-cube': {
|
|
@@ -1141,7 +1269,10 @@ export async function main() {
|
|
|
1141
1269
|
if (Array.isArray(args?.message_taxonomy)) updates.message_taxonomy = args.message_taxonomy as MessageTaxonomy;
|
|
1142
1270
|
if (Object.keys(updates).length === 0) throw new Error('Pass at least one of: cube_directive, message_taxonomy.');
|
|
1143
1271
|
const { cube, advisory } = await updateCube(cubeId, updates);
|
|
1144
|
-
return {
|
|
1272
|
+
return {
|
|
1273
|
+
content: [{ type: 'text', text: formatUpdatedCubeResult(cube, advisory) }],
|
|
1274
|
+
structuredContent: { cube, advisory: advisory ?? null },
|
|
1275
|
+
};
|
|
1145
1276
|
}
|
|
1146
1277
|
|
|
1147
1278
|
case 'borg_patch-taxonomy-class': {
|
|
@@ -1167,7 +1298,10 @@ export async function main() {
|
|
|
1167
1298
|
label = String(classDef.class ?? '');
|
|
1168
1299
|
}
|
|
1169
1300
|
const verb = action === 'add' ? 'Added' : action === 'replace' ? 'Replaced' : 'Removed';
|
|
1170
|
-
return {
|
|
1301
|
+
return {
|
|
1302
|
+
content: [{ type: 'text', text: `${verb} taxonomy class **${label}** in cube **${cube.name}** (id: ${cube.id}).` }],
|
|
1303
|
+
structuredContent: { action, class: label, cube },
|
|
1304
|
+
};
|
|
1171
1305
|
}
|
|
1172
1306
|
|
|
1173
1307
|
case 'borg_delete-cube': {
|
|
@@ -1178,7 +1312,10 @@ export async function main() {
|
|
|
1178
1312
|
throw new CubeDeletionConfirmationError(cubeId, confirmCubeId);
|
|
1179
1313
|
}
|
|
1180
1314
|
await deleteCube(cubeId, confirmCubeId);
|
|
1181
|
-
return {
|
|
1315
|
+
return {
|
|
1316
|
+
content: [{ type: 'text', text: `Deleted cube ${cubeId} (and all its roles, drones, log entries).` }],
|
|
1317
|
+
structuredContent: { cube_id: cubeId, deleted: true },
|
|
1318
|
+
};
|
|
1182
1319
|
}
|
|
1183
1320
|
|
|
1184
1321
|
case 'borg_create-role': {
|
|
@@ -1213,7 +1350,10 @@ export async function main() {
|
|
|
1213
1350
|
role.is_mandatory ? 'mandatory' : null,
|
|
1214
1351
|
].filter(Boolean).join(', ');
|
|
1215
1352
|
const tag = tags ? ` (${tags})` : '';
|
|
1216
|
-
return {
|
|
1353
|
+
return {
|
|
1354
|
+
content: [{ type: 'text', text: `Created role **${role.name}**${tag} (id: ${role.id}) in cube ${cubeId}.` }],
|
|
1355
|
+
structuredContent: { role, cube_id: cubeId },
|
|
1356
|
+
};
|
|
1217
1357
|
}
|
|
1218
1358
|
|
|
1219
1359
|
case 'borg_update-role': {
|
|
@@ -1231,7 +1371,10 @@ export async function main() {
|
|
|
1231
1371
|
if (typeof args?.default_model === 'string') updates.default_model = args.default_model as string;
|
|
1232
1372
|
if (Object.keys(updates).length === 0) 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.');
|
|
1233
1373
|
const { role, advisory } = await updateRole(roleId, updates);
|
|
1234
|
-
return {
|
|
1374
|
+
return {
|
|
1375
|
+
content: [{ type: 'text', text: formatUpdatedRoleResult(role, advisory) }],
|
|
1376
|
+
structuredContent: { role, advisory: advisory ?? null },
|
|
1377
|
+
};
|
|
1235
1378
|
}
|
|
1236
1379
|
|
|
1237
1380
|
case 'borg_patch-role-section': {
|
|
@@ -1259,28 +1402,47 @@ export async function main() {
|
|
|
1259
1402
|
({ role, advisory } = await patchRoleSection(roleId, { action, heading, body }));
|
|
1260
1403
|
}
|
|
1261
1404
|
}
|
|
1262
|
-
return {
|
|
1405
|
+
return {
|
|
1406
|
+
content: [{ type: 'text', text: formatPatchedRoleSectionResult(action, heading, role, advisory) }],
|
|
1407
|
+
structuredContent: { action, heading, role, advisory: advisory ?? null },
|
|
1408
|
+
};
|
|
1263
1409
|
}
|
|
1264
1410
|
|
|
1265
1411
|
case 'borg_delete-role': {
|
|
1266
1412
|
const roleId = args?.role_id as string;
|
|
1267
1413
|
if (!roleId) throw new Error('role_id is required');
|
|
1268
1414
|
await deleteRole(roleId);
|
|
1269
|
-
return {
|
|
1415
|
+
return {
|
|
1416
|
+
content: [{ type: 'text', text: `Deleted role ${roleId}.` }],
|
|
1417
|
+
structuredContent: { role_id: roleId, deleted: true },
|
|
1418
|
+
};
|
|
1270
1419
|
}
|
|
1271
1420
|
|
|
1272
1421
|
case 'borg_reassign-drone': {
|
|
1422
|
+
const reassigned = await runReassignDroneTool({
|
|
1423
|
+
droneId: args?.drone_id,
|
|
1424
|
+
roleId: args?.role_id,
|
|
1425
|
+
});
|
|
1273
1426
|
return {
|
|
1274
|
-
content: [{ type: 'text', text:
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1427
|
+
content: [{ type: 'text', text: reassigned.text }],
|
|
1428
|
+
structuredContent: {
|
|
1429
|
+
drone: reassigned.drone,
|
|
1430
|
+
role_name: reassigned.roleName,
|
|
1431
|
+
cube_name: reassigned.cubeName,
|
|
1432
|
+
},
|
|
1278
1433
|
};
|
|
1279
1434
|
}
|
|
1280
1435
|
|
|
1281
1436
|
case 'borg_evict-drone': {
|
|
1437
|
+
const evicted = await runEvictDroneTool(args);
|
|
1282
1438
|
return {
|
|
1283
|
-
content: [{ type: 'text', text:
|
|
1439
|
+
content: [{ type: 'text', text: evicted.text }],
|
|
1440
|
+
structuredContent: {
|
|
1441
|
+
drone_id: evicted.droneId,
|
|
1442
|
+
label: evicted.label,
|
|
1443
|
+
cube_name: evicted.cubeName,
|
|
1444
|
+
evicted: true,
|
|
1445
|
+
},
|
|
1284
1446
|
};
|
|
1285
1447
|
}
|
|
1286
1448
|
|
|
@@ -1289,7 +1451,10 @@ export async function main() {
|
|
|
1289
1451
|
if (!cubeId) throw new Error('cube_id is required');
|
|
1290
1452
|
const { drones, roles } = await getCube(cubeId);
|
|
1291
1453
|
if (!drones.length) {
|
|
1292
|
-
return {
|
|
1454
|
+
return {
|
|
1455
|
+
content: [{ type: 'text', text: 'No drones in this cube yet.' }],
|
|
1456
|
+
structuredContent: { cube_id: cubeId, drones: [], roles },
|
|
1457
|
+
};
|
|
1293
1458
|
}
|
|
1294
1459
|
const rolesById = new Map(roles.map((r: any) => [r.id, r]));
|
|
1295
1460
|
const lines = drones.map((d: any) => {
|
|
@@ -1303,7 +1468,10 @@ export async function main() {
|
|
|
1303
1468
|
...renderRuntimeMetadataLines(d),
|
|
1304
1469
|
].join('\n');
|
|
1305
1470
|
});
|
|
1306
|
-
return {
|
|
1471
|
+
return {
|
|
1472
|
+
content: [{ type: 'text', text: `Drones in cube ${cubeId} (${drones.length}):\n\n_${RUNTIME_METADATA_ADVISORY}_\n\n${lines.join('\n')}` }],
|
|
1473
|
+
structuredContent: { cube_id: cubeId, drones, roles },
|
|
1474
|
+
};
|
|
1307
1475
|
}
|
|
1308
1476
|
|
|
1309
1477
|
case 'borg_list-roles': {
|
|
@@ -1318,7 +1486,10 @@ export async function main() {
|
|
|
1318
1486
|
const cubeId = args?.cube_id as string;
|
|
1319
1487
|
if (!cubeId) throw new Error('cube_id is required');
|
|
1320
1488
|
const roles = await listRoles(cubeId);
|
|
1321
|
-
return {
|
|
1489
|
+
return {
|
|
1490
|
+
content: [{ type: 'text', text: renderRoleList(roles, cubeId) }],
|
|
1491
|
+
structuredContent: { cube_id: cubeId, roles },
|
|
1492
|
+
};
|
|
1322
1493
|
}
|
|
1323
1494
|
|
|
1324
1495
|
case 'borg_list-templates': {
|
|
@@ -1327,7 +1498,12 @@ export async function main() {
|
|
|
1327
1498
|
const t = getTemplate(n)!;
|
|
1328
1499
|
return `- **${n}**: ${t.description}`;
|
|
1329
1500
|
});
|
|
1330
|
-
return {
|
|
1501
|
+
return {
|
|
1502
|
+
content: [{ type: 'text', text: `Available templates:\n\n${lines.join('\n')}` }],
|
|
1503
|
+
structuredContent: {
|
|
1504
|
+
templates: names.map((n) => ({ name: n, description: getTemplate(n)!.description })),
|
|
1505
|
+
},
|
|
1506
|
+
};
|
|
1331
1507
|
}
|
|
1332
1508
|
|
|
1333
1509
|
case 'borg_sync-roles': {
|
|
@@ -1344,7 +1520,10 @@ export async function main() {
|
|
|
1344
1520
|
: undefined;
|
|
1345
1521
|
if (!cubeId) throw new Error('cube_id is required');
|
|
1346
1522
|
const result = await syncRoles(cubeId, templateName, apply, decisions);
|
|
1347
|
-
return {
|
|
1523
|
+
return {
|
|
1524
|
+
content: [{ type: 'text', text: renderSyncRolesResult(result, templateName) }],
|
|
1525
|
+
structuredContent: { cube_id: cubeId, template: templateName, apply, result },
|
|
1526
|
+
};
|
|
1348
1527
|
}
|
|
1349
1528
|
|
|
1350
1529
|
case 'borg_apply-template': {
|
|
@@ -1364,7 +1543,16 @@ export async function main() {
|
|
|
1364
1543
|
});
|
|
1365
1544
|
const { summary, cubeDirectiveNote } = await runApplyTemplateTool(cubeId, template, authority);
|
|
1366
1545
|
|
|
1367
|
-
return {
|
|
1546
|
+
return {
|
|
1547
|
+
content: [{ type: 'text', text: `Applied template **${templateName}** to cube ${cubeId} — ${summary.created} role(s) created, ${summary.updated} updated.${cubeDirectiveNote}` }],
|
|
1548
|
+
structuredContent: {
|
|
1549
|
+
cube_id: cubeId,
|
|
1550
|
+
template: templateName,
|
|
1551
|
+
roles_created: summary.created,
|
|
1552
|
+
roles_updated: summary.updated,
|
|
1553
|
+
cube_directive_applied: cubeDirectiveNote !== '',
|
|
1554
|
+
},
|
|
1555
|
+
};
|
|
1368
1556
|
}
|
|
1369
1557
|
|
|
1370
1558
|
default:
|