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/coding-plane.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { decodeUtf8Strict } from './text-policy.mjs';
|
|
|
9
9
|
import { isInside, validatePortableRelativePath } from './path-policy.mjs';
|
|
10
10
|
import { loadPrivateSigningKey, loadPublicVerifyKey } from './trust.mjs';
|
|
11
11
|
import { createCodingSearch } from './coding-search.mjs';
|
|
12
|
+
import { createSearchCursorCodec } from './search-cursor.mjs';
|
|
12
13
|
|
|
13
14
|
export const CODING_POLICY_SCHEMA = 'deadbyte.coding-policy.v1';
|
|
14
15
|
export const CODING_LEASE_SCHEMA = 'deadbyte.coding-lease.v1';
|
|
@@ -613,18 +614,52 @@ export function createCodingRuntime({ policy, signingKeyPath, verifyKeyPath }) {
|
|
|
613
614
|
async function statPath({ rootId, relativePath = '.', hash = false }) {
|
|
614
615
|
const lease = await assertCodingArmed(policy, rootId);
|
|
615
616
|
const root = getRoot(policy, rootId, 'read');
|
|
616
|
-
let
|
|
617
|
+
let lexical = root.real_path;
|
|
617
618
|
let reported = '.';
|
|
618
619
|
if (relativePath !== '.') {
|
|
619
|
-
|
|
620
|
-
|
|
620
|
+
validatePortableRelativePath(relativePath);
|
|
621
|
+
if (!lease.root_ids.includes(rootId)) throw new Error(`coding root '${rootId}' is outside active lease`);
|
|
622
|
+
assertNotDenied(root, relativePath);
|
|
623
|
+
lexical = path.resolve(root.real_path, relativePath);
|
|
624
|
+
if (!isInside(root.real_path, lexical)) throw new Error('coding stat path escapes allowed root');
|
|
621
625
|
reported = relativePath.replaceAll('\\', '/');
|
|
622
626
|
}
|
|
623
|
-
const info = await lstat(
|
|
627
|
+
const info = await lstat(lexical);
|
|
624
628
|
const type = info.isFile() ? 'file' : info.isDirectory() ? 'directory' : info.isSymbolicLink() ? 'symlink' : 'other';
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
629
|
+
const reparseState = info.isSymbolicLink() ? 'symlink' : 'none';
|
|
630
|
+
if (type !== 'symlink') {
|
|
631
|
+
const resolved = await realpath(lexical);
|
|
632
|
+
if (!isInside(root.real_path, resolved) && resolved !== root.real_path) throw new Error('coding stat path resolves outside allowed root');
|
|
633
|
+
}
|
|
634
|
+
const contentSha = type === 'file' ? await sha256File(lexical) : null;
|
|
635
|
+
const objectIdentitySha = sha256Object({
|
|
636
|
+
schema:'deadbyte.coding-object-identity.v1',type,bytes:type==='file'?info.size:0,
|
|
637
|
+
content_sha256:contentSha,device:Number(info.dev),inode:Number(info.ino),reparse_state:reparseState
|
|
638
|
+
});
|
|
639
|
+
const result = {
|
|
640
|
+
status:'ok',root_id:rootId,path:reported,normalized_path:reported,type,
|
|
641
|
+
bytes:type==='file'?info.size:0,mtime_utc:info.mtime.toISOString(),
|
|
642
|
+
sha256:hash&&type==='file'?contentSha:null,reparse_state:reparseState,
|
|
643
|
+
object_identity_sha256:objectIdentitySha,policy_root_id:rootId
|
|
644
|
+
};
|
|
645
|
+
return {...result,observation_sha256:sha256Object({schema:'deadbyte.coding-stat-observation.v1',...result})};
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
async function filesRead({ rootId, files, maxTotalBytes = 1048576 }) {
|
|
649
|
+
if (!Array.isArray(files) || files.length < 1 || files.length > 32) throw new Error('coding multi-read requires 1-32 files');
|
|
650
|
+
if (!Number.isInteger(maxTotalBytes) || maxTotalBytes < 1 || maxTotalBytes > 2097152) throw new Error('coding multi-read max_total_bytes must be in [1, 2097152]');
|
|
651
|
+
const values=[]; let total=0;
|
|
652
|
+
for(const item of files){
|
|
653
|
+
if(!item||typeof item.path!=='string'||!['utf8','base64'].includes(item.encoding??'utf8')) throw new Error('coding multi-read file entry invalid');
|
|
654
|
+
const encoding=item.encoding??'utf8';
|
|
655
|
+
const read=await fileRead({rootId,relativePath:item.path,encoding});
|
|
656
|
+
total+=read.bytes;
|
|
657
|
+
if(total>maxTotalBytes) throw new Error(`coding multi-read exceeds ${maxTotalBytes} byte total limit`);
|
|
658
|
+
values.push({path:item.path,encoding,bytes:read.bytes,sha256:read.sha256,content:read.content});
|
|
659
|
+
}
|
|
660
|
+
const identity=values.map(item=>({path:item.path,encoding:item.encoding,bytes:item.bytes,sha256:item.sha256}));
|
|
661
|
+
return {status:'ok',root_id:rootId,total_bytes:total,files:values,
|
|
662
|
+
observation_sha256:sha256Object({schema:'deadbyte.coding-files-read-observation.v1',root_id:rootId,files:identity})};
|
|
628
663
|
}
|
|
629
664
|
|
|
630
665
|
async function fileState({ rootId, relativePath }) {
|
|
@@ -651,7 +686,8 @@ export function createCodingRuntime({ policy, signingKeyPath, verifyKeyPath }) {
|
|
|
651
686
|
return verifyCodingReceiptFile(policy, verifyKeyPath, receiptId);
|
|
652
687
|
}
|
|
653
688
|
|
|
654
|
-
const
|
|
655
|
-
|
|
689
|
+
const cursorCodec = createSearchCursorCodec({ signingKeyPath, verifyKeyPath });
|
|
690
|
+
const search = createCodingSearch({ tree, fileRead, cursorCodec });
|
|
691
|
+
return Object.freeze({ policy, sessionStatus, tree, stat: statPath, search, filesRead, fileRead, fileWrite, fileDelete, textReplace, commandRun, benchmarkRun, receiptVerify,
|
|
656
692
|
fileState, verifyReceiptById: receiptVerify, verifyReceiptDetailed, requestSha });
|
|
657
693
|
}
|
package/src/coding-search.mjs
CHANGED
|
@@ -1,55 +1,138 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { canonicalJson } from './canonical-json.mjs';
|
|
3
|
+
import { decodeUtf8Strict } from './text-policy.mjs';
|
|
4
|
+
|
|
5
|
+
const sha256Object=value=>createHash('sha256').update(canonicalJson(value),'utf8').digest('hex');
|
|
6
|
+
const sha256Bytes=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
7
|
+
|
|
8
|
+
function validateInt(value,name,min,max){
|
|
9
|
+
if(!Number.isInteger(value)||value<min||value>max) throw new Error(`${name} must be in [${min}, ${max}]`);
|
|
10
|
+
}
|
|
11
|
+
function compileMatcher({pattern,mode,caseSensitive}){
|
|
12
|
+
if(typeof pattern!=='string'||pattern.length<1||pattern.length>256) throw new Error('coding search pattern must be 1-256 characters');
|
|
13
|
+
if(mode==='literal'){
|
|
14
|
+
const needle=caseSensitive?pattern:pattern.toLowerCase();
|
|
15
|
+
return {
|
|
16
|
+
all(text){
|
|
17
|
+
const haystack=caseSensitive?text:text.toLowerCase();
|
|
18
|
+
const out=[]; let from=0;
|
|
19
|
+
while(from<=haystack.length){
|
|
20
|
+
const index=haystack.indexOf(needle,from);
|
|
21
|
+
if(index<0) break;
|
|
22
|
+
out.push({index,length:Math.max(1,pattern.length)});
|
|
23
|
+
from=index+Math.max(1,pattern.length);
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
},
|
|
27
|
+
path(value){return (caseSensitive?value:value.toLowerCase()).includes(needle);}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if(mode!=='regex') throw new Error('coding search mode must be literal or regex');
|
|
31
|
+
let regex;
|
|
32
|
+
try{regex=new RegExp(pattern,caseSensitive?'gu':'giu');}
|
|
33
|
+
catch(error){throw new Error(`coding search regex invalid: ${error.message}`);}
|
|
34
|
+
return {
|
|
35
|
+
all(text){
|
|
36
|
+
const out=[]; regex.lastIndex=0; let match;
|
|
37
|
+
while((match=regex.exec(text))!==null){
|
|
38
|
+
out.push({index:match.index,length:Math.max(1,match[0].length)});
|
|
39
|
+
if(match[0].length===0) regex.lastIndex+=1;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
},
|
|
43
|
+
path(value){regex.lastIndex=0;return regex.test(value);}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function lineColumn(text,index){
|
|
47
|
+
let line=1,column=1;
|
|
48
|
+
for(let i=0;i<index;i+=1){if(text.charCodeAt(i)===10){line+=1;column=1;}else column+=1;}
|
|
49
|
+
return {line,column};
|
|
50
|
+
}
|
|
51
|
+
function preview(text,index,length){
|
|
52
|
+
const start=Math.max(0,index-48); const end=Math.min(text.length,index+Math.max(length,1)+112);
|
|
53
|
+
return text.slice(start,end);
|
|
54
|
+
}
|
|
55
|
+
function normalizeQuery({rootId,path,target,mode,pattern,caseSensitive,maxResults,maxFileBytes,maxScanBytes,pageSize}){
|
|
56
|
+
return {
|
|
57
|
+
schema:'deadbyte.coding-search-query.v2',root_id:rootId,path,target,mode,pattern,
|
|
58
|
+
case_sensitive:caseSensitive,max_results:maxResults,max_file_bytes:maxFileBytes,
|
|
59
|
+
max_scan_bytes:maxScanBytes,page_size:pageSize
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function createCodingSearch({tree,fileRead,cursorCodec}){
|
|
64
|
+
if(typeof tree!=='function'||typeof fileRead!=='function'||!cursorCodec||typeof cursorCodec.encode!=='function'||typeof cursorCodec.decode!=='function'){
|
|
65
|
+
throw new Error('coding search requires tree, fileRead, and cursorCodec');
|
|
4
66
|
}
|
|
5
67
|
return async function search({
|
|
6
|
-
rootId,
|
|
7
|
-
maxResults
|
|
8
|
-
})
|
|
9
|
-
if
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
68
|
+
rootId,path='.',pattern,target='content',mode='literal',caseSensitive=false,
|
|
69
|
+
maxResults=200,maxFileBytes=262144,maxScanBytes=4*1024*1024,pageSize=100,cursor=null
|
|
70
|
+
}){
|
|
71
|
+
if(!['content','path'].includes(target)) throw new Error('coding search target must be content or path');
|
|
72
|
+
validateInt(maxResults,'max_results',1,1000);
|
|
73
|
+
validateInt(maxFileBytes,'max_file_bytes',1,4*1024*1024);
|
|
74
|
+
validateInt(maxScanBytes,'max_scan_bytes',1,64*1024*1024);
|
|
75
|
+
validateInt(pageSize,'page_size',1,500);
|
|
76
|
+
const matcher=compileMatcher({pattern,mode,caseSensitive});
|
|
77
|
+
const query=normalizeQuery({rootId,path,target,mode,pattern,caseSensitive,maxResults,maxFileBytes,maxScanBytes,pageSize});
|
|
78
|
+
const querySha=sha256Object(query);
|
|
79
|
+
let decodedCursor=null;
|
|
80
|
+
if(cursor!==null){
|
|
81
|
+
decodedCursor=await cursorCodec.decode(cursor);
|
|
82
|
+
if(decodedCursor.query_sha256!==querySha) throw new Error('coding search cursor query mismatch');
|
|
18
83
|
}
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
84
|
+
|
|
85
|
+
const listed=await tree({rootId,path,maxDepth:12,maxEntries:2000});
|
|
86
|
+
const entries=listed.entries.filter(entry=>entry.type==='file').sort((a,b)=>a.path.localeCompare(b.path,'en'));
|
|
87
|
+
const matches=[]; const snapshotEntries=[];
|
|
88
|
+
let filesScanned=0,bytesScanned=0,binaryFilesSkipped=0;
|
|
89
|
+
let truncated=listed.truncated===true;
|
|
90
|
+
let truncationReason=listed.truncated===true?'tree_limit':null;
|
|
91
|
+
|
|
92
|
+
if(target==='path'){
|
|
93
|
+
for(const entry of entries){
|
|
94
|
+
snapshotEntries.push({path:entry.path,bytes:entry.bytes,type:'file'});
|
|
95
|
+
if(matcher.path(entry.path)){
|
|
96
|
+
matches.push({path:entry.path,line:null,column:null,preview:entry.path,file_sha256:null});
|
|
97
|
+
if(matches.length>=maxResults){truncated=true;truncationReason='max_results';break;}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
for(const entry of entries){
|
|
102
|
+
if(entry.bytes>maxFileBytes) continue;
|
|
103
|
+
if(bytesScanned+entry.bytes>maxScanBytes){truncated=true;truncationReason='scan_byte_limit';break;}
|
|
104
|
+
let item;
|
|
105
|
+
try{item=await fileRead({rootId,relativePath:entry.path,encoding:'base64'});}catch{continue;}
|
|
106
|
+
const raw=Buffer.from(item.content,'base64');
|
|
107
|
+
filesScanned+=1; bytesScanned+=item.bytes;
|
|
108
|
+
const fileSha=item.sha256??sha256Bytes(raw);
|
|
109
|
+
snapshotEntries.push({path:entry.path,bytes:item.bytes,sha256:fileSha});
|
|
110
|
+
let text;
|
|
111
|
+
try{text=decodeUtf8Strict(raw);}catch{binaryFilesSkipped+=1;continue;}
|
|
112
|
+
const found=matcher.all(text);
|
|
113
|
+
for(const hit of found){
|
|
114
|
+
const lc=lineColumn(text,hit.index);
|
|
115
|
+
matches.push({path:entry.path,line:lc.line,column:lc.column,preview:preview(text,hit.index,hit.length),file_sha256:fileSha});
|
|
116
|
+
if(matches.length>=maxResults){truncated=true;truncationReason='max_results';break;}
|
|
117
|
+
}
|
|
118
|
+
if(matches.length>=maxResults) break;
|
|
119
|
+
}
|
|
47
120
|
}
|
|
121
|
+
|
|
122
|
+
const snapshotSha=sha256Object({schema:'deadbyte.coding-search-snapshot.v2',query_sha256:querySha,entries:snapshotEntries});
|
|
123
|
+
if(decodedCursor&&decodedCursor.snapshot_sha256!==snapshotSha) throw new Error('coding search cursor stale snapshot mismatch');
|
|
124
|
+
const offset=decodedCursor?.offset??0;
|
|
125
|
+
if(offset>matches.length) throw new Error('coding search cursor offset exceeds retained results');
|
|
126
|
+
const pageMatches=matches.slice(offset,offset+pageSize);
|
|
127
|
+
const nextOffset=offset+pageMatches.length;
|
|
128
|
+
const hasMore=nextOffset<matches.length;
|
|
129
|
+
const nextCursor=hasMore?await cursorCodec.encode({query_sha256:querySha,snapshot_sha256:snapshotSha,offset:nextOffset}):null;
|
|
130
|
+
const pageSha=sha256Object({schema:'deadbyte.coding-search-page.v2',query_sha256:querySha,snapshot_sha256:snapshotSha,offset,matches:pageMatches});
|
|
48
131
|
return {
|
|
49
|
-
status:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
132
|
+
status:'ok',root_id:rootId,path,pattern,target,mode,case_sensitive:caseSensitive,
|
|
133
|
+
matches:pageMatches,files_scanned:filesScanned,bytes_scanned:bytesScanned,binary_files_skipped:binaryFilesSkipped,
|
|
134
|
+
truncated:truncated||hasMore,truncation_reason:truncationReason,query_sha256:querySha,snapshot_sha256:snapshotSha,
|
|
135
|
+
page_sha256:pageSha,next_cursor:nextCursor
|
|
53
136
|
};
|
|
54
137
|
};
|
|
55
138
|
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as z from 'zod/v4';
|
|
2
|
+
import { compactGatewayOutputSchema, compactGatewayResult } from './compact-gateway-output-contracts.mjs';
|
|
3
|
+
|
|
4
|
+
const id=z.string().regex(/^[A-Za-z0-9._-]{1,64}$/);
|
|
5
|
+
const rel=z.string().min(1).max(2048);
|
|
6
|
+
const rel512=z.string().min(1).max(512);
|
|
7
|
+
const hex64=z.string().regex(/^[0-9a-f]{64}$/);
|
|
8
|
+
const cursor=z.string().max(4096).nullable().default(null);
|
|
9
|
+
const nonneg=z.number().int().nonnegative();
|
|
10
|
+
const symbolName=z.string().regex(/^[A-Za-z_$][A-Za-z0-9_$]{0,127}$/);
|
|
11
|
+
|
|
12
|
+
export const codingInspectInputSchema=z.discriminatedUnion('op',[
|
|
13
|
+
z.strictObject({op:z.literal('stat'),root_id:id,path:rel512.default('.'),hash:z.boolean().default(false)}),
|
|
14
|
+
z.strictObject({op:z.literal('search'),root_id:id,path:rel512.default('.'),pattern:z.string().min(1).max(256),target:z.enum(['content','path']).default('content'),mode:z.enum(['literal','regex']).default('literal'),case_sensitive:z.boolean().default(false),max_results:z.number().int().min(1).max(1000).default(200),max_file_bytes:z.number().int().min(1).max(4*1024*1024).default(262144),max_scan_bytes:z.number().int().min(1).max(64*1024*1024).default(4*1024*1024),page_size:z.number().int().min(1).max(500).default(100),cursor}),
|
|
15
|
+
z.strictObject({op:z.literal('files_read'),root_id:id,files:z.array(z.strictObject({path:rel512,encoding:z.enum(['utf8','base64']).default('utf8')})).min(1).max(32),max_total_bytes:z.number().int().min(1).max(2097152).default(1048576)}),
|
|
16
|
+
z.strictObject({op:z.literal('symbol_outline'),root_id:id,path:rel512,max_symbols:z.number().int().min(1).max(500).default(200)}),
|
|
17
|
+
z.strictObject({op:z.literal('symbol_definition'),root_id:id,path:rel512,line:nonneg,column:nonneg,max_results:z.number().int().min(1).max(200).default(50)}),
|
|
18
|
+
z.strictObject({op:z.literal('symbol_references'),root_id:id,path:rel512,line:nonneg,column:nonneg,max_results:z.number().int().min(1).max(500).default(200)}),
|
|
19
|
+
z.strictObject({op:z.literal('symbol_diagnostics'),root_id:id,path:rel512,max_results:z.number().int().min(1).max(500).default(200)}),
|
|
20
|
+
z.strictObject({op:z.literal('symbol_implementations'),root_id:id,path:rel512,line:nonneg,column:nonneg,max_results:z.number().int().min(1).max(500).default(200)}),
|
|
21
|
+
z.strictObject({op:z.literal('symbol_rename_preview'),root_id:id,path:rel512,line:nonneg,column:nonneg,new_name:symbolName})
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
export const machineFsGatewayInputSchema=z.discriminatedUnion('op',[
|
|
25
|
+
z.strictObject({op:z.literal('stat'),root_id:id,path:rel.default('.'),hash:z.boolean().default(false)}),
|
|
26
|
+
z.strictObject({op:z.literal('list'),root_id:id,path:rel.default('.'),cursor,limit:z.number().int().min(1).max(1000).default(100),hash_files:z.boolean().default(false)}),
|
|
27
|
+
z.strictObject({op:z.literal('read'),root_id:id,path:rel,offset:nonneg.default(0),max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536),hash_file:z.boolean().default(false)}),
|
|
28
|
+
z.strictObject({op:z.literal('write'),root_id:id,path:rel,content:z.string().max(12*1024*1024),encoding:z.enum(['utf8','base64']).default('utf8'),expected_sha256:z.string().regex(/^(?:absent|[0-9a-f]{64})$/)}),
|
|
29
|
+
z.strictObject({op:z.literal('edit_exact'),root_id:id,path:rel,expected_sha256:hex64,old_string:z.string().min(1).max(262144),new_string:z.string().max(524288),expected_replacements:z.number().int().min(1).max(64).default(1)}),
|
|
30
|
+
z.strictObject({op:z.literal('mkdir'),root_id:id,path:rel}),
|
|
31
|
+
z.strictObject({op:z.literal('move'),root_id:id,source_path:rel,destination_path:rel,expected_source_identity:hex64}),
|
|
32
|
+
z.strictObject({op:z.literal('delete'),root_id:id,path:rel,expected_source_identity:hex64})
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
export const processSessionGatewayInputSchema=z.discriminatedUnion('op',[
|
|
36
|
+
z.strictObject({op:z.literal('start'),profile_id:id,root_id:id,cwd:rel.default('.'),args:z.array(z.string().max(8192)).max(64).default([])}),
|
|
37
|
+
z.strictObject({op:z.literal('read'),session_id:hex64,offset:nonneg.default(0),max_bytes:z.number().int().min(1).max(262144).default(65536)}),
|
|
38
|
+
z.strictObject({op:z.literal('status'),session_id:hex64}),
|
|
39
|
+
z.strictObject({op:z.literal('list')}),
|
|
40
|
+
z.strictObject({op:z.literal('action'),session_id:hex64,action_id:id}),
|
|
41
|
+
z.strictObject({op:z.literal('terminate'),session_id:hex64})
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
export const machineObserveInputSchema=z.discriminatedUnion('op',[
|
|
45
|
+
z.strictObject({op:z.literal('machine_list')}),
|
|
46
|
+
z.strictObject({op:z.literal('machine_status')}),
|
|
47
|
+
z.strictObject({op:z.literal('machine_ping'),nonce:z.string().min(1).max(256)}),
|
|
48
|
+
z.strictObject({op:z.literal('search_start'),root_id:id,path:rel512.default('.'),pattern:z.string().min(1).max(256),case_sensitive:z.boolean().default(false),max_results:z.number().int().min(1).max(1000).default(200),max_files:z.number().int().min(1).max(10000).default(2000),max_bytes:z.number().int().min(1).max(64*1024*1024).default(4*1024*1024),max_file_bytes:z.number().int().min(1).max(4*1024*1024).default(262144)}),
|
|
49
|
+
z.strictObject({op:z.literal('search_page'),search_id:hex64,limit:z.number().int().min(1).max(500).default(100),cursor:z.string().max(512).nullable().default(null)}),
|
|
50
|
+
z.strictObject({op:z.literal('search_status'),search_id:hex64}),
|
|
51
|
+
z.strictObject({op:z.literal('search_cancel'),search_id:hex64}),
|
|
52
|
+
z.strictObject({op:z.literal('process_list'),limit:z.number().int().min(1).max(256).default(100),include_external:z.boolean().default(false),cursor:z.string().max(512).nullable().default(null)}),
|
|
53
|
+
z.strictObject({op:z.literal('system_status')})
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
const capabilityManifestInputSchema=z.strictObject({});
|
|
57
|
+
|
|
58
|
+
function unavailable(op,name){return compactGatewayResult({status:'unavailable',op,error:`${name} runtime unavailable`},true);}
|
|
59
|
+
async function invoke(op,runtime,name,call){
|
|
60
|
+
if(!runtime) return unavailable(op,name);
|
|
61
|
+
try{return compactGatewayResult({status:'ok',op,result:await call(runtime)},false);}
|
|
62
|
+
catch(error){return compactGatewayResult({status:'denied',op,error:String(error)},true);}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function codingInspect(args,codingRuntime,semanticRuntime){
|
|
66
|
+
switch(args.op){
|
|
67
|
+
case 'stat': return invoke(args.op,codingRuntime,'coding',r=>r.stat({rootId:args.root_id,relativePath:args.path,hash:args.hash}));
|
|
68
|
+
case 'search': return invoke(args.op,codingRuntime,'coding',r=>r.search({rootId:args.root_id,path:args.path,pattern:args.pattern,target:args.target,mode:args.mode,caseSensitive:args.case_sensitive,maxResults:args.max_results,maxFileBytes:args.max_file_bytes,maxScanBytes:args.max_scan_bytes,pageSize:args.page_size,cursor:args.cursor}));
|
|
69
|
+
case 'files_read': return invoke(args.op,codingRuntime,'coding',r=>r.filesRead({rootId:args.root_id,files:args.files,maxTotalBytes:args.max_total_bytes}));
|
|
70
|
+
case 'symbol_outline': return invoke(args.op,semanticRuntime,'semantic',r=>r.outline({rootId:args.root_id,relativePath:args.path,maxSymbols:args.max_symbols}));
|
|
71
|
+
case 'symbol_definition': return invoke(args.op,semanticRuntime,'semantic',r=>r.definition({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,maxResults:args.max_results}));
|
|
72
|
+
case 'symbol_references': return invoke(args.op,semanticRuntime,'semantic',r=>r.references({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,maxResults:args.max_results}));
|
|
73
|
+
case 'symbol_diagnostics': return invoke(args.op,semanticRuntime,'semantic',r=>r.diagnostics({rootId:args.root_id,relativePath:args.path,maxResults:args.max_results}));
|
|
74
|
+
case 'symbol_implementations': return invoke(args.op,semanticRuntime,'semantic',r=>{if(typeof r.implementations!=='function') throw new Error('semantic implementations unavailable');return r.implementations({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,maxResults:args.max_results});});
|
|
75
|
+
case 'symbol_rename_preview': return invoke(args.op,semanticRuntime,'semantic',r=>{if(typeof r.renamePreview!=='function') throw new Error('semantic rename preview unavailable');return r.renamePreview({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,newName:args.new_name});});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function machineFs(args,runtime){
|
|
80
|
+
const map={
|
|
81
|
+
stat:r=>r.stat({rootId:args.root_id,relativePath:args.path,hash:args.hash}),
|
|
82
|
+
list:r=>r.list({rootId:args.root_id,relativePath:args.path,cursor:args.cursor,limit:args.limit,hashFiles:args.hash_files}),
|
|
83
|
+
read:r=>r.read({rootId:args.root_id,relativePath:args.path,offset:args.offset,maxBytes:args.max_bytes,hashFile:args.hash_file}),
|
|
84
|
+
write:r=>r.write({rootId:args.root_id,relativePath:args.path,content:args.content,encoding:args.encoding,expectedSha256:args.expected_sha256}),
|
|
85
|
+
edit_exact:r=>r.editExact({rootId:args.root_id,relativePath:args.path,expectedSha256:args.expected_sha256,oldString:args.old_string,newString:args.new_string,expectedReplacements:args.expected_replacements}),
|
|
86
|
+
mkdir:r=>r.mkdir({rootId:args.root_id,relativePath:args.path}),
|
|
87
|
+
move:r=>r.move({rootId:args.root_id,sourcePath:args.source_path,destinationPath:args.destination_path,expectedSourceIdentity:args.expected_source_identity}),
|
|
88
|
+
delete:r=>r.delete({rootId:args.root_id,relativePath:args.path,expectedSourceIdentity:args.expected_source_identity})
|
|
89
|
+
};
|
|
90
|
+
return invoke(args.op,runtime,'machine_fs',map[args.op]);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function processSession(args,runtime){
|
|
94
|
+
const map={
|
|
95
|
+
start:r=>r.start({profileId:args.profile_id,rootId:args.root_id,cwd:args.cwd,args:args.args}),
|
|
96
|
+
read:r=>r.read({sessionId:args.session_id,offset:args.offset,maxBytes:args.max_bytes}),
|
|
97
|
+
status:r=>r.status({sessionId:args.session_id}),
|
|
98
|
+
list:r=>r.list(),
|
|
99
|
+
action:r=>r.action({sessionId:args.session_id,actionId:args.action_id}),
|
|
100
|
+
terminate:r=>r.terminate({sessionId:args.session_id})
|
|
101
|
+
};
|
|
102
|
+
return invoke(args.op,runtime,'process',map[args.op]);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function machineObserve(args,machineRuntime,observationRuntime){
|
|
106
|
+
if(args.op==='machine_list') return invoke(args.op,machineRuntime,'machine',r=>r.list());
|
|
107
|
+
if(args.op==='machine_status') return invoke(args.op,machineRuntime,'machine',r=>r.status());
|
|
108
|
+
if(args.op==='machine_ping') return invoke(args.op,machineRuntime,'machine',r=>r.ping({nonce:args.nonce}));
|
|
109
|
+
const map={
|
|
110
|
+
search_start:r=>r.searchStart({rootId:args.root_id,relativePath:args.path,pattern:args.pattern,caseSensitive:args.case_sensitive,maxResults:args.max_results,maxFiles:args.max_files,maxBytes:args.max_bytes,maxFileBytes:args.max_file_bytes}),
|
|
111
|
+
search_page:r=>r.searchPage({searchId:args.search_id,limit:args.limit,cursor:args.cursor}),
|
|
112
|
+
search_status:r=>r.searchStatus({searchId:args.search_id}),
|
|
113
|
+
search_cancel:r=>r.searchCancel({searchId:args.search_id}),
|
|
114
|
+
process_list:r=>r.processList({limit:args.limit,includeExternal:args.include_external,cursor:args.cursor}),
|
|
115
|
+
system_status:r=>r.systemStatus()
|
|
116
|
+
};
|
|
117
|
+
return invoke(args.op,observationRuntime,'observation',map[args.op]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function registerCompactGatewayTools(server,{profile,ledger,codingRuntime,semanticRuntime,machineFsRuntime,processRuntime,observationRuntime,machineRuntime}){
|
|
121
|
+
if(!server) throw new Error('compact gateway registration requires server');
|
|
122
|
+
if(profile!=='compact') return;
|
|
123
|
+
server.registerTool('capability_manifest',{description:'Read the canonical R36 capability ledger and active compact profile.',inputSchema:capabilityManifestInputSchema,outputSchema:compactGatewayOutputSchema},async()=>compactGatewayResult({status:'ok',op:'manifest',result:{schema:'deadbyte.capability-manifest.v1',profile,ledger_sha256:ledger?.ledger_sha256??null,capabilities:ledger?.entries??[]}},false));
|
|
124
|
+
server.registerTool('coding_inspect',{description:'Typed compact coding inspection and semantic navigation gateway. No arbitrary tool dispatch.',inputSchema:codingInspectInputSchema,outputSchema:compactGatewayOutputSchema},args=>codingInspect(args,codingRuntime,semanticRuntime));
|
|
125
|
+
server.registerTool('machine_fs',{description:'Typed compact machine filesystem gateway preserving root policy and mutation preconditions.',inputSchema:machineFsGatewayInputSchema,outputSchema:compactGatewayOutputSchema},args=>machineFs(args,machineFsRuntime));
|
|
126
|
+
server.registerTool('process_session',{description:'Typed compact DEADBYTE-owned process session gateway. No raw stdin or PID authority.',inputSchema:processSessionGatewayInputSchema,outputSchema:compactGatewayOutputSchema},args=>processSession(args,processRuntime));
|
|
127
|
+
server.registerTool('machine_observe',{description:'Typed compact machine identity and read-only observation gateway. Revoke is intentionally excluded.',inputSchema:machineObserveInputSchema,outputSchema:compactGatewayOutputSchema},args=>machineObserve(args,machineRuntime,observationRuntime));
|
|
128
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as z from 'zod/v4';
|
|
2
|
+
import { structuredToolResult } from './output-contracts.mjs';
|
|
3
|
+
|
|
4
|
+
export const compactGatewayOutputSchema=z.strictObject({
|
|
5
|
+
status:z.enum(['ok','denied','failed','unavailable']),
|
|
6
|
+
op:z.string().min(1).max(64),
|
|
7
|
+
result:z.json().optional(),
|
|
8
|
+
error:z.string().max(4096).optional()
|
|
9
|
+
}).superRefine((value,ctx)=>{
|
|
10
|
+
if(value.status==='ok'&&value.result===undefined) ctx.addIssue({code:'custom',path:['result'],message:'result is required for status=ok'});
|
|
11
|
+
if(value.status!=='ok'&&value.error===undefined) ctx.addIssue({code:'custom',path:['error'],message:'error is required for non-ok status'});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export function compactGatewayResult(value,isError=false){
|
|
15
|
+
return structuredToolResult(compactGatewayOutputSchema,value,isError);
|
|
16
|
+
}
|