borgmcp 3.0.0 → 3.1.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/bare-launch-menu.d.ts +5 -5
- package/dist/bare-launch-menu.d.ts.map +1 -1
- package/dist/bare-launch-menu.js +2 -2
- package/dist/bare-launch-menu.js.map +1 -1
- package/dist/claude.js +3 -3
- package/dist/claude.js.map +1 -1
- package/dist/cli-platform.d.ts +4 -0
- package/dist/cli-platform.d.ts.map +1 -1
- package/dist/cli-platform.js +29 -10
- package/dist/cli-platform.js.map +1 -1
- package/dist/cubes.d.ts.map +1 -1
- package/dist/cubes.js +28 -10
- package/dist/cubes.js.map +1 -1
- package/dist/first-run-server.d.ts.map +1 -1
- package/dist/first-run-server.js +4 -1
- package/dist/first-run-server.js.map +1 -1
- package/dist/launch-all-cmd.js +1 -1
- package/dist/launch-all-cmd.js.map +1 -1
- package/dist/lifecycle-log-guard.d.ts.map +1 -1
- package/dist/lifecycle-log-guard.js +12 -3
- package/dist/lifecycle-log-guard.js.map +1 -1
- package/dist/remote-client.d.ts.map +1 -1
- package/dist/remote-client.js +36 -14
- package/dist/remote-client.js.map +1 -1
- package/dist/server-handshake.d.ts +1 -1
- package/dist/tool-manifest.js +3 -3
- package/dist/tool-manifest.js.map +1 -1
- package/docs/EXTRACTION_PROVENANCE.md +16 -28
- package/docs/LOCAL_SERVER.md +1 -1
- package/docs/RELEASING.md +3 -3
- package/package.json +2 -2
- package/src/bare-launch-menu.ts +6 -6
- package/src/claude.ts +6 -4
- package/src/cli-platform.ts +42 -10
- package/src/cubes.ts +27 -12
- package/src/first-run-server.ts +4 -1
- package/src/launch-all-cmd.ts +1 -1
- package/src/lifecycle-log-guard.ts +15 -3
- package/src/remote-client.ts +57 -15
- package/src/server-handshake.ts +1 -1
- package/src/tool-manifest.ts +3 -3
package/src/remote-client.ts
CHANGED
|
@@ -17,17 +17,23 @@ import { randomUUID } from 'node:crypto';
|
|
|
17
17
|
import {
|
|
18
18
|
createProtocolEnvelope,
|
|
19
19
|
decodeDeleteCubeResponse,
|
|
20
|
+
decodeDeleteRoleRequest,
|
|
21
|
+
decodeDeleteRoleResult,
|
|
20
22
|
decodeDroneRuntimeMetadataState,
|
|
21
23
|
decodeEvictDroneResult,
|
|
22
24
|
decodeProtocolEnvelope,
|
|
23
25
|
decodeProtocolErrorEnvelope,
|
|
24
26
|
decodeReassignDroneResult,
|
|
27
|
+
decodeRoleRationaleRequest,
|
|
28
|
+
decodeRoleRationaleResult,
|
|
25
29
|
decodeUpdateDroneRuntimeMetadataResponse,
|
|
26
30
|
ErrorCode,
|
|
27
31
|
ProtocolContractError,
|
|
28
32
|
type AgentKind,
|
|
33
|
+
type DeleteRoleResult,
|
|
29
34
|
type EvictDroneResult,
|
|
30
35
|
type ReassignDroneResult,
|
|
36
|
+
type RoleRationaleResult,
|
|
31
37
|
} from 'borgmcp-shared/protocol';
|
|
32
38
|
import { consolePrefix } from './console-prefix.js';
|
|
33
39
|
import { debugLog } from './debug.js';
|
|
@@ -95,16 +101,22 @@ export const LOCAL_SERVER_REQUEST_TIMEOUT_MS = 5_000;
|
|
|
95
101
|
const LOCAL_SERVER_RESPONSE_LIMIT_MESSAGE =
|
|
96
102
|
'Local Borg server response exceeded the response limit';
|
|
97
103
|
|
|
104
|
+
export const SERVER_ADVISORY_MAX_CHARS = 512;
|
|
105
|
+
// Keep enough source headroom to remove control sequences that cross the
|
|
106
|
+
// visible 512-character boundary without letting regex work scale with the
|
|
107
|
+
// 32 MiB response-body limit.
|
|
108
|
+
const SERVER_MESSAGE_SANITIZE_MAX_CHARS = SERVER_ADVISORY_MAX_CHARS * 8;
|
|
109
|
+
|
|
98
110
|
function sanitizeServerMessage(message: string): string {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
111
|
+
const bounded = message.slice(0, SERVER_MESSAGE_SANITIZE_MAX_CHARS);
|
|
112
|
+
|
|
113
|
+
return bounded
|
|
114
|
+
.replace(/\u001b\][^\u0007]*(?:\u0007|\u001b\\|$)/g, '')
|
|
115
|
+
.replace(/\u001b\[[0-?]*[ -/]*(?:[@-~]|$)/g, '')
|
|
102
116
|
.replace(/[\u0000-\u001f\u007f-\u009f]/g, '')
|
|
103
117
|
.replace(/\\u(?:000[0-9a-f]|001[0-9a-f]|007f|008[0-9a-f]|009[0-9a-f])/gi, '');
|
|
104
118
|
}
|
|
105
119
|
|
|
106
|
-
export const SERVER_ADVISORY_MAX_CHARS = 512;
|
|
107
|
-
|
|
108
120
|
export function sanitizeServerAdvisory(value: unknown): string | undefined {
|
|
109
121
|
if (typeof value !== 'string') return undefined;
|
|
110
122
|
const sanitized = sanitizeServerMessage(value).trim();
|
|
@@ -295,7 +307,10 @@ async function localServerRequest<T>(
|
|
|
295
307
|
path: string,
|
|
296
308
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH',
|
|
297
309
|
payload?: Record<string, unknown>,
|
|
298
|
-
options: {
|
|
310
|
+
options: {
|
|
311
|
+
retryMode?: AuthedFetchRetryMode;
|
|
312
|
+
decodePayload?: (value: unknown) => T;
|
|
313
|
+
} = {},
|
|
299
314
|
): Promise<T | null> {
|
|
300
315
|
return decodeLocalProtocolResponse<T>((signal) => authedFetch(path, {
|
|
301
316
|
method,
|
|
@@ -312,7 +327,7 @@ async function localServerRequest<T>(
|
|
|
312
327
|
body: JSON.stringify(createProtocolEnvelope(randomUUID(), payload)),
|
|
313
328
|
}),
|
|
314
329
|
retryMode: options.retryMode,
|
|
315
|
-
}), true);
|
|
330
|
+
}), true, options.decodePayload);
|
|
316
331
|
}
|
|
317
332
|
|
|
318
333
|
export interface LocalManageOperation {
|
|
@@ -1247,12 +1262,21 @@ export async function roleRationale(
|
|
|
1247
1262
|
section: string,
|
|
1248
1263
|
serverTrustIdentity?: string,
|
|
1249
1264
|
): Promise<{ role: string; section: string; body: string }> {
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1265
|
+
const local = await localAuthorityContext(sessionToken, apiUrl, serverTrustIdentity);
|
|
1266
|
+
const request = decodeRoleRationaleRequest({ role, section });
|
|
1267
|
+
const result = await localServerRequest<RoleRationaleResult>(
|
|
1268
|
+
local,
|
|
1269
|
+
`/api/cubes/${local.cubeId}/role-rationale`,
|
|
1270
|
+
'POST',
|
|
1271
|
+
{ ...request },
|
|
1272
|
+
{ decodePayload: decodeRoleRationaleResult },
|
|
1273
|
+
);
|
|
1274
|
+
if (!result) throw new Error('Local Borg server returned an empty role rationale response');
|
|
1275
|
+
return {
|
|
1276
|
+
role: result.role_name,
|
|
1277
|
+
section: result.section.heading,
|
|
1278
|
+
body: result.section.body,
|
|
1279
|
+
};
|
|
1256
1280
|
}
|
|
1257
1281
|
|
|
1258
1282
|
/**
|
|
@@ -1656,8 +1680,26 @@ export async function patchRoleSection(
|
|
|
1656
1680
|
* (reassign or evict those drones first).
|
|
1657
1681
|
*/
|
|
1658
1682
|
export async function deleteRole(roleId: string): Promise<void> {
|
|
1659
|
-
|
|
1660
|
-
|
|
1683
|
+
assertUuidShape(roleId, 'role_id');
|
|
1684
|
+
const active = await getActiveCube();
|
|
1685
|
+
if (!active?.serverTrustIdentity) throw new Error('Selected Borg server authority state is missing or unreadable');
|
|
1686
|
+
assertUuidShape(active.cubeId, 'cube_id');
|
|
1687
|
+
const result = await localManageRequest<DeleteRoleResult>(
|
|
1688
|
+
active,
|
|
1689
|
+
`/api/cubes/${active.cubeId}/roles/${roleId}`,
|
|
1690
|
+
'DELETE',
|
|
1691
|
+
{
|
|
1692
|
+
operation: `delete role ${manageCopyValue(roleId)} from cube ${manageCopyValue(active.name)}`,
|
|
1693
|
+
cubeName: active.name,
|
|
1694
|
+
noMutation: 'No role was deleted.',
|
|
1695
|
+
},
|
|
1696
|
+
decodeDeleteRoleRequest({}),
|
|
1697
|
+
decodeDeleteRoleResult,
|
|
1698
|
+
);
|
|
1699
|
+
if (!result) throw new Error('Local Borg server returned an empty role deletion response');
|
|
1700
|
+
if (result.role_id !== roleId) {
|
|
1701
|
+
throw new Error('Local Borg server returned a deletion response for an unexpected role');
|
|
1702
|
+
}
|
|
1661
1703
|
}
|
|
1662
1704
|
|
|
1663
1705
|
/**
|
package/src/server-handshake.ts
CHANGED
|
@@ -214,7 +214,7 @@ export interface ServerAttachResult {
|
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
/**
|
|
217
|
-
* Attach an enrolled client principal to one granted cube/role over protocol
|
|
217
|
+
* Attach an enrolled client principal to one granted cube/role over protocol v8.
|
|
218
218
|
* The client CSPRNG-generates the session bearer and persists it PENDING in the
|
|
219
219
|
* OS keychain (keyed by the stable per-seat identity) BEFORE this request, so an
|
|
220
220
|
* interrupted/lost response is recovered by re-sending the exact same bearer —
|
package/src/tool-manifest.ts
CHANGED
|
@@ -154,8 +154,8 @@ export const TOOL_MANIFEST: ToolManifestEntry[] = [
|
|
|
154
154
|
{
|
|
155
155
|
name: 'borg_role-rationale',
|
|
156
156
|
description:
|
|
157
|
-
"Fetch
|
|
158
|
-
"Pass a role name/
|
|
157
|
+
"Fetch exactly one named section from a role's detailed playbook using the current drone session. " +
|
|
158
|
+
"Pass a role name/UUID and a plain-label section key. Role names and section keys match case-insensitively; UUIDs match exactly. Malformed selectors, ambiguous role names, and unknown roles/sections refuse. Returns the server's canonical role name, role_id, section heading, and the section body in full, refusing rather than truncating when it exceeds the server's role-text size limit, so a drone can read one section on demand instead of carrying the whole playbook in every borg_regen.",
|
|
159
159
|
inputSchema: {
|
|
160
160
|
type: 'object',
|
|
161
161
|
properties: {
|
|
@@ -481,7 +481,7 @@ export const TOOL_MANIFEST: ToolManifestEntry[] = [
|
|
|
481
481
|
},
|
|
482
482
|
{
|
|
483
483
|
name: 'borg_delete-role',
|
|
484
|
-
description: 'Delete a role.
|
|
484
|
+
description: 'Delete a role using the selected local client\'s cube-management grant. Unknown or inaccessible roles refuse. Also refuses for the default, mandatory, or human-seat role; a role referenced by message-taxonomy routing; or a role assigned to an active drone. Reassign active drones with borg_reassign-drone or remove them with borg_evict-drone first. Evicted drones that held the deleted role are reassigned to the cube\'s default role; their activity-log attribution is unaffected.',
|
|
485
485
|
inputSchema: {
|
|
486
486
|
type: 'object',
|
|
487
487
|
properties: {
|