deadbyte-mcp 0.9.0 → 0.11.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/MANIFEST.SHA256 +134 -92
- package/README.txt +19 -15
- package/bench/fixtures/corpus.json +32 -13
- package/bench/fixtures/r36/case-map.json +8 -0
- package/bin/WORKER-REGISTRY.txt +3 -3
- package/bin/appcontainer-stage.exe +0 -0
- package/bin/appcontainer-stage.obj +0 -0
- package/bin/bootstrap-advapi32.exe +0 -0
- package/bin/bootstrap-advapi32.obj +0 -0
- package/bin/bootstrap-exitcode.exe +0 -0
- package/bin/bootstrap-exitcode.obj +0 -0
- package/bin/bootstrap-kernel32.exe +0 -0
- package/bin/bootstrap-kernel32.obj +0 -0
- package/bin/child-control-probe.exe +0 -0
- package/bin/child-control-probe.obj +0 -0
- package/bin/child-control-stage.exe +0 -0
- package/bin/child-control-stage.obj +0 -0
- package/bin/contained-reverse-worker.exe +0 -0
- package/bin/contained-reverse-worker.obj +0 -0
- package/bin/contained-transform-worker.exe +0 -0
- package/bin/contained-transform-worker.obj +0 -0
- package/bin/containment-probe.exe +0 -0
- package/bin/containment-probe.obj +0 -0
- package/bin/deadbyte-contain.exe +0 -0
- package/bin/deadbyte-contain.obj +0 -0
- package/bin/deadbyte-exec.exe +0 -0
- package/bin/deadbyte-exec.obj +0 -0
- package/bin/deadbyte-process-host.exe +0 -0
- package/bin/deadbyte-process-host.obj +0 -0
- package/bin/deadbyte-tunnel-host.exe +0 -0
- package/bin/deadbyte-tunnel-host.obj +0 -0
- package/controller/README.TXT +8 -6
- package/controller/deadbyte-controller.ps1 +48 -2
- package/controller/deadbyte-process-policy.json +5 -5
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/R36-CAPABILITY-EVIDENCE.md +43 -0
- package/docs/superpowers/plans/2026-09-18-r36-zero-loss-autonomy.md +739 -0
- package/docs/superpowers/specs/2026-09-18-r36-zero-loss-autonomy-design.md +640 -0
- package/package.json +1 -1
- package/proof/CONTAINMENT-BUILD.txt +6 -6
- package/scripts/deferred-slot-operation.mjs +53 -15
- package/scripts/final-closure-r36.mjs +113 -0
- package/scripts/final-closure-verify-r36.mjs +208 -0
- package/scripts/final-closure-verify.mjs +88 -39
- package/scripts/final-closure.mjs +63 -56
- package/scripts/gate-windows-r36.ps1 +42 -0
- package/scripts/gate-windows.ps1 +3 -3
- package/scripts/release-parity-r36.mjs +200 -0
- package/scripts/release-parity-tests.ps1 +9 -0
- package/scripts/release-parity.mjs +149 -139
- package/scripts/windows-gate-evidence-r36.mjs +52 -0
- package/scripts/windows-gate-evidence.mjs +5 -5
- package/src/agent-memory-plane.mjs +98 -0
- package/src/autonomous-context-engine.mjs +2 -1
- package/src/autonomous-mcp-tools.mjs +5 -1
- package/src/autonomous-output-contracts.mjs +9 -6
- package/src/autonomous-planner-contracts.mjs +36 -1
- package/src/autonomous-planner.mjs +25 -3
- package/src/autonomous-runtime.mjs +337 -43
- package/src/autonomous-timeout-recovery.mjs +27 -0
- package/src/capability-benchmark-runner.mjs +86 -1
- package/src/capability-benchmark.mjs +45 -0
- package/src/capability-ledger.mjs +158 -0
- package/src/coding-mcp-tools.mjs +31 -17
- package/src/coding-output-contracts.mjs +48 -10
- package/src/coding-plane.mjs +45 -9
- package/src/coding-search.mjs +130 -47
- package/src/compact-gateway-mcp-tools.mjs +128 -0
- package/src/compact-gateway-output-contracts.mjs +16 -0
- package/src/deadbyte-cli.mjs +62 -78
- package/src/effect-ledger.mjs +47 -0
- package/src/machine-fs-smoke-client.mjs +1 -1
- package/src/machine-fs.mjs +51 -8
- package/src/mcp-server.mjs +32 -9
- package/src/native-diff-v2.mjs +337 -0
- package/src/native-diff.mjs +50 -2
- package/src/observation-lease.mjs +32 -0
- package/src/observation-smoke-client.mjs +1 -1
- package/src/operator-surface.mjs +7 -1
- package/src/process-runtime.mjs +98 -11
- package/src/process-smoke-client.mjs +11 -3
- package/src/r36-compact-disarmed-probe.mjs +50 -0
- package/src/r36-full-surface-probe.mjs +56 -0
- package/src/remote-live-log.mjs +135 -0
- package/src/remote-mcp-autonomous-smoke-client.mjs +22 -12
- package/src/remote-mcp-coding-smoke-client.mjs +1 -1
- package/src/remote-mcp-r36-parity-client.mjs +175 -0
- package/src/remote-mcp-smoke-client.mjs +112 -56
- package/src/runtime-update.mjs +51 -1
- package/src/search-cursor.mjs +45 -0
- package/src/semantic-code.mjs +72 -5
- package/src/semantic-lsp-backend.mjs +39 -3
- package/src/version.mjs +1 -1
- package/src/worker-scheduler.mjs +53 -0
- package/test/autonomous-capability-r36.test.mjs +151 -0
- package/test/autonomous-output-contract.test.mjs +1 -1
- package/test/autonomous-runtime.test.mjs +2 -2
- package/test/capability-benchmark-r36.test.mjs +107 -0
- package/test/capability-benchmark-semantic-r36.test.mjs +52 -0
- package/test/capability-claims-r36.test.mjs +23 -0
- package/test/capability-ledger-r36.test.mjs +102 -0
- package/test/coding-catalog-consistency.test.mjs +2 -2
- package/test/coding-plane.test.mjs +2 -2
- package/test/coding-runtime.test.mjs +16 -0
- package/test/coding-search-r36.test.mjs +90 -0
- package/test/compact-catalog-r36.test.mjs +37 -0
- package/test/compact-gateway-r36.test.mjs +66 -0
- package/test/contained.test.mjs +1 -1
- package/test/core.test.mjs +1 -1
- package/test/deferred-slot-operation.test.mjs +9 -0
- package/test/fixtures/lsp-framed-server.mjs +2 -0
- package/test/helpers/autonomous-r34-fixture.mjs +5 -3
- package/test/multi-file-read.test.mjs +3 -0
- package/test/native-diff-topology-r36.test.mjs +105 -0
- package/test/package-boundary.test.mjs +6 -0
- package/test/process-longrun-r36.test.mjs +82 -0
- package/test/process-release-gate.test.mjs +9 -0
- package/test/production-docs.test.mjs +5 -5
- package/test/prompts-resources.test.mjs +7 -1
- package/test/r33-closeout-regression.test.mjs +4 -3
- package/test/r33-finalization.test.mjs +14 -9
- package/test/r36-finalization.test.mjs +104 -0
- package/test/r36-release-identity.test.mjs +45 -0
- package/test/r37-agent-fabric.test.mjs +92 -0
- package/test/r37-autonomous-timeout-recovery.test.mjs +60 -0
- package/test/r37-finalization.test.mjs +74 -0
- package/test/release-version.test.mjs +42 -33
- package/test/remote-live-log-r36.test.mjs +37 -0
- package/test/remote-live-log-r37.test.mjs +47 -0
- package/test/remote-live-log-recovery-r36.test.mjs +41 -0
- package/test/remote-r24-catalog.test.mjs +13 -0
- package/test/remote-session-cli.test.mjs +53 -66
- package/test/runtime-self-update.test.mjs +58 -1
- package/test/semantic-lsp-backend.test.mjs +9 -0
- package/test/semantic-r36-rename.test.mjs +82 -0
- package/deadbyte-mcp-0.8.9.tgz +0 -0
package/src/deadbyte-cli.mjs
CHANGED
|
@@ -9,18 +9,19 @@ import { fileURLToPath } from 'node:url';
|
|
|
9
9
|
import { defaultPublicKeyPath } from './trust.mjs';
|
|
10
10
|
import { verifyAuditChain } from './audit-verify.mjs';
|
|
11
11
|
import { openRemoteResultJournal, parseRemoteResultCursor } from './remote-result-journal.mjs';
|
|
12
|
+
import { createLiveTimelineTracker, formatCompactAuditEvent, formatRemoteLifecycle, formatRuntimeDiagnosticLine } from './remote-live-log.mjs';
|
|
12
13
|
|
|
13
14
|
const REMOTE_COMMANDS=new Set([
|
|
14
15
|
'menu','start','resume','park','stop','restart','status','url','test','fulltest','toggle','clean','machinetest',
|
|
15
16
|
'armprocess','disarmprocess','processstatus','armhost','disarmhost','hoststatus','hosttest',
|
|
16
17
|
'armcoding','disarmcoding','codingstatus','codingtest','armautonomous','disarmautonomous','autonomousstatus','autonomoustest'
|
|
17
18
|
]);
|
|
18
|
-
const SESSION_START=['start','armprocess','armcoding','armautonomous'
|
|
19
|
+
const SESSION_START=['start','armprocess','armcoding','armautonomous'];
|
|
19
20
|
const SESSION_STATUS=[
|
|
20
21
|
['processstatus',/^Process plane\s*:\s*ARMED\b/m],
|
|
21
22
|
['codingstatus',/^Coding plane\s*:\s*ARMED\b/m],
|
|
22
23
|
['autonomousstatus',/^Autonomous\s*:\s*ARMED\b/m],
|
|
23
|
-
['hoststatus',/^Host plane\s*:\s*
|
|
24
|
+
['hoststatus',/^Host plane\s*:\s*DISARMED\b/m]
|
|
24
25
|
];
|
|
25
26
|
const SESSION_CLEANUP=['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park'];
|
|
26
27
|
const SUPERVISOR_COMMANDS=Object.freeze({
|
|
@@ -33,9 +34,8 @@ function printHelp(){
|
|
|
33
34
|
process.stdout.write([
|
|
34
35
|
'DEADBYTE MCP CLI','',
|
|
35
36
|
' npx deadbyte-mcp@latest mcp # stdio MCP server for local clients',
|
|
36
|
-
' npx deadbyte-mcp@latest remote #
|
|
37
|
-
' npx deadbyte-mcp@latest remote --
|
|
38
|
-
' npx deadbyte-mcp@latest remote --resume <cursor> # replay missed compact results, then reconnect',
|
|
37
|
+
' npx deadbyte-mcp@latest remote # unified foreground device session + live timeline',
|
|
38
|
+
' npx deadbyte-mcp@latest remote --resume <cursor> # replay missed results, then reconnect',
|
|
39
39
|
' npx deadbyte-mcp@latest remote status',
|
|
40
40
|
' npx deadbyte-mcp@latest remote restart',
|
|
41
41
|
' npx deadbyte-mcp@latest supervisor status',
|
|
@@ -77,39 +77,15 @@ async function listLogFiles(root){
|
|
|
77
77
|
}
|
|
78
78
|
return files;
|
|
79
79
|
}
|
|
80
|
-
function formatLogLine(file,line,{
|
|
80
|
+
function formatLogLine(file,line,{activityTracker=null}={}){
|
|
81
81
|
if(!line) return null;
|
|
82
82
|
if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))){
|
|
83
83
|
try{
|
|
84
84
|
const event=JSON.parse(line);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const tool=typeof event.tool==='string'&&event.tool?event.tool:'tool';
|
|
88
|
-
return `${event.outcome?.is_error===true?'[ERR]':'[OK]'} ${tool}`;
|
|
89
|
-
}
|
|
90
|
-
const seq=Number.isInteger(event.seq)?`#${event.seq}`:'#?';
|
|
91
|
-
const request=typeof event.request_id==='string'?` ${event.request_id.slice(0,8)}`:'';
|
|
92
|
-
const tool=typeof event.tool==='string'?` ${event.tool}`:'';
|
|
93
|
-
let marker='';
|
|
94
|
-
if(event.event_type==='tool.request') marker='📥 ';
|
|
95
|
-
else if(event.event_type==='tool.result'){
|
|
96
|
-
if(event.outcome?.is_error===true) marker='📤❌ ';
|
|
97
|
-
else if(event.outcome?.is_error===false) marker='📤✅ ';
|
|
98
|
-
else marker='📤 ';
|
|
99
|
-
}
|
|
100
|
-
return `${marker}[AUDIT ${seq}] ${event.event_type||'event'}${tool}${request}`;
|
|
101
|
-
}catch{return verbose?`[AUDIT] ${line}`:null;}
|
|
85
|
+
return activityTracker?activityTracker.observe(event):formatCompactAuditEvent(event);
|
|
86
|
+
}catch{return null;}
|
|
102
87
|
}
|
|
103
|
-
|
|
104
|
-
const label=path.basename(file).replace(/\.log$/i,'').toUpperCase();
|
|
105
|
-
let marker='';
|
|
106
|
-
if(/\[TOOL IN \]/.test(line)) marker='📥 ';
|
|
107
|
-
else if(/\[TOOL OUT\]/.test(line)){
|
|
108
|
-
if(/"is_error"\s*:\s*true/.test(line)) marker='📤❌ ';
|
|
109
|
-
else if(/"is_error"\s*:\s*false/.test(line)) marker='📤✅ ';
|
|
110
|
-
else marker='📤 ';
|
|
111
|
-
}
|
|
112
|
-
return `${marker}[${label}] ${line}`;
|
|
88
|
+
return formatRuntimeDiagnosticLine(file,line);
|
|
113
89
|
}
|
|
114
90
|
function remoteResultJournalPath(root,sessionId){return path.join(root,'runtime','remote-results',`${sessionId}.json`);}
|
|
115
91
|
function auditTerminalResult(file,line){
|
|
@@ -120,7 +96,7 @@ function auditTerminalResult(file,line){
|
|
|
120
96
|
return {request_id:event.request_id,tool:event.tool,status:event.outcome?.is_error===true?'error':'ok',observed_at_utc:observed,
|
|
121
97
|
payload_sha256:createHash('sha256').update(Buffer.from(line,'utf8')).digest('hex')};
|
|
122
98
|
}
|
|
123
|
-
async function replayRemoteResults(root,cursor
|
|
99
|
+
async function replayRemoteResults(root,cursor){
|
|
124
100
|
const parsed=parseRemoteResultCursor(cursor);
|
|
125
101
|
const file=remoteResultJournalPath(root,parsed.session_id);
|
|
126
102
|
await requireRegular(file,'remote result journal');
|
|
@@ -130,7 +106,7 @@ async function replayRemoteResults(root,cursor,{verbose=false}={}){
|
|
|
130
106
|
const page=await journal.replayAfter(next,{limit:200});
|
|
131
107
|
for(const event of page.events){
|
|
132
108
|
const marker=event.status==='error'?'[ERR]':'[OK]';
|
|
133
|
-
process.stdout.write(
|
|
109
|
+
process.stdout.write(`[REPLAY] ${marker} ${event.tool} [cursor r1:${event.session_id}:${event.seq}]\n`);
|
|
134
110
|
}
|
|
135
111
|
next=page.next_cursor;
|
|
136
112
|
if(!page.has_more) return next;
|
|
@@ -147,39 +123,39 @@ async function readAppend(file,offset){
|
|
|
147
123
|
try{await handle.read(buffer,0,length,start);}finally{await handle.close();}
|
|
148
124
|
return {offset:info.size,text:buffer.toString('utf8')};
|
|
149
125
|
}
|
|
150
|
-
async function
|
|
126
|
+
async function snapshotRemoteLogOffsets(root){
|
|
151
127
|
const offsets=new Map();
|
|
152
128
|
for(const file of await listLogFiles(root)){
|
|
153
129
|
try{offsets.set(file,(await stat(file)).size);}catch{}
|
|
154
130
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
131
|
+
return offsets;
|
|
132
|
+
}
|
|
133
|
+
async function tailRemoteLogs(root,signal,{journal=null,offsets=null,activityTracker=null}={}){
|
|
134
|
+
process.stdout.write('[LOG] Unified live timeline. Ctrl+C disconnects and revokes authority.\n');
|
|
135
|
+
const activeOffsets=offsets??await snapshotRemoteLogOffsets(root);
|
|
158
136
|
while(!signal.aborted){
|
|
159
137
|
for(const file of await listLogFiles(root)){
|
|
160
|
-
const prior=
|
|
138
|
+
const prior=activeOffsets.has(file)?activeOffsets.get(file):0;
|
|
161
139
|
const next=await readAppend(file,prior);
|
|
162
|
-
|
|
140
|
+
activeOffsets.set(file,next.offset);
|
|
163
141
|
for(const line of next.text.split(/\r?\n/)){
|
|
164
142
|
const terminal=auditTerminalResult(file,line);
|
|
165
143
|
let recorded=null;
|
|
166
144
|
if(terminal&&journal) recorded=await journal.recordTerminal(terminal);
|
|
167
|
-
if(recorded?.duplicate
|
|
168
|
-
const formatted=formatLogLine(file,line,{
|
|
145
|
+
if(recorded?.duplicate) continue;
|
|
146
|
+
const formatted=formatLogLine(file,line,{activityTracker});
|
|
169
147
|
if(!formatted) continue;
|
|
170
|
-
if(
|
|
148
|
+
if(recorded) process.stdout.write(`${formatted} [cursor ${recorded.cursor}]\n`);
|
|
171
149
|
else process.stdout.write(`${formatted}\n`);
|
|
172
150
|
}
|
|
173
151
|
}
|
|
174
152
|
try{await sleep(250,null,{signal});}catch(error){if(error?.name!=='AbortError') throw error;}
|
|
175
153
|
}
|
|
176
154
|
}
|
|
177
|
-
async function cleanupRemoteSession(ctx
|
|
155
|
+
async function cleanupRemoteSession(ctx){
|
|
178
156
|
for(const command of SESSION_CLEANUP){
|
|
179
157
|
try{
|
|
180
|
-
const result=invokeController(ctx,command,
|
|
181
|
-
?{allowFailure:true}
|
|
182
|
-
:{allowFailure:true,capture:true,echoCaptured:false});
|
|
158
|
+
const result=invokeController(ctx,command,{allowFailure:true,capture:true,echoCaptured:false});
|
|
183
159
|
if(result.status!==0) process.stderr.write(`⚠️ [WARN] cleanup ${command} exit=${result.status}\n`);
|
|
184
160
|
}
|
|
185
161
|
catch(error){process.stderr.write(`⚠️ [WARN] cleanup ${command}: ${String(error?.message||error)}\n`);}
|
|
@@ -258,62 +234,70 @@ async function releaseRemoteSession(ctx,marker){
|
|
|
258
234
|
const same=current?.schema==='deadbyte.remote-session.v2'&¤t.owner_pid===marker.owner_pid&¤t.session_nonce===marker.session_nonce;
|
|
259
235
|
if(same) await rm(remoteSessionMarker(ctx.root),{force:true});
|
|
260
236
|
}
|
|
261
|
-
async function runRemoteSession({
|
|
237
|
+
async function runRemoteSession({resumeCursor=null}={}){
|
|
262
238
|
const ctx=await remoteContext();
|
|
263
|
-
if(resumeCursor!==null) await replayRemoteResults(ctx.root,resumeCursor
|
|
239
|
+
if(resumeCursor!==null) await replayRemoteResults(ctx.root,resumeCursor);
|
|
264
240
|
await recoverRemoteSession(ctx);
|
|
265
241
|
const marker=await claimRemoteSession(ctx);
|
|
266
242
|
const resultJournal=await openRemoteResultJournal({
|
|
267
243
|
filePath:remoteResultJournalPath(ctx.root,marker.result_session_id),sessionId:marker.result_session_id,maxEntries:2048
|
|
268
244
|
});
|
|
245
|
+
const activityTracker=createLiveTimelineTracker();
|
|
269
246
|
const aborter=new AbortController();
|
|
270
247
|
const abort=()=>aborter.abort();
|
|
271
248
|
const watchStdin=!process.stdin.isTTY;
|
|
272
249
|
process.once('SIGINT',abort);process.once('SIGTERM',abort);
|
|
273
250
|
if(watchStdin){process.stdin.once('end',abort);process.stdin.once('close',abort);process.stdin.resume();}
|
|
274
251
|
let ready=false;
|
|
252
|
+
let logTask=null;
|
|
275
253
|
try{
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
if(
|
|
254
|
+
process.stdout.write('DEADBYTE MCP\n');
|
|
255
|
+
process.stdout.write(`${formatRemoteLifecycle('device_start')}\n`);
|
|
256
|
+
process.stdout.write(`${formatRemoteLifecycle(resumeCursor!==null?'session_restored':'session_new')}\n`);
|
|
257
|
+
const logOffsets=await snapshotRemoteLogOffsets(ctx.root);
|
|
258
|
+
logTask=tailRemoteLogs(ctx.root,aborter.signal,{journal:resultJournal,offsets:logOffsets,activityTracker});
|
|
259
|
+
process.stdout.write('[BOOT] Starting local + remote runtime...\n');
|
|
260
|
+
const started=[];
|
|
261
|
+
for(const command of SESSION_START){
|
|
262
|
+
if(command==='start') process.stdout.write('[BOOT] Starting bridge/runtime...\n');
|
|
263
|
+
else process.stdout.write(`🔐 [AUTH] Arming ${command.slice(3)}...\n`);
|
|
264
|
+
const controllerResult=invokeController(ctx,command,{capture:true,echoCaptured:false});
|
|
265
|
+
started.push(controllerResult);
|
|
266
|
+
if(command==='start'){
|
|
267
|
+
process.stdout.write(`${formatRemoteLifecycle('bridge_connected')}\n`);
|
|
268
|
+
process.stdout.write(`${formatRemoteLifecycle('cloud_connected')}\n`);
|
|
269
|
+
}
|
|
289
270
|
}
|
|
271
|
+
const startText=started[0]?.stdout||'';
|
|
272
|
+
const url=startText.match(/^URL\s*:\s*(\S+)/m)?.[1]||'';
|
|
273
|
+
process.stdout.write('[OK] ONLINE\n');
|
|
274
|
+
process.stdout.write(`${formatRemoteLifecycle('ready')}\n`);
|
|
275
|
+
if(url) process.stdout.write(`URL: ${url}\n`);
|
|
276
|
+
process.stdout.write('🔐 [AUTH] Verifying process, coding, autonomous; host must stay DISARMED...\n');
|
|
290
277
|
for(const [command,pattern] of SESSION_STATUS){
|
|
291
|
-
const result=invokeController(ctx,command,{capture:true,echoCaptured:
|
|
292
|
-
if(!pattern.test(result.stdout)) throw new Error(`remote session authority verification failed: ${command}
|
|
278
|
+
const result=invokeController(ctx,command,{capture:true,echoCaptured:false});
|
|
279
|
+
if(!pattern.test(result.stdout)) throw new Error(`remote session authority verification failed: ${command} state mismatch`);
|
|
293
280
|
}
|
|
294
281
|
ready=true;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
await tailRemoteLogs(ctx.root,aborter.signal,{verbose,journal:resultJournal});
|
|
282
|
+
process.stdout.write('🔐 [AUTH] ARMED: process, coding, autonomous | host DISARMED\n');
|
|
283
|
+
await logTask;
|
|
298
284
|
}finally{
|
|
285
|
+
const wasAborted=aborter.signal.aborted;
|
|
286
|
+
aborter.abort();
|
|
287
|
+
if(logTask) await logTask.catch(()=>{});
|
|
288
|
+
for(const line of activityTracker.reconcileInterrupted('session_end')) process.stdout.write(`${line}\n`);
|
|
299
289
|
process.removeListener('SIGINT',abort);process.removeListener('SIGTERM',abort);
|
|
300
290
|
if(watchStdin){process.stdin.removeListener('end',abort);process.stdin.removeListener('close',abort);process.stdin.pause();}
|
|
301
|
-
|
|
302
|
-
|
|
291
|
+
process.stdout.write(`${formatRemoteLifecycle('cleanup')}\n`);
|
|
292
|
+
if(ready||!wasAborted) process.stdout.write('[INFO] Disconnecting; revoking authority...\n');
|
|
293
|
+
await cleanupRemoteSession(ctx);
|
|
303
294
|
await releaseRemoteSession(ctx,marker);
|
|
304
295
|
}
|
|
305
296
|
}
|
|
306
297
|
async function runRemote(args){
|
|
307
298
|
if(args.length===0){await runRemoteSession();return;}
|
|
308
|
-
if(args.length===1&&args[0]==='--verbose'){await runRemoteSession({verbose:true});return;}
|
|
309
299
|
if(args.length===2&&args[0]==='--resume'){await runRemoteSession({resumeCursor:args[1]});return;}
|
|
310
|
-
if(args.length
|
|
311
|
-
await runRemoteSession({verbose:true,resumeCursor:args[2]});return;
|
|
312
|
-
}
|
|
313
|
-
if(args.length===3&&args[0]==='--resume'&&args[2]==='--verbose'){
|
|
314
|
-
await runRemoteSession({verbose:true,resumeCursor:args[1]});return;
|
|
315
|
-
}
|
|
316
|
-
if(args.length>1) throw new Error('remote accepts one controller command, --verbose, or --resume <cursor>');
|
|
300
|
+
if(args.length>1) throw new Error('remote accepts one controller command or --resume <cursor>');
|
|
317
301
|
const command=args[0];if(!REMOTE_COMMANDS.has(command)) throw new Error(`unsupported remote command '${command}'`);
|
|
318
302
|
const ctx=await remoteContext();
|
|
319
303
|
const result=invokeController(ctx,command,{allowFailure:true});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { canonicalJson } from './canonical-json.mjs';
|
|
3
|
+
|
|
4
|
+
export const EFFECT_LEDGER_SCHEMA='deadbyte.effect-ledger.v1';
|
|
5
|
+
const HEX64=/^[0-9a-f]{64}$/;
|
|
6
|
+
const ID=/^[A-Za-z0-9._-]{1,128}$/;
|
|
7
|
+
const sha=value=>createHash('sha256').update(Buffer.from(canonicalJson(value),'utf8')).digest('hex');
|
|
8
|
+
|
|
9
|
+
function assertHex(name,value){if(!HEX64.test(value??'')) throw new Error(`${name} must be sha256`);}
|
|
10
|
+
function assertId(name,value){if(!ID.test(value??'')) throw new Error(`${name} invalid`);}
|
|
11
|
+
|
|
12
|
+
export function effectIdentity({goalId,planId,stepId,mutationEpoch,action,observationHeadSha256=null}){
|
|
13
|
+
assertHex('goalId',goalId);
|
|
14
|
+
assertHex('planId',planId);
|
|
15
|
+
assertId('stepId',stepId);
|
|
16
|
+
if(!Number.isInteger(mutationEpoch)||mutationEpoch<0) throw new Error('mutationEpoch invalid');
|
|
17
|
+
if(!action||typeof action!=='object'||Array.isArray(action)||typeof action.kind!=='string') throw new Error('action invalid');
|
|
18
|
+
if(observationHeadSha256!==null) assertHex('observationHeadSha256',observationHeadSha256);
|
|
19
|
+
const effectShape={schema:EFFECT_LEDGER_SCHEMA,kind:action.kind,mutation_epoch:mutationEpoch,
|
|
20
|
+
observation_head_sha256:observationHeadSha256,action};
|
|
21
|
+
const fingerprint=sha(effectShape);
|
|
22
|
+
const identity={schema:EFFECT_LEDGER_SCHEMA,goal_id:goalId,plan_id:planId,step_id:stepId,
|
|
23
|
+
mutation_epoch:mutationEpoch,fingerprint};
|
|
24
|
+
return Object.freeze({...identity,effect_id:sha(identity)});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function loopGuardDisposition(events,candidate,{maxRepeats=3,window=24}={}){
|
|
28
|
+
if(!Array.isArray(events)) throw new Error('effect events must be array');
|
|
29
|
+
if(!candidate||!HEX64.test(candidate.fingerprint??'')) throw new Error('effect candidate invalid');
|
|
30
|
+
if(!Number.isInteger(maxRepeats)||maxRepeats<1) throw new Error('maxRepeats invalid');
|
|
31
|
+
if(!Number.isInteger(window)||window<1) throw new Error('window invalid');
|
|
32
|
+
const recent=events.slice(-window);
|
|
33
|
+
const started=recent.filter(event=>event?.type==='effect_started'&&event.payload?.fingerprint===candidate.fingerprint);
|
|
34
|
+
const terminal=new Set(recent.filter(event=>['effect_completed','effect_failed'].includes(event?.type)&&HEX64.test(event.payload?.effect_id??''))
|
|
35
|
+
.map(event=>event.payload.effect_id));
|
|
36
|
+
const repeated=started.filter(event=>terminal.has(event.payload?.effect_id)).length;
|
|
37
|
+
return Object.freeze({allowed:repeated<maxRepeats,reason:repeated<maxRepeats?'allowed':'effect_repeat_limit',
|
|
38
|
+
repeated_count:repeated,max_repeats:maxRepeats,fingerprint:candidate.fingerprint});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function bindEffectCompletion(effect,outcome){
|
|
42
|
+
if(!effect||!HEX64.test(effect.effect_id??'')||!HEX64.test(effect.fingerprint??'')) throw new Error('effect identity invalid');
|
|
43
|
+
if(!outcome||typeof outcome!=='object'||Array.isArray(outcome)) throw new Error('effect outcome invalid');
|
|
44
|
+
const result_sha256=sha(outcome);
|
|
45
|
+
return Object.freeze({schema:'deadbyte.effect-completion.v1',effect_id:effect.effect_id,
|
|
46
|
+
fingerprint:effect.fingerprint,result_sha256});
|
|
47
|
+
}
|
|
@@ -60,7 +60,7 @@ const baseTools = ['contained_transform','evidence_verify','file_read','proof_ex
|
|
|
60
60
|
const codingTools = [
|
|
61
61
|
'coding_benchmark_run','coding_command_run','coding_file_read','coding_file_write','coding_files_read',
|
|
62
62
|
'coding_receipt_verify','coding_search','coding_session_status','coding_stat',
|
|
63
|
-
'coding_symbol_definition','coding_symbol_outline','coding_symbol_references','coding_symbol_replace',
|
|
63
|
+
'coding_symbol_definition','coding_symbol_diagnostics','coding_symbol_implementations','coding_symbol_outline','coding_symbol_references','coding_symbol_rename_preview','coding_symbol_replace',
|
|
64
64
|
'coding_task_approve','coding_task_cancel','coding_task_events','coding_task_run',
|
|
65
65
|
'coding_task_status','coding_task_submit','coding_task_verify','coding_text_replace','coding_tree'
|
|
66
66
|
];
|
package/src/machine-fs.mjs
CHANGED
|
@@ -168,9 +168,10 @@ function decodeCursor(cursor) {
|
|
|
168
168
|
|
|
169
169
|
function encodeCursor(name) { return Buffer.from(name, 'utf8').toString('base64url'); }
|
|
170
170
|
|
|
171
|
-
async function signReceipt(policy, signingKeyPath, grant, operation, requestSha256, body) {
|
|
171
|
+
async function signReceipt(policy, signingKeyPath, grant, operation, requestSha256, body, requestedReceiptId = null) {
|
|
172
172
|
await fsMkdir(path.join(policy.evidence_dir, 'machine-fs'), { recursive: true });
|
|
173
|
-
const receiptId = randomBytes(12).toString('hex');
|
|
173
|
+
const receiptId = requestedReceiptId ?? randomBytes(12).toString('hex');
|
|
174
|
+
if (!RECEIPT_ID_RE.test(receiptId)) throw new Error('machine fs receipt id must be 24 lowercase hex characters');
|
|
174
175
|
const core = {
|
|
175
176
|
schema: MACHINE_FS_RECEIPT_SCHEMA, receipt_id: receiptId,
|
|
176
177
|
policy_sha256: policy.policy_sha256, grant_instance_nonce: grant.instance_nonce,
|
|
@@ -311,7 +312,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
311
312
|
};
|
|
312
313
|
}
|
|
313
314
|
|
|
314
|
-
async function writePath({ rootId, relativePath, content, encoding = 'utf8', expectedSha256 }) {
|
|
315
|
+
async function writePath({ rootId, relativePath, content, encoding = 'utf8', expectedSha256, receiptId = null }) {
|
|
315
316
|
const grant = await assertCodingArmed(policy, rootId);
|
|
316
317
|
const target = await resolveTarget(policy, grant, rootId, relativePath, 'write');
|
|
317
318
|
const bytes = decodeContent(content, encoding);
|
|
@@ -325,7 +326,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
325
326
|
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_write', request, {
|
|
326
327
|
root_id: rootId, path: target.relative, started_at_utc: started, completed_at_utc: nowUtc(),
|
|
327
328
|
before_sha256: before.sha256, after_sha256: after.sha256, bytes: after.bytes
|
|
328
|
-
});
|
|
329
|
+
}, receiptId);
|
|
329
330
|
return {
|
|
330
331
|
status: 'committed', root_id: rootId, path: target.relative,
|
|
331
332
|
previous_sha256: before.sha256, sha256: after.sha256, bytes: after.bytes,
|
|
@@ -368,7 +369,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
368
369
|
receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request
|
|
369
370
|
};
|
|
370
371
|
}
|
|
371
|
-
async function mkdirPath({ rootId, relativePath }) {
|
|
372
|
+
async function mkdirPath({ rootId, relativePath, receiptId = null }) {
|
|
372
373
|
const grant = await assertCodingArmed(policy, rootId);
|
|
373
374
|
const target = await resolveTarget(policy, grant, rootId, relativePath, 'write');
|
|
374
375
|
try { await lstat(target.lexical); throw new Error('machine fs mkdir precondition mismatch: expected absent'); }
|
|
@@ -382,7 +383,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
382
383
|
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_mkdir', request, {
|
|
383
384
|
root_id: rootId, path: target.relative, started_at_utc: started, completed_at_utc: nowUtc(),
|
|
384
385
|
before_identity_sha256: null, after_identity_sha256: identity.identity_sha256
|
|
385
|
-
});
|
|
386
|
+
}, receiptId);
|
|
386
387
|
return {
|
|
387
388
|
status: 'committed', root_id: rootId, path: target.relative, identity_sha256: identity.identity_sha256,
|
|
388
389
|
receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request
|
|
@@ -392,7 +393,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
392
393
|
throw error;
|
|
393
394
|
}
|
|
394
395
|
}
|
|
395
|
-
async function movePath({ rootId, sourcePath, destinationPath, expectedSourceIdentity }) {
|
|
396
|
+
async function movePath({ rootId, sourcePath, destinationPath, expectedSourceIdentity, receiptId = null }) {
|
|
396
397
|
if (!SHA256_RE.test(expectedSourceIdentity ?? '')) throw new Error('machine fs expected_source_identity must be lowercase SHA-256');
|
|
397
398
|
const grant = await assertCodingArmed(policy, rootId);
|
|
398
399
|
const source = await resolveExisting(policy, grant, rootId, sourcePath, 'write', false);
|
|
@@ -415,7 +416,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
415
416
|
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_move', request, {
|
|
416
417
|
root_id: rootId, source_path: source.relative, destination_path: destination.relative,
|
|
417
418
|
started_at_utc: started, completed_at_utc: nowUtc(), source_identity_sha256: expectedSourceIdentity
|
|
418
|
-
});
|
|
419
|
+
}, receiptId);
|
|
419
420
|
return {
|
|
420
421
|
status: 'committed', root_id: rootId, source_path: source.relative, destination_path: destination.relative,
|
|
421
422
|
identity_sha256: expectedSourceIdentity, receipt_id: signed.receipt.receipt_id,
|
|
@@ -460,6 +461,46 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
460
461
|
}
|
|
461
462
|
}
|
|
462
463
|
|
|
464
|
+
async function statePath({ rootId, relativePath }) {
|
|
465
|
+
try {
|
|
466
|
+
const value = await statPath({ rootId, relativePath, hash: true });
|
|
467
|
+
return { exists: true, root_id: rootId, path: value.path, kind: value.kind, bytes: value.bytes,
|
|
468
|
+
sha256: value.sha256, identity_sha256: value.identity_sha256 };
|
|
469
|
+
} catch (error) {
|
|
470
|
+
if (error?.code === 'ENOENT') return { exists: false, root_id: rootId, path: relativePath, kind: null, bytes: 0, sha256: null, identity_sha256: null };
|
|
471
|
+
throw error;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function removeEmptyDir({ rootId, relativePath, expectedSourceIdentity, receiptId = null }) {
|
|
476
|
+
if (!SHA256_RE.test(expectedSourceIdentity ?? '')) throw new Error('machine fs expected_source_identity must be lowercase SHA-256');
|
|
477
|
+
const grant = await assertCodingArmed(policy, rootId);
|
|
478
|
+
const source = await resolveExisting(policy, grant, rootId, relativePath, 'write', false);
|
|
479
|
+
const before = await objectIdentity(source.resolved);
|
|
480
|
+
if (before.kind !== 'directory' || before.entries.length !== 0) throw new Error('machine fs rmdir requires an empty directory');
|
|
481
|
+
if (before.identity_sha256 !== expectedSourceIdentity) throw new Error(`machine fs source identity mismatch: expected ${expectedSourceIdentity}, found ${before.identity_sha256}`);
|
|
482
|
+
const request = requestSha('machine_fs_rmdir_empty', { root_id: rootId, path: source.relative, expected_source_identity: expectedSourceIdentity });
|
|
483
|
+
const started = nowUtc();
|
|
484
|
+
const race = await objectIdentity(source.resolved);
|
|
485
|
+
if (race.kind !== 'directory' || race.entries.length !== 0 || race.identity_sha256 !== expectedSourceIdentity) {
|
|
486
|
+
throw new Error('machine fs rmdir precondition changed before commit');
|
|
487
|
+
}
|
|
488
|
+
await rmdir(source.lexical);
|
|
489
|
+
try {
|
|
490
|
+
try { await lstat(source.lexical); throw new Error('machine fs rmdir post-commit path still exists'); }
|
|
491
|
+
catch (error) { if (error?.code !== 'ENOENT') throw error; }
|
|
492
|
+
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_rmdir_empty', request, {
|
|
493
|
+
root_id: rootId, path: source.relative, started_at_utc: started, completed_at_utc: nowUtc(),
|
|
494
|
+
before_identity_sha256: expectedSourceIdentity, after_identity_sha256: null
|
|
495
|
+
}, receiptId);
|
|
496
|
+
return { status: 'committed', root_id: rootId, path: source.relative, identity_sha256: expectedSourceIdentity,
|
|
497
|
+
receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request };
|
|
498
|
+
} catch (error) {
|
|
499
|
+
await fsMkdir(source.lexical, { recursive: false }).catch(() => {});
|
|
500
|
+
throw error;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
463
504
|
return Object.freeze({
|
|
464
505
|
policy,
|
|
465
506
|
stat: statPath,
|
|
@@ -470,6 +511,8 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
470
511
|
move: movePath,
|
|
471
512
|
mkdir: mkdirPath,
|
|
472
513
|
delete: deletePath,
|
|
514
|
+
state: statePath,
|
|
515
|
+
removeEmptyDir,
|
|
473
516
|
verifyReceipt: receiptId => verifyMachineFsReceiptFile({ policy, verifyKeyPath, receiptId })
|
|
474
517
|
});
|
|
475
518
|
}
|
package/src/mcp-server.mjs
CHANGED
|
@@ -39,6 +39,8 @@ import { registerAutonomousTools } from './autonomous-mcp-tools.mjs';
|
|
|
39
39
|
import { createToolAudit, installToolAudit } from './tool-audit.mjs';
|
|
40
40
|
import { createAuditContextProvider } from './audit-context.mjs';
|
|
41
41
|
import { registerOperatorSurface } from './operator-surface.mjs';
|
|
42
|
+
import { capabilityProfileFromEnv, COMPACT_SURFACE_TOOL_LIMIT, R36_CAPABILITY_LEDGER } from './capability-ledger.mjs';
|
|
43
|
+
import { registerCompactGatewayTools } from './compact-gateway-mcp-tools.mjs';
|
|
42
44
|
import {
|
|
43
45
|
containedTransformOutputSchema,
|
|
44
46
|
evidenceVerifyOutputSchema,
|
|
@@ -58,6 +60,7 @@ const verifyKeyPath = process.env.DEADBYTE_VERIFY_KEY ?? defaultPublicKeyPath();
|
|
|
58
60
|
const auditRuntimeMode = process.env.DEADBYTE_AUDIT_RUNTIME ?? '0';
|
|
59
61
|
if (!['0','1'].includes(auditRuntimeMode)) throw new Error('DEADBYTE_AUDIT_RUNTIME must be 0 or 1');
|
|
60
62
|
const runtimeStateRoot = path.resolve(process.env.DEADBYTE_STATE_ROOT || path.join(os.homedir(),'.deadbyte-mcp'));
|
|
63
|
+
const surfaceProfile = capabilityProfileFromEnv(process.env);
|
|
61
64
|
const localPrivilegedPolicyPath = path.join(packageRoot, 'controller', 'deadbyte-host-policy.json');
|
|
62
65
|
let privilegedPolicyPath = process.env.DEADBYTE_PRIVILEGED_POLICY ?? '';
|
|
63
66
|
if (!privilegedPolicyPath) {
|
|
@@ -106,7 +109,7 @@ const semanticLspBinding = semanticConfigBindingFromEnv(process.env);
|
|
|
106
109
|
const semanticLsp = codingRuntime && semanticLspBinding
|
|
107
110
|
? await loadSemanticLspBackends({ ...semanticLspBinding, codingRuntime })
|
|
108
111
|
: { backends: [], required_ids: [] };
|
|
109
|
-
|
|
112
|
+
let semanticRuntime = null;
|
|
110
113
|
const machineFsRuntimeMode = process.env.DEADBYTE_MACHINE_FS_RUNTIME ?? '0';
|
|
111
114
|
if (!['0','1'].includes(machineFsRuntimeMode)) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME must be 0 or 1');
|
|
112
115
|
if (machineFsRuntimeMode === '1' && !codingPolicy) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME=1 requires DEADBYTE_CODING_RUNTIME=1');
|
|
@@ -137,9 +140,10 @@ if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) {
|
|
|
137
140
|
}
|
|
138
141
|
if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME=1 requires an autonomous policy');
|
|
139
142
|
const autonomousPolicy = autonomousRuntimeMode === '1' ? await loadAutonomousPolicy(autonomousPolicyPath,codingPolicy) : null;
|
|
140
|
-
const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
143
|
+
const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,machineFsRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
144
|
+
semanticRuntime = codingRuntime ? createSemanticCodeRuntime({ codingRuntime, backends: semanticLsp.backends, nativeDiffRuntime }) : null;
|
|
141
145
|
const autonomousRuntime = autonomousPolicy ? createAutonomousRuntime({ policy:autonomousPolicy,codingRuntime,nativeDiffRuntime,
|
|
142
|
-
machineFsRuntime,observationRuntime,processRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
146
|
+
machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
143
147
|
const autonomousSupervisor = autonomousRuntime && autonomousPolicy.planner.backend === 'openai_compatible' &&
|
|
144
148
|
autonomousSupervisorMode === 'in_process'
|
|
145
149
|
? startAutonomousSupervisor({ runtime: autonomousRuntime, policy: autonomousPolicy })
|
|
@@ -169,11 +173,22 @@ function textResult(schema, object, isError = false) {
|
|
|
169
173
|
return structuredToolResult(schema, object, isError);
|
|
170
174
|
}
|
|
171
175
|
|
|
176
|
+
const COMPACT_CODING_DIRECT_TOOLS=new Set([
|
|
177
|
+
'coding_session_status','coding_tree','coding_symbol_replace','coding_file_read','coding_file_write',
|
|
178
|
+
'coding_text_replace','coding_command_run','coding_benchmark_run','coding_receipt_verify',
|
|
179
|
+
'coding_task_submit','coding_task_run','coding_task_status','coding_task_events','coding_task_cancel',
|
|
180
|
+
'coding_task_approve','coding_task_verify'
|
|
181
|
+
]);
|
|
182
|
+
function filteredToolServer(server,allowed){
|
|
183
|
+
return {registerTool(name,...args){if(allowed.has(name)) return server.registerTool(name,...args);}};
|
|
184
|
+
}
|
|
185
|
+
|
|
172
186
|
serveStdio(() => {
|
|
173
187
|
const server = new McpServer({ name: 'deadbyte-mcp', version: DEADBYTE_VERSION });
|
|
174
|
-
registerOperatorSurface(server,{packageRoot});
|
|
188
|
+
registerOperatorSurface(server,{packageRoot,surfaceProfile,compactToolLimit:COMPACT_SURFACE_TOOL_LIMIT});
|
|
175
189
|
if (toolAudit) installToolAudit(server,toolAudit);
|
|
176
190
|
|
|
191
|
+
if (surfaceProfile === 'full') {
|
|
177
192
|
server.registerTool(
|
|
178
193
|
'workspace_open',
|
|
179
194
|
{
|
|
@@ -289,6 +304,8 @@ serveStdio(() => {
|
|
|
289
304
|
}
|
|
290
305
|
);
|
|
291
306
|
|
|
307
|
+
}
|
|
308
|
+
|
|
292
309
|
server.registerTool(
|
|
293
310
|
'evidence_verify',
|
|
294
311
|
{
|
|
@@ -319,23 +336,24 @@ serveStdio(() => {
|
|
|
319
336
|
});
|
|
320
337
|
}
|
|
321
338
|
|
|
322
|
-
if (agentRuntime) {
|
|
339
|
+
if (agentRuntime && surfaceProfile === 'full') {
|
|
323
340
|
registerAgentTools(server, { runtime: agentRuntime, workspacePathFromId });
|
|
324
341
|
}
|
|
325
342
|
|
|
326
|
-
if (processRuntime) {
|
|
343
|
+
if (processRuntime && surfaceProfile === 'full') {
|
|
327
344
|
registerProcessTools(server, { runtime: processRuntime });
|
|
328
345
|
}
|
|
329
346
|
|
|
330
347
|
if (codingRuntime && codingTaskRuntime && semanticRuntime) {
|
|
331
|
-
|
|
348
|
+
const codingServer=surfaceProfile==='full'?server:filteredToolServer(server,COMPACT_CODING_DIRECT_TOOLS);
|
|
349
|
+
registerCodingTools(codingServer, { codingRuntime, taskRuntime: codingTaskRuntime, semanticRuntime });
|
|
332
350
|
}
|
|
333
351
|
|
|
334
|
-
if (machineFsRuntime) {
|
|
352
|
+
if (machineFsRuntime && surfaceProfile === 'full') {
|
|
335
353
|
registerMachineFsTools(server, { runtime: machineFsRuntime });
|
|
336
354
|
}
|
|
337
355
|
|
|
338
|
-
if (observationRuntime) {
|
|
356
|
+
if (observationRuntime && surfaceProfile === 'full') {
|
|
339
357
|
registerObservationTools(server, { runtime: observationRuntime });
|
|
340
358
|
}
|
|
341
359
|
|
|
@@ -343,6 +361,11 @@ serveStdio(() => {
|
|
|
343
361
|
registerAutonomousTools(server, { autonomousRuntime, nativeDiffRuntime });
|
|
344
362
|
}
|
|
345
363
|
|
|
364
|
+
registerCompactGatewayTools(server,{
|
|
365
|
+
profile:surfaceProfile,ledger:R36_CAPABILITY_LEDGER,codingRuntime,semanticRuntime,machineFsRuntime,
|
|
366
|
+
processRuntime,observationRuntime,machineRuntime
|
|
367
|
+
});
|
|
368
|
+
|
|
346
369
|
if (hostPolicy) {
|
|
347
370
|
server.registerTool(
|
|
348
371
|
'host_file_read',
|