enigma-memory 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +55 -0
- package/README.md +379 -0
- package/apps/cli/bin/enigma.mjs +1117 -0
- package/apps/desktop/src/app.js +1327 -0
- package/apps/desktop/src/index.html +1373 -0
- package/apps/desktop/src/styles.css +386 -0
- package/apps/gateway/bin/enigma-gateway.mjs +52 -0
- package/apps/gateway/src/server.mjs +1403 -0
- package/apps/native-host/README.md +265 -0
- package/apps/native-host/bin/enigma-native-host.mjs +499 -0
- package/apps/native-host/manifests/com.enigma.native_host.chrome.json +9 -0
- package/apps/native-host/manifests/com.enigma.native_host.edge.json +9 -0
- package/apps/native-host/manifests/com.enigma.native_host.firefox.json +9 -0
- package/apps/relay/bin/enigma-relay.mjs +52 -0
- package/apps/relay/src/server.mjs +1571 -0
- package/apps/verifier/bin/enigma-verify.mjs +240 -0
- package/deploy/docker-compose.production.example.yml +150 -0
- package/deploy/kubernetes/enigma-backend.example.yaml +580 -0
- package/package.json +196 -0
- package/packages/adapters/PACKAGE_CONTRACT.md +47 -0
- package/packages/adapters/src/index.js +183 -0
- package/packages/boundary/src/index.js +468 -0
- package/packages/connectors/src/index.js +533 -0
- package/packages/core/src/index.js +766 -0
- package/packages/enterprise/src/index.js +505 -0
- package/packages/importers/src/index.js +1083 -0
- package/packages/mcp-server/bin/enigma-mcp.mjs +19 -0
- package/packages/mcp-server/src/index.js +1185 -0
- package/packages/mesh/src/index.js +531 -0
- package/packages/metering/PACKAGE_CONTRACT.md +20 -0
- package/packages/metering/src/index.js +246 -0
- package/packages/optimizer/src/index.js +707 -0
- package/packages/passport/src/index.js +651 -0
- package/packages/settlement/PACKAGE_CONTRACT.md +28 -0
- package/packages/settlement/src/index.js +369 -0
- package/packages/storage/PACKAGE_CONTRACT.md +23 -0
- package/packages/storage/src/index.js +392 -0
- package/packages/vault/src/index.js +904 -0
- package/scripts/build-ai-orchestration-plan.mjs +248 -0
- package/scripts/build-cloudflare-pages-release-packet.mjs +287 -0
- package/scripts/build-cloudflare-token-policy.mjs +239 -0
- package/scripts/build-cloudflare-token-request.mjs +314 -0
- package/scripts/build-demo-assets.mjs +263 -0
- package/scripts/build-edge-backend-workers.mjs +353 -0
- package/scripts/build-goal-completion-audit.mjs +398 -0
- package/scripts/build-hosted-probe-worker.mjs +191 -0
- package/scripts/build-operator-acceptance-packet.mjs +254 -0
- package/scripts/build-operator-evidence-starter.mjs +525 -0
- package/scripts/build-production-backend-env-kit.mjs +384 -0
- package/scripts/build-production-dependency-report.mjs +369 -0
- package/scripts/build-production-handoff-packet.mjs +475 -0
- package/scripts/build-production-readiness-manifest.mjs +209 -0
- package/scripts/build-production-status-board.mjs +297 -0
- package/scripts/build-production-storage-migration.mjs +86 -0
- package/scripts/build-production-workplan.mjs +371 -0
- package/scripts/build-review-packet.mjs +594 -0
- package/scripts/check.mjs +419 -0
- package/scripts/cloudflare-ops.mjs +1672 -0
- package/scripts/cloudflare-secret-env.mjs +128 -0
- package/scripts/collect-hosted-backend-live-evidence.mjs +263 -0
- package/scripts/infrastructure-readiness.mjs +944 -0
- package/scripts/install-enigma-local.mjs +270 -0
- package/scripts/memory-optimization-benchmark.mjs +242 -0
- package/scripts/monitor-live-endpoints.mjs +358 -0
- package/scripts/release-audit.mjs +5588 -0
- package/scripts/release-provenance.mjs +250 -0
- package/scripts/run-backend-readiness-smoke.mjs +220 -0
- package/scripts/validate-backup-restore-drill.mjs +166 -0
- package/scripts/validate-cloudflare-credentials.mjs +112 -0
- package/scripts/validate-cloudflare-worker-inspect.mjs +179 -0
- package/scripts/validate-domain-tls.mjs +248 -0
- package/scripts/validate-hosted-backend-live.mjs +319 -0
- package/scripts/validate-incident-drill.mjs +221 -0
- package/scripts/validate-kms-custody.mjs +235 -0
- package/scripts/validate-legal-compliance-approval.mjs +274 -0
- package/scripts/validate-monitoring-alerting.mjs +263 -0
- package/scripts/validate-network-access-policy.mjs +285 -0
- package/scripts/validate-operator-acceptance.mjs +298 -0
- package/scripts/validate-production-manifests.mjs +325 -0
- package/scripts/validate-public-site-security.mjs +252 -0
- package/scripts/validate-security-threat-model.mjs +285 -0
- package/scripts/validate-service-settlement.mjs +256 -0
- package/scripts/validate-support-sla.mjs +190 -0
- package/scripts/validate-tenant-policy-approval.mjs +228 -0
- package/scripts/validate-usage-metering.mjs +224 -0
- package/scripts/validate-whitepaper-claims.mjs +166 -0
- package/specs/boundary-manifest-v1.schema.json +35 -0
- package/specs/capsule-v1.schema.json +55 -0
- package/specs/claim-boundary-manifest-v1.schema.json +22 -0
- package/specs/connector-profile-v1.schema.json +62 -0
- package/specs/deletion-tombstone-v1.schema.json +26 -0
- package/specs/enterprise-policy-v1.schema.json +59 -0
- package/specs/gateway-request-v1.schema.json +32 -0
- package/specs/goal-completion-audit-v1.schema.json +70 -0
- package/specs/hosted-backend-live-evidence-v1.schema.json +147 -0
- package/specs/import-report-v1.schema.json +214 -0
- package/specs/infrastructure-readiness-manifest-v1.schema.json +130 -0
- package/specs/memory-event-v1.schema.json +42 -0
- package/specs/mesh-node-v1.schema.json +126 -0
- package/specs/passport-v1.schema.json +50 -0
- package/specs/production-handoff-packet-v1.schema.json +149 -0
- package/specs/receipt-v1.schema.json +61 -0
- package/specs/relay-record-v1.schema.json +43 -0
- package/specs/state-checkpoint-v1.schema.json +37 -0
- package/specs/trust-bundle-v1.schema.json +56 -0
|
@@ -0,0 +1,1185 @@
|
|
|
1
|
+
import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { createVault, remember, recall, deleteMemory, exportBundle } from '../../vault/src/index.js';
|
|
5
|
+
import { createPassport, compileContextPack } from '../../passport/src/index.js';
|
|
6
|
+
import { verifyBundle } from '../../../apps/verifier/bin/enigma-verify.mjs';
|
|
7
|
+
import { aggregateUsageEvents, createUsageEvent } from '../../metering/src/index.js';
|
|
8
|
+
import {
|
|
9
|
+
createConsumerGpuCapacityProfile,
|
|
10
|
+
createOperatorServiceQuote,
|
|
11
|
+
createPermissionlessMemoryJob,
|
|
12
|
+
createServiceSettlementReceipt,
|
|
13
|
+
createSettlementBatch,
|
|
14
|
+
verifyServiceSettlementReceipt,
|
|
15
|
+
} from '../../settlement/src/index.js';
|
|
16
|
+
|
|
17
|
+
const DEFAULT_BUNDLE = '.enigma/bundle.json';
|
|
18
|
+
const JSONRPC_VERSION = '2.0';
|
|
19
|
+
const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
20
|
+
const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.0' });
|
|
21
|
+
const JSON_RPC_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
22
|
+
const JSON_RPC_ERROR = Object.freeze({
|
|
23
|
+
INVALID_REQUEST: -32600,
|
|
24
|
+
METHOD_NOT_FOUND: -32601,
|
|
25
|
+
INVALID_PARAMS: -32602,
|
|
26
|
+
INTERNAL_ERROR: -32603,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
class JsonRpcProtocolError extends Error {
|
|
30
|
+
constructor(code, message, data = undefined) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = 'JsonRpcProtocolError';
|
|
33
|
+
this.code = code;
|
|
34
|
+
this.data = data;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function invalidParams(message = 'Invalid params', data = undefined) {
|
|
39
|
+
return new JsonRpcProtocolError(JSON_RPC_ERROR.INVALID_PARAMS, message, data);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isJsonRpcProtocolError(error) {
|
|
43
|
+
return error instanceof JsonRpcProtocolError;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isPlainObject(value) {
|
|
47
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isValidJsonRpcId(id) {
|
|
51
|
+
return id === null
|
|
52
|
+
|| (typeof id === 'string' && JSON_RPC_ID_PATTERN.test(id))
|
|
53
|
+
|| (typeof id === 'number' && Number.isSafeInteger(id));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function ensureParamsObject(params, method) {
|
|
57
|
+
if (params === undefined) return {};
|
|
58
|
+
if (!isPlainObject(params)) throw invalidParams(`${method} params must be an object.`);
|
|
59
|
+
return params;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function rejectAdditionalProperties(object, allowed, context) {
|
|
63
|
+
for (const key of Object.keys(object)) {
|
|
64
|
+
if (!allowed.has(key)) throw invalidParams(`${context} contains unsupported properties.`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function requireString(object, key, context) {
|
|
69
|
+
if (typeof object[key] !== 'string') throw invalidParams(`${context} requires ${key} as a string.`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function optionalString(object, key, context) {
|
|
73
|
+
if (object[key] !== undefined && typeof object[key] !== 'string') {
|
|
74
|
+
throw invalidParams(`${context} ${key} must be a string.`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function optionalPlainObject(object, key, context) {
|
|
79
|
+
if (object[key] !== undefined && !isPlainObject(object[key])) {
|
|
80
|
+
throw invalidParams(`${context} ${key} must be an object.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function optionalStringArray(object, key, context) {
|
|
85
|
+
if (object[key] === undefined) return;
|
|
86
|
+
if (!Array.isArray(object[key]) || object[key].some((item) => typeof item !== 'string')) {
|
|
87
|
+
throw invalidParams(`${context} ${key} must be an array of strings.`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function optionalLimit(object, key, context) {
|
|
92
|
+
if (object[key] === undefined) return;
|
|
93
|
+
if (!Number.isInteger(object[key]) || object[key] < 1 || object[key] > 50) {
|
|
94
|
+
throw invalidParams(`${context} ${key} must be an integer from 1 through 50.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function optionalBoolean(object, key, context) {
|
|
99
|
+
if (object[key] !== undefined && typeof object[key] !== 'boolean') {
|
|
100
|
+
throw invalidParams(`${context} ${key} must be a boolean.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function optionalNonNegativeNumber(object, key, context) {
|
|
105
|
+
if (object[key] === undefined) return;
|
|
106
|
+
if (typeof object[key] !== 'number' || !Number.isFinite(object[key]) || object[key] < 0) {
|
|
107
|
+
throw invalidParams(`${context} ${key} must be a non-negative number.`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function requireNumber(object, key, context) {
|
|
112
|
+
if (typeof object[key] !== 'number' || !Number.isFinite(object[key])) {
|
|
113
|
+
throw invalidParams(`${context} requires ${key} as a finite number.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function optionalObjectArray(object, key, context) {
|
|
118
|
+
if (object[key] === undefined) return;
|
|
119
|
+
if (!Array.isArray(object[key]) || object[key].some((item) => !isPlainObject(item))) {
|
|
120
|
+
throw invalidParams(`${context} ${key} must be an array of objects.`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function validateToolArguments(name, args) {
|
|
125
|
+
if (!isPlainObject(args)) throw invalidParams('tools/call arguments must be an object.');
|
|
126
|
+
switch (name) {
|
|
127
|
+
case 'enigma_init':
|
|
128
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'tenant_id', 'subject_id', 'actor_id', 'policy_id']), name);
|
|
129
|
+
optionalString(args, 'bundlePath', name);
|
|
130
|
+
optionalString(args, 'tenant_id', name);
|
|
131
|
+
optionalString(args, 'subject_id', name);
|
|
132
|
+
optionalString(args, 'actor_id', name);
|
|
133
|
+
optionalString(args, 'policy_id', name);
|
|
134
|
+
return args;
|
|
135
|
+
case 'enigma_remember':
|
|
136
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'text', 'purpose', 'tags', 'metadata']), name);
|
|
137
|
+
optionalString(args, 'bundlePath', name);
|
|
138
|
+
requireString(args, 'text', name);
|
|
139
|
+
optionalString(args, 'purpose', name);
|
|
140
|
+
optionalStringArray(args, 'tags', name);
|
|
141
|
+
optionalPlainObject(args, 'metadata', name);
|
|
142
|
+
return args;
|
|
143
|
+
case 'enigma_search':
|
|
144
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'query', 'memory_addr', 'purpose', 'limit']), name);
|
|
145
|
+
optionalString(args, 'bundlePath', name);
|
|
146
|
+
optionalString(args, 'query', name);
|
|
147
|
+
optionalString(args, 'memory_addr', name);
|
|
148
|
+
optionalString(args, 'purpose', name);
|
|
149
|
+
optionalLimit(args, 'limit', name);
|
|
150
|
+
return args;
|
|
151
|
+
case 'enigma_context_pack':
|
|
152
|
+
rejectAdditionalProperties(args, new Set([
|
|
153
|
+
'bundlePath',
|
|
154
|
+
'query',
|
|
155
|
+
'purpose',
|
|
156
|
+
'limit',
|
|
157
|
+
'memory_addresses',
|
|
158
|
+
'optimize',
|
|
159
|
+
'max_estimated_tokens',
|
|
160
|
+
'price_per_million_tokens',
|
|
161
|
+
'currency',
|
|
162
|
+
]), name);
|
|
163
|
+
optionalString(args, 'bundlePath', name);
|
|
164
|
+
optionalString(args, 'query', name);
|
|
165
|
+
optionalString(args, 'purpose', name);
|
|
166
|
+
optionalLimit(args, 'limit', name);
|
|
167
|
+
optionalStringArray(args, 'memory_addresses', name);
|
|
168
|
+
optionalBoolean(args, 'optimize', name);
|
|
169
|
+
optionalNonNegativeNumber(args, 'max_estimated_tokens', name);
|
|
170
|
+
optionalNonNegativeNumber(args, 'price_per_million_tokens', name);
|
|
171
|
+
optionalString(args, 'currency', name);
|
|
172
|
+
return args;
|
|
173
|
+
case 'enigma_delete':
|
|
174
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'memory_addr', 'reason']), name);
|
|
175
|
+
optionalString(args, 'bundlePath', name);
|
|
176
|
+
requireString(args, 'memory_addr', name);
|
|
177
|
+
optionalString(args, 'reason', name);
|
|
178
|
+
return args;
|
|
179
|
+
case 'enigma_verify_receipts':
|
|
180
|
+
rejectAdditionalProperties(args, new Set(['bundlePath', 'bundle']), name);
|
|
181
|
+
optionalString(args, 'bundlePath', name);
|
|
182
|
+
optionalPlainObject(args, 'bundle', name);
|
|
183
|
+
return args;
|
|
184
|
+
case 'enigma_meter_usage':
|
|
185
|
+
rejectAdditionalProperties(args, new Set([
|
|
186
|
+
'events',
|
|
187
|
+
'tenant_id',
|
|
188
|
+
'meter_id',
|
|
189
|
+
'provider',
|
|
190
|
+
'model',
|
|
191
|
+
'operation',
|
|
192
|
+
'timestamp',
|
|
193
|
+
'generated_at',
|
|
194
|
+
'prompt_tokens',
|
|
195
|
+
'completion_tokens',
|
|
196
|
+
'memory_baseline_tokens',
|
|
197
|
+
'memory_optimized_tokens',
|
|
198
|
+
'currency',
|
|
199
|
+
'input_price_per_million_tokens',
|
|
200
|
+
'output_price_per_million_tokens',
|
|
201
|
+
'price_per_million_tokens',
|
|
202
|
+
]), name);
|
|
203
|
+
optionalObjectArray(args, 'events', name);
|
|
204
|
+
optionalString(args, 'tenant_id', name);
|
|
205
|
+
optionalString(args, 'meter_id', name);
|
|
206
|
+
optionalString(args, 'provider', name);
|
|
207
|
+
optionalString(args, 'model', name);
|
|
208
|
+
optionalString(args, 'operation', name);
|
|
209
|
+
optionalString(args, 'timestamp', name);
|
|
210
|
+
optionalString(args, 'generated_at', name);
|
|
211
|
+
optionalString(args, 'currency', name);
|
|
212
|
+
optionalNonNegativeNumber(args, 'prompt_tokens', name);
|
|
213
|
+
optionalNonNegativeNumber(args, 'completion_tokens', name);
|
|
214
|
+
optionalNonNegativeNumber(args, 'memory_baseline_tokens', name);
|
|
215
|
+
optionalNonNegativeNumber(args, 'memory_optimized_tokens', name);
|
|
216
|
+
optionalNonNegativeNumber(args, 'input_price_per_million_tokens', name);
|
|
217
|
+
optionalNonNegativeNumber(args, 'output_price_per_million_tokens', name);
|
|
218
|
+
optionalNonNegativeNumber(args, 'price_per_million_tokens', name);
|
|
219
|
+
return args;
|
|
220
|
+
case 'enigma_settlement_job':
|
|
221
|
+
rejectAdditionalProperties(args, new Set(['tenant_id', 'job_type', 'memory_commitment_root', 'policy_hash', 'usage_event_hash', 'requested_at', 'expires_at', 'max_price_amount', 'payment_asset']), name);
|
|
222
|
+
requireString(args, 'tenant_id', name);
|
|
223
|
+
requireString(args, 'job_type', name);
|
|
224
|
+
requireString(args, 'memory_commitment_root', name);
|
|
225
|
+
requireString(args, 'policy_hash', name);
|
|
226
|
+
requireString(args, 'usage_event_hash', name);
|
|
227
|
+
optionalString(args, 'requested_at', name);
|
|
228
|
+
requireString(args, 'expires_at', name);
|
|
229
|
+
requireNumber(args, 'max_price_amount', name);
|
|
230
|
+
optionalString(args, 'payment_asset', name);
|
|
231
|
+
return args;
|
|
232
|
+
case 'enigma_settlement_capacity':
|
|
233
|
+
rejectAdditionalProperties(args, new Set(['operator_id', 'accelerator_class', 'hardware_ref', 'region', 'model_family', 'model_refs', 'observed_at', 'expires_at', 'vram_gb', 'max_context_window_tokens', 'available_context_tokens_per_minute', 'p95_latency_ms', 'price_per_million_context_tokens', 'asset', 'capacity_ref', 'terms_ref']), name);
|
|
234
|
+
requireString(args, 'operator_id', name);
|
|
235
|
+
requireString(args, 'accelerator_class', name);
|
|
236
|
+
requireString(args, 'hardware_ref', name);
|
|
237
|
+
requireString(args, 'region', name);
|
|
238
|
+
requireString(args, 'model_family', name);
|
|
239
|
+
optionalStringArray(args, 'model_refs', name);
|
|
240
|
+
if (!Array.isArray(args.model_refs)) throw invalidParams(`${name} requires model_refs as an array.`);
|
|
241
|
+
optionalString(args, 'observed_at', name);
|
|
242
|
+
requireString(args, 'expires_at', name);
|
|
243
|
+
requireNumber(args, 'vram_gb', name);
|
|
244
|
+
requireNumber(args, 'max_context_window_tokens', name);
|
|
245
|
+
requireNumber(args, 'available_context_tokens_per_minute', name);
|
|
246
|
+
requireNumber(args, 'p95_latency_ms', name);
|
|
247
|
+
requireNumber(args, 'price_per_million_context_tokens', name);
|
|
248
|
+
optionalString(args, 'asset', name);
|
|
249
|
+
requireString(args, 'capacity_ref', name);
|
|
250
|
+
requireString(args, 'terms_ref', name);
|
|
251
|
+
return args;
|
|
252
|
+
case 'enigma_settlement_quote':
|
|
253
|
+
rejectAdditionalProperties(args, new Set(['job', 'operator_id', 'service_kind', 'quoted_at', 'expires_at', 'price_amount', 'asset', 'capacity_ref', 'capacity_profile', 'terms_ref']), name);
|
|
254
|
+
optionalPlainObject(args, 'job', name);
|
|
255
|
+
optionalPlainObject(args, 'capacity_profile', name);
|
|
256
|
+
if (args.job === undefined) throw invalidParams(`${name} requires job as an object.`);
|
|
257
|
+
requireString(args, 'operator_id', name);
|
|
258
|
+
requireString(args, 'service_kind', name);
|
|
259
|
+
optionalString(args, 'quoted_at', name);
|
|
260
|
+
requireString(args, 'expires_at', name);
|
|
261
|
+
requireNumber(args, 'price_amount', name);
|
|
262
|
+
optionalString(args, 'asset', name);
|
|
263
|
+
if (args.capacity_profile === undefined) requireString(args, 'capacity_ref', name);
|
|
264
|
+
requireString(args, 'terms_ref', name);
|
|
265
|
+
return args;
|
|
266
|
+
case 'enigma_settlement_receipt':
|
|
267
|
+
rejectAdditionalProperties(args, new Set(['job', 'quote', 'completed_at', 'settled_amount', 'settlement_ref', 'service_receipt_ref']), name);
|
|
268
|
+
optionalPlainObject(args, 'job', name);
|
|
269
|
+
optionalPlainObject(args, 'quote', name);
|
|
270
|
+
if (args.job === undefined) throw invalidParams(`${name} requires job as an object.`);
|
|
271
|
+
if (args.quote === undefined) throw invalidParams(`${name} requires quote as an object.`);
|
|
272
|
+
optionalString(args, 'completed_at', name);
|
|
273
|
+
requireNumber(args, 'settled_amount', name);
|
|
274
|
+
requireString(args, 'settlement_ref', name);
|
|
275
|
+
requireString(args, 'service_receipt_ref', name);
|
|
276
|
+
return args;
|
|
277
|
+
case 'enigma_settlement_verify':
|
|
278
|
+
rejectAdditionalProperties(args, new Set(['job', 'quote', 'receipt']), name);
|
|
279
|
+
optionalPlainObject(args, 'job', name);
|
|
280
|
+
optionalPlainObject(args, 'quote', name);
|
|
281
|
+
optionalPlainObject(args, 'receipt', name);
|
|
282
|
+
if (args.job === undefined) throw invalidParams(`${name} requires job as an object.`);
|
|
283
|
+
if (args.quote === undefined) throw invalidParams(`${name} requires quote as an object.`);
|
|
284
|
+
if (args.receipt === undefined) throw invalidParams(`${name} requires receipt as an object.`);
|
|
285
|
+
return args;
|
|
286
|
+
case 'enigma_settlement_batch':
|
|
287
|
+
rejectAdditionalProperties(args, new Set(['receipts', 'asset', 'batch_ref', 'generated_at']), name);
|
|
288
|
+
optionalObjectArray(args, 'receipts', name);
|
|
289
|
+
if (args.receipts === undefined) throw invalidParams(`${name} requires receipts as an array.`);
|
|
290
|
+
optionalString(args, 'asset', name);
|
|
291
|
+
requireString(args, 'batch_ref', name);
|
|
292
|
+
optionalString(args, 'generated_at', name);
|
|
293
|
+
return args;
|
|
294
|
+
default:
|
|
295
|
+
throw invalidParams('Unknown tool.');
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function validatePromptArguments(args) {
|
|
300
|
+
if (args === undefined) return undefined;
|
|
301
|
+
if (!isPlainObject(args)) throw invalidParams('prompts/get arguments must be an object.');
|
|
302
|
+
rejectAdditionalProperties(args, new Set(['question', 'purpose']), 'prompts/get arguments');
|
|
303
|
+
optionalString(args, 'question', 'prompts/get arguments');
|
|
304
|
+
optionalString(args, 'purpose', 'prompts/get arguments');
|
|
305
|
+
return args;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function sanitizeOperationalError(error) {
|
|
309
|
+
return {
|
|
310
|
+
ok: false,
|
|
311
|
+
error: 'Tool execution failed.',
|
|
312
|
+
error_name: typeof error?.name === 'string' ? error.name : 'Error',
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
export const toolDescriptors = [
|
|
318
|
+
{
|
|
319
|
+
name: 'enigma_init',
|
|
320
|
+
description: 'Create a local Enigma vault bundle when one does not already exist.',
|
|
321
|
+
inputSchema: {
|
|
322
|
+
type: 'object',
|
|
323
|
+
properties: {
|
|
324
|
+
bundlePath: { type: 'string' },
|
|
325
|
+
tenant_id: { type: 'string' },
|
|
326
|
+
subject_id: { type: 'string' },
|
|
327
|
+
actor_id: { type: 'string' },
|
|
328
|
+
policy_id: { type: 'string' },
|
|
329
|
+
},
|
|
330
|
+
additionalProperties: false,
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
name: 'enigma_remember',
|
|
335
|
+
description: 'Store a memory in the local Enigma vault and emit a receipt without using provider-native memory as canonical state.',
|
|
336
|
+
inputSchema: {
|
|
337
|
+
type: 'object',
|
|
338
|
+
properties: {
|
|
339
|
+
bundlePath: { type: 'string' },
|
|
340
|
+
text: { type: 'string' },
|
|
341
|
+
purpose: { type: 'string' },
|
|
342
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
343
|
+
metadata: { type: 'object' },
|
|
344
|
+
},
|
|
345
|
+
required: ['text'],
|
|
346
|
+
additionalProperties: false,
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
name: 'enigma_search',
|
|
351
|
+
description: 'Search active local Enigma memories by query, or recall one memory by address when memory_addr is supplied.',
|
|
352
|
+
inputSchema: {
|
|
353
|
+
type: 'object',
|
|
354
|
+
properties: {
|
|
355
|
+
bundlePath: { type: 'string' },
|
|
356
|
+
query: { type: 'string' },
|
|
357
|
+
memory_addr: { type: 'string' },
|
|
358
|
+
purpose: { type: 'string' },
|
|
359
|
+
limit: { type: 'integer', minimum: 1, maximum: 50 },
|
|
360
|
+
},
|
|
361
|
+
additionalProperties: false,
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
name: 'enigma_context_pack',
|
|
366
|
+
description: 'Compile an MCP-safe context pack from active local memories and emit retrieval/injection receipts.',
|
|
367
|
+
inputSchema: {
|
|
368
|
+
type: 'object',
|
|
369
|
+
properties: {
|
|
370
|
+
bundlePath: { type: 'string' },
|
|
371
|
+
query: { type: 'string' },
|
|
372
|
+
purpose: { type: 'string' },
|
|
373
|
+
limit: { type: 'integer', minimum: 1, maximum: 50 },
|
|
374
|
+
memory_addresses: { type: 'array', items: { type: 'string' } },
|
|
375
|
+
optimize: { type: 'boolean' },
|
|
376
|
+
max_estimated_tokens: { type: 'number', minimum: 0 },
|
|
377
|
+
price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
378
|
+
currency: { type: 'string' },
|
|
379
|
+
},
|
|
380
|
+
additionalProperties: false,
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: 'enigma_delete',
|
|
385
|
+
description: 'Tombstone an Enigma memory so it is not served in future context packs.',
|
|
386
|
+
inputSchema: {
|
|
387
|
+
type: 'object',
|
|
388
|
+
properties: {
|
|
389
|
+
bundlePath: { type: 'string' },
|
|
390
|
+
memory_addr: { type: 'string' },
|
|
391
|
+
reason: { type: 'string' },
|
|
392
|
+
},
|
|
393
|
+
required: ['memory_addr'],
|
|
394
|
+
additionalProperties: false,
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
name: 'enigma_verify_receipts',
|
|
399
|
+
description: 'Verify receipts/checkpoints in a local or exported Enigma bundle and return a machine-readable verdict.',
|
|
400
|
+
inputSchema: {
|
|
401
|
+
type: 'object',
|
|
402
|
+
properties: {
|
|
403
|
+
bundlePath: { type: 'string' },
|
|
404
|
+
bundle: { type: 'object' },
|
|
405
|
+
},
|
|
406
|
+
additionalProperties: false,
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: 'enigma_meter_usage',
|
|
411
|
+
description: 'Create content-minimized memory usage events or aggregate supplied usage events without raw prompts or provider responses.',
|
|
412
|
+
inputSchema: {
|
|
413
|
+
type: 'object',
|
|
414
|
+
properties: {
|
|
415
|
+
events: { type: 'array', items: { type: 'object' } },
|
|
416
|
+
tenant_id: { type: 'string' },
|
|
417
|
+
meter_id: { type: 'string' },
|
|
418
|
+
provider: { type: 'string' },
|
|
419
|
+
model: { type: 'string' },
|
|
420
|
+
operation: { type: 'string' },
|
|
421
|
+
timestamp: { type: 'string' },
|
|
422
|
+
generated_at: { type: 'string' },
|
|
423
|
+
prompt_tokens: { type: 'number', minimum: 0 },
|
|
424
|
+
completion_tokens: { type: 'number', minimum: 0 },
|
|
425
|
+
memory_baseline_tokens: { type: 'number', minimum: 0 },
|
|
426
|
+
memory_optimized_tokens: { type: 'number', minimum: 0 },
|
|
427
|
+
currency: { type: 'string' },
|
|
428
|
+
input_price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
429
|
+
output_price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
430
|
+
price_per_million_tokens: { type: 'number', minimum: 0 },
|
|
431
|
+
},
|
|
432
|
+
additionalProperties: false,
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
name: 'enigma_settlement_job',
|
|
437
|
+
description: 'Create a permissionless hash-only memory service job for settlement rails.',
|
|
438
|
+
inputSchema: {
|
|
439
|
+
type: 'object',
|
|
440
|
+
properties: {
|
|
441
|
+
tenant_id: { type: 'string' },
|
|
442
|
+
job_type: { type: 'string' },
|
|
443
|
+
memory_commitment_root: { type: 'string' },
|
|
444
|
+
policy_hash: { type: 'string' },
|
|
445
|
+
usage_event_hash: { type: 'string' },
|
|
446
|
+
requested_at: { type: 'string' },
|
|
447
|
+
expires_at: { type: 'string' },
|
|
448
|
+
max_price_amount: { type: 'number' },
|
|
449
|
+
payment_asset: { type: 'string' },
|
|
450
|
+
},
|
|
451
|
+
required: ['tenant_id', 'job_type', 'memory_commitment_root', 'policy_hash', 'usage_event_hash', 'expires_at', 'max_price_amount'],
|
|
452
|
+
additionalProperties: false,
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
name: 'enigma_settlement_capacity',
|
|
457
|
+
description: 'Create a consumer/workstation GPU memory-optimizer capacity profile for permissionless discovery and settlement without raw-memory decentralization claims.',
|
|
458
|
+
inputSchema: {
|
|
459
|
+
type: 'object',
|
|
460
|
+
properties: {
|
|
461
|
+
operator_id: { type: 'string' },
|
|
462
|
+
accelerator_class: { type: 'string' },
|
|
463
|
+
hardware_ref: { type: 'string' },
|
|
464
|
+
region: { type: 'string' },
|
|
465
|
+
model_family: { type: 'string' },
|
|
466
|
+
model_refs: { type: 'array', items: { type: 'string' } },
|
|
467
|
+
observed_at: { type: 'string' },
|
|
468
|
+
expires_at: { type: 'string' },
|
|
469
|
+
vram_gb: { type: 'number' },
|
|
470
|
+
max_context_window_tokens: { type: 'number' },
|
|
471
|
+
available_context_tokens_per_minute: { type: 'number' },
|
|
472
|
+
p95_latency_ms: { type: 'number' },
|
|
473
|
+
price_per_million_context_tokens: { type: 'number' },
|
|
474
|
+
asset: { type: 'string' },
|
|
475
|
+
capacity_ref: { type: 'string' },
|
|
476
|
+
terms_ref: { type: 'string' },
|
|
477
|
+
},
|
|
478
|
+
required: ['operator_id', 'accelerator_class', 'hardware_ref', 'region', 'model_family', 'model_refs', 'expires_at', 'vram_gb', 'max_context_window_tokens', 'available_context_tokens_per_minute', 'p95_latency_ms', 'price_per_million_context_tokens', 'capacity_ref', 'terms_ref'],
|
|
479
|
+
additionalProperties: false,
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
name: 'enigma_settlement_quote',
|
|
484
|
+
description: 'Create an operator quote for a permissionless memory service job.',
|
|
485
|
+
inputSchema: {
|
|
486
|
+
type: 'object',
|
|
487
|
+
properties: {
|
|
488
|
+
job: { type: 'object' },
|
|
489
|
+
operator_id: { type: 'string' },
|
|
490
|
+
service_kind: { type: 'string' },
|
|
491
|
+
quoted_at: { type: 'string' },
|
|
492
|
+
expires_at: { type: 'string' },
|
|
493
|
+
price_amount: { type: 'number' },
|
|
494
|
+
asset: { type: 'string' },
|
|
495
|
+
capacity_ref: { type: 'string' },
|
|
496
|
+
capacity_profile: { type: 'object' },
|
|
497
|
+
terms_ref: { type: 'string' },
|
|
498
|
+
},
|
|
499
|
+
required: ['job', 'operator_id', 'service_kind', 'expires_at', 'price_amount', 'terms_ref'],
|
|
500
|
+
additionalProperties: false,
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
name: 'enigma_settlement_receipt',
|
|
505
|
+
description: 'Create a service settlement receipt linking job, quote, usage hash, memory root, policy hash, service receipt, and settlement ref.',
|
|
506
|
+
inputSchema: {
|
|
507
|
+
type: 'object',
|
|
508
|
+
properties: {
|
|
509
|
+
job: { type: 'object' },
|
|
510
|
+
quote: { type: 'object' },
|
|
511
|
+
completed_at: { type: 'string' },
|
|
512
|
+
settled_amount: { type: 'number' },
|
|
513
|
+
settlement_ref: { type: 'string' },
|
|
514
|
+
service_receipt_ref: { type: 'string' },
|
|
515
|
+
},
|
|
516
|
+
required: ['job', 'quote', 'settled_amount', 'settlement_ref', 'service_receipt_ref'],
|
|
517
|
+
additionalProperties: false,
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
name: 'enigma_settlement_verify',
|
|
522
|
+
description: 'Verify a service settlement receipt against its job and quote.',
|
|
523
|
+
inputSchema: {
|
|
524
|
+
type: 'object',
|
|
525
|
+
properties: {
|
|
526
|
+
job: { type: 'object' },
|
|
527
|
+
quote: { type: 'object' },
|
|
528
|
+
receipt: { type: 'object' },
|
|
529
|
+
},
|
|
530
|
+
required: ['job', 'quote', 'receipt'],
|
|
531
|
+
additionalProperties: false,
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: 'enigma_settlement_batch',
|
|
536
|
+
description: 'Aggregate service settlement receipts into a hash-only settlement batch without investment or provider-invoice claims.',
|
|
537
|
+
inputSchema: {
|
|
538
|
+
type: 'object',
|
|
539
|
+
properties: {
|
|
540
|
+
receipts: { type: 'array', items: { type: 'object' } },
|
|
541
|
+
asset: { type: 'string' },
|
|
542
|
+
batch_ref: { type: 'string' },
|
|
543
|
+
generated_at: { type: 'string' },
|
|
544
|
+
},
|
|
545
|
+
required: ['receipts', 'batch_ref'],
|
|
546
|
+
additionalProperties: false,
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
];
|
|
550
|
+
|
|
551
|
+
const PASSPORT_SUMMARY_RESOURCE_URI = 'enigma://passport/summary';
|
|
552
|
+
const STANDARD_MEMORY_PROMPT_NAME = 'enigma_standard_memory_prompt';
|
|
553
|
+
|
|
554
|
+
export const resourceDescriptors = [
|
|
555
|
+
{
|
|
556
|
+
uri: PASSPORT_SUMMARY_RESOURCE_URI,
|
|
557
|
+
name: 'Enigma Passport Summary',
|
|
558
|
+
description: 'MCP-safe Passport and Vault metadata for the local Enigma bundle. Raw memory plaintext is never exposed.',
|
|
559
|
+
mimeType: 'application/json',
|
|
560
|
+
},
|
|
561
|
+
];
|
|
562
|
+
|
|
563
|
+
export const promptDescriptors = [
|
|
564
|
+
{
|
|
565
|
+
name: STANDARD_MEMORY_PROMPT_NAME,
|
|
566
|
+
description: 'Standard Enigma memory prompt for provider-neutral, receipt-aware user-specific answers.',
|
|
567
|
+
arguments: [
|
|
568
|
+
{
|
|
569
|
+
name: 'question',
|
|
570
|
+
description: 'Optional user question the assistant is preparing to answer.',
|
|
571
|
+
required: false,
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
name: 'purpose',
|
|
575
|
+
description: 'Optional retrieval purpose to pass when requesting Enigma context.',
|
|
576
|
+
required: false,
|
|
577
|
+
},
|
|
578
|
+
],
|
|
579
|
+
},
|
|
580
|
+
];
|
|
581
|
+
|
|
582
|
+
function bundlePath(input = {}) {
|
|
583
|
+
return resolve(String(input.bundlePath ?? input.bundle_path ?? DEFAULT_BUNDLE));
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
async function readJson(path) {
|
|
587
|
+
return JSON.parse(await readFile(path, 'utf8'));
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
async function writeJson(path, value) {
|
|
591
|
+
await mkdir(dirname(path), { recursive: true });
|
|
592
|
+
await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
async function fileExists(path) {
|
|
596
|
+
try {
|
|
597
|
+
await access(path);
|
|
598
|
+
return true;
|
|
599
|
+
} catch (error) {
|
|
600
|
+
if (error?.code === 'ENOENT') return false;
|
|
601
|
+
throw error;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function reviveVault(stored) {
|
|
606
|
+
if (stored.schema !== 'enigma.vault_bundle.v1') throw new Error(`Unsupported Enigma bundle schema: ${stored.schema ?? '<missing>'}`);
|
|
607
|
+
const signingKeyPair = stored.keyring?.privateKey
|
|
608
|
+
? { key_id: stored.keyring.signer?.key_id, publicKey: stored.keyring.publicKey, privateKey: stored.keyring.privateKey }
|
|
609
|
+
: undefined;
|
|
610
|
+
const vault = createVault({
|
|
611
|
+
vault_id: stored.vault?.vault_id,
|
|
612
|
+
tenant_id: stored.vault?.tenant_id,
|
|
613
|
+
subject_id: stored.vault?.subject_id,
|
|
614
|
+
actor_id: stored.vault?.actor_id,
|
|
615
|
+
policy_id: stored.vault?.policy_id,
|
|
616
|
+
vault_key: stored.keyring?.vault_key_b64,
|
|
617
|
+
address_key: stored.keyring?.address_key_b64,
|
|
618
|
+
signingKeyPair,
|
|
619
|
+
now: stored.vault?.created_at,
|
|
620
|
+
});
|
|
621
|
+
if (stored.keyring?.signer) vault.signer = stored.keyring.signer;
|
|
622
|
+
vault.created_at = stored.vault?.created_at ?? vault.created_at;
|
|
623
|
+
vault.updated_at = stored.vault?.updated_at ?? vault.updated_at;
|
|
624
|
+
vault.sequence = Number.isInteger(stored.vault?.sequence) ? stored.vault.sequence : 0;
|
|
625
|
+
vault.events = Array.isArray(stored.events) ? stored.events : [];
|
|
626
|
+
vault.receipts = Array.isArray(stored.receipts) ? stored.receipts : [];
|
|
627
|
+
vault.memories = new Map((stored.memory_objects ?? []).map((record) => [record.memory_addr, { ...record }]));
|
|
628
|
+
vault.activeAddresses = new Set(stored.active_memory_addresses ?? []);
|
|
629
|
+
vault.tombstones = new Map((stored.tombstones ?? []).map((tombstone) => [tombstone.memory_addr, tombstone]));
|
|
630
|
+
const roots = vault.__computeRoots();
|
|
631
|
+
vault.active_set_root = roots.active_set_root;
|
|
632
|
+
vault.receipt_log_root = roots.receipt_log_root;
|
|
633
|
+
return vault;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
async function loadState(path) {
|
|
637
|
+
const stored = await readJson(path);
|
|
638
|
+
const vault = reviveVault(stored);
|
|
639
|
+
return { stored, vault, passport: createPassport({ vault }) };
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
async function persistState(path, vault) {
|
|
643
|
+
const exported = exportBundle({ vault, includePlaintext: false });
|
|
644
|
+
const bundle = exported.bundle ?? exported;
|
|
645
|
+
await writeJson(path, bundle);
|
|
646
|
+
return bundle;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
function bundleSummary(path, bundle, created) {
|
|
650
|
+
return {
|
|
651
|
+
ok: true,
|
|
652
|
+
created,
|
|
653
|
+
bundlePath: path,
|
|
654
|
+
schema: bundle.schema,
|
|
655
|
+
vault_id: bundle.vault?.vault_id,
|
|
656
|
+
tenant_id: bundle.vault?.tenant_id,
|
|
657
|
+
subject_id: bundle.vault?.subject_id,
|
|
658
|
+
active_count: Array.isArray(bundle.active_memory_addresses) ? bundle.active_memory_addresses.length : 0,
|
|
659
|
+
receipt_count: Array.isArray(bundle.receipts) ? bundle.receipts.length : 0,
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
function normalizeResourceUri(uri) {
|
|
664
|
+
try {
|
|
665
|
+
const parsed = new URL(String(uri));
|
|
666
|
+
return parsed.protocol === 'enigma:' ? `enigma://${parsed.hostname}${parsed.pathname}` : String(uri);
|
|
667
|
+
} catch {
|
|
668
|
+
return String(uri);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
function inputWithBundlePath(params = {}) {
|
|
673
|
+
const uri = String(params?.uri ?? PASSPORT_SUMMARY_RESOURCE_URI);
|
|
674
|
+
const args = params?.arguments && typeof params.arguments === 'object' && !Array.isArray(params.arguments)
|
|
675
|
+
? params.arguments
|
|
676
|
+
: {};
|
|
677
|
+
let requestedPath = params?.bundlePath ?? params?.bundle_path ?? args.bundlePath ?? args.bundle_path;
|
|
678
|
+
try {
|
|
679
|
+
const parsed = new URL(uri);
|
|
680
|
+
requestedPath ??= parsed.searchParams.get('bundlePath') ?? parsed.searchParams.get('bundle_path') ?? undefined;
|
|
681
|
+
} catch {
|
|
682
|
+
// Invalid or relative resource identifiers are rejected by the resource handler.
|
|
683
|
+
}
|
|
684
|
+
return requestedPath === undefined ? { uri } : { uri, bundlePath: requestedPath };
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function passportFromBundle(bundle) {
|
|
688
|
+
const vault = {
|
|
689
|
+
...bundle.vault,
|
|
690
|
+
active_memory_addresses: Array.isArray(bundle.active_memory_addresses) ? bundle.active_memory_addresses : [],
|
|
691
|
+
tombstones: Array.isArray(bundle.tombstones) ? bundle.tombstones : [],
|
|
692
|
+
};
|
|
693
|
+
return createPassport({
|
|
694
|
+
vault,
|
|
695
|
+
passport_id: `passport:${vault.vault_id ?? 'local-vault'}`,
|
|
696
|
+
now: vault.updated_at ?? vault.created_at ?? bundle.exported_at,
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function passportSummary(path, bundle) {
|
|
701
|
+
if (bundle.schema !== 'enigma.vault_bundle.v1') throw new Error(`Unsupported Enigma bundle schema: ${bundle.schema ?? '<missing>'}`);
|
|
702
|
+
const passport = passportFromBundle(bundle);
|
|
703
|
+
return {
|
|
704
|
+
ok: true,
|
|
705
|
+
schema: 'enigma.mcp.passport_summary.v1',
|
|
706
|
+
bundlePath: path,
|
|
707
|
+
bundle_schema: bundle.schema,
|
|
708
|
+
exported_at: bundle.exported_at,
|
|
709
|
+
passport: {
|
|
710
|
+
schema: passport.schema,
|
|
711
|
+
passport_id: passport.passport_id,
|
|
712
|
+
owner: passport.owner,
|
|
713
|
+
created_at: passport.created_at,
|
|
714
|
+
updated_at: passport.updated_at,
|
|
715
|
+
vault: passport.vault,
|
|
716
|
+
policies: passport.policies,
|
|
717
|
+
checkpoints: passport.checkpoints,
|
|
718
|
+
active_memory_addresses: passport.active_memory_addresses,
|
|
719
|
+
tombstone_addresses: passport.tombstone_addresses,
|
|
720
|
+
},
|
|
721
|
+
vault: {
|
|
722
|
+
schema: bundle.vault?.schema,
|
|
723
|
+
vault_id: bundle.vault?.vault_id,
|
|
724
|
+
tenant_id: bundle.vault?.tenant_id,
|
|
725
|
+
subject_id: bundle.vault?.subject_id,
|
|
726
|
+
actor_id: bundle.vault?.actor_id,
|
|
727
|
+
policy_id: bundle.vault?.policy_id,
|
|
728
|
+
created_at: bundle.vault?.created_at,
|
|
729
|
+
updated_at: bundle.vault?.updated_at,
|
|
730
|
+
encryption: bundle.vault?.encryption,
|
|
731
|
+
key_id: bundle.vault?.key_id,
|
|
732
|
+
active_set_root: bundle.vault?.active_set_root,
|
|
733
|
+
receipt_log_root: bundle.vault?.receipt_log_root,
|
|
734
|
+
sequence: bundle.vault?.sequence,
|
|
735
|
+
},
|
|
736
|
+
counts: {
|
|
737
|
+
active_memory_addresses: Array.isArray(bundle.active_memory_addresses) ? bundle.active_memory_addresses.length : 0,
|
|
738
|
+
tombstones: Array.isArray(bundle.tombstones) ? bundle.tombstones.length : 0,
|
|
739
|
+
memory_objects: Array.isArray(bundle.memory_objects) ? bundle.memory_objects.length : 0,
|
|
740
|
+
events: Array.isArray(bundle.events) ? bundle.events.length : 0,
|
|
741
|
+
receipts: Array.isArray(bundle.receipts) ? bundle.receipts.length : 0,
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
export async function enigma_passport_summary_resource(input = {}) {
|
|
747
|
+
const options = input && typeof input === 'object' ? input : {};
|
|
748
|
+
const uri = options.uri ?? PASSPORT_SUMMARY_RESOURCE_URI;
|
|
749
|
+
if (normalizeResourceUri(uri) !== PASSPORT_SUMMARY_RESOURCE_URI) {
|
|
750
|
+
throw new Error(`Unknown Enigma resource: ${uri ?? '<missing>'}`);
|
|
751
|
+
}
|
|
752
|
+
const path = bundlePath(options);
|
|
753
|
+
const bundle = await readJson(path);
|
|
754
|
+
return {
|
|
755
|
+
contents: [
|
|
756
|
+
{
|
|
757
|
+
uri: String(uri),
|
|
758
|
+
mimeType: 'application/json',
|
|
759
|
+
text: JSON.stringify(passportSummary(path, bundle)),
|
|
760
|
+
},
|
|
761
|
+
],
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
export function enigma_standard_memory_prompt(input = {}) {
|
|
766
|
+
const args = input?.arguments && typeof input.arguments === 'object' && !Array.isArray(input.arguments)
|
|
767
|
+
? input.arguments
|
|
768
|
+
: (input && typeof input === 'object' ? input : {});
|
|
769
|
+
const question = typeof args.question === 'string' && args.question.trim() ? args.question.trim() : 'the user-specific question';
|
|
770
|
+
const purpose = typeof args.purpose === 'string' && args.purpose.trim() ? args.purpose.trim() : 'answer_user_specific_question';
|
|
771
|
+
return {
|
|
772
|
+
description: 'Use Enigma as the canonical memory and proof layer before making user-specific claims.',
|
|
773
|
+
messages: [
|
|
774
|
+
{
|
|
775
|
+
role: 'user',
|
|
776
|
+
content: {
|
|
777
|
+
type: 'text',
|
|
778
|
+
text: [
|
|
779
|
+
'Before answering user-specific questions, request relevant context through Enigma instead of relying on provider-native memory.',
|
|
780
|
+
`Use the Enigma MCP tools with purpose "${purpose}" to retrieve a context pack or search result for: ${question}`,
|
|
781
|
+
'Treat provider-native memory as a cache only; Enigma receipts and active Vault state are the source of truth.',
|
|
782
|
+
'Be honest: if Enigma has no relevant context, receipts, or permission for a claim, say you do not know or need more context rather than guessing.',
|
|
783
|
+
'Do not put raw memory plaintext into receipts, relay records, witness artifacts, SIEM events, or public proof artifacts.',
|
|
784
|
+
].join('\n'),
|
|
785
|
+
},
|
|
786
|
+
},
|
|
787
|
+
],
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
export async function enigma_init(input = {}) {
|
|
792
|
+
input = validateToolArguments('enigma_init', input);
|
|
793
|
+
const path = bundlePath(input);
|
|
794
|
+
if (await fileExists(path)) {
|
|
795
|
+
const bundle = await readJson(path);
|
|
796
|
+
if (bundle.schema !== 'enigma.vault_bundle.v1') throw new Error(`Unsupported Enigma bundle schema: ${bundle.schema ?? '<missing>'}`);
|
|
797
|
+
return bundleSummary(path, bundle, false);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const vault = createVault({
|
|
801
|
+
tenant_id: input.tenant_id,
|
|
802
|
+
subject_id: input.subject_id,
|
|
803
|
+
actor_id: input.actor_id,
|
|
804
|
+
policy_id: input.policy_id,
|
|
805
|
+
});
|
|
806
|
+
const bundle = await persistState(path, vault);
|
|
807
|
+
return bundleSummary(path, bundle, true);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
export async function enigma_remember(input = {}) {
|
|
811
|
+
input = validateToolArguments('enigma_remember', input);
|
|
812
|
+
const path = bundlePath(input);
|
|
813
|
+
const { vault, passport } = await loadState(path);
|
|
814
|
+
const result = remember({
|
|
815
|
+
vault,
|
|
816
|
+
passport,
|
|
817
|
+
text: input.text,
|
|
818
|
+
purpose: input.purpose ?? 'mcp_memory',
|
|
819
|
+
purpose_tags: Array.isArray(input.tags) ? input.tags : [],
|
|
820
|
+
metadata: input.metadata ?? {},
|
|
821
|
+
});
|
|
822
|
+
await persistState(path, vault);
|
|
823
|
+
return { ok: true, memory_addr: result.memory_addr, receipt_id: result.receipt?.receipt_id };
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
export async function enigma_search(input = {}) {
|
|
827
|
+
input = validateToolArguments('enigma_search', input);
|
|
828
|
+
const path = bundlePath(input);
|
|
829
|
+
const { vault, passport } = await loadState(path);
|
|
830
|
+
if (input.memory_addr) {
|
|
831
|
+
const result = recall({ vault, passport, memory_addr: input.memory_addr, purpose: input.purpose ?? 'mcp_search' });
|
|
832
|
+
await persistState(path, vault);
|
|
833
|
+
return result;
|
|
834
|
+
}
|
|
835
|
+
const pack = compileContextPack({
|
|
836
|
+
vault,
|
|
837
|
+
passport,
|
|
838
|
+
query: input.query ?? '',
|
|
839
|
+
purpose: input.purpose ?? 'mcp_search',
|
|
840
|
+
limit: Number(input.limit ?? 8),
|
|
841
|
+
});
|
|
842
|
+
await persistState(path, vault);
|
|
843
|
+
return { memories: pack.memories ?? [], receipts: pack.retrieval_receipts ?? pack.receipts ?? [] };
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
export async function enigma_context_pack(input = {}) {
|
|
847
|
+
input = validateToolArguments('enigma_context_pack', input);
|
|
848
|
+
const path = bundlePath(input);
|
|
849
|
+
const { vault, passport } = await loadState(path);
|
|
850
|
+
const pack = compileContextPack({
|
|
851
|
+
vault,
|
|
852
|
+
passport,
|
|
853
|
+
query: input.query ?? '',
|
|
854
|
+
purpose: input.purpose ?? 'mcp_context_pack',
|
|
855
|
+
optimize: input.optimize,
|
|
856
|
+
max_estimated_tokens: input.max_estimated_tokens,
|
|
857
|
+
price_per_million_tokens: input.price_per_million_tokens,
|
|
858
|
+
currency: input.currency,
|
|
859
|
+
limit: Number(input.limit ?? 8),
|
|
860
|
+
memory_addresses: input.memory_addresses,
|
|
861
|
+
});
|
|
862
|
+
await persistState(path, vault);
|
|
863
|
+
return pack;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
export async function enigma_delete(input = {}) {
|
|
867
|
+
input = validateToolArguments('enigma_delete', input);
|
|
868
|
+
const path = bundlePath(input);
|
|
869
|
+
const { vault, passport } = await loadState(path);
|
|
870
|
+
const result = deleteMemory({
|
|
871
|
+
vault,
|
|
872
|
+
passport,
|
|
873
|
+
memory_addr: input.memory_addr,
|
|
874
|
+
reason: input.reason ?? 'mcp_delete',
|
|
875
|
+
});
|
|
876
|
+
await persistState(path, vault);
|
|
877
|
+
return { ok: true, memory_addr: result.memory_addr, receipt_id: result.receipt?.receipt_id };
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
export async function enigma_verify_receipts(input = {}) {
|
|
881
|
+
input = validateToolArguments('enigma_verify_receipts', input);
|
|
882
|
+
const bundle = input.bundle ?? await readJson(bundlePath(input));
|
|
883
|
+
return verifyBundle(bundle);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
export async function enigma_meter_usage(input = {}) {
|
|
887
|
+
input = validateToolArguments('enigma_meter_usage', input);
|
|
888
|
+
if (Array.isArray(input.events)) {
|
|
889
|
+
return aggregateUsageEvents({
|
|
890
|
+
events: input.events,
|
|
891
|
+
tenant_id: input.tenant_id,
|
|
892
|
+
meter_id: input.meter_id,
|
|
893
|
+
generated_at: input.generated_at,
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
return createUsageEvent({
|
|
897
|
+
tenant_id: input.tenant_id,
|
|
898
|
+
meter_id: input.meter_id,
|
|
899
|
+
provider: input.provider,
|
|
900
|
+
model: input.model,
|
|
901
|
+
operation: input.operation,
|
|
902
|
+
timestamp: input.timestamp,
|
|
903
|
+
prompt_tokens: input.prompt_tokens,
|
|
904
|
+
completion_tokens: input.completion_tokens,
|
|
905
|
+
memory_baseline_tokens: input.memory_baseline_tokens,
|
|
906
|
+
memory_optimized_tokens: input.memory_optimized_tokens,
|
|
907
|
+
pricing: {
|
|
908
|
+
currency: input.currency,
|
|
909
|
+
input_price_per_million_tokens: input.input_price_per_million_tokens ?? input.price_per_million_tokens,
|
|
910
|
+
output_price_per_million_tokens: input.output_price_per_million_tokens ?? input.price_per_million_tokens,
|
|
911
|
+
},
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
export async function enigma_settlement_job(input = {}) {
|
|
916
|
+
input = validateToolArguments('enigma_settlement_job', input);
|
|
917
|
+
return createPermissionlessMemoryJob(input);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
export async function enigma_settlement_capacity(input = {}) {
|
|
921
|
+
input = validateToolArguments('enigma_settlement_capacity', input);
|
|
922
|
+
return createConsumerGpuCapacityProfile(input);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
export async function enigma_settlement_quote(input = {}) {
|
|
926
|
+
input = validateToolArguments('enigma_settlement_quote', input);
|
|
927
|
+
return createOperatorServiceQuote(input);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
export async function enigma_settlement_receipt(input = {}) {
|
|
931
|
+
input = validateToolArguments('enigma_settlement_receipt', input);
|
|
932
|
+
return createServiceSettlementReceipt(input);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
export async function enigma_settlement_verify(input = {}) {
|
|
936
|
+
input = validateToolArguments('enigma_settlement_verify', input);
|
|
937
|
+
return verifyServiceSettlementReceipt(input);
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
export async function enigma_settlement_batch(input = {}) {
|
|
941
|
+
input = validateToolArguments('enigma_settlement_batch', input);
|
|
942
|
+
return createSettlementBatch(input);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
export const handlers = Object.freeze({
|
|
947
|
+
enigma_init,
|
|
948
|
+
enigma_remember,
|
|
949
|
+
enigma_search,
|
|
950
|
+
enigma_context_pack,
|
|
951
|
+
enigma_delete,
|
|
952
|
+
enigma_verify_receipts,
|
|
953
|
+
enigma_meter_usage,
|
|
954
|
+
enigma_settlement_job,
|
|
955
|
+
enigma_settlement_capacity,
|
|
956
|
+
enigma_settlement_quote,
|
|
957
|
+
enigma_settlement_receipt,
|
|
958
|
+
enigma_settlement_verify,
|
|
959
|
+
enigma_settlement_batch,
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
function jsonRpcResult(id, result) {
|
|
963
|
+
return { jsonrpc: JSONRPC_VERSION, id, result };
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function jsonRpcError(id, code, message, data = undefined) {
|
|
967
|
+
const error = data === undefined ? { code, message } : { code, message, data };
|
|
968
|
+
return { jsonrpc: JSONRPC_VERSION, id, error };
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
function isRequestObject(request) {
|
|
972
|
+
return request !== null && typeof request === 'object' && !Array.isArray(request);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
function hasJsonRpcId(request) {
|
|
976
|
+
return Object.prototype.hasOwnProperty.call(request, 'id');
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
function toolArguments(name, params) {
|
|
980
|
+
const args = params.arguments ?? {};
|
|
981
|
+
return validateToolArguments(name, args);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
function toolHandler(name) {
|
|
985
|
+
return Object.prototype.hasOwnProperty.call(handlers, name) ? handlers[name] : undefined;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function toolCallContent(result, toolName) {
|
|
989
|
+
const verificationFailed = (toolName === 'enigma_verify_receipts' || toolName === 'enigma_settlement_verify') && result && typeof result === 'object' && result.ok === false;
|
|
990
|
+
return {
|
|
991
|
+
content: [{ type: 'text', text: JSON.stringify(result ?? null) }],
|
|
992
|
+
structuredContent: result ?? null,
|
|
993
|
+
isError: verificationFailed,
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
function toolCallError(error) {
|
|
998
|
+
const result = sanitizeOperationalError(error);
|
|
999
|
+
return {
|
|
1000
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
1001
|
+
structuredContent: result,
|
|
1002
|
+
isError: true,
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
function validateInitializeParams(params) {
|
|
1007
|
+
const input = ensureParamsObject(params, 'initialize');
|
|
1008
|
+
rejectAdditionalProperties(input, new Set(['protocolVersion', 'capabilities', 'clientInfo']), 'initialize params');
|
|
1009
|
+
optionalString(input, 'protocolVersion', 'initialize params');
|
|
1010
|
+
optionalPlainObject(input, 'capabilities', 'initialize params');
|
|
1011
|
+
optionalPlainObject(input, 'clientInfo', 'initialize params');
|
|
1012
|
+
if (input.protocolVersion !== undefined && input.protocolVersion !== MCP_PROTOCOL_VERSION) {
|
|
1013
|
+
throw invalidParams('Unsupported MCP protocol version.', { supportedProtocolVersions: [MCP_PROTOCOL_VERSION] });
|
|
1014
|
+
}
|
|
1015
|
+
return input;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
function validateNoParams(params, method) {
|
|
1019
|
+
const input = ensureParamsObject(params, method);
|
|
1020
|
+
rejectAdditionalProperties(input, new Set(), `${method} params`);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
async function handleSingleJsonRpcRequest(request) {
|
|
1024
|
+
if (!isRequestObject(request)) return jsonRpcError(null, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
1025
|
+
|
|
1026
|
+
const notification = !hasJsonRpcId(request);
|
|
1027
|
+
const id = notification ? null : request.id;
|
|
1028
|
+
if (!notification && !isValidJsonRpcId(id)) {
|
|
1029
|
+
return jsonRpcError(null, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
1030
|
+
}
|
|
1031
|
+
if (request.jsonrpc !== JSONRPC_VERSION || typeof request.method !== 'string') {
|
|
1032
|
+
return jsonRpcError(id, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
try {
|
|
1036
|
+
switch (request.method) {
|
|
1037
|
+
case 'initialize': {
|
|
1038
|
+
validateInitializeParams(request.params);
|
|
1039
|
+
return notification ? undefined : jsonRpcResult(id, {
|
|
1040
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
1041
|
+
capabilities: {
|
|
1042
|
+
tools: { listChanged: false },
|
|
1043
|
+
resources: { listChanged: false },
|
|
1044
|
+
prompts: { listChanged: false },
|
|
1045
|
+
},
|
|
1046
|
+
serverInfo: SERVER_INFO,
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
case 'notifications/initialized':
|
|
1050
|
+
validateNoParams(request.params, 'notifications/initialized');
|
|
1051
|
+
return undefined;
|
|
1052
|
+
case 'ping':
|
|
1053
|
+
validateNoParams(request.params, 'ping');
|
|
1054
|
+
return notification ? undefined : jsonRpcResult(id, {});
|
|
1055
|
+
case 'tools/list':
|
|
1056
|
+
validateNoParams(request.params, 'tools/list');
|
|
1057
|
+
return notification ? undefined : jsonRpcResult(id, { tools: toolDescriptors });
|
|
1058
|
+
case 'resources/list':
|
|
1059
|
+
validateNoParams(request.params, 'resources/list');
|
|
1060
|
+
return notification ? undefined : jsonRpcResult(id, { resources: resourceDescriptors });
|
|
1061
|
+
case 'resources/templates/list':
|
|
1062
|
+
validateNoParams(request.params, 'resources/templates/list');
|
|
1063
|
+
return notification ? undefined : jsonRpcResult(id, { resourceTemplates: [] });
|
|
1064
|
+
case 'resources/read': {
|
|
1065
|
+
const params = ensureParamsObject(request.params, 'resources/read');
|
|
1066
|
+
rejectAdditionalProperties(params, new Set(['uri', 'bundlePath']), 'resources/read params');
|
|
1067
|
+
requireString(params, 'uri', 'resources/read params');
|
|
1068
|
+
optionalString(params, 'bundlePath', 'resources/read params');
|
|
1069
|
+
if (normalizeResourceUri(params.uri) !== PASSPORT_SUMMARY_RESOURCE_URI) throw invalidParams('Unknown resource.');
|
|
1070
|
+
const result = await enigma_passport_summary_resource(inputWithBundlePath(params));
|
|
1071
|
+
return notification ? undefined : jsonRpcResult(id, result);
|
|
1072
|
+
}
|
|
1073
|
+
case 'prompts/list':
|
|
1074
|
+
validateNoParams(request.params, 'prompts/list');
|
|
1075
|
+
return notification ? undefined : jsonRpcResult(id, { prompts: promptDescriptors });
|
|
1076
|
+
case 'prompts/get': {
|
|
1077
|
+
const params = ensureParamsObject(request.params, 'prompts/get');
|
|
1078
|
+
rejectAdditionalProperties(params, new Set(['name', 'arguments']), 'prompts/get params');
|
|
1079
|
+
requireString(params, 'name', 'prompts/get params');
|
|
1080
|
+
if (params.name !== STANDARD_MEMORY_PROMPT_NAME) throw invalidParams('Unknown prompt.');
|
|
1081
|
+
validatePromptArguments(params.arguments);
|
|
1082
|
+
return notification ? undefined : jsonRpcResult(id, enigma_standard_memory_prompt(params));
|
|
1083
|
+
}
|
|
1084
|
+
case 'tools/call': {
|
|
1085
|
+
const params = ensureParamsObject(request.params, 'tools/call');
|
|
1086
|
+
rejectAdditionalProperties(params, new Set(['name', 'arguments']), 'tools/call params');
|
|
1087
|
+
requireString(params, 'name', 'tools/call params');
|
|
1088
|
+
const handler = toolHandler(params.name);
|
|
1089
|
+
if (!handler) throw invalidParams('Unknown tool.');
|
|
1090
|
+
const args = toolArguments(params.name, params);
|
|
1091
|
+
try {
|
|
1092
|
+
const result = await handler(args);
|
|
1093
|
+
return notification ? undefined : jsonRpcResult(id, toolCallContent(result, params.name));
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
return notification ? undefined : jsonRpcResult(id, toolCallError(error));
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
default:
|
|
1099
|
+
return notification ? undefined : jsonRpcError(id, JSON_RPC_ERROR.METHOD_NOT_FOUND, 'Method not found');
|
|
1100
|
+
}
|
|
1101
|
+
} catch (error) {
|
|
1102
|
+
if (notification) return undefined;
|
|
1103
|
+
if (isJsonRpcProtocolError(error)) return jsonRpcError(id, error.code, error.message, error.data);
|
|
1104
|
+
return jsonRpcError(id, JSON_RPC_ERROR.INTERNAL_ERROR, 'Internal error', { name: error.name });
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
export async function handleJsonRpcRequest(request) {
|
|
1109
|
+
if (!Array.isArray(request)) return handleSingleJsonRpcRequest(request);
|
|
1110
|
+
if (request.length === 0) return jsonRpcError(null, JSON_RPC_ERROR.INVALID_REQUEST, 'Invalid Request');
|
|
1111
|
+
|
|
1112
|
+
const responses = [];
|
|
1113
|
+
for (const item of request) {
|
|
1114
|
+
const response = await handleSingleJsonRpcRequest(item);
|
|
1115
|
+
if (response !== undefined) responses.push(response);
|
|
1116
|
+
}
|
|
1117
|
+
return responses.length === 0 ? undefined : responses;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
function writeJsonLine(output, value) {
|
|
1121
|
+
if (value !== undefined) output.write(`${JSON.stringify(value)}\n`);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
export function startStdioServer(io = {}) {
|
|
1125
|
+
const input = io.input ?? io.stdin ?? process.stdin;
|
|
1126
|
+
const output = io.output ?? io.stdout ?? process.stdout;
|
|
1127
|
+
const errorOutput = io.errorOutput ?? io.stderr ?? process.stderr;
|
|
1128
|
+
const lines = createInterface({ input, crlfDelay: Infinity });
|
|
1129
|
+
let queue = Promise.resolve();
|
|
1130
|
+
|
|
1131
|
+
async function processLine(line) {
|
|
1132
|
+
const trimmed = line.trim();
|
|
1133
|
+
if (!trimmed) return;
|
|
1134
|
+
try {
|
|
1135
|
+
writeJsonLine(output, await handleJsonRpcRequest(JSON.parse(trimmed)));
|
|
1136
|
+
} catch (error) {
|
|
1137
|
+
const parseError = error instanceof SyntaxError
|
|
1138
|
+
? jsonRpcError(null, -32700, 'Parse error')
|
|
1139
|
+
: jsonRpcError(null, JSON_RPC_ERROR.INTERNAL_ERROR, 'Internal error', { name: error.name });
|
|
1140
|
+
writeJsonLine(output, parseError);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
lines.on('line', (line) => {
|
|
1145
|
+
queue = queue.then(() => processLine(line), () => processLine(line));
|
|
1146
|
+
});
|
|
1147
|
+
lines.on('error', (error) => {
|
|
1148
|
+
errorOutput?.write?.(`${error.message}\n`);
|
|
1149
|
+
});
|
|
1150
|
+
|
|
1151
|
+
return {
|
|
1152
|
+
close() {
|
|
1153
|
+
lines.close();
|
|
1154
|
+
},
|
|
1155
|
+
done: new Promise((resolveDone) => {
|
|
1156
|
+
lines.on('close', () => {
|
|
1157
|
+
queue.then(resolveDone, resolveDone);
|
|
1158
|
+
});
|
|
1159
|
+
}),
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
export default {
|
|
1164
|
+
toolDescriptors,
|
|
1165
|
+
resourceDescriptors,
|
|
1166
|
+
promptDescriptors,
|
|
1167
|
+
handlers,
|
|
1168
|
+
enigma_init,
|
|
1169
|
+
enigma_remember,
|
|
1170
|
+
enigma_search,
|
|
1171
|
+
enigma_context_pack,
|
|
1172
|
+
enigma_delete,
|
|
1173
|
+
enigma_verify_receipts,
|
|
1174
|
+
enigma_meter_usage,
|
|
1175
|
+
enigma_settlement_job,
|
|
1176
|
+
enigma_settlement_capacity,
|
|
1177
|
+
enigma_settlement_quote,
|
|
1178
|
+
enigma_settlement_receipt,
|
|
1179
|
+
enigma_settlement_verify,
|
|
1180
|
+
enigma_settlement_batch,
|
|
1181
|
+
enigma_passport_summary_resource,
|
|
1182
|
+
enigma_standard_memory_prompt,
|
|
1183
|
+
handleJsonRpcRequest,
|
|
1184
|
+
startStdioServer,
|
|
1185
|
+
};
|