@mikeargento/bitgraph-mcp 0.6.0 → 0.7.1
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/__tests__/carrier.test.js +2 -2
- package/dist/__tests__/carrier.test.js.map +1 -1
- package/dist/__tests__/format.test.js +1 -1
- package/dist/__tests__/format.test.js.map +1 -1
- package/dist/__tests__/proof-beside.test.js +1 -1
- package/dist/__tests__/proof-beside.test.js.map +1 -1
- package/dist/__tests__/tools.test.js +1 -1
- package/dist/__tests__/tools.test.js.map +1 -1
- package/dist/format.d.ts +11 -2
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +3 -4
- package/dist/format.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +2 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +9 -0
- package/dist/instructions.js.map +1 -0
- package/dist/server.d.ts +3 -38
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +15 -106
- package/dist/server.js.map +1 -1
- package/package.json +4 -3
- package/src/__tests__/carrier.test.ts +2 -2
- package/src/__tests__/format.test.ts +2 -2
- package/src/__tests__/proof-beside.test.ts +1 -1
- package/src/__tests__/tools.test.ts +1 -1
- package/src/format.ts +3 -5
- package/src/index.ts +1 -1
- package/src/instructions.ts +11 -0
- package/src/server.ts +25 -186
- package/dist/__tests__/encoding.test.d.ts +0 -2
- package/dist/__tests__/encoding.test.d.ts.map +0 -1
- package/dist/__tests__/encoding.test.js +0 -51
- package/dist/__tests__/encoding.test.js.map +0 -1
- package/dist/__tests__/scan.test.d.ts +0 -2
- package/dist/__tests__/scan.test.d.ts.map +0 -1
- package/dist/__tests__/scan.test.js +0 -73
- package/dist/__tests__/scan.test.js.map +0 -1
- package/dist/api.d.ts +0 -42
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js +0 -121
- package/dist/api.js.map +0 -1
- package/dist/carrier-io.d.ts +0 -52
- package/dist/carrier-io.d.ts.map +0 -1
- package/dist/carrier-io.js +0 -91
- package/dist/carrier-io.js.map +0 -1
- package/dist/encoding.d.ts +0 -19
- package/dist/encoding.d.ts.map +0 -1
- package/dist/encoding.js +0 -64
- package/dist/encoding.js.map +0 -1
- package/dist/scan.d.ts +0 -60
- package/dist/scan.d.ts.map +0 -1
- package/dist/scan.js +0 -201
- package/dist/scan.js.map +0 -1
- package/dist/task.d.ts +0 -55
- package/dist/task.d.ts.map +0 -1
- package/dist/task.js +0 -182
- package/dist/task.js.map +0 -1
- package/dist/types.d.ts +0 -108
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/src/__tests__/encoding.test.ts +0 -64
- package/src/__tests__/scan.test.ts +0 -80
- package/src/api.ts +0 -170
- package/src/carrier-io.ts +0 -120
- package/src/encoding.ts +0 -72
- package/src/scan.ts +0 -220
- package/src/task.ts +0 -187
- package/src/types.ts +0 -96
package/dist/task.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
|
|
2
|
-
/**
|
|
3
|
-
* A position BEFORE the work: the task form of the stdio server.
|
|
4
|
-
*
|
|
5
|
-
* bitgraph_open with no files asks the site's own /api/fuse/allocate for a
|
|
6
|
-
* slot and returns its commitment, and nothing else. The caller puts the
|
|
7
|
-
* commitment into the task it is about to run (the prompt, the request, a
|
|
8
|
-
* seed, a line in the document) and, within the slot's life, commits the
|
|
9
|
-
* digest of those task bytes under the slot with the inline marker
|
|
10
|
-
* (bitgraph-fuse/1, title base64url): a verifier recomputes the commitment
|
|
11
|
-
* from the slot record and finds its base64url text inside the bytes.
|
|
12
|
-
* Outputs are recorded afterwards with bitgraph_record and sit later.
|
|
13
|
-
*
|
|
14
|
-
* The slot allocation and the commit go through the same two site routes
|
|
15
|
-
* the core package's fuse() uses; the recovery rule is the core's (read back
|
|
16
|
-
* by digest, refuse a proof under any other slot).
|
|
17
|
-
*/
|
|
18
|
-
import { readFile } from "node:fs/promises";
|
|
19
|
-
import { createHash } from "node:crypto";
|
|
20
|
-
import { bytesToBase64, computeSlotCommitment, findCommitment, inlineAttribution, verifyProofIntegrity, ENCODING_BASE64URL } from "@mikeargento/bitgraph-verify";
|
|
21
|
-
import { ApiError } from "./api.js";
|
|
22
|
-
import { toUrlSafeB64 } from "./encoding.js";
|
|
23
|
-
export const SLOT_TTL_SECONDS = 120;
|
|
24
|
-
const CHAIN = "bitgraph:main";
|
|
25
|
-
const B64_32 = /^[A-Za-z0-9+/]{43}=$/;
|
|
26
|
-
const B64_64 = /^[A-Za-z0-9+/]{86}==$/;
|
|
27
|
-
function isSlotRecord(x) {
|
|
28
|
-
if (x === null || typeof x !== "object" || Array.isArray(x))
|
|
29
|
-
return false;
|
|
30
|
-
const s = x;
|
|
31
|
-
return s.version === "bitgraph/slot/1" && typeof s.nonceB64 === "string" && B64_32.test(s.nonceB64) && typeof s.counter === "string" && /^(0|[1-9][0-9]*)$/.test(s.counter)
|
|
32
|
-
&& typeof s.epochId === "string" && typeof s.publicKeyB64 === "string" && typeof s.signatureB64 === "string" && B64_64.test(s.signatureB64) && s.chainId === CHAIN;
|
|
33
|
-
}
|
|
34
|
-
export function encodeTaskToken(state) {
|
|
35
|
-
return Buffer.from(JSON.stringify(state), "utf8").toString("base64url");
|
|
36
|
-
}
|
|
37
|
-
export function decodeTaskToken(token) {
|
|
38
|
-
let parsed;
|
|
39
|
-
try {
|
|
40
|
-
parsed = JSON.parse(Buffer.from(token, "base64url").toString("utf8"));
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
if (typeof parsed !== "object" || parsed === null)
|
|
46
|
-
return null;
|
|
47
|
-
const s = parsed;
|
|
48
|
-
if (s.v !== 1 || s.task !== true || !isSlotRecord(s.slot))
|
|
49
|
-
return null;
|
|
50
|
-
return { v: 1, task: true, slot: s.slot };
|
|
51
|
-
}
|
|
52
|
-
async function post(config, path, body, timeoutMs) {
|
|
53
|
-
const headers = { "content-type": "application/json", accept: "application/json" };
|
|
54
|
-
if (config.apiKey)
|
|
55
|
-
headers["authorization"] = `Bearer ${config.apiKey}`;
|
|
56
|
-
const res = await fetch(`${config.baseUrl}${path}`, { method: "POST", headers, body: JSON.stringify(body), signal: AbortSignal.timeout(timeoutMs) });
|
|
57
|
-
let json = null;
|
|
58
|
-
try {
|
|
59
|
-
json = await res.json();
|
|
60
|
-
}
|
|
61
|
-
catch { /* non-JSON */ }
|
|
62
|
-
const raw = res.headers.get("retry-after");
|
|
63
|
-
const retry = raw !== null ? Number.parseInt(raw, 10) : NaN;
|
|
64
|
-
return { status: res.status, json, retryAfterSec: Number.isFinite(retry) ? retry : null };
|
|
65
|
-
}
|
|
66
|
-
const messageOf = (json, fallback) => {
|
|
67
|
-
const e = json?.error;
|
|
68
|
-
return typeof e === "string" ? e : fallback;
|
|
69
|
-
};
|
|
70
|
-
/** Step one of the task form: a held slot and its commitment, before any work exists. */
|
|
71
|
-
export async function beginTask(config) {
|
|
72
|
-
const r = await post(config, "/api/fuse/allocate", {}, 20_000);
|
|
73
|
-
if (r.status !== 200)
|
|
74
|
-
throw new ApiError(r.status, messageOf(r.json, `allocation refused (${r.status})`), r.retryAfterSec);
|
|
75
|
-
const slot = r.json?.slot;
|
|
76
|
-
if (!isSlotRecord(slot))
|
|
77
|
-
throw new ApiError(502, "the allocation response is not a slot record on bitgraph:main");
|
|
78
|
-
const commitmentB64 = bytesToBase64(computeSlotCommitment(slot));
|
|
79
|
-
let floor = null;
|
|
80
|
-
try {
|
|
81
|
-
const res = await fetch(`${config.baseUrl}/api/proofs/anchors?counter=${encodeURIComponent(slot.counter)}&epoch=${encodeURIComponent(slot.epochId)}&before=1`, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(10_000) });
|
|
82
|
-
const data = res.status === 200 ? (await res.json()) : null;
|
|
83
|
-
const b = data?.anchors?.[0]?.commit?.anchor?.blockNumber;
|
|
84
|
-
if (typeof b === "number")
|
|
85
|
-
floor = { block: b };
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
floor = null;
|
|
89
|
-
}
|
|
90
|
-
return { token: encodeTaskToken({ v: 1, task: true, slot }), commitment: toUrlSafeB64(commitmentB64), commitmentB64, slotCounter: slot.counter, epoch: toUrlSafeB64(slot.epochId), floor };
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Step two: the task bytes (a path, or the bytes themselves) sealed under
|
|
94
|
-
* the held slot with the inline marker. When the bytes are in hand the
|
|
95
|
-
* commitment is looked for BEFORE the commit, so a task that does not carry
|
|
96
|
-
* it is refused without spending the slot.
|
|
97
|
-
*/
|
|
98
|
-
export async function sealTask(config, state, task) {
|
|
99
|
-
const { slot } = state;
|
|
100
|
-
const commitment = computeSlotCommitment(slot);
|
|
101
|
-
let bytes = null;
|
|
102
|
-
let artifactDigestB64;
|
|
103
|
-
if ("digestB64" in task) {
|
|
104
|
-
if (!B64_32.test(task.digestB64))
|
|
105
|
-
throw new ApiError(400, "artifact digest must be a base64 SHA-256");
|
|
106
|
-
artifactDigestB64 = task.digestB64;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
bytes = "path" in task ? new Uint8Array(await readFile(task.path)) : task.bytes;
|
|
110
|
-
artifactDigestB64 = createHash("sha256").update(bytes).digest("base64");
|
|
111
|
-
}
|
|
112
|
-
const offsets = bytes === null ? null : findCommitment(bytes, commitment, ENCODING_BASE64URL);
|
|
113
|
-
if (offsets !== null && offsets.length === 0) {
|
|
114
|
-
throw new ApiError(400, `the task bytes do not contain the commitment string ${toUrlSafeB64(bytesToBase64(commitment))}; put it in before sealing. Nothing was committed and the slot is still held.`);
|
|
115
|
-
}
|
|
116
|
-
const attribution = inlineAttribution();
|
|
117
|
-
const r = await post(config, "/api/fuse/commit", { digests: [{ digestB64: artifactDigestB64, hashAlg: "sha256" }], slotId: slot.nonceB64, slot, chainId: CHAIN, attribution }, 40_000);
|
|
118
|
-
let proof = null;
|
|
119
|
-
if (r.status === 200)
|
|
120
|
-
proof = (r.json?.proof ?? null);
|
|
121
|
-
else if (r.status === 409 || r.status === 503)
|
|
122
|
-
proof = await recover(config, artifactDigestB64, slot);
|
|
123
|
-
if (proof === null)
|
|
124
|
-
throw new ApiError(r.status, messageOf(r.json, `commit refused (${r.status})`), r.retryAfterSec);
|
|
125
|
-
if (proof.artifact?.digestB64 !== artifactDigestB64 || proof.commit?.nonceB64 !== slot.nonceB64 || proof.slotAllocation?.nonceB64 !== slot.nonceB64)
|
|
126
|
-
throw new ApiError(502, "the boundary returned a proof under a different slot; nothing is labelled sealed");
|
|
127
|
-
const a = proof.attribution;
|
|
128
|
-
if (a?.name !== attribution.name || a?.title !== attribution.title || a?.message !== undefined)
|
|
129
|
-
throw new ApiError(502, "the returned proof does not carry the inline marker that was sent; nothing is labelled sealed");
|
|
130
|
-
const integrity = await verifyProofIntegrity({ proof });
|
|
131
|
-
if (!integrity.valid)
|
|
132
|
-
throw new ApiError(502, `the returned proof does not verify: ${integrity.reason ?? "unknown reason"}`);
|
|
133
|
-
return { proof, artifactDigestB64, offsets };
|
|
134
|
-
}
|
|
135
|
-
async function recover(config, artifactDigestB64, slot) {
|
|
136
|
-
for (let attempt = 0; attempt < 4; attempt++) {
|
|
137
|
-
if (attempt > 0)
|
|
138
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
139
|
-
try {
|
|
140
|
-
const res = await fetch(`${config.baseUrl}/api/proofs/${encodeURIComponent(toUrlSafeB64(artifactDigestB64))}`, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(15_000) });
|
|
141
|
-
if (res.status !== 200)
|
|
142
|
-
continue;
|
|
143
|
-
const j = (await res.json());
|
|
144
|
-
for (const e of j?.proofs ?? []) {
|
|
145
|
-
const p = e.proof;
|
|
146
|
-
if (p && p.artifact?.digestB64 === artifactDigestB64 && p.commit?.nonceB64 === slot.nonceB64)
|
|
147
|
-
return p;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
catch { /* try again */ }
|
|
151
|
-
}
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
export const TASK_INSTRUCTIONS = "You hold a position and its commitment, and no work exists yet. Put the commitment string INSIDE THE OUTPUT you are about to make whenever its format can hold text (SVG, HTML, code, JSON, Markdown, CSV, a document): as a comment, a field, a line that stays in the file. " +
|
|
155
|
-
`When the output exists, call bitgraph_commit with this fuse_token and the output file's path, within ${SLOT_TTL_SECONDS} seconds of opening: the output itself is sealed under the position, and the proof is written beside it. ` +
|
|
156
|
-
"If the output cannot hold text (a PNG, audio, video) or will take longer than that to make, put the commitment into a task file instead (the exact prompt or request you send), seal that file the same way, and when the output exists record it with bitgraph_record: the task is sealed before the output existed, and the output is recorded after. " +
|
|
157
|
-
"Keep the exact bytes that were sealed unchanged: a verifier recomputes the commitment from the proof and looks for the string inside them. " +
|
|
158
|
-
"Leave the proof file as written, whole, every field, environment.attestation.reportB64 included: a proof missing slotAllocation, environment, or the attestation cannot be verified.";
|
|
159
|
-
/**
|
|
160
|
-
* Write a sealed task's proof beside the file it is about, whole, and say
|
|
161
|
-
* where. `make_task.txt` gets `make_task.proof.json`; a name already taken
|
|
162
|
-
* gets the position's counter in it rather than being overwritten.
|
|
163
|
-
*
|
|
164
|
-
* ⚠️ THE SERVER WRITES IT, NOT THE AGENT. Handed the JSON to save, an agent
|
|
165
|
-
* tidied it and dropped slotAllocation and environment, and the signature
|
|
166
|
-
* had no body left to be checked against (Grok, 2026-09-13). A file this
|
|
167
|
-
* process writes is the proof exactly as the boundary returned it.
|
|
168
|
-
*/
|
|
169
|
-
export async function writeProofBeside(sealedPath, proof) {
|
|
170
|
-
const { writeFile, access } = await import("node:fs/promises");
|
|
171
|
-
const { basename, dirname, extname, join } = await import("node:path");
|
|
172
|
-
const dir = dirname(sealedPath);
|
|
173
|
-
const base = basename(sealedPath);
|
|
174
|
-
const stem = extname(base) === "" ? base : base.slice(0, -extname(base).length);
|
|
175
|
-
const counter = proof.commit?.counter ?? "0";
|
|
176
|
-
let target = join(dir, `${stem}.proof.json`);
|
|
177
|
-
if (await access(target).then(() => true).catch(() => false))
|
|
178
|
-
target = join(dir, `${stem}.proof.${counter}.json`);
|
|
179
|
-
await writeFile(target, JSON.stringify(proof, null, 2) + "\n", { flag: "wx" });
|
|
180
|
-
return target;
|
|
181
|
-
}
|
|
182
|
-
//# sourceMappingURL=task.js.map
|
package/dist/task.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task.js","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @mikeargento/bitgraph-mcp: wire types.
|
|
3
|
-
*
|
|
4
|
-
* Minimal views of the bitgraph/1 schema and the bitgraph.ing API responses.
|
|
5
|
-
* The canonical, fully documented schema lives in @mikeargento/bitgraph-verify.
|
|
6
|
-
* Fields not needed for display are kept as unknown; proofs are passed through
|
|
7
|
-
* verbatim when the caller asks for JSON.
|
|
8
|
-
*/
|
|
9
|
-
export interface ProofCommit {
|
|
10
|
-
counter?: string;
|
|
11
|
-
epochId?: string;
|
|
12
|
-
time?: number;
|
|
13
|
-
slotCounter?: string;
|
|
14
|
-
[k: string]: unknown;
|
|
15
|
-
}
|
|
16
|
-
export interface BitGraphProof {
|
|
17
|
-
version?: string;
|
|
18
|
-
artifact?: {
|
|
19
|
-
hashAlg?: string;
|
|
20
|
-
digestB64?: string;
|
|
21
|
-
};
|
|
22
|
-
commit?: ProofCommit;
|
|
23
|
-
signer?: {
|
|
24
|
-
publicKeyB64?: string;
|
|
25
|
-
signatureB64?: string;
|
|
26
|
-
};
|
|
27
|
-
environment?: {
|
|
28
|
-
enforcement?: string;
|
|
29
|
-
measurement?: string;
|
|
30
|
-
attestation?: {
|
|
31
|
-
format?: string;
|
|
32
|
-
reportB64?: string;
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
attribution?: {
|
|
36
|
-
name?: string;
|
|
37
|
-
title?: string;
|
|
38
|
-
message?: string;
|
|
39
|
-
};
|
|
40
|
-
metadata?: unknown;
|
|
41
|
-
proofHash?: string;
|
|
42
|
-
[k: string]: unknown;
|
|
43
|
-
}
|
|
44
|
-
/** A set member's row as the site reports it: which row of N these bytes are, and whether as the original or the new file. */
|
|
45
|
-
export interface SetMemberView {
|
|
46
|
-
index: number;
|
|
47
|
-
count: number;
|
|
48
|
-
role?: "origin" | "fused";
|
|
49
|
-
}
|
|
50
|
-
/** POST /api/proofs/batch response. Keyed by the digest exactly as sent (URL-safe). */
|
|
51
|
-
export interface BatchCheckResponse {
|
|
52
|
-
results: Record<string, {
|
|
53
|
-
proofs: Array<{
|
|
54
|
-
proof: BitGraphProof;
|
|
55
|
-
kind?: "recorded" | "fused";
|
|
56
|
-
member?: SetMemberView;
|
|
57
|
-
setDigest?: string;
|
|
58
|
-
}>;
|
|
59
|
-
}>;
|
|
60
|
-
}
|
|
61
|
-
/** POST /api/fuse/set-index response: how many members' evidence the site wrote. */
|
|
62
|
-
export interface SetIndexResponse {
|
|
63
|
-
count?: number;
|
|
64
|
-
written: number;
|
|
65
|
-
failed: number;
|
|
66
|
-
rejected: number;
|
|
67
|
-
}
|
|
68
|
-
export interface AnchorView {
|
|
69
|
-
counter?: string;
|
|
70
|
-
attrName?: string;
|
|
71
|
-
blockNumber?: number | null;
|
|
72
|
-
blockHash?: string | null;
|
|
73
|
-
etherscanUrl?: string | null;
|
|
74
|
-
blockTime?: string | null;
|
|
75
|
-
}
|
|
76
|
-
export interface PositionView {
|
|
77
|
-
counter: string | null;
|
|
78
|
-
epoch: string | null;
|
|
79
|
-
lowerTime: string | null;
|
|
80
|
-
upperTime: string | null;
|
|
81
|
-
kind?: "recorded" | "fused";
|
|
82
|
-
placement?: string | null;
|
|
83
|
-
member?: SetMemberView;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* GET /api/proofs/digest/{digest} response.
|
|
87
|
-
* causalWindow naming note: anchorBefore is the EARLIER Ethereum block (the
|
|
88
|
-
* proof was BitGraphed after it, the lower time bound); anchorAfter is the
|
|
89
|
-
* LATER block (the upper bound). Present time as "between lower and upper".
|
|
90
|
-
*/
|
|
91
|
-
export interface ProofDetailResponse {
|
|
92
|
-
proofs: Array<{
|
|
93
|
-
proof: BitGraphProof;
|
|
94
|
-
}>;
|
|
95
|
-
positions?: PositionView[];
|
|
96
|
-
causalWindow?: {
|
|
97
|
-
anchorBefore: AnchorView | null;
|
|
98
|
-
anchorAfter: AnchorView | null;
|
|
99
|
-
} | null;
|
|
100
|
-
anchorBlock?: AnchorView | null;
|
|
101
|
-
}
|
|
102
|
-
/** GET /api/search response. */
|
|
103
|
-
export interface SearchResponse {
|
|
104
|
-
found: boolean;
|
|
105
|
-
digest?: string;
|
|
106
|
-
counter?: string | null;
|
|
107
|
-
}
|
|
108
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
DELETED
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8FAA8F"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
|
|
2
|
-
|
|
3
|
-
import { test } from "node:test";
|
|
4
|
-
import { strict as assert } from "node:assert";
|
|
5
|
-
import { createHash } from "node:crypto";
|
|
6
|
-
import { writeFile, mkdtemp } from "node:fs/promises";
|
|
7
|
-
import { tmpdir } from "node:os";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import {
|
|
10
|
-
fromUrlSafeB64,
|
|
11
|
-
looksLikeDigest,
|
|
12
|
-
mapConcurrent,
|
|
13
|
-
sha256FileB64,
|
|
14
|
-
toUrlSafeB64,
|
|
15
|
-
} from "../encoding.js";
|
|
16
|
-
|
|
17
|
-
// A real 32-byte digest with + and / to exercise both substitutions.
|
|
18
|
-
const STANDARD = createHash("sha256").update("bitgraph").digest("base64");
|
|
19
|
-
|
|
20
|
-
test("url-safe round trip preserves the digest", () => {
|
|
21
|
-
const safe = toUrlSafeB64(STANDARD);
|
|
22
|
-
assert.ok(!safe.includes("+") && !safe.includes("/") && !safe.includes("="));
|
|
23
|
-
assert.equal(fromUrlSafeB64(safe), STANDARD);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("fromUrlSafeB64 is a no-op on standard base64", () => {
|
|
27
|
-
assert.equal(fromUrlSafeB64(STANDARD), STANDARD);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test("looksLikeDigest accepts both forms, rejects junk", () => {
|
|
31
|
-
assert.ok(looksLikeDigest(STANDARD));
|
|
32
|
-
assert.ok(looksLikeDigest(toUrlSafeB64(STANDARD)));
|
|
33
|
-
assert.ok(!looksLikeDigest("not-a-digest"));
|
|
34
|
-
assert.ok(!looksLikeDigest(""));
|
|
35
|
-
assert.ok(!looksLikeDigest(Buffer.alloc(16).toString("base64"))); // 16 bytes, not 32
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("sha256FileB64 matches crypto over the same bytes", async () => {
|
|
39
|
-
const dir = await mkdtemp(join(tmpdir(), "bitgraph-mcp-"));
|
|
40
|
-
const file = join(dir, "sample.bin");
|
|
41
|
-
const bytes = Buffer.from("BitGraph proves causal ordering.\n");
|
|
42
|
-
await writeFile(file, bytes);
|
|
43
|
-
const expected = createHash("sha256").update(bytes).digest("base64");
|
|
44
|
-
assert.equal(await sha256FileB64(file), expected);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test("sha256FileB64 rejects directories and missing files", async () => {
|
|
48
|
-
await assert.rejects(() => sha256FileB64(tmpdir()), /Not a regular file/);
|
|
49
|
-
await assert.rejects(() => sha256FileB64(join(tmpdir(), "definitely-missing-9x7")));
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test("mapConcurrent preserves order and honors the limit", async () => {
|
|
53
|
-
let inFlight = 0;
|
|
54
|
-
let peak = 0;
|
|
55
|
-
const out = await mapConcurrent([1, 2, 3, 4, 5, 6, 7, 8], 3, async (n) => {
|
|
56
|
-
inFlight += 1;
|
|
57
|
-
peak = Math.max(peak, inFlight);
|
|
58
|
-
await new Promise((r) => setTimeout(r, 5));
|
|
59
|
-
inFlight -= 1;
|
|
60
|
-
return n * 2;
|
|
61
|
-
});
|
|
62
|
-
assert.deepEqual(out, [2, 4, 6, 8, 10, 12, 14, 16]);
|
|
63
|
-
assert.ok(peak <= 3, `peak concurrency ${peak} exceeded 3`);
|
|
64
|
-
});
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The scan's two promises: the digest is the file's own, and a state
|
|
5
|
-
* finished with the placement's suffix for a slot is the hash of the
|
|
6
|
-
* placement's own build for that slot. Both are pinned across sizes on both
|
|
7
|
-
* sides of every boundary that matters (the 64-byte sniff, the tar block,
|
|
8
|
-
* the 64 KB stream chunk) for both placements the scan makes.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { test, before } from "node:test";
|
|
12
|
-
import { strict as assert } from "node:assert";
|
|
13
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
14
|
-
import { mkdtemp, mkdir, symlink, writeFile } from "node:fs/promises";
|
|
15
|
-
import { tmpdir } from "node:os";
|
|
16
|
-
import { join } from "node:path";
|
|
17
|
-
import { placementForBytes } from "@mikeargento/bitgraph";
|
|
18
|
-
import { getPlacement } from "@mikeargento/bitgraph-verify";
|
|
19
|
-
import { expandPaths, fusedDigestFor, scanFile } from "../scan.js";
|
|
20
|
-
|
|
21
|
-
let root = "";
|
|
22
|
-
before(async () => {
|
|
23
|
-
root = await mkdtemp(join(tmpdir(), "bitgraph-mcp-scan-"));
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const PNG = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
27
|
-
const SIZES = [0, 1, 8, 63, 64, 65, 511, 512, 513, 1024, 65_535, 65_536, 65_537, 200_000];
|
|
28
|
-
|
|
29
|
-
test("a scan's digest is the file's own and its state finishes to the placement's own build", async () => {
|
|
30
|
-
let checked = 0;
|
|
31
|
-
for (const size of SIZES) {
|
|
32
|
-
for (const kind of ["png", "txt"] as const) {
|
|
33
|
-
const lead = kind === "png" ? PNG : Buffer.from("txt:");
|
|
34
|
-
const bytes = Buffer.concat([lead, randomBytes(Math.max(0, size - lead.length))]).subarray(0, size);
|
|
35
|
-
const path = join(root, `${kind}-${size}.bin`);
|
|
36
|
-
await writeFile(path, bytes);
|
|
37
|
-
const s = await scanFile(path);
|
|
38
|
-
assert.equal(s.size, size);
|
|
39
|
-
assert.equal(s.digestB64, createHash("sha256").update(bytes).digest("base64"), `${kind} ${size}: digest`);
|
|
40
|
-
assert.equal(s.placement, placementForBytes(new Uint8Array(bytes)), `${kind} ${size}: the core's own placement choice`);
|
|
41
|
-
assert.ok(s.state !== null, "a file that did not change keeps its state");
|
|
42
|
-
const placement = getPlacement(s.placement);
|
|
43
|
-
if (placement === undefined) throw new Error("placement missing");
|
|
44
|
-
// Two slots, both finished from the same saved state: the copy leaves the state intact.
|
|
45
|
-
for (const commitment of [randomBytes(32), randomBytes(32)]) {
|
|
46
|
-
const built = placement.build({ original: new Uint8Array(bytes), originDigest: s.originDigest, commitment: new Uint8Array(commitment) });
|
|
47
|
-
const expected = createHash("sha256").update(built).digest();
|
|
48
|
-
assert.deepEqual(Buffer.from(fusedDigestFor(s, new Uint8Array(commitment))), expected, `${kind} ${size}: state finished == sha256(build)`);
|
|
49
|
-
checked += 1;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
assert.equal(checked, SIZES.length * 4);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test("expandPaths: files, directories, hidden entries, links, duplicates, limits, missing paths", async () => {
|
|
57
|
-
const lone = join(root, "lone.txt");
|
|
58
|
-
await writeFile(lone, "lone");
|
|
59
|
-
const dir = join(root, "tree");
|
|
60
|
-
await mkdir(join(dir, "sub", ".secret"), { recursive: true });
|
|
61
|
-
await writeFile(join(dir, "a.txt"), "a");
|
|
62
|
-
await writeFile(join(dir, ".DS_Store"), "junk");
|
|
63
|
-
await writeFile(join(dir, "sub", "b.txt"), "b");
|
|
64
|
-
await writeFile(join(dir, "sub", ".secret", "c.txt"), "c");
|
|
65
|
-
await symlink(join(dir, "a.txt"), join(dir, "link.txt"));
|
|
66
|
-
|
|
67
|
-
const e = await expandPaths([lone, dir], 100);
|
|
68
|
-
assert.deepEqual(e.files, [lone, join(dir, "a.txt"), join(dir, "sub", "b.txt")]);
|
|
69
|
-
assert.equal(e.directories, 1);
|
|
70
|
-
|
|
71
|
-
const twice = await expandPaths([lone, lone, dir, join(dir, "a.txt")], 100);
|
|
72
|
-
assert.deepEqual(twice.files, [lone, join(dir, "a.txt"), join(dir, "sub", "b.txt")], "the same file twice is one file");
|
|
73
|
-
|
|
74
|
-
await assert.rejects(expandPaths([dir], 1), /more than 1 files/);
|
|
75
|
-
await assert.rejects(expandPaths([lone, join(root, "missing.txt")], 100), (err: Error) => {
|
|
76
|
-
assert.ok(err.message.includes("nothing was BitGraphed"));
|
|
77
|
-
assert.ok(err.message.includes(join(root, "missing.txt")));
|
|
78
|
-
return true;
|
|
79
|
-
});
|
|
80
|
-
});
|
package/src/api.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @mikeargento/bitgraph-mcp: HTTP client for the hosted BitGraph API.
|
|
5
|
-
*
|
|
6
|
-
* The reads: the batch lookup, the proof detail, the number search. Making a
|
|
7
|
-
* BitGraph goes through the core package's own transport against the same
|
|
8
|
-
* site (its /api/fuse routes), which is what maintains the per-position
|
|
9
|
-
* by-digest index that makes every member of a set discoverable afterward;
|
|
10
|
-
* the one write here is a set/2's member evidence, indexed after the commit.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { mapConcurrent } from "./encoding.js";
|
|
14
|
-
import type { BatchCheckResponse, ProofDetailResponse, SearchResponse, SetIndexResponse } from "./types.js";
|
|
15
|
-
|
|
16
|
-
export interface ApiConfig {
|
|
17
|
-
baseUrl: string;
|
|
18
|
-
apiKey?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Read configuration from the environment at call time (testable via env). */
|
|
22
|
-
export function configFromEnv(): ApiConfig {
|
|
23
|
-
const baseUrl = (process.env["BITGRAPH_API_URL"] ?? "https://bitgraph.ing").replace(/\/+$/, "");
|
|
24
|
-
const apiKey = process.env["BITGRAPH_API_KEY"];
|
|
25
|
-
return apiKey ? { baseUrl, apiKey } : { baseUrl };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Matches the batch endpoint's MAX_DIGESTS. */
|
|
29
|
-
export const BATCH_CHECK_LIMIT = 500;
|
|
30
|
-
/** Batch lookups in flight at once: a large folder is many pages. */
|
|
31
|
-
const BATCH_CHECK_CONCURRENCY = 4;
|
|
32
|
-
|
|
33
|
-
const CHECK_TIMEOUT_MS = 30_000;
|
|
34
|
-
const SET_INDEX_TIMEOUT_MS = 60_000;
|
|
35
|
-
|
|
36
|
-
export class ApiError extends Error {
|
|
37
|
-
readonly status: number;
|
|
38
|
-
readonly retryAfterSec: number | null;
|
|
39
|
-
|
|
40
|
-
constructor(status: number, message: string, retryAfterSec: number | null = null) {
|
|
41
|
-
super(message);
|
|
42
|
-
this.status = status;
|
|
43
|
-
this.retryAfterSec = retryAfterSec;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function parseError(res: Response): Promise<ApiError> {
|
|
48
|
-
let message = res.statusText || `HTTP ${res.status}`;
|
|
49
|
-
try {
|
|
50
|
-
const body = (await res.json()) as { error?: string };
|
|
51
|
-
if (typeof body.error === "string" && body.error.length > 0) message = body.error;
|
|
52
|
-
} catch {
|
|
53
|
-
/* non-JSON error body */
|
|
54
|
-
}
|
|
55
|
-
const retryAfterRaw = res.headers.get("retry-after");
|
|
56
|
-
const retryAfterSec = retryAfterRaw !== null ? Number.parseInt(retryAfterRaw, 10) : null;
|
|
57
|
-
return new ApiError(res.status, message, Number.isFinite(retryAfterSec) ? retryAfterSec : null);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Redirects are refused everywhere: an Authorization header must never follow
|
|
62
|
-
* one to a different host, and the canonical endpoint serves without them.
|
|
63
|
-
*/
|
|
64
|
-
function redirectHint(err: unknown): never {
|
|
65
|
-
if (err instanceof TypeError && /redirect/i.test(err.message)) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
"The BitGraph endpoint redirected. Set BITGRAPH_API_URL to the canonical https://bitgraph.ing (apex, no www)."
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
throw err;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async function getJson<T>(config: ApiConfig, path: string, timeoutMs: number): Promise<T> {
|
|
74
|
-
const res = await fetch(`${config.baseUrl}${path}`, {
|
|
75
|
-
method: "GET",
|
|
76
|
-
redirect: "error",
|
|
77
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
78
|
-
}).catch(redirectHint);
|
|
79
|
-
if (!res.ok) throw await parseError(res);
|
|
80
|
-
return (await res.json()) as T;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function postJson<T>(
|
|
84
|
-
config: ApiConfig,
|
|
85
|
-
path: string,
|
|
86
|
-
body: unknown,
|
|
87
|
-
timeoutMs: number,
|
|
88
|
-
authenticated: boolean
|
|
89
|
-
): Promise<T> {
|
|
90
|
-
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
91
|
-
if (authenticated && config.apiKey) headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
92
|
-
const res = await fetch(`${config.baseUrl}${path}`, {
|
|
93
|
-
method: "POST",
|
|
94
|
-
headers,
|
|
95
|
-
body: JSON.stringify(body),
|
|
96
|
-
redirect: "error",
|
|
97
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
98
|
-
}).catch(redirectHint);
|
|
99
|
-
if (!res.ok) throw await parseError(res);
|
|
100
|
-
return (await res.json()) as T;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Look up which digests are on record. Input digests must be URL-safe base64;
|
|
105
|
-
* the response is keyed by the exact strings sent. Pages of up to 500, a few
|
|
106
|
-
* in flight at once.
|
|
107
|
-
*/
|
|
108
|
-
export async function batchCheck(
|
|
109
|
-
config: ApiConfig,
|
|
110
|
-
urlSafeDigests: readonly string[]
|
|
111
|
-
): Promise<BatchCheckResponse> {
|
|
112
|
-
const chunks: string[][] = [];
|
|
113
|
-
for (let offset = 0; offset < urlSafeDigests.length; offset += BATCH_CHECK_LIMIT) {
|
|
114
|
-
chunks.push(urlSafeDigests.slice(offset, offset + BATCH_CHECK_LIMIT));
|
|
115
|
-
}
|
|
116
|
-
const pages = await mapConcurrent(chunks, BATCH_CHECK_CONCURRENCY, (chunk) =>
|
|
117
|
-
postJson<BatchCheckResponse>(config, "/api/proofs/batch", { digests: chunk }, CHECK_TIMEOUT_MS, false)
|
|
118
|
-
);
|
|
119
|
-
const merged: BatchCheckResponse = { results: {} };
|
|
120
|
-
for (const page of pages) Object.assign(merged.results, page.results);
|
|
121
|
-
return merged;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** One request's worth of a set/2's member evidence, for the site to index. */
|
|
125
|
-
export interface SetIndexRequest {
|
|
126
|
-
/** The set proof's artifact digest, URL-safe base64. */
|
|
127
|
-
setDigest: string;
|
|
128
|
-
/** The set proof's epoch id, URL-safe base64. */
|
|
129
|
-
epoch: string;
|
|
130
|
-
/** The set proof's commit counter. */
|
|
131
|
-
counter: string;
|
|
132
|
-
members: unknown[];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Index members of a set/2 from their evidence. The site reads the set proof
|
|
137
|
-
* from its own position, binds the root document, and checks every member's
|
|
138
|
-
* path before writing a key; a row that does not bind is rejected, never
|
|
139
|
-
* written.
|
|
140
|
-
*/
|
|
141
|
-
export async function indexSetMembers(config: ApiConfig, body: SetIndexRequest): Promise<SetIndexResponse> {
|
|
142
|
-
return postJson<SetIndexResponse>(config, "/api/fuse/set-index", body, SET_INDEX_TIMEOUT_MS, false);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** Full detail for one digest: proof, all causal positions, anchor window. */
|
|
146
|
-
export async function getProofDetail(
|
|
147
|
-
config: ApiConfig,
|
|
148
|
-
urlSafeDigest: string,
|
|
149
|
-
counter?: string,
|
|
150
|
-
urlSafeEpoch?: string
|
|
151
|
-
): Promise<ProofDetailResponse> {
|
|
152
|
-
const params = new URLSearchParams();
|
|
153
|
-
if (counter !== undefined) params.set("counter", counter);
|
|
154
|
-
if (urlSafeEpoch !== undefined) params.set("epoch", urlSafeEpoch);
|
|
155
|
-
const query = params.size > 0 ? `?${params.toString()}` : "";
|
|
156
|
-
return getJson<ProofDetailResponse>(
|
|
157
|
-
config,
|
|
158
|
-
`/api/proofs/digest/${encodeURIComponent(urlSafeDigest)}${query}`,
|
|
159
|
-
CHECK_TIMEOUT_MS
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** Resolve a BitGraph number (or digest string) to a digest via /api/search. */
|
|
164
|
-
export async function search(config: ApiConfig, q: string): Promise<SearchResponse> {
|
|
165
|
-
return getJson<SearchResponse>(
|
|
166
|
-
config,
|
|
167
|
-
`/api/search?q=${encodeURIComponent(q)}`,
|
|
168
|
-
CHECK_TIMEOUT_MS
|
|
169
|
-
);
|
|
170
|
-
}
|