@truealter/sdk 0.2.2 → 0.4.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/README.md +23 -25
- package/dist/bin/alter-identity.js +881 -53
- package/dist/bin/mcp-bridge.js +179 -10
- package/dist/index.cjs +815 -81
- package/dist/index.d.cts +333 -143
- package/dist/index.d.ts +333 -143
- package/dist/index.js +747 -85
- package/package.json +11 -5
- package/dist/bin/alter-identity.js.map +0 -1
- package/dist/bin/mcp-bridge.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var p256 = require('@noble/curves/p256');
|
|
4
|
+
var sha256 = require('@noble/hashes/sha256');
|
|
5
|
+
var utils = require('@noble/hashes/utils');
|
|
3
6
|
var ed25519 = require('@noble/ed25519');
|
|
4
7
|
var sha512 = require('@noble/hashes/sha512');
|
|
5
|
-
var
|
|
8
|
+
var child_process = require('child_process');
|
|
9
|
+
var os = require('os');
|
|
10
|
+
var path = require('path');
|
|
11
|
+
var process$1 = require('process');
|
|
12
|
+
var fs = require('fs');
|
|
13
|
+
var crypto$1 = require('crypto');
|
|
6
14
|
|
|
7
15
|
function _interopNamespace(e) {
|
|
8
16
|
if (e && e.__esModule) return e;
|
|
@@ -24,7 +32,166 @@ function _interopNamespace(e) {
|
|
|
24
32
|
|
|
25
33
|
var ed25519__namespace = /*#__PURE__*/_interopNamespace(ed25519);
|
|
26
34
|
|
|
35
|
+
var __defProp = Object.defineProperty;
|
|
36
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
37
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
38
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
39
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
40
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
41
|
+
}) : x)(function(x) {
|
|
42
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
43
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
44
|
+
});
|
|
45
|
+
var __esm = (fn, res) => function __init() {
|
|
46
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
47
|
+
};
|
|
48
|
+
var __export = (target, all) => {
|
|
49
|
+
for (var name in all)
|
|
50
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
51
|
+
};
|
|
52
|
+
var __copyProps = (to, from, except, desc) => {
|
|
53
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
54
|
+
for (let key of __getOwnPropNames(from))
|
|
55
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
56
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
57
|
+
}
|
|
58
|
+
return to;
|
|
59
|
+
};
|
|
60
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
61
|
+
|
|
62
|
+
// node_modules/tsup/assets/cjs_shims.js
|
|
63
|
+
var init_cjs_shims = __esm({
|
|
64
|
+
"node_modules/tsup/assets/cjs_shims.js"() {
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// src/signing.ts
|
|
69
|
+
var signing_exports = {};
|
|
70
|
+
__export(signing_exports, {
|
|
71
|
+
canonicalArgsSha256: () => canonicalArgsSha256,
|
|
72
|
+
canonicalStringify: () => canonicalStringify,
|
|
73
|
+
loadPrivateKey: () => loadPrivateKey,
|
|
74
|
+
signInvocation: () => signInvocation
|
|
75
|
+
});
|
|
76
|
+
function canonicalStringify(value) {
|
|
77
|
+
return stringifyInner(value);
|
|
78
|
+
}
|
|
79
|
+
function stringifyInner(value) {
|
|
80
|
+
if (value === null) return "null";
|
|
81
|
+
if (value === void 0) {
|
|
82
|
+
throw new TypeError("canonicalStringify: undefined is not representable in JSON");
|
|
83
|
+
}
|
|
84
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
85
|
+
if (typeof value === "number") {
|
|
86
|
+
if (!Number.isFinite(value)) {
|
|
87
|
+
throw new TypeError("canonicalStringify: non-finite numbers are not representable");
|
|
88
|
+
}
|
|
89
|
+
return JSON.stringify(value);
|
|
90
|
+
}
|
|
91
|
+
if (typeof value === "string") return encodeString(value);
|
|
92
|
+
if (Array.isArray(value)) {
|
|
93
|
+
return "[" + value.map((v) => stringifyInner(v)).join(",") + "]";
|
|
94
|
+
}
|
|
95
|
+
if (typeof value === "object") {
|
|
96
|
+
const obj = value;
|
|
97
|
+
const keys = Object.keys(obj).sort();
|
|
98
|
+
return "{" + keys.map((k) => encodeString(k) + ":" + stringifyInner(obj[k])).join(",") + "}";
|
|
99
|
+
}
|
|
100
|
+
throw new TypeError(`canonicalStringify: unsupported type ${typeof value}`);
|
|
101
|
+
}
|
|
102
|
+
function encodeString(s) {
|
|
103
|
+
return JSON.stringify(s);
|
|
104
|
+
}
|
|
105
|
+
function canonicalArgsSha256(toolArgs) {
|
|
106
|
+
const canonical = canonicalStringify(toolArgs ?? {});
|
|
107
|
+
const bytes = new TextEncoder().encode(canonical);
|
|
108
|
+
const digest = sha256.sha256(bytes);
|
|
109
|
+
return bytesToHex(digest);
|
|
110
|
+
}
|
|
111
|
+
function bytesToHex(bytes) {
|
|
112
|
+
let out = "";
|
|
113
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
114
|
+
out += bytes[i].toString(16).padStart(2, "0");
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
function base64urlEncode(bytes) {
|
|
119
|
+
const raw = typeof bytes === "string" ? new TextEncoder().encode(bytes) : bytes;
|
|
120
|
+
if (typeof Buffer !== "undefined") {
|
|
121
|
+
return Buffer.from(raw).toString("base64url");
|
|
122
|
+
}
|
|
123
|
+
let binary = "";
|
|
124
|
+
for (let i = 0; i < raw.length; i++) binary += String.fromCharCode(raw[i]);
|
|
125
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
126
|
+
}
|
|
127
|
+
function loadPrivateKey(key) {
|
|
128
|
+
if (key instanceof Uint8Array) {
|
|
129
|
+
if (key.length !== 32) {
|
|
130
|
+
throw new TypeError("ES256 raw private key must be 32 bytes.");
|
|
131
|
+
}
|
|
132
|
+
return key;
|
|
133
|
+
}
|
|
134
|
+
if (typeof key === "string" && key.includes("-----BEGIN")) {
|
|
135
|
+
const nodeCrypto = __require("crypto");
|
|
136
|
+
const keyObj = nodeCrypto.createPrivateKey({ key, format: "pem" });
|
|
137
|
+
const jwk = keyObj.export({ format: "jwk" });
|
|
138
|
+
if (jwk.crv !== "P-256" || !jwk.d) {
|
|
139
|
+
throw new TypeError("PEM is not a P-256 private key.");
|
|
140
|
+
}
|
|
141
|
+
return base64urlDecodeToBytes(jwk.d);
|
|
142
|
+
}
|
|
143
|
+
throw new TypeError("loadPrivateKey: expected Uint8Array(32) or PEM string.");
|
|
144
|
+
}
|
|
145
|
+
function base64urlDecodeToBytes(s) {
|
|
146
|
+
const pad = s.length % 4 === 0 ? "" : "=".repeat(4 - s.length % 4);
|
|
147
|
+
const b64 = (s + pad).replace(/-/g, "+").replace(/_/g, "/");
|
|
148
|
+
if (typeof Buffer !== "undefined") {
|
|
149
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
150
|
+
}
|
|
151
|
+
const binary = atob(b64);
|
|
152
|
+
const out = new Uint8Array(binary.length);
|
|
153
|
+
for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
function signInvocation(toolName, toolArgs, options) {
|
|
157
|
+
const { kid, privateKey, handle } = options;
|
|
158
|
+
const nonce = options.nonce ?? base64urlEncode(utils.randomBytes(24));
|
|
159
|
+
const iat = options.iatSeconds ?? Math.floor(Date.now() / 1e3);
|
|
160
|
+
const claims = {
|
|
161
|
+
tool: toolName,
|
|
162
|
+
args_sha256: canonicalArgsSha256(toolArgs ?? {}),
|
|
163
|
+
nonce,
|
|
164
|
+
iat,
|
|
165
|
+
iss: handle
|
|
166
|
+
};
|
|
167
|
+
const headerB64 = base64urlEncode(JSON.stringify({ alg: "ES256", kid }));
|
|
168
|
+
const payloadB64 = base64urlEncode(JSON.stringify(claims));
|
|
169
|
+
const signingInput = `${headerB64}.${payloadB64}`;
|
|
170
|
+
const signingBytes = new TextEncoder().encode(signingInput);
|
|
171
|
+
const dBytes = loadPrivateKey(privateKey);
|
|
172
|
+
const digest = sha256.sha256(signingBytes);
|
|
173
|
+
const sig = p256.p256.sign(digest, dBytes, { prehash: false });
|
|
174
|
+
const sigBytes = sig.toCompactRawBytes();
|
|
175
|
+
const sigB64 = base64urlEncode(sigBytes);
|
|
176
|
+
return `${signingInput}.${sigB64}`;
|
|
177
|
+
}
|
|
178
|
+
var init_signing = __esm({
|
|
179
|
+
"src/signing.ts"() {
|
|
180
|
+
init_cjs_shims();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// src/index.ts
|
|
185
|
+
init_cjs_shims();
|
|
186
|
+
|
|
187
|
+
// src/client.ts
|
|
188
|
+
init_cjs_shims();
|
|
189
|
+
|
|
190
|
+
// src/discovery.ts
|
|
191
|
+
init_cjs_shims();
|
|
192
|
+
|
|
27
193
|
// src/errors.ts
|
|
194
|
+
init_cjs_shims();
|
|
28
195
|
var AlterError = class extends Error {
|
|
29
196
|
code;
|
|
30
197
|
cause;
|
|
@@ -123,7 +290,12 @@ async function discover(domain, opts = {}) {
|
|
|
123
290
|
try {
|
|
124
291
|
const dnsHit = await tryDns(host);
|
|
125
292
|
if (dnsHit) {
|
|
126
|
-
const
|
|
293
|
+
const parsed = validateDiscoveredUrl(dnsHit, "dns");
|
|
294
|
+
const result = {
|
|
295
|
+
url: parsed.toString().replace(/\/$/, ""),
|
|
296
|
+
transport: "streamable-http",
|
|
297
|
+
source: "dns"
|
|
298
|
+
};
|
|
127
299
|
if (cache) _cache.set(host, result);
|
|
128
300
|
return result;
|
|
129
301
|
}
|
|
@@ -164,6 +336,28 @@ function normaliseDomain(input) {
|
|
|
164
336
|
if (!host) throw new AlterDiscoveryError(`Empty domain: "${input}"`);
|
|
165
337
|
return host;
|
|
166
338
|
}
|
|
339
|
+
function validateDiscoveredUrl(url, source) {
|
|
340
|
+
let parsed;
|
|
341
|
+
try {
|
|
342
|
+
parsed = new URL(url);
|
|
343
|
+
} catch {
|
|
344
|
+
throw new AlterDiscoveryError(`${source}: malformed URL ${url}`);
|
|
345
|
+
}
|
|
346
|
+
if (parsed.protocol !== "https:") {
|
|
347
|
+
throw new AlterDiscoveryError(
|
|
348
|
+
`${source}: non-https MCP endpoint rejected (got ${parsed.protocol}//${parsed.hostname})`
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
if (parsed.username || parsed.password) {
|
|
352
|
+
throw new AlterDiscoveryError(
|
|
353
|
+
`${source}: MCP endpoint must not contain userinfo (user:pass@host)`
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
if (!parsed.hostname) {
|
|
357
|
+
throw new AlterDiscoveryError(`${source}: MCP endpoint missing hostname`);
|
|
358
|
+
}
|
|
359
|
+
return parsed;
|
|
360
|
+
}
|
|
167
361
|
async function tryDns(host) {
|
|
168
362
|
let resolveTxt;
|
|
169
363
|
try {
|
|
@@ -224,14 +418,17 @@ async function tryWellKnown(host, file, timeoutMs, fetchImpl) {
|
|
|
224
418
|
if (file === "mcp.json") {
|
|
225
419
|
const remotes = doc.remotes || [];
|
|
226
420
|
const remote = remotes.find((r) => r.transportType === "streamable-http" || r.transportType === "http");
|
|
227
|
-
const
|
|
228
|
-
if (!
|
|
229
|
-
|
|
421
|
+
const rawUrl = remote?.url || doc.url;
|
|
422
|
+
if (!rawUrl) return null;
|
|
423
|
+
const parsed = validateDiscoveredUrl(rawUrl, "mcp.json");
|
|
424
|
+
return { url: parsed.toString().replace(/\/$/, ""), transport: "streamable-http", source: "mcp.json", raw: doc };
|
|
230
425
|
}
|
|
231
426
|
const mcpHost = doc.mcp;
|
|
232
427
|
if (!mcpHost) return null;
|
|
428
|
+
const normalised = ensureMcpPath(mcpHost);
|
|
429
|
+
validateDiscoveredUrl(normalised, "alter.json");
|
|
233
430
|
return {
|
|
234
|
-
url:
|
|
431
|
+
url: normalised,
|
|
235
432
|
transport: "streamable-http",
|
|
236
433
|
source: "alter.json",
|
|
237
434
|
publicKey: doc.pk,
|
|
@@ -250,7 +447,11 @@ function ensureMcpPath(url) {
|
|
|
250
447
|
}
|
|
251
448
|
}
|
|
252
449
|
|
|
450
|
+
// src/mcp.ts
|
|
451
|
+
init_cjs_shims();
|
|
452
|
+
|
|
253
453
|
// src/x402.ts
|
|
454
|
+
init_cjs_shims();
|
|
254
455
|
var X402Client = class {
|
|
255
456
|
signer;
|
|
256
457
|
maxPerQuery;
|
|
@@ -277,11 +478,14 @@ var X402Client = class {
|
|
|
277
478
|
if (!this.assets.has(envelope.asset)) {
|
|
278
479
|
throw new AlterError("PAYMENT_REQUIRED", `asset ${envelope.asset} not permitted by client policy`);
|
|
279
480
|
}
|
|
280
|
-
if (this.maxPerQuery !== void 0
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
481
|
+
if (this.maxPerQuery !== void 0) {
|
|
482
|
+
const amt = Number(envelope.amount);
|
|
483
|
+
if (!Number.isFinite(amt) || amt < 0 || amt > this.maxPerQuery) {
|
|
484
|
+
throw new AlterError(
|
|
485
|
+
"PAYMENT_REQUIRED",
|
|
486
|
+
`quote ${envelope.amount} ${envelope.asset} exceeds maxPerQuery ${this.maxPerQuery}`
|
|
487
|
+
);
|
|
488
|
+
}
|
|
285
489
|
}
|
|
286
490
|
if (!this.signer) {
|
|
287
491
|
throw new AlterPaymentRequired(envelope.resource ?? "unknown", envelope);
|
|
@@ -339,6 +543,7 @@ var MCPClient = class {
|
|
|
339
543
|
maxRetries;
|
|
340
544
|
clientInfo;
|
|
341
545
|
x402;
|
|
546
|
+
signing;
|
|
342
547
|
requestCounter = 0;
|
|
343
548
|
initialised = false;
|
|
344
549
|
constructor(opts = {}) {
|
|
@@ -349,6 +554,7 @@ var MCPClient = class {
|
|
|
349
554
|
this.maxRetries = opts.maxRetries ?? 2;
|
|
350
555
|
this.clientInfo = opts.clientInfo ?? { name: "@truealter/sdk", version: "0.2.0" };
|
|
351
556
|
this.x402 = opts.x402;
|
|
557
|
+
this.signing = opts.signing;
|
|
352
558
|
}
|
|
353
559
|
/**
|
|
354
560
|
* Send the MCP `initialize` handshake and capture the resulting session
|
|
@@ -435,6 +641,7 @@ var MCPClient = class {
|
|
|
435
641
|
method
|
|
436
642
|
};
|
|
437
643
|
if (params !== void 0) payload.params = params;
|
|
644
|
+
const signatureHeader = this.buildSignatureHeader(method, params);
|
|
438
645
|
let attempt = 0;
|
|
439
646
|
let lastErr = null;
|
|
440
647
|
while (attempt <= this.maxRetries) {
|
|
@@ -445,7 +652,7 @@ var MCPClient = class {
|
|
|
445
652
|
try {
|
|
446
653
|
resp = await this.fetchImpl(this.endpoint, {
|
|
447
654
|
method: "POST",
|
|
448
|
-
headers: this.buildHeaders(),
|
|
655
|
+
headers: this.buildHeaders(signatureHeader),
|
|
449
656
|
body: JSON.stringify(payload),
|
|
450
657
|
signal: controller.signal
|
|
451
658
|
});
|
|
@@ -472,7 +679,8 @@ var MCPClient = class {
|
|
|
472
679
|
throw new AlterPaymentRequired(this.guessToolName(payload), envelope);
|
|
473
680
|
}
|
|
474
681
|
if (resp.status === 429) {
|
|
475
|
-
const
|
|
682
|
+
const rawRetryAfter = Number(resp.headers.get("Retry-After") ?? 60);
|
|
683
|
+
const retryAfter = Number.isFinite(rawRetryAfter) && rawRetryAfter >= 0 ? Math.min(rawRetryAfter, 300) : 60;
|
|
476
684
|
if (attempt > this.maxRetries) {
|
|
477
685
|
throw new AlterRateLimited(`HTTP 429 on ${method}`, retryAfter);
|
|
478
686
|
}
|
|
@@ -508,7 +716,7 @@ var MCPClient = class {
|
|
|
508
716
|
}
|
|
509
717
|
throw lastErr ?? new AlterNetworkError(`MCP ${method}: exhausted retries`);
|
|
510
718
|
}
|
|
511
|
-
buildHeaders() {
|
|
719
|
+
buildHeaders(extra) {
|
|
512
720
|
const headers = {
|
|
513
721
|
"Content-Type": "application/json",
|
|
514
722
|
Accept: "application/json",
|
|
@@ -516,8 +724,27 @@ var MCPClient = class {
|
|
|
516
724
|
};
|
|
517
725
|
if (this.apiKey) headers["X-ALTER-API-Key"] = this.apiKey;
|
|
518
726
|
if (this.sessionId) headers["Mcp-Session-Id"] = this.sessionId;
|
|
727
|
+
if (extra) Object.assign(headers, extra);
|
|
519
728
|
return headers;
|
|
520
729
|
}
|
|
730
|
+
/**
|
|
731
|
+
* Produce the `Mcp-Invocation-Signature` header for a `tools/call`
|
|
732
|
+
* payload, when signing is configured. Returns `undefined` when no
|
|
733
|
+
* signing key is attached or the method is not `tools/call`.
|
|
734
|
+
*/
|
|
735
|
+
buildSignatureHeader(method, params) {
|
|
736
|
+
if (!this.signing) return void 0;
|
|
737
|
+
if (method !== "tools/call") return void 0;
|
|
738
|
+
const p = params;
|
|
739
|
+
if (!p?.name) return void 0;
|
|
740
|
+
const { signInvocation: signInvocation2 } = (init_signing(), __toCommonJS(signing_exports));
|
|
741
|
+
const headerValue = signInvocation2(p.name, p.arguments ?? {}, {
|
|
742
|
+
kid: this.signing.kid,
|
|
743
|
+
privateKey: this.signing.privateKey,
|
|
744
|
+
handle: this.signing.handle
|
|
745
|
+
});
|
|
746
|
+
return { "Mcp-Invocation-Signature": headerValue };
|
|
747
|
+
}
|
|
521
748
|
async extractPaymentEnvelope(resp) {
|
|
522
749
|
const headerValue = resp.headers.get("X-402-Payment") ?? resp.headers.get("x-402-payment");
|
|
523
750
|
if (headerValue) {
|
|
@@ -555,6 +782,12 @@ async function safeText(resp) {
|
|
|
555
782
|
return "";
|
|
556
783
|
}
|
|
557
784
|
}
|
|
785
|
+
|
|
786
|
+
// src/provenance.ts
|
|
787
|
+
init_cjs_shims();
|
|
788
|
+
|
|
789
|
+
// src/auth.ts
|
|
790
|
+
init_cjs_shims();
|
|
558
791
|
ed25519__namespace.etc.sha512Sync = (...m) => sha512.sha512(ed25519__namespace.etc.concatBytes(...m));
|
|
559
792
|
function generateKeypair() {
|
|
560
793
|
const privateKey = utils.randomBytes(32);
|
|
@@ -593,14 +826,14 @@ async function verify(publicKeyHex, signatureHex, message) {
|
|
|
593
826
|
}
|
|
594
827
|
function encodeDid(publicKey) {
|
|
595
828
|
const bytes = typeof publicKey === "string" ? utils.hexToBytes(publicKey) : publicKey;
|
|
596
|
-
return `ed25519:${
|
|
829
|
+
return `ed25519:${base64urlEncode2(bytes)}`;
|
|
597
830
|
}
|
|
598
831
|
function decodeDid(did) {
|
|
599
832
|
const ed25519Match = did.match(/^ed25519:(.+)$/);
|
|
600
833
|
if (ed25519Match) return base64urlDecode(ed25519Match[1]);
|
|
601
834
|
throw new Error(`Unrecognised DID encoding: ${did}`);
|
|
602
835
|
}
|
|
603
|
-
function
|
|
836
|
+
function base64urlEncode2(bytes) {
|
|
604
837
|
let b64;
|
|
605
838
|
if (typeof Buffer !== "undefined") {
|
|
606
839
|
b64 = Buffer.from(bytes).toString("base64");
|
|
@@ -625,6 +858,8 @@ function base64urlDecode(input) {
|
|
|
625
858
|
// src/provenance.ts
|
|
626
859
|
var _jwksCache = /* @__PURE__ */ new Map();
|
|
627
860
|
var JWKS_TTL_MS = 5 * 60 * 1e3;
|
|
861
|
+
var JWKS_MAX_BYTES = 64 * 1024;
|
|
862
|
+
var JWKS_CACHE_MAX_ENTRIES = 32;
|
|
628
863
|
var DEFAULT_VERIFY_AT_ALLOWLIST = Object.freeze([
|
|
629
864
|
"api.truealter.com",
|
|
630
865
|
"mcp.truealter.com"
|
|
@@ -734,7 +969,8 @@ async function fetchPublicKeys(jwksUrl, fetchImpl = fetch) {
|
|
|
734
969
|
return fetchJwks(jwksUrl, fetchImpl);
|
|
735
970
|
}
|
|
736
971
|
async function fetchJwks(url, fetchImpl) {
|
|
737
|
-
const
|
|
972
|
+
const cacheKey = jwksCacheKey(url);
|
|
973
|
+
const cached = _jwksCache.get(cacheKey);
|
|
738
974
|
if (cached && Date.now() - cached.fetched < JWKS_TTL_MS) return cached.jwks;
|
|
739
975
|
let resp;
|
|
740
976
|
try {
|
|
@@ -751,13 +987,45 @@ async function fetchJwks(url, fetchImpl) {
|
|
|
751
987
|
);
|
|
752
988
|
}
|
|
753
989
|
if (!resp.ok) throw new AlterNetworkError(`${url} \u2192 HTTP ${resp.status}`);
|
|
754
|
-
const
|
|
990
|
+
const contentLength = resp.headers.get("content-length");
|
|
991
|
+
if (contentLength !== null) {
|
|
992
|
+
const n = Number.parseInt(contentLength, 10);
|
|
993
|
+
if (Number.isFinite(n) && n > JWKS_MAX_BYTES) {
|
|
994
|
+
throw new AlterProvenanceError(
|
|
995
|
+
`${url} \u2192 JWKS too large: ${n} > ${JWKS_MAX_BYTES} bytes`
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
const body = await resp.text();
|
|
1000
|
+
if (body.length > JWKS_MAX_BYTES) {
|
|
1001
|
+
throw new AlterProvenanceError(
|
|
1002
|
+
`${url} \u2192 JWKS too large: ${body.length} > ${JWKS_MAX_BYTES} bytes`
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
let doc;
|
|
1006
|
+
try {
|
|
1007
|
+
doc = JSON.parse(body);
|
|
1008
|
+
} catch (err) {
|
|
1009
|
+
throw new AlterProvenanceError(`invalid JWKS at ${url}: ${err.message}`);
|
|
1010
|
+
}
|
|
755
1011
|
if (!doc || !Array.isArray(doc.keys)) {
|
|
756
1012
|
throw new AlterProvenanceError(`invalid JWKS at ${url}`);
|
|
757
1013
|
}
|
|
758
|
-
_jwksCache.
|
|
1014
|
+
if (_jwksCache.size >= JWKS_CACHE_MAX_ENTRIES && !_jwksCache.has(cacheKey)) {
|
|
1015
|
+
const oldest = _jwksCache.keys().next().value;
|
|
1016
|
+
if (oldest !== void 0) _jwksCache.delete(oldest);
|
|
1017
|
+
}
|
|
1018
|
+
_jwksCache.set(cacheKey, { fetched: Date.now(), jwks: doc });
|
|
759
1019
|
return doc;
|
|
760
1020
|
}
|
|
1021
|
+
function jwksCacheKey(url) {
|
|
1022
|
+
try {
|
|
1023
|
+
const parsed = new URL(url);
|
|
1024
|
+
return `${parsed.origin}${parsed.pathname}`;
|
|
1025
|
+
} catch {
|
|
1026
|
+
return url;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
761
1029
|
function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
762
1030
|
if (typeof verifyAt !== "string" || verifyAt.length === 0) {
|
|
763
1031
|
throw new Error("verify_at must be a non-empty string");
|
|
@@ -780,6 +1048,9 @@ function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
|
780
1048
|
if (parsed.protocol !== "https:") {
|
|
781
1049
|
throw new Error(`verify_at must be https: ${verifyAt}`);
|
|
782
1050
|
}
|
|
1051
|
+
if (parsed.username || parsed.password) {
|
|
1052
|
+
throw new Error(`verify_at must not contain userinfo: ${verifyAt}`);
|
|
1053
|
+
}
|
|
783
1054
|
const host = parsed.hostname.toLowerCase();
|
|
784
1055
|
const allowed = allowlist.some((h) => h.toLowerCase() === host);
|
|
785
1056
|
if (!allowed) {
|
|
@@ -860,6 +1131,15 @@ var AlterClient = class {
|
|
|
860
1131
|
await this.mcp.initialize();
|
|
861
1132
|
}
|
|
862
1133
|
// ── Free tier ────────────────────────────────────────────────────────
|
|
1134
|
+
/** First handshake — confirms the connection, returns trust tier and tool counts. */
|
|
1135
|
+
async helloAgent() {
|
|
1136
|
+
return this.mcp.callTool("hello_agent", {});
|
|
1137
|
+
}
|
|
1138
|
+
/** Resolve a ~handle (e.g. ~drew) to its canonical form and kind. No auth required. */
|
|
1139
|
+
async resolveHandle(args) {
|
|
1140
|
+
const payload = typeof args === "string" ? { query: args } : args;
|
|
1141
|
+
return this.mcp.callTool("alter_resolve_handle", payload);
|
|
1142
|
+
}
|
|
863
1143
|
/** Verify a person is registered with ALTER (handle or id). */
|
|
864
1144
|
async verify(handleOrId, claims) {
|
|
865
1145
|
const args = handleOrId.includes("@") ? { candidate_id: "", email: handleOrId } : handleOrId.startsWith("~") ? (
|
|
@@ -896,12 +1176,6 @@ var AlterClient = class {
|
|
|
896
1176
|
async getCompetencies(args) {
|
|
897
1177
|
return this.mcp.callTool("get_competencies", args);
|
|
898
1178
|
}
|
|
899
|
-
async createIdentityStub(args) {
|
|
900
|
-
return this.mcp.callTool("create_identity_stub", args);
|
|
901
|
-
}
|
|
902
|
-
async submitContext(args) {
|
|
903
|
-
return this.mcp.callTool("submit_context", args);
|
|
904
|
-
}
|
|
905
1179
|
async searchIdentities(args) {
|
|
906
1180
|
return this.mcp.callTool("search_identities", args);
|
|
907
1181
|
}
|
|
@@ -926,9 +1200,6 @@ var AlterClient = class {
|
|
|
926
1200
|
async getPrivacyBudget(args) {
|
|
927
1201
|
return this.mcp.callTool("get_privacy_budget", args);
|
|
928
1202
|
}
|
|
929
|
-
async disputeAttestation(args) {
|
|
930
|
-
return this.mcp.callTool("dispute_attestation", args);
|
|
931
|
-
}
|
|
932
1203
|
// ── Golden Thread ────────────────────────────────────────────────────
|
|
933
1204
|
async goldenThreadStatus() {
|
|
934
1205
|
return this.mcp.callTool("golden_thread_status", {});
|
|
@@ -964,18 +1235,6 @@ var AlterClient = class {
|
|
|
964
1235
|
async generateMatchNarrative(args, opts) {
|
|
965
1236
|
return this.mcp.callTool("generate_match_narrative", args, opts);
|
|
966
1237
|
}
|
|
967
|
-
async submitBatchContext(args, opts) {
|
|
968
|
-
return this.mcp.callTool("submit_batch_context", args, opts);
|
|
969
|
-
}
|
|
970
|
-
async submitStructuredProfile(args, opts) {
|
|
971
|
-
return this.mcp.callTool("submit_structured_profile", args, opts);
|
|
972
|
-
}
|
|
973
|
-
async submitSocialLinks(args, opts) {
|
|
974
|
-
return this.mcp.callTool("submit_social_links", args, opts);
|
|
975
|
-
}
|
|
976
|
-
async attestDomain(args, opts) {
|
|
977
|
-
return this.mcp.callTool("attest_domain", args, opts);
|
|
978
|
-
}
|
|
979
1238
|
async getSideQuestGraph(args, opts) {
|
|
980
1239
|
return this.mcp.callTool("get_side_quest_graph", args, opts);
|
|
981
1240
|
}
|
|
@@ -1043,7 +1302,14 @@ var AlterClient = class {
|
|
|
1043
1302
|
}
|
|
1044
1303
|
};
|
|
1045
1304
|
|
|
1305
|
+
// src/index.ts
|
|
1306
|
+
init_signing();
|
|
1307
|
+
|
|
1308
|
+
// src/adapters/claude-code.ts
|
|
1309
|
+
init_cjs_shims();
|
|
1310
|
+
|
|
1046
1311
|
// src/adapters/generic-mcp.ts
|
|
1312
|
+
init_cjs_shims();
|
|
1047
1313
|
function generateGenericMcpConfig(opts = {}) {
|
|
1048
1314
|
const serverName = opts.serverName ?? "alter";
|
|
1049
1315
|
const headers = { ...opts.headers ?? {} };
|
|
@@ -1063,12 +1329,491 @@ function generateClaudeConfig(opts = {}) {
|
|
|
1063
1329
|
}
|
|
1064
1330
|
|
|
1065
1331
|
// src/adapters/cursor.ts
|
|
1332
|
+
init_cjs_shims();
|
|
1066
1333
|
function generateCursorConfig(opts = {}) {
|
|
1067
1334
|
return generateGenericMcpConfig({ serverName: "alter", ...opts });
|
|
1068
1335
|
}
|
|
1069
1336
|
|
|
1337
|
+
// src/adapters/claude-desktop.ts
|
|
1338
|
+
init_cjs_shims();
|
|
1339
|
+
function generateClaudeDesktopConfig(opts = {}) {
|
|
1340
|
+
const serverName = opts.serverName ?? "alter";
|
|
1341
|
+
const bridgeCommand = opts.bridgeCommand ?? "alter-mcp-bridge";
|
|
1342
|
+
const env2 = {};
|
|
1343
|
+
env2.ALTER_MCP_ENDPOINT = opts.endpoint ?? DEFAULT_ENDPOINT;
|
|
1344
|
+
if (opts.apiKey) env2.ALTER_API_KEY = opts.apiKey;
|
|
1345
|
+
const entry = {
|
|
1346
|
+
command: bridgeCommand,
|
|
1347
|
+
env: env2,
|
|
1348
|
+
description: "ALTER Identity \u2014 psychometric identity field for AI agents"
|
|
1349
|
+
};
|
|
1350
|
+
if (opts.extraArgs && opts.extraArgs.length > 0) {
|
|
1351
|
+
entry.args = [...opts.extraArgs];
|
|
1352
|
+
}
|
|
1353
|
+
return { mcpServers: { [serverName]: entry } };
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// src/wire/index.ts
|
|
1357
|
+
init_cjs_shims();
|
|
1358
|
+
|
|
1359
|
+
// src/meta.ts
|
|
1360
|
+
init_cjs_shims();
|
|
1361
|
+
var SDK_NAME = "@truealter/sdk";
|
|
1362
|
+
var SDK_VERSION = "0.3.0";
|
|
1363
|
+
|
|
1364
|
+
// src/wire/paths.ts
|
|
1365
|
+
init_cjs_shims();
|
|
1366
|
+
var HOME = os.homedir();
|
|
1367
|
+
var PLAT = os.platform();
|
|
1368
|
+
function appData() {
|
|
1369
|
+
return process$1.env.APPDATA ?? path.join(HOME, "AppData", "Roaming");
|
|
1370
|
+
}
|
|
1371
|
+
function xdgConfig() {
|
|
1372
|
+
return process$1.env.XDG_CONFIG_HOME ?? path.join(HOME, ".config");
|
|
1373
|
+
}
|
|
1374
|
+
function macAppSupport() {
|
|
1375
|
+
return path.join(HOME, "Library", "Application Support");
|
|
1376
|
+
}
|
|
1377
|
+
function claudeDesktopConfigPath() {
|
|
1378
|
+
if (PLAT === "darwin") return path.join(macAppSupport(), "Claude", "claude_desktop_config.json");
|
|
1379
|
+
if (PLAT === "win32") return path.join(appData(), "Claude", "claude_desktop_config.json");
|
|
1380
|
+
return path.join(xdgConfig(), "Claude", "claude_desktop_config.json");
|
|
1381
|
+
}
|
|
1382
|
+
function claudeDesktopDir() {
|
|
1383
|
+
if (PLAT === "darwin") return path.join(macAppSupport(), "Claude");
|
|
1384
|
+
if (PLAT === "win32") return path.join(appData(), "Claude");
|
|
1385
|
+
return path.join(xdgConfig(), "Claude");
|
|
1386
|
+
}
|
|
1387
|
+
function vscodeConfigPath() {
|
|
1388
|
+
if (PLAT === "darwin") return path.join(macAppSupport(), "Code", "User", "mcp.json");
|
|
1389
|
+
if (PLAT === "win32") return path.join(appData(), "Code", "User", "mcp.json");
|
|
1390
|
+
return path.join(xdgConfig(), "Code", "User", "mcp.json");
|
|
1391
|
+
}
|
|
1392
|
+
function vscodeDir() {
|
|
1393
|
+
if (PLAT === "darwin") return path.join(macAppSupport(), "Code", "User");
|
|
1394
|
+
if (PLAT === "win32") return path.join(appData(), "Code", "User");
|
|
1395
|
+
return path.join(xdgConfig(), "Code", "User");
|
|
1396
|
+
}
|
|
1397
|
+
var cursorDir = path.join(HOME, ".cursor");
|
|
1398
|
+
var cursorConfigPath = path.join(cursorDir, "mcp.json");
|
|
1399
|
+
var claudeCodeProbeDir = path.join(HOME, ".claude");
|
|
1400
|
+
var CLAUDE_CODE = {
|
|
1401
|
+
id: "claude-code",
|
|
1402
|
+
label: "Claude Code",
|
|
1403
|
+
configPath: null,
|
|
1404
|
+
probeDir: claudeCodeProbeDir,
|
|
1405
|
+
rootKey: "mcpServers"
|
|
1406
|
+
};
|
|
1407
|
+
var CURSOR = {
|
|
1408
|
+
id: "cursor",
|
|
1409
|
+
label: "Cursor",
|
|
1410
|
+
configPath: cursorConfigPath,
|
|
1411
|
+
probeDir: cursorDir,
|
|
1412
|
+
rootKey: "mcpServers"
|
|
1413
|
+
};
|
|
1414
|
+
var CLAUDE_DESKTOP = {
|
|
1415
|
+
id: "claude-desktop",
|
|
1416
|
+
label: "Claude Desktop",
|
|
1417
|
+
configPath: claudeDesktopConfigPath(),
|
|
1418
|
+
probeDir: claudeDesktopDir(),
|
|
1419
|
+
rootKey: "mcpServers"
|
|
1420
|
+
};
|
|
1421
|
+
var VSCODE = {
|
|
1422
|
+
id: "vscode",
|
|
1423
|
+
label: "VS Code",
|
|
1424
|
+
configPath: vscodeConfigPath(),
|
|
1425
|
+
probeDir: vscodeDir(),
|
|
1426
|
+
// VS Code's user-scoped mcp.json uses `servers`, not `mcpServers`.
|
|
1427
|
+
rootKey: "servers"
|
|
1428
|
+
};
|
|
1429
|
+
var ALL_CLIENTS = [CLAUDE_CODE, CURSOR, CLAUDE_DESKTOP, VSCODE];
|
|
1430
|
+
function alterConfigDir() {
|
|
1431
|
+
return path.join(xdgConfig(), "alter");
|
|
1432
|
+
}
|
|
1433
|
+
function wireStatePath() {
|
|
1434
|
+
return path.join(alterConfigDir(), "wire-state.json");
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
// src/wire/probe.ts
|
|
1438
|
+
init_cjs_shims();
|
|
1439
|
+
function probeClaudeCode() {
|
|
1440
|
+
try {
|
|
1441
|
+
const result = child_process.spawnSync("claude", ["--version"], {
|
|
1442
|
+
encoding: "utf8",
|
|
1443
|
+
shell: process.platform === "win32",
|
|
1444
|
+
timeout: 5e3
|
|
1445
|
+
});
|
|
1446
|
+
if (result.error) {
|
|
1447
|
+
return {
|
|
1448
|
+
client: ALL_CLIENTS.find((c) => c.id === "claude-code"),
|
|
1449
|
+
installed: false,
|
|
1450
|
+
reason: `claude binary not on PATH (${result.error.message})`
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
if (result.status === 0) {
|
|
1454
|
+
return {
|
|
1455
|
+
client: ALL_CLIENTS.find((c) => c.id === "claude-code"),
|
|
1456
|
+
installed: true,
|
|
1457
|
+
version: result.stdout.trim() || void 0,
|
|
1458
|
+
reason: "claude --version returned 0"
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
client: ALL_CLIENTS.find((c) => c.id === "claude-code"),
|
|
1463
|
+
installed: false,
|
|
1464
|
+
reason: `claude --version exited ${String(result.status)}`
|
|
1465
|
+
};
|
|
1466
|
+
} catch (err) {
|
|
1467
|
+
return {
|
|
1468
|
+
client: ALL_CLIENTS.find((c) => c.id === "claude-code"),
|
|
1469
|
+
installed: false,
|
|
1470
|
+
reason: err.message
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
function probeByDir(id) {
|
|
1475
|
+
const client = ALL_CLIENTS.find((c) => c.id === id);
|
|
1476
|
+
if (!client) throw new Error(`unknown client id: ${id}`);
|
|
1477
|
+
const installed = fs.existsSync(client.probeDir);
|
|
1478
|
+
return {
|
|
1479
|
+
client,
|
|
1480
|
+
installed,
|
|
1481
|
+
reason: installed ? `found ${client.probeDir}` : `no directory at ${client.probeDir}`
|
|
1482
|
+
};
|
|
1483
|
+
}
|
|
1484
|
+
function probeAll() {
|
|
1485
|
+
return [
|
|
1486
|
+
probeClaudeCode(),
|
|
1487
|
+
probeByDir("cursor"),
|
|
1488
|
+
probeByDir("claude-desktop"),
|
|
1489
|
+
probeByDir("vscode")
|
|
1490
|
+
];
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// src/wire/sync.ts
|
|
1494
|
+
init_cjs_shims();
|
|
1495
|
+
var SYNC_PREFIXES = [
|
|
1496
|
+
// iCloud Drive — both the new and legacy mounts.
|
|
1497
|
+
"Library/Mobile Documents/com~apple~CloudDocs",
|
|
1498
|
+
"iCloud Drive",
|
|
1499
|
+
// OneDrive variants Microsoft ships across editions.
|
|
1500
|
+
"OneDrive",
|
|
1501
|
+
"OneDrive - ",
|
|
1502
|
+
// Dropbox standard + enterprise mounts.
|
|
1503
|
+
"Dropbox",
|
|
1504
|
+
"Dropbox (",
|
|
1505
|
+
// Google Drive (ALTER does not integrate with Google; still refuse).
|
|
1506
|
+
"Google Drive",
|
|
1507
|
+
"GoogleDrive",
|
|
1508
|
+
"CloudStorage/GoogleDrive",
|
|
1509
|
+
// Box, pCloud, Sync.com, MEGA — high-signal names worth refusing.
|
|
1510
|
+
"Box Sync",
|
|
1511
|
+
"pCloud Drive",
|
|
1512
|
+
"Sync.com",
|
|
1513
|
+
"MEGAsync"
|
|
1514
|
+
];
|
|
1515
|
+
function detectSyncedVolume(path$1) {
|
|
1516
|
+
const absolute = path.resolve(path$1);
|
|
1517
|
+
const normalised = os.platform() === "win32" ? absolute.replace(/\\/g, "/") : absolute;
|
|
1518
|
+
for (const prefix of SYNC_PREFIXES) {
|
|
1519
|
+
if (normalised.includes(`/${prefix}/`) || normalised.includes(`/${prefix}`)) {
|
|
1520
|
+
return { refused: true, matchedPrefix: prefix, resolvedPath: absolute };
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
return null;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
// src/wire/state.ts
|
|
1527
|
+
init_cjs_shims();
|
|
1528
|
+
var WIRE_STATE_VERSION = 1;
|
|
1529
|
+
function readWireState() {
|
|
1530
|
+
const path = wireStatePath();
|
|
1531
|
+
if (!fs.existsSync(path)) return null;
|
|
1532
|
+
try {
|
|
1533
|
+
const parsed = JSON.parse(fs.readFileSync(path, "utf8"));
|
|
1534
|
+
if (parsed.version !== WIRE_STATE_VERSION) {
|
|
1535
|
+
throw new Error(
|
|
1536
|
+
`wire-state.json version ${String(parsed.version)} is not supported by this SDK (expected ${WIRE_STATE_VERSION})`
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
return parsed;
|
|
1540
|
+
} catch (err) {
|
|
1541
|
+
throw new Error(`failed to parse wire-state.json: ${err.message}`);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
function writeWireState(state) {
|
|
1545
|
+
const path$1 = wireStatePath();
|
|
1546
|
+
fs.mkdirSync(path.dirname(path$1), { recursive: true, mode: 448 });
|
|
1547
|
+
fs.writeFileSync(path$1, JSON.stringify(state, null, 2) + "\n", { mode: 384 });
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
// src/wire/write.ts
|
|
1551
|
+
init_cjs_shims();
|
|
1552
|
+
function sha2562(bytes) {
|
|
1553
|
+
return crypto$1.createHash("sha256").update(bytes).digest("hex");
|
|
1554
|
+
}
|
|
1555
|
+
function atomicJsonMerge(opts) {
|
|
1556
|
+
const { path: path$1, timestamp, merge, idempotent = true } = opts;
|
|
1557
|
+
const tmpPath = `${path$1}.alter-tmp-${timestamp}`;
|
|
1558
|
+
const backupPath = `${path$1}.alter-backup-${timestamp}`;
|
|
1559
|
+
let existed = false;
|
|
1560
|
+
let preBytes = null;
|
|
1561
|
+
let parsed = {};
|
|
1562
|
+
if (fs.existsSync(path$1)) {
|
|
1563
|
+
existed = true;
|
|
1564
|
+
preBytes = fs.readFileSync(path$1, "utf8");
|
|
1565
|
+
if (preBytes.trim().length > 0) {
|
|
1566
|
+
try {
|
|
1567
|
+
parsed = JSON.parse(preBytes);
|
|
1568
|
+
} catch (err) {
|
|
1569
|
+
throw new Error(
|
|
1570
|
+
`refusing to wire ${path$1}: existing file is not valid JSON (${err.message}). Hand-fix the file, then re-run \`alter-identity wire\`.`
|
|
1571
|
+
);
|
|
1572
|
+
}
|
|
1573
|
+
if (typeof parsed !== "object" || Array.isArray(parsed) || parsed === null) {
|
|
1574
|
+
throw new Error(`refusing to wire ${path$1}: existing JSON root is not an object`);
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
const merged = merge(parsed);
|
|
1579
|
+
const serialised = JSON.stringify(merged, null, 2) + "\n";
|
|
1580
|
+
if (idempotent && preBytes !== null && preBytes === serialised) {
|
|
1581
|
+
return {
|
|
1582
|
+
path: path$1,
|
|
1583
|
+
backupPath: null,
|
|
1584
|
+
preSha256: sha2562(preBytes),
|
|
1585
|
+
postSha256: sha2562(preBytes),
|
|
1586
|
+
noop: true
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1589
|
+
fs.mkdirSync(path.dirname(path$1), { recursive: true });
|
|
1590
|
+
fs.writeFileSync(tmpPath, serialised, { mode: 384 });
|
|
1591
|
+
try {
|
|
1592
|
+
if (existed) fs.copyFileSync(path$1, backupPath);
|
|
1593
|
+
fs.renameSync(tmpPath, path$1);
|
|
1594
|
+
} catch (err) {
|
|
1595
|
+
try {
|
|
1596
|
+
fs.unlinkSync(tmpPath);
|
|
1597
|
+
} catch {
|
|
1598
|
+
}
|
|
1599
|
+
throw err;
|
|
1600
|
+
}
|
|
1601
|
+
return {
|
|
1602
|
+
path: path$1,
|
|
1603
|
+
backupPath: existed ? backupPath : null,
|
|
1604
|
+
preSha256: preBytes === null ? null : sha2562(preBytes),
|
|
1605
|
+
postSha256: sha2562(serialised),
|
|
1606
|
+
noop: false
|
|
1607
|
+
};
|
|
1608
|
+
}
|
|
1609
|
+
function restoreFromBackup(path, backupPath) {
|
|
1610
|
+
if (backupPath === null) {
|
|
1611
|
+
if (fs.existsSync(path)) fs.unlinkSync(path);
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
if (!fs.existsSync(backupPath)) {
|
|
1615
|
+
throw new Error(`cannot restore ${path}: backup missing at ${backupPath}`);
|
|
1616
|
+
}
|
|
1617
|
+
fs.renameSync(backupPath, path);
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
// src/wire/index.ts
|
|
1621
|
+
var TIMESTAMP = () => String(Math.floor(Date.now() / 1e3));
|
|
1622
|
+
var ISO_NOW = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
1623
|
+
function clientById(id) {
|
|
1624
|
+
const hit = ALL_CLIENTS.find((c) => c.id === id);
|
|
1625
|
+
if (!hit) throw new Error(`unknown client id: ${id}`);
|
|
1626
|
+
return hit;
|
|
1627
|
+
}
|
|
1628
|
+
function wire(opts = {}) {
|
|
1629
|
+
const endpoint = opts.endpoint ?? DEFAULT_ENDPOINT;
|
|
1630
|
+
const apiKey = opts.apiKey;
|
|
1631
|
+
const probes = probeAll();
|
|
1632
|
+
const selection = opts.only ?? probes.filter((p) => p.installed).map((p) => p.client.id);
|
|
1633
|
+
const ts = TIMESTAMP();
|
|
1634
|
+
const targets = [];
|
|
1635
|
+
for (const id of selection) {
|
|
1636
|
+
const probe = id === "claude-code" ? probeClaudeCode() : probeByDir(id);
|
|
1637
|
+
if (!probe.installed && opts.skipMissing !== false) {
|
|
1638
|
+
targets.push({
|
|
1639
|
+
client: id,
|
|
1640
|
+
method: id === "claude-code" ? "cli" : "file",
|
|
1641
|
+
status: "skipped",
|
|
1642
|
+
...id === "claude-code" ? { command: "" } : { path: clientById(id).configPath ?? "", backupPath: null, rootKey: clientById(id).rootKey, serverName: "alter", preSha256: null, postSha256: "" },
|
|
1643
|
+
reason: probe.reason
|
|
1644
|
+
});
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
try {
|
|
1648
|
+
if (id === "claude-code") {
|
|
1649
|
+
targets.push(wireClaudeCode({ endpoint, apiKey }));
|
|
1650
|
+
} else {
|
|
1651
|
+
targets.push(wireFileTarget({ id, endpoint, apiKey, timestamp: ts }));
|
|
1652
|
+
}
|
|
1653
|
+
} catch (err) {
|
|
1654
|
+
const message = err.message;
|
|
1655
|
+
targets.push({
|
|
1656
|
+
client: id,
|
|
1657
|
+
method: id === "claude-code" ? "cli" : "file",
|
|
1658
|
+
status: "failed",
|
|
1659
|
+
...id === "claude-code" ? { command: "" } : { path: clientById(id).configPath ?? "", backupPath: null, rootKey: clientById(id).rootKey, serverName: "alter", preSha256: null, postSha256: "" },
|
|
1660
|
+
reason: message
|
|
1661
|
+
});
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
const state = {
|
|
1665
|
+
version: 1,
|
|
1666
|
+
sdkVersion: SDK_VERSION,
|
|
1667
|
+
writtenAt: ISO_NOW(),
|
|
1668
|
+
endpoint,
|
|
1669
|
+
targets
|
|
1670
|
+
};
|
|
1671
|
+
writeWireState(state);
|
|
1672
|
+
return { state, probes };
|
|
1673
|
+
}
|
|
1674
|
+
function wireFileTarget(args) {
|
|
1675
|
+
const client = clientById(args.id);
|
|
1676
|
+
if (!client.configPath) {
|
|
1677
|
+
throw new Error(`client ${client.id} has no file-based config path`);
|
|
1678
|
+
}
|
|
1679
|
+
const sync = detectSyncedVolume(client.configPath);
|
|
1680
|
+
if (sync) {
|
|
1681
|
+
throw new Error(
|
|
1682
|
+
`refusing to wire ${client.label}: config path ${sync.resolvedPath} lives under ${sync.matchedPrefix}. Synced volumes propagate credentials across devices \u2014 move the config off the sync root, or run wire on the device you want to target.`
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
const entry = args.id === "claude-desktop" ? generateClaudeDesktopConfig({ endpoint: args.endpoint, apiKey: args.apiKey }) : generateGenericMcpConfig({ endpoint: args.endpoint, apiKey: args.apiKey });
|
|
1686
|
+
const rootKey = client.rootKey;
|
|
1687
|
+
const serverName = "alter";
|
|
1688
|
+
const result = atomicJsonMerge({
|
|
1689
|
+
path: client.configPath,
|
|
1690
|
+
timestamp: args.timestamp,
|
|
1691
|
+
merge: (existing) => {
|
|
1692
|
+
const bucket = existing[rootKey] ?? {};
|
|
1693
|
+
const source = entry.mcpServers.alter;
|
|
1694
|
+
return {
|
|
1695
|
+
...existing,
|
|
1696
|
+
[rootKey]: {
|
|
1697
|
+
...bucket,
|
|
1698
|
+
[serverName]: source
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
});
|
|
1703
|
+
return {
|
|
1704
|
+
client: args.id,
|
|
1705
|
+
method: "file",
|
|
1706
|
+
status: result.noop ? "already-wired" : "written",
|
|
1707
|
+
path: result.path,
|
|
1708
|
+
backupPath: result.backupPath,
|
|
1709
|
+
rootKey,
|
|
1710
|
+
serverName,
|
|
1711
|
+
preSha256: result.preSha256,
|
|
1712
|
+
postSha256: result.postSha256
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
function wireClaudeCode(args) {
|
|
1716
|
+
const cmd = "claude";
|
|
1717
|
+
const argList = [
|
|
1718
|
+
"mcp",
|
|
1719
|
+
"add",
|
|
1720
|
+
"--scope",
|
|
1721
|
+
"user",
|
|
1722
|
+
"--transport",
|
|
1723
|
+
"http",
|
|
1724
|
+
"alter",
|
|
1725
|
+
args.endpoint
|
|
1726
|
+
];
|
|
1727
|
+
if (args.apiKey) {
|
|
1728
|
+
argList.push("--header", `X-ALTER-API-Key:${args.apiKey}`);
|
|
1729
|
+
}
|
|
1730
|
+
const full = `${cmd} ${argList.join(" ")}`;
|
|
1731
|
+
const run = child_process.spawnSync(cmd, argList, {
|
|
1732
|
+
encoding: "utf8",
|
|
1733
|
+
shell: process.platform === "win32",
|
|
1734
|
+
timeout: 1e4
|
|
1735
|
+
});
|
|
1736
|
+
if (run.error) {
|
|
1737
|
+
return {
|
|
1738
|
+
client: "claude-code",
|
|
1739
|
+
method: "cli",
|
|
1740
|
+
status: "failed",
|
|
1741
|
+
command: full,
|
|
1742
|
+
stdout: run.stdout,
|
|
1743
|
+
stderr: run.stderr,
|
|
1744
|
+
reason: run.error.message
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1747
|
+
const stderr = (run.stderr ?? "").toLowerCase();
|
|
1748
|
+
const alreadyExists = stderr.includes("already exists") || stderr.includes("already configured");
|
|
1749
|
+
if (run.status === 0) {
|
|
1750
|
+
return { client: "claude-code", method: "cli", status: "written", command: full, stdout: run.stdout, stderr: run.stderr };
|
|
1751
|
+
}
|
|
1752
|
+
if (alreadyExists) {
|
|
1753
|
+
return { client: "claude-code", method: "cli", status: "already-wired", command: full, stdout: run.stdout, stderr: run.stderr };
|
|
1754
|
+
}
|
|
1755
|
+
return {
|
|
1756
|
+
client: "claude-code",
|
|
1757
|
+
method: "cli",
|
|
1758
|
+
status: "failed",
|
|
1759
|
+
command: full,
|
|
1760
|
+
stdout: run.stdout,
|
|
1761
|
+
stderr: run.stderr,
|
|
1762
|
+
reason: `claude mcp add exited ${String(run.status)}`
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
function unwire() {
|
|
1766
|
+
const state = readWireState();
|
|
1767
|
+
const undone = [];
|
|
1768
|
+
if (!state || state.targets.length === 0) {
|
|
1769
|
+
return { state, undone };
|
|
1770
|
+
}
|
|
1771
|
+
for (const target of state.targets) {
|
|
1772
|
+
try {
|
|
1773
|
+
if (target.method === "file") {
|
|
1774
|
+
if (target.status === "written") {
|
|
1775
|
+
restoreFromBackup(target.path, target.backupPath);
|
|
1776
|
+
undone.push({ client: target.client, action: target.backupPath ? "restored" : "removed" });
|
|
1777
|
+
} else {
|
|
1778
|
+
undone.push({ client: target.client, action: "skipped", reason: `target status was ${target.status}` });
|
|
1779
|
+
}
|
|
1780
|
+
} else if (target.method === "cli") {
|
|
1781
|
+
if (target.status === "written") {
|
|
1782
|
+
const run = child_process.spawnSync("claude", ["mcp", "remove", "--scope", "user", "alter"], {
|
|
1783
|
+
encoding: "utf8",
|
|
1784
|
+
shell: process.platform === "win32",
|
|
1785
|
+
timeout: 1e4
|
|
1786
|
+
});
|
|
1787
|
+
if (run.error) {
|
|
1788
|
+
undone.push({ client: target.client, action: "failed", reason: run.error.message });
|
|
1789
|
+
} else if (run.status === 0) {
|
|
1790
|
+
undone.push({ client: target.client, action: "cli-removed" });
|
|
1791
|
+
} else {
|
|
1792
|
+
undone.push({ client: target.client, action: "failed", reason: `claude mcp remove exited ${String(run.status)}` });
|
|
1793
|
+
}
|
|
1794
|
+
} else {
|
|
1795
|
+
undone.push({ client: target.client, action: "skipped", reason: `target status was ${target.status}` });
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
} catch (err) {
|
|
1799
|
+
undone.push({ client: target.client, action: "failed", reason: err.message });
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
writeWireState({
|
|
1803
|
+
version: 1,
|
|
1804
|
+
sdkVersion: state.sdkVersion,
|
|
1805
|
+
writtenAt: ISO_NOW(),
|
|
1806
|
+
endpoint: state.endpoint,
|
|
1807
|
+
targets: []
|
|
1808
|
+
});
|
|
1809
|
+
return { state, undone };
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1070
1812
|
// src/types.ts
|
|
1813
|
+
init_cjs_shims();
|
|
1071
1814
|
var FREE_TOOL_NAMES = [
|
|
1815
|
+
"hello_agent",
|
|
1816
|
+
"alter_resolve_handle",
|
|
1072
1817
|
"list_archetypes",
|
|
1073
1818
|
"verify_identity",
|
|
1074
1819
|
"initiate_assessment",
|
|
@@ -1076,8 +1821,6 @@ var FREE_TOOL_NAMES = [
|
|
|
1076
1821
|
"get_profile",
|
|
1077
1822
|
"query_matches",
|
|
1078
1823
|
"get_competencies",
|
|
1079
|
-
"create_identity_stub",
|
|
1080
|
-
"submit_context",
|
|
1081
1824
|
"search_identities",
|
|
1082
1825
|
"get_identity_earnings",
|
|
1083
1826
|
"get_network_stats",
|
|
@@ -1088,7 +1831,6 @@ var FREE_TOOL_NAMES = [
|
|
|
1088
1831
|
"get_agent_trust_tier",
|
|
1089
1832
|
"get_agent_portfolio",
|
|
1090
1833
|
"get_privacy_budget",
|
|
1091
|
-
"dispute_attestation",
|
|
1092
1834
|
"golden_thread_status",
|
|
1093
1835
|
"begin_golden_thread",
|
|
1094
1836
|
"complete_knot",
|
|
@@ -1102,15 +1844,13 @@ var PREMIUM_TOOL_NAMES = [
|
|
|
1102
1844
|
"compute_belonging",
|
|
1103
1845
|
"get_match_recommendations",
|
|
1104
1846
|
"generate_match_narrative",
|
|
1105
|
-
"submit_batch_context",
|
|
1106
|
-
"submit_structured_profile",
|
|
1107
|
-
"submit_social_links",
|
|
1108
|
-
"attest_domain",
|
|
1109
1847
|
"get_side_quest_graph",
|
|
1110
1848
|
"query_graph_similarity"
|
|
1111
1849
|
];
|
|
1112
1850
|
var TOOL_TIERS = {
|
|
1113
1851
|
// L0 (free)
|
|
1852
|
+
hello_agent: 0,
|
|
1853
|
+
alter_resolve_handle: 0,
|
|
1114
1854
|
list_archetypes: 0,
|
|
1115
1855
|
verify_identity: 0,
|
|
1116
1856
|
initiate_assessment: 0,
|
|
@@ -1118,9 +1858,7 @@ var TOOL_TIERS = {
|
|
|
1118
1858
|
get_profile: 0,
|
|
1119
1859
|
query_matches: 0,
|
|
1120
1860
|
get_competencies: 0,
|
|
1121
|
-
|
|
1122
|
-
submit_context: 1,
|
|
1123
|
-
search_identities: 1,
|
|
1861
|
+
search_identities: 0,
|
|
1124
1862
|
get_identity_earnings: 0,
|
|
1125
1863
|
get_network_stats: 0,
|
|
1126
1864
|
recommend_tool: 0,
|
|
@@ -1128,8 +1866,6 @@ var TOOL_TIERS = {
|
|
|
1128
1866
|
check_assessment_status: 0,
|
|
1129
1867
|
get_earning_summary: 0,
|
|
1130
1868
|
get_privacy_budget: 0,
|
|
1131
|
-
dispute_attestation: 0,
|
|
1132
|
-
// Free tools not present in upstream TOOL_TIERS — default to 0
|
|
1133
1869
|
get_agent_trust_tier: 0,
|
|
1134
1870
|
get_agent_portfolio: 0,
|
|
1135
1871
|
golden_thread_status: 0,
|
|
@@ -1140,12 +1876,8 @@ var TOOL_TIERS = {
|
|
|
1140
1876
|
// L1
|
|
1141
1877
|
assess_traits: 1,
|
|
1142
1878
|
get_trait_snapshot: 1,
|
|
1143
|
-
submit_structured_profile: 1,
|
|
1144
|
-
submit_social_links: 1,
|
|
1145
|
-
attest_domain: 1,
|
|
1146
1879
|
// L2
|
|
1147
1880
|
get_full_trait_vector: 2,
|
|
1148
|
-
submit_batch_context: 2,
|
|
1149
1881
|
get_side_quest_graph: 2,
|
|
1150
1882
|
// L3
|
|
1151
1883
|
query_graph_similarity: 3,
|
|
@@ -1157,6 +1889,8 @@ var TOOL_TIERS = {
|
|
|
1157
1889
|
};
|
|
1158
1890
|
var TOOL_COSTS = {
|
|
1159
1891
|
// L0 free
|
|
1892
|
+
hello_agent: 0,
|
|
1893
|
+
alter_resolve_handle: 0,
|
|
1160
1894
|
list_archetypes: 0,
|
|
1161
1895
|
verify_identity: 0,
|
|
1162
1896
|
initiate_assessment: 0,
|
|
@@ -1164,7 +1898,6 @@ var TOOL_COSTS = {
|
|
|
1164
1898
|
get_profile: 0,
|
|
1165
1899
|
query_matches: 0,
|
|
1166
1900
|
get_competencies: 0,
|
|
1167
|
-
create_identity_stub: 0,
|
|
1168
1901
|
search_identities: 0,
|
|
1169
1902
|
get_identity_earnings: 0,
|
|
1170
1903
|
get_network_stats: 0,
|
|
@@ -1175,22 +1908,16 @@ var TOOL_COSTS = {
|
|
|
1175
1908
|
get_agent_trust_tier: 0,
|
|
1176
1909
|
get_agent_portfolio: 0,
|
|
1177
1910
|
get_privacy_budget: 0,
|
|
1178
|
-
dispute_attestation: 0,
|
|
1179
1911
|
golden_thread_status: 0,
|
|
1180
1912
|
begin_golden_thread: 0,
|
|
1181
1913
|
complete_knot: 0,
|
|
1182
1914
|
check_golden_thread: 0,
|
|
1183
1915
|
thread_census: 0,
|
|
1184
1916
|
// L1 ($0.005)
|
|
1185
|
-
submit_context: 5e-3,
|
|
1186
1917
|
assess_traits: 5e-3,
|
|
1187
1918
|
get_trait_snapshot: 5e-3,
|
|
1188
|
-
submit_structured_profile: 5e-3,
|
|
1189
|
-
submit_social_links: 5e-3,
|
|
1190
|
-
attest_domain: 5e-3,
|
|
1191
1919
|
// L2 ($0.01)
|
|
1192
1920
|
get_full_trait_vector: 0.01,
|
|
1193
|
-
submit_batch_context: 0.01,
|
|
1194
1921
|
get_side_quest_graph: 0.01,
|
|
1195
1922
|
// L3 ($0.025)
|
|
1196
1923
|
query_graph_similarity: 0.025,
|
|
@@ -1202,6 +1929,8 @@ var TOOL_COSTS = {
|
|
|
1202
1929
|
};
|
|
1203
1930
|
var TOOL_BLAST_RADIUS = {
|
|
1204
1931
|
// Low: read-only reference
|
|
1932
|
+
hello_agent: "low",
|
|
1933
|
+
alter_resolve_handle: "low",
|
|
1205
1934
|
list_archetypes: "low",
|
|
1206
1935
|
verify_identity: "low",
|
|
1207
1936
|
get_engagement_level: "low",
|
|
@@ -1214,13 +1943,12 @@ var TOOL_BLAST_RADIUS = {
|
|
|
1214
1943
|
begin_golden_thread: "low",
|
|
1215
1944
|
check_golden_thread: "low",
|
|
1216
1945
|
thread_census: "low",
|
|
1217
|
-
dispute_attestation: "low",
|
|
1218
1946
|
get_identity_earnings: "low",
|
|
1219
1947
|
get_identity_trust_score: "low",
|
|
1220
1948
|
initiate_assessment: "low",
|
|
1949
|
+
get_agent_trust_tier: "low",
|
|
1950
|
+
get_agent_portfolio: "low",
|
|
1221
1951
|
// Medium: writes data or searches
|
|
1222
|
-
create_identity_stub: "medium",
|
|
1223
|
-
submit_context: "medium",
|
|
1224
1952
|
search_identities: "medium",
|
|
1225
1953
|
get_profile: "medium",
|
|
1226
1954
|
query_matches: "medium",
|
|
@@ -1228,26 +1956,16 @@ var TOOL_BLAST_RADIUS = {
|
|
|
1228
1956
|
complete_knot: "medium",
|
|
1229
1957
|
assess_traits: "medium",
|
|
1230
1958
|
get_trait_snapshot: "medium",
|
|
1231
|
-
submit_structured_profile: "medium",
|
|
1232
|
-
submit_social_links: "medium",
|
|
1233
|
-
submit_batch_context: "medium",
|
|
1234
|
-
attest_domain: "medium",
|
|
1235
1959
|
// High: returns sensitive identity data or computes scores
|
|
1236
1960
|
get_full_trait_vector: "high",
|
|
1237
1961
|
compute_belonging: "high",
|
|
1238
1962
|
get_match_recommendations: "high",
|
|
1239
1963
|
generate_match_narrative: "high",
|
|
1240
1964
|
get_side_quest_graph: "high",
|
|
1241
|
-
query_graph_similarity: "high"
|
|
1242
|
-
// Tools not in upstream TOOL_BLAST_RADIUS — default to "low"
|
|
1243
|
-
get_agent_trust_tier: "low",
|
|
1244
|
-
get_agent_portfolio: "low"
|
|
1965
|
+
query_graph_similarity: "high"
|
|
1245
1966
|
};
|
|
1246
1967
|
|
|
1247
|
-
|
|
1248
|
-
var SDK_NAME = "@truealter/sdk";
|
|
1249
|
-
var SDK_VERSION = "0.1.1";
|
|
1250
|
-
|
|
1968
|
+
exports.ALL_CLIENTS = ALL_CLIENTS;
|
|
1251
1969
|
exports.AlterAuthError = AlterAuthError;
|
|
1252
1970
|
exports.AlterClient = AlterClient;
|
|
1253
1971
|
exports.AlterDiscoveryError = AlterDiscoveryError;
|
|
@@ -1259,6 +1977,9 @@ exports.AlterProvenanceError = AlterProvenanceError;
|
|
|
1259
1977
|
exports.AlterRateLimited = AlterRateLimited;
|
|
1260
1978
|
exports.AlterTimeoutError = AlterTimeoutError;
|
|
1261
1979
|
exports.AlterToolError = AlterToolError;
|
|
1980
|
+
exports.CLAUDE_CODE = CLAUDE_CODE;
|
|
1981
|
+
exports.CLAUDE_DESKTOP = CLAUDE_DESKTOP;
|
|
1982
|
+
exports.CURSOR = CURSOR;
|
|
1262
1983
|
exports.DEFAULT_DOMAIN = DEFAULT_DOMAIN;
|
|
1263
1984
|
exports.DEFAULT_ENDPOINT = DEFAULT_ENDPOINT;
|
|
1264
1985
|
exports.DEFAULT_VERIFY_AT_ALLOWLIST = DEFAULT_VERIFY_AT_ALLOWLIST;
|
|
@@ -1271,24 +1992,37 @@ exports.SDK_VERSION = SDK_VERSION;
|
|
|
1271
1992
|
exports.TOOL_BLAST_RADIUS = TOOL_BLAST_RADIUS;
|
|
1272
1993
|
exports.TOOL_COSTS = TOOL_COSTS;
|
|
1273
1994
|
exports.TOOL_TIERS = TOOL_TIERS;
|
|
1995
|
+
exports.VSCODE = VSCODE;
|
|
1274
1996
|
exports.X402Client = X402Client;
|
|
1275
1997
|
exports.base64urlDecode = base64urlDecode;
|
|
1276
|
-
exports.base64urlEncode =
|
|
1998
|
+
exports.base64urlEncode = base64urlEncode2;
|
|
1999
|
+
exports.canonicalArgsSha256 = canonicalArgsSha256;
|
|
2000
|
+
exports.canonicalStringify = canonicalStringify;
|
|
1277
2001
|
exports.clearDiscoveryCache = clearDiscoveryCache;
|
|
1278
2002
|
exports.decodeDid = decodeDid;
|
|
2003
|
+
exports.detectSyncedVolume = detectSyncedVolume;
|
|
1279
2004
|
exports.discover = discover;
|
|
1280
2005
|
exports.encodeDid = encodeDid;
|
|
1281
2006
|
exports.fetchPublicKeys = fetchPublicKeys;
|
|
1282
2007
|
exports.generateClaudeConfig = generateClaudeConfig;
|
|
2008
|
+
exports.generateClaudeDesktopConfig = generateClaudeDesktopConfig;
|
|
1283
2009
|
exports.generateCursorConfig = generateCursorConfig;
|
|
1284
2010
|
exports.generateGenericMcpConfig = generateGenericMcpConfig;
|
|
1285
2011
|
exports.generateKeypair = generateKeypair;
|
|
1286
2012
|
exports.keypairFromPrivateKey = keypairFromPrivateKey;
|
|
2013
|
+
exports.loadPrivateKey = loadPrivateKey;
|
|
1287
2014
|
exports.parsePaymentHeader = parsePaymentHeader;
|
|
2015
|
+
exports.probeAll = probeAll;
|
|
2016
|
+
exports.probeByDir = probeByDir;
|
|
2017
|
+
exports.probeClaudeCode = probeClaudeCode;
|
|
2018
|
+
exports.readWireState = readWireState;
|
|
1288
2019
|
exports.resolveVerifyAt = resolveVerifyAt;
|
|
2020
|
+
exports.sha256 = sha2562;
|
|
1289
2021
|
exports.sign = sign;
|
|
2022
|
+
exports.signInvocation = signInvocation;
|
|
2023
|
+
exports.unwire = unwire;
|
|
1290
2024
|
exports.verify = verify;
|
|
1291
2025
|
exports.verifyProvenance = verifyProvenance;
|
|
1292
2026
|
exports.verifyToolSignatures = verifyToolSignatures;
|
|
1293
|
-
|
|
1294
|
-
|
|
2027
|
+
exports.wire = wire;
|
|
2028
|
+
exports.writeWireState = writeWireState;
|