enigma-memory 0.1.12 → 0.1.14
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 +36 -17
- package/apps/cli/bin/enigma.mjs +425 -49
- package/deploy/docker-compose.local-production-simulation.yml +10 -11
- package/docs/benchmark-attestation-network.md +487 -487
- package/docs/benchmark-reproducibility.md +10 -9
- package/docs/client-connectors.md +512 -0
- package/docs/demo-proof-network.md +275 -275
- package/docs/developer-ecosystem.md +223 -223
- package/docs/developer-proof-quickstart.md +325 -325
- package/docs/enigma-memory-ready-conformance.md +376 -376
- package/docs/hosted-cloud-product.md +10 -0
- package/docs/install-anywhere.md +534 -0
- package/docs/installers-and-desktop.md +9 -7
- package/docs/proof-network-build-notes.md +240 -240
- package/docs/proof-network.md +257 -257
- package/docs/sdk-api.md +324 -322
- package/docs/solana-devnet-acceptance.md +48 -0
- package/docs/solana-proof-rail.md +453 -453
- package/examples/ci/github-actions.yml +7 -6
- package/package.json +11 -1
- package/packages/mcp-server/src/index.js +1 -1
- package/packages/passport/src/index.js +9 -5
- package/scripts/build-benchmark-proof-release.mjs +391 -0
- package/scripts/build-goal-completion-audit.mjs +11 -5
- package/scripts/build-hosted-api-key-lifecycle.mjs +1 -1
- package/scripts/build-hosted-customer-lifecycle.mjs +1 -1
- package/scripts/build-installer-assets.mjs +126 -10
- package/scripts/build-production-handoff-packet.mjs +7 -6
- package/scripts/build-production-unblocker.mjs +409 -0
- package/scripts/build-proof-network-packet.mjs +1 -1
- package/scripts/install-enigma-local.mjs +270 -0
- package/scripts/release-audit.mjs +71 -2
- package/scripts/run-standard-memory-benchmarks.mjs +1 -1
- package/scripts/verify-registry-install.mjs +1 -0
- package/scripts/wait-for-backend-ready.mjs +4 -2
package/apps/cli/bin/enigma.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { createServer as createHttpServer } from 'node:http';
|
|
4
|
-
import { realpathSync } from 'node:fs';
|
|
5
|
-
import { access, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { constants as fsConstants, realpathSync } from 'node:fs';
|
|
5
|
+
import { access, mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';
|
|
6
6
|
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
7
7
|
import { pathToFileURL } from 'node:url';
|
|
8
8
|
import { createVault, remember, recall, updateMemory, deleteMemory, exportBundle } from '../../../packages/vault/src/index.js';
|
|
@@ -574,6 +574,86 @@ function minimumNodeMajor(range) {
|
|
|
574
574
|
return match ? Number(match[1]) : 0;
|
|
575
575
|
}
|
|
576
576
|
|
|
577
|
+
function npmUserAgentCheck(userAgent = process.env.npm_config_user_agent) {
|
|
578
|
+
const raw = typeof userAgent === 'string' ? userAgent.trim() : '';
|
|
579
|
+
const npmToken = raw.split(/\s+/).find((token) => token.startsWith('npm/'));
|
|
580
|
+
const version = npmToken ? npmToken.slice(4) : null;
|
|
581
|
+
return {
|
|
582
|
+
ok: true,
|
|
583
|
+
detected: version !== null,
|
|
584
|
+
name: version === null ? null : 'npm',
|
|
585
|
+
version,
|
|
586
|
+
source: version === null ? null : 'npm_config_user_agent',
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
async function statIfExists(path) {
|
|
591
|
+
try {
|
|
592
|
+
return await stat(path);
|
|
593
|
+
} catch (error) {
|
|
594
|
+
if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') return null;
|
|
595
|
+
throw error;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
async function nearestExistingAncestor(path) {
|
|
600
|
+
let current = resolve(path);
|
|
601
|
+
for (;;) {
|
|
602
|
+
const stats = await statIfExists(current);
|
|
603
|
+
if (stats !== null) return { path: current, stats };
|
|
604
|
+
const parent = dirname(current);
|
|
605
|
+
if (parent === current) return null;
|
|
606
|
+
current = parent;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function publicParentDisplay(path, label) {
|
|
611
|
+
const value = String(path);
|
|
612
|
+
if (/^<[^>]+>$/.test(value)) return `<${label}>`;
|
|
613
|
+
const parent = dirname(value);
|
|
614
|
+
return parent === '' ? '.' : publicPathDisplay(parent, label);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
async function writableVaultPathCheck(bundleInput, displayInput = bundleInput) {
|
|
618
|
+
const bundlePath = resolve(String(bundleInput));
|
|
619
|
+
const parentPath = dirname(bundlePath);
|
|
620
|
+
const targetStats = await statIfExists(bundlePath);
|
|
621
|
+
const nearest = await nearestExistingAncestor(parentPath);
|
|
622
|
+
let ok = false;
|
|
623
|
+
let reason = null;
|
|
624
|
+
let parentExists = false;
|
|
625
|
+
let nearestExistingParent = null;
|
|
626
|
+
if (targetStats?.isDirectory()) {
|
|
627
|
+
reason = 'target_is_directory';
|
|
628
|
+
} else if (nearest === null) {
|
|
629
|
+
reason = 'no_existing_parent';
|
|
630
|
+
} else if (!nearest.stats.isDirectory()) {
|
|
631
|
+
reason = 'nearest_parent_not_directory';
|
|
632
|
+
nearestExistingParent = '<existing-parent-path>';
|
|
633
|
+
} else {
|
|
634
|
+
parentExists = nearest.path === parentPath;
|
|
635
|
+
nearestExistingParent = parentExists ? publicParentDisplay(displayInput, 'bundle-dir') : '<existing-parent-dir>';
|
|
636
|
+
try {
|
|
637
|
+
await access(nearest.path, fsConstants.W_OK);
|
|
638
|
+
ok = true;
|
|
639
|
+
} catch {
|
|
640
|
+
reason = 'parent_not_writable';
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return {
|
|
644
|
+
ok,
|
|
645
|
+
path: publicPathDisplay(displayInput, 'bundle-path'),
|
|
646
|
+
parent: publicParentDisplay(displayInput, 'bundle-dir'),
|
|
647
|
+
parent_exists: parentExists,
|
|
648
|
+
nearest_existing_parent: nearestExistingParent,
|
|
649
|
+
target_exists: targetStats !== null,
|
|
650
|
+
target_is_directory: targetStats?.isDirectory() === true,
|
|
651
|
+
writable: ok,
|
|
652
|
+
reason,
|
|
653
|
+
hint: ok ? null : 'Choose a writable --bundle path or create a writable parent directory.',
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
577
657
|
async function schemaFiles() {
|
|
578
658
|
return (await readdir(SPECS_URL)).filter((name) => name.endsWith('.schema.json')).sort();
|
|
579
659
|
}
|
|
@@ -762,15 +842,78 @@ async function persistState(bundlePath, vault) {
|
|
|
762
842
|
}
|
|
763
843
|
|
|
764
844
|
async function initCommand(flags, io) {
|
|
765
|
-
const
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
|
|
845
|
+
const bundleInput = pathFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE);
|
|
846
|
+
const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], dirname(bundleInput));
|
|
847
|
+
const requestedSelection = setupClientIds(flags);
|
|
848
|
+
const overwrite = booleanFlag(flags, ['overwrite'], false);
|
|
849
|
+
const dryRun = booleanFlag(flags, ['dry-run', 'dryRun'], false);
|
|
850
|
+
const connectRequested = booleanFlag(flags, ['connect'], false);
|
|
851
|
+
const displays = setupPublicDisplays(bundleInput, outDirInput);
|
|
852
|
+
const rawDisplays = setupRawDisplays(bundleInput, outDirInput);
|
|
853
|
+
let artifacts;
|
|
854
|
+
try {
|
|
855
|
+
artifacts = await buildQuickstartArtifacts(flags, { bundleInput, outDirInput, overwrite, write: !dryRun });
|
|
856
|
+
} catch (error) {
|
|
857
|
+
throw publicSetupError(error, rawDisplays, displays);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
const autoSelect = requestedSelection.auto || (connectRequested && requestedSelection.mode === 'default');
|
|
861
|
+
const selection = await setupClientSelection(
|
|
862
|
+
flags,
|
|
863
|
+
artifacts,
|
|
864
|
+
requestedSelection,
|
|
865
|
+
autoSelect,
|
|
866
|
+
connectRequested && requestedSelection.mode === 'default' ? 'connect_installed' : requestedSelection.mode,
|
|
867
|
+
);
|
|
868
|
+
const clients = selection.clients;
|
|
869
|
+
const connectorWritesRequested = connectRequested && !dryRun;
|
|
870
|
+
const writeClientIds = connectRequested && selection.connectable_client_ids ? selection.connectable_client_ids : null;
|
|
871
|
+
const connectors = await setupConnectorPlans(flags, artifacts, clients, connectorWritesRequested, displays, writeClientIds);
|
|
872
|
+
const doctor = await setupDoctorChecks(flags, artifacts, clients, displays);
|
|
873
|
+
const ok = artifacts.verifyReport.ok === true;
|
|
874
|
+
const anyConnectorWritePerformed = connectors.some((connector) => connector.connect_plan.writes_performed === true);
|
|
875
|
+
|
|
876
|
+
print({
|
|
877
|
+
ok,
|
|
878
|
+
schema: artifacts.bundle.schema,
|
|
879
|
+
command: 'enigma init',
|
|
880
|
+
onboarding_schema: 'enigma.init.v1',
|
|
881
|
+
dry_run: dryRun,
|
|
882
|
+
artifacts_written: !dryRun,
|
|
883
|
+
bundle: displays.bundle,
|
|
884
|
+
out_dir: publicPathDisplay(outDirInput, 'out-dir'),
|
|
885
|
+
context_pack: displays.context_pack,
|
|
886
|
+
export: displays.export,
|
|
887
|
+
verify_report: displays.verify_report,
|
|
888
|
+
subject_id: artifacts.bundle.vault?.subject_id,
|
|
889
|
+
client_configs_written: anyConnectorWritePerformed,
|
|
890
|
+
client_config_write_requested: connectorWritesRequested,
|
|
891
|
+
connector_write_mode: connectRequested ? (selection.connectable_client_ids ? 'installed_only' : 'selected_clients') : 'plan_only',
|
|
892
|
+
connect_requested: connectRequested,
|
|
893
|
+
selected_clients: clients,
|
|
894
|
+
skipped_clients: selection.skipped,
|
|
895
|
+
client_selection: publicSetupClientSelection(selection),
|
|
896
|
+
connector_write_skips: connectorWriteSkips(connectors),
|
|
897
|
+
connectors,
|
|
898
|
+
mcp_config_snippets: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.mcp_config_snippet])),
|
|
899
|
+
connect_plans: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.connect_plan])),
|
|
900
|
+
memory_source: setupMemorySource(flags),
|
|
901
|
+
memory_plaintext_echoed: false,
|
|
902
|
+
raw_memory_printed: false,
|
|
903
|
+
memory_count: Array.isArray(artifacts.bundle.memory_objects) ? artifacts.bundle.memory_objects.length : 0,
|
|
904
|
+
receipt_count: Array.isArray(artifacts.bundle.receipts) ? artifacts.bundle.receipts.length : 0,
|
|
905
|
+
context_item_count: Array.isArray(artifacts.contextPack.memories) ? artifacts.contextPack.memories.length : 0,
|
|
906
|
+
verify_ok: ok,
|
|
907
|
+
provider_credentials_required: false,
|
|
908
|
+
hosted_saas_live: false,
|
|
909
|
+
solana_required: false,
|
|
910
|
+
browser_extension_required: false,
|
|
911
|
+
provider_native_memory_canonical: false,
|
|
912
|
+
next_commands: initNextCommands({ dryRun, bundleDisplay: displays.bundle, outDirDisplay: publicPathDisplay(outDirInput, 'out-dir'), exportDisplay: displays.export, clients, requestedSelection, connectRequested, overwrite, connectorWritesPerformed: anyConnectorWritePerformed }),
|
|
913
|
+
checks: doctor.checks,
|
|
914
|
+
claim_boundaries: { ...SETUP_CLAIM_BOUNDARIES, hosted_saas_live: false, raw_memory_printed: false, solana_required: false, browser_extension_required: false },
|
|
915
|
+
}, io);
|
|
916
|
+
return ok ? 0 : 1;
|
|
774
917
|
}
|
|
775
918
|
|
|
776
919
|
function setupClientIds(flags) {
|
|
@@ -908,10 +1051,34 @@ function setupNextCommands(bundleInput, exportDisplay, clients, writeConnectors)
|
|
|
908
1051
|
`enigma context --bundle ${commandPath(bundleInput)} --query "project context"`,
|
|
909
1052
|
`enigma verify --export ${commandPath(exportDisplay)}`,
|
|
910
1053
|
];
|
|
911
|
-
if (!writeConnectors) commands.push(`enigma connect ${primaryClient} --bundle ${commandPath(bundleInput)}`);
|
|
1054
|
+
if (!writeConnectors) commands.push(`enigma connect ${primaryClient} --bundle ${commandPath(bundleInput)} --dry-run`);
|
|
1055
|
+
return commands;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
function initExecuteCommand(bundleDisplay, outDirDisplay, requestedSelection, connectRequested, overwrite) {
|
|
1059
|
+
let command = `enigma init --bundle ${commandPath(bundleDisplay)} --out-dir ${commandPath(outDirDisplay)}`;
|
|
1060
|
+
for (const client of requestedSelection.explicit_clients) command += ` --client ${client}`;
|
|
1061
|
+
if (requestedSelection.auto) command += ' --client auto';
|
|
1062
|
+
if (connectRequested) command += ' --connect';
|
|
1063
|
+
if (overwrite) command += ' --overwrite';
|
|
1064
|
+
return command;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
function initNextCommands({ dryRun, bundleDisplay, outDirDisplay, exportDisplay, clients, requestedSelection, connectRequested, overwrite, connectorWritesPerformed }) {
|
|
1068
|
+
const commands = dryRun ? [initExecuteCommand(bundleDisplay, outDirDisplay, requestedSelection, connectRequested, overwrite || dryRun)] : [];
|
|
1069
|
+
commands.push(...setupNextCommands(bundleDisplay, exportDisplay, clients, connectRequested && connectorWritesPerformed));
|
|
912
1070
|
return commands;
|
|
913
1071
|
}
|
|
914
1072
|
|
|
1073
|
+
function doctorNextCommands(bundleDisplay, client) {
|
|
1074
|
+
const clientId = client ?? DEFAULT_SETUP_CLIENTS[0];
|
|
1075
|
+
return [
|
|
1076
|
+
`enigma setup --bundle ${commandPath(bundleDisplay)}`,
|
|
1077
|
+
`enigma doctor --bundle ${commandPath(bundleDisplay)} --client ${clientId}`,
|
|
1078
|
+
`enigma connect ${clientId} --bundle ${commandPath(bundleDisplay)}`,
|
|
1079
|
+
];
|
|
1080
|
+
}
|
|
1081
|
+
|
|
915
1082
|
async function setupDoctorChecks(flags, artifacts, clients, displays) {
|
|
916
1083
|
const packageJson = await readPackageJson();
|
|
917
1084
|
const requiredNodeMajor = minimumNodeMajor(packageJson.engines?.node);
|
|
@@ -938,12 +1105,15 @@ async function setupDoctorChecks(flags, artifacts, clients, displays) {
|
|
|
938
1105
|
const doctor = await doctorConnectors({ ...connectorBaseOptions, clientId: client });
|
|
939
1106
|
connectorClients.push(...doctor.clients);
|
|
940
1107
|
}
|
|
1108
|
+
const vaultPath = await writableVaultPathCheck(artifacts.bundlePath, displays.bundle);
|
|
941
1109
|
const checks = {
|
|
942
1110
|
node: {
|
|
943
1111
|
ok: requiredNodeMajor === 0 || currentNodeMajor >= requiredNodeMajor,
|
|
944
1112
|
current: process.versions.node,
|
|
945
1113
|
required: packageJson.engines?.node ?? null,
|
|
946
1114
|
},
|
|
1115
|
+
npm: npmUserAgentCheck(),
|
|
1116
|
+
vault_path: vaultPath,
|
|
947
1117
|
package_bins: {
|
|
948
1118
|
ok: binEntries.every((entry) => entry.declared && entry.exists),
|
|
949
1119
|
required: REQUIRED_PACKAGE_BINS,
|
|
@@ -1038,6 +1208,33 @@ function publicSetupClientSelection(selection) {
|
|
|
1038
1208
|
};
|
|
1039
1209
|
}
|
|
1040
1210
|
|
|
1211
|
+
function setupStaticClientSelection(requestedSelection) {
|
|
1212
|
+
return {
|
|
1213
|
+
...requestedSelection,
|
|
1214
|
+
fallback_used: false,
|
|
1215
|
+
selected: requestedSelection.clients.map((clientId) => {
|
|
1216
|
+
const profile = getClientProfile(clientId);
|
|
1217
|
+
return publicSetupClientSelectionEntry({ client_id: clientId, display_name: profile.display_name }, requestedSelection.mode === 'default' ? 'default_setup_client' : 'explicit_client');
|
|
1218
|
+
}),
|
|
1219
|
+
skipped: [],
|
|
1220
|
+
connectable_client_ids: null,
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
async function setupClientSelection(flags, artifacts, requestedSelection, autoSelect, mode) {
|
|
1225
|
+
return autoSelect ? setupAutoClientSelection(flags, artifacts, DEFAULT_SETUP_CLIENTS, mode) : setupStaticClientSelection(requestedSelection);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
function connectorWriteSkips(connectors) {
|
|
1229
|
+
return connectors
|
|
1230
|
+
.filter((connector) => connector.write_skipped_reason)
|
|
1231
|
+
.map((connector) => ({
|
|
1232
|
+
client_id: connector.client_id,
|
|
1233
|
+
display_name: connector.display_name,
|
|
1234
|
+
reason: connector.write_skipped_reason,
|
|
1235
|
+
}));
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1041
1238
|
export async function setupCommand(flags, io) {
|
|
1042
1239
|
const bundleInput = pathFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE);
|
|
1043
1240
|
const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], dirname(bundleInput));
|
|
@@ -1055,18 +1252,13 @@ export async function setupCommand(flags, io) {
|
|
|
1055
1252
|
} catch (error) {
|
|
1056
1253
|
throw publicSetupError(error, rawDisplays, displays);
|
|
1057
1254
|
}
|
|
1058
|
-
const selection =
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
return publicSetupClientSelectionEntry({ client_id: clientId, display_name: profile.display_name }, requestedSelection.mode === 'default' ? 'default_setup_client' : 'explicit_client');
|
|
1066
|
-
}),
|
|
1067
|
-
skipped: [],
|
|
1068
|
-
connectable_client_ids: null,
|
|
1069
|
-
};
|
|
1255
|
+
const selection = await setupClientSelection(
|
|
1256
|
+
flags,
|
|
1257
|
+
artifacts,
|
|
1258
|
+
requestedSelection,
|
|
1259
|
+
connectInstalled || requestedSelection.auto,
|
|
1260
|
+
connectInstalled ? 'connect_installed' : 'auto',
|
|
1261
|
+
);
|
|
1070
1262
|
const clients = selection.clients;
|
|
1071
1263
|
const writeClientIds = connectInstalled ? selection.connectable_client_ids : null;
|
|
1072
1264
|
const connectors = await setupConnectorPlans(flags, artifacts, clients, connectorWritesRequested, displays, writeClientIds);
|
|
@@ -1090,28 +1282,26 @@ export async function setupCommand(flags, io) {
|
|
|
1090
1282
|
verify_report: displays.verify_report,
|
|
1091
1283
|
memory_source: setupMemorySource(flags),
|
|
1092
1284
|
memory_plaintext_echoed: false,
|
|
1285
|
+
raw_memory_printed: false,
|
|
1093
1286
|
memory_count: Array.isArray(artifacts.bundle.memory_objects) ? artifacts.bundle.memory_objects.length : 0,
|
|
1094
1287
|
receipt_count: Array.isArray(artifacts.bundle.receipts) ? artifacts.bundle.receipts.length : 0,
|
|
1095
1288
|
context_item_count: Array.isArray(artifacts.contextPack.memories) ? artifacts.contextPack.memories.length : 0,
|
|
1096
1289
|
verify_ok: artifacts.verifyReport.ok === true,
|
|
1097
1290
|
provider_credentials_required: false,
|
|
1291
|
+
hosted_saas_live: false,
|
|
1292
|
+
solana_required: false,
|
|
1293
|
+
browser_extension_required: false,
|
|
1098
1294
|
provider_native_memory_canonical: false,
|
|
1099
1295
|
selected_clients: clients,
|
|
1100
1296
|
skipped_clients: selection.skipped,
|
|
1101
1297
|
client_selection: publicSetupClientSelection(selection),
|
|
1102
|
-
connector_write_skips: connectors
|
|
1103
|
-
.filter((connector) => connector.write_skipped_reason)
|
|
1104
|
-
.map((connector) => ({
|
|
1105
|
-
client_id: connector.client_id,
|
|
1106
|
-
display_name: connector.display_name,
|
|
1107
|
-
reason: connector.write_skipped_reason,
|
|
1108
|
-
})),
|
|
1298
|
+
connector_write_skips: connectorWriteSkips(connectors),
|
|
1109
1299
|
connectors,
|
|
1110
1300
|
mcp_config_snippets: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.mcp_config_snippet])),
|
|
1111
1301
|
connect_plans: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.connect_plan])),
|
|
1112
1302
|
next_commands: setupNextCommands(displays.bundle, displays.export, clients, connectorWritesRequested && (!connectInstalled || anyConnectorWritePerformed)),
|
|
1113
1303
|
checks: doctor.checks,
|
|
1114
|
-
claim_boundaries: { ...SETUP_CLAIM_BOUNDARIES },
|
|
1304
|
+
claim_boundaries: { ...SETUP_CLAIM_BOUNDARIES, hosted_saas_live: false, raw_memory_printed: false, solana_required: false, browser_extension_required: false },
|
|
1115
1305
|
}, io);
|
|
1116
1306
|
return ok ? 0 : 1;
|
|
1117
1307
|
}
|
|
@@ -1120,21 +1310,29 @@ export async function quickstartCommand(flags, io) {
|
|
|
1120
1310
|
const bundleInput = pathFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE);
|
|
1121
1311
|
const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], dirname(bundleInput));
|
|
1122
1312
|
const overwrite = booleanFlag(flags, ['overwrite'], false);
|
|
1123
|
-
const
|
|
1313
|
+
const displays = setupPublicDisplays(bundleInput, outDirInput);
|
|
1314
|
+
const rawOutputs = quickstartOutputs(bundleInput, outDirInput);
|
|
1315
|
+
await assertCanWriteQuickstartOutputs([
|
|
1316
|
+
{ path: rawOutputs.bundlePath, display: displays.bundle },
|
|
1317
|
+
{ path: rawOutputs.contextPackPath, display: displays.context_pack },
|
|
1318
|
+
{ path: rawOutputs.exportPath, display: displays.export },
|
|
1319
|
+
{ path: rawOutputs.verifyReportPath, display: displays.verify_report },
|
|
1320
|
+
], overwrite);
|
|
1321
|
+
const artifacts = await buildQuickstartArtifacts(flags, { bundleInput, outDirInput, overwrite, write: true, checkExisting: false });
|
|
1124
1322
|
|
|
1125
1323
|
print({
|
|
1126
1324
|
ok: artifacts.verifyReport.ok === true,
|
|
1127
|
-
bundle:
|
|
1128
|
-
context_pack:
|
|
1129
|
-
export:
|
|
1130
|
-
verify_report:
|
|
1325
|
+
bundle: displays.bundle,
|
|
1326
|
+
context_pack: displays.context_pack,
|
|
1327
|
+
export: displays.export,
|
|
1328
|
+
verify_report: displays.verify_report,
|
|
1131
1329
|
memory_count: Array.isArray(artifacts.bundle.memory_objects) ? artifacts.bundle.memory_objects.length : 0,
|
|
1132
1330
|
receipt_count: Array.isArray(artifacts.bundle.receipts) ? artifacts.bundle.receipts.length : 0,
|
|
1133
1331
|
context_item_count: Array.isArray(artifacts.contextPack.memories) ? artifacts.contextPack.memories.length : 0,
|
|
1134
1332
|
verify_ok: artifacts.verifyReport.ok === true,
|
|
1135
1333
|
next_commands: [
|
|
1136
|
-
`enigma verify --export ${
|
|
1137
|
-
`enigma connect generic-mcp --bundle ${
|
|
1334
|
+
`enigma verify --export ${displays.export}`,
|
|
1335
|
+
`enigma connect generic-mcp --bundle ${displays.bundle} --dry-run`,
|
|
1138
1336
|
],
|
|
1139
1337
|
claim_boundaries: {
|
|
1140
1338
|
local_only: true,
|
|
@@ -1329,13 +1527,17 @@ async function deleteCommand(flags, io) {
|
|
|
1329
1527
|
async function contextCommand(flags, io) {
|
|
1330
1528
|
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1331
1529
|
const { vault, passport } = await loadState(bundlePath);
|
|
1530
|
+
const query = getFlag(flags, ['query', 'q'], '');
|
|
1531
|
+
const optimize = getFlag(flags, ['optimize']) === true
|
|
1532
|
+
|| getFlag(flags, ['optimize']) === 'true'
|
|
1533
|
+
|| String(query).trim().length > 0;
|
|
1332
1534
|
const pack = compileContextPack({
|
|
1333
1535
|
vault,
|
|
1334
1536
|
passport,
|
|
1335
|
-
query
|
|
1537
|
+
query,
|
|
1336
1538
|
purpose: getFlag(flags, ['purpose'], 'local_context'),
|
|
1337
1539
|
limit: Number(getFlag(flags, ['limit'], 8)),
|
|
1338
|
-
optimize
|
|
1540
|
+
optimize,
|
|
1339
1541
|
max_estimated_tokens: parseOptionalNumber(getFlag(flags, ['max-estimated-tokens', 'maxEstimatedTokens'])),
|
|
1340
1542
|
price_per_million_tokens: parseOptionalNumber(getFlag(flags, ['price-per-million-tokens', 'pricePerMillionTokens'])),
|
|
1341
1543
|
currency: getFlag(flags, ['currency']),
|
|
@@ -1531,7 +1733,7 @@ function testDriveNextCommands(bundleDisplay, crossModelReportDisplay) {
|
|
|
1531
1733
|
`enigma status --bundle ${quotedBundle}`,
|
|
1532
1734
|
`enigma search --bundle ${quotedBundle} --query "local proof bundle"`,
|
|
1533
1735
|
`enigma demo cross-model --bundle ${quotedBundle} --out ${quotedReport}`,
|
|
1534
|
-
'
|
|
1736
|
+
'enigma setup --overwrite',
|
|
1535
1737
|
];
|
|
1536
1738
|
}
|
|
1537
1739
|
|
|
@@ -1736,7 +1938,7 @@ export async function testDriveCommand(flags, io) {
|
|
|
1736
1938
|
out_dir: outDirInput,
|
|
1737
1939
|
bundle: bundleInput,
|
|
1738
1940
|
install_command: `npm install -g ${packageJson.name ?? 'enigma-memory'}`,
|
|
1739
|
-
release_target: '0.1.
|
|
1941
|
+
release_target: '0.1.14',
|
|
1740
1942
|
artifacts_written: !dryRun,
|
|
1741
1943
|
client_configs_written: false,
|
|
1742
1944
|
client_config_write_required: false,
|
|
@@ -1842,10 +2044,11 @@ export async function doctorCommand(flags, io) {
|
|
|
1842
2044
|
};
|
|
1843
2045
|
}));
|
|
1844
2046
|
const schemas = await schemaFiles();
|
|
2047
|
+
const bundleInput = pathFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE);
|
|
1845
2048
|
const selectedClient = getFlag(flags, ['client']);
|
|
1846
2049
|
const doctorOptions = selectedClient && selectedClient !== true
|
|
1847
|
-
? { ...connectorOptions(flags), clientId: String(selectedClient) }
|
|
1848
|
-
: { ...connectorOptions(flags), clientId: undefined };
|
|
2050
|
+
? { ...connectorOptions(flags), clientId: String(selectedClient), redactPaths: true }
|
|
2051
|
+
: { ...connectorOptions(flags), clientId: undefined, redactPaths: true };
|
|
1849
2052
|
const connectorDoctor = await doctorConnectors(doctorOptions);
|
|
1850
2053
|
const profile = getClientProfile(String(selectedClient && selectedClient !== true ? selectedClient : 'generic-mcp'), connectorOptions(flags));
|
|
1851
2054
|
const checks = {
|
|
@@ -1854,6 +2057,7 @@ export async function doctorCommand(flags, io) {
|
|
|
1854
2057
|
current: process.versions.node,
|
|
1855
2058
|
required: packageJson.engines?.node ?? null,
|
|
1856
2059
|
},
|
|
2060
|
+
npm: npmUserAgentCheck(),
|
|
1857
2061
|
package_bins: {
|
|
1858
2062
|
ok: binEntries.every((entry) => entry.declared && entry.exists),
|
|
1859
2063
|
required: REQUIRED_PACKAGE_BINS,
|
|
@@ -1864,8 +2068,9 @@ export async function doctorCommand(flags, io) {
|
|
|
1864
2068
|
bundle_default_path: {
|
|
1865
2069
|
ok: DEFAULT_BUNDLE === '.enigma/bundle.json',
|
|
1866
2070
|
path: DEFAULT_BUNDLE,
|
|
1867
|
-
resolved: resolve(
|
|
2071
|
+
resolved: publicPathDisplay(resolve(bundleInput), 'bundle-path'),
|
|
1868
2072
|
},
|
|
2073
|
+
vault_path: await writableVaultPathCheck(resolve(bundleInput), publicPathDisplay(bundleInput, 'bundle-path')),
|
|
1869
2074
|
schemas: {
|
|
1870
2075
|
ok: schemas.length > 0,
|
|
1871
2076
|
count: schemas.length,
|
|
@@ -1883,11 +2088,14 @@ export async function doctorCommand(flags, io) {
|
|
|
1883
2088
|
ok,
|
|
1884
2089
|
node: checks.node,
|
|
1885
2090
|
package_bins: checks.package_bins,
|
|
2091
|
+
npm: checks.npm,
|
|
2092
|
+
vault_path: checks.vault_path,
|
|
1886
2093
|
bundle_default_path: checks.bundle_default_path,
|
|
1887
2094
|
schema_count: checks.schemas.count,
|
|
1888
2095
|
schemas: checks.schemas,
|
|
1889
2096
|
mcp_command_name: checks.mcp_command_name.command,
|
|
1890
2097
|
connectors: checks.connectors,
|
|
2098
|
+
next_commands: doctorNextCommands(checks.vault_path.path, String(selectedClient && selectedClient !== true ? selectedClient : 'generic-mcp')),
|
|
1891
2099
|
checks,
|
|
1892
2100
|
}, io);
|
|
1893
2101
|
return ok ? 0 : 1;
|
|
@@ -2181,7 +2389,162 @@ function chainArtifactValidator(artifact) {
|
|
|
2181
2389
|
if (schema === 'enigma.proof_network.capability_revocation.v1') return [schema, validateCapabilityRevocation];
|
|
2182
2390
|
if (schema === 'enigma.proof_network.benchmark_attestation.v1') return [schema, validateBenchmarkAttestation];
|
|
2183
2391
|
if (schema === 'enigma.proof_network.packet.v1') return [schema, validateProofNetworkPacket];
|
|
2184
|
-
throw new Error(
|
|
2392
|
+
throw new Error(schema ? 'Unsupported proof-network artifact schema.' : 'Unsupported proof-network artifact schema: missing.');
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
const SOLANA_SUBMIT_CLUSTERS = new Set(['devnet', 'testnet', 'mainnet-beta', 'localnet']);
|
|
2396
|
+
const SOLANA_MEMO_PROGRAM_ID = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
|
|
2397
|
+
|
|
2398
|
+
function solanaSubmitCluster(flags) {
|
|
2399
|
+
const cluster = String(requireFlag(flags, ['cluster'], 'cluster'));
|
|
2400
|
+
if (!SOLANA_SUBMIT_CLUSTERS.has(cluster)) {
|
|
2401
|
+
throw new Error('--cluster must be one of devnet, testnet, mainnet-beta, or localnet.');
|
|
2402
|
+
}
|
|
2403
|
+
return cluster;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
function createSolanaProofMemoRef(schema, artifact, cluster) {
|
|
2407
|
+
const artifactHash = proofNetworkSha256Json(artifact);
|
|
2408
|
+
const proofCommitment = proofNetworkSha256Json({
|
|
2409
|
+
rail: 'solana-memo-v1',
|
|
2410
|
+
cluster,
|
|
2411
|
+
artifact_type: schema,
|
|
2412
|
+
artifact_hash: artifactHash,
|
|
2413
|
+
});
|
|
2414
|
+
return {
|
|
2415
|
+
v: 1,
|
|
2416
|
+
protocol: 'enigma-proof-network',
|
|
2417
|
+
rail: 'solana-memo',
|
|
2418
|
+
cluster,
|
|
2419
|
+
artifact_type: schema,
|
|
2420
|
+
artifact_hash: artifactHash,
|
|
2421
|
+
proof_commitment: proofCommitment,
|
|
2422
|
+
};
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
function solanaSubmitRpcLabel(flags, cluster) {
|
|
2426
|
+
return getFlag(flags, ['rpc']) ? '<custom-rpc>' : `${cluster}:default`;
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
function solanaSubmitDryRunExplanation() {
|
|
2430
|
+
return 'Dry run only. Execute mode would submit one Solana Memo instruction containing only memo_ref JSON: schema, artifact hash, cluster, and compact proof commitment. The raw artifact body, memory, prompts, transcripts, embeddings, provider responses, private keys, and local paths are not included.';
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
async function loadSolanaWeb3() {
|
|
2434
|
+
try {
|
|
2435
|
+
return await import('@solana/web3.js');
|
|
2436
|
+
} catch {
|
|
2437
|
+
throw new Error('Solana execute mode requires optional dependency @solana/web3.js. Install package dependencies before using --execute.');
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
async function readSolanaKeypair(path) {
|
|
2442
|
+
let parsed;
|
|
2443
|
+
try {
|
|
2444
|
+
parsed = JSON.parse(await readFile(path, 'utf8'));
|
|
2445
|
+
} catch {
|
|
2446
|
+
throw new Error('Unable to read a valid Solana --keypair JSON array.');
|
|
2447
|
+
}
|
|
2448
|
+
if (!Array.isArray(parsed) || parsed.length === 0) throw new Error('Solana --keypair must be a JSON array of secret-key bytes.');
|
|
2449
|
+
const bytes = new Uint8Array(parsed.length);
|
|
2450
|
+
for (let i = 0; i < parsed.length; i += 1) {
|
|
2451
|
+
const value = parsed[i];
|
|
2452
|
+
if (!Number.isInteger(value) || value < 0 || value > 255) throw new Error('Solana --keypair must be a JSON array of secret-key bytes.');
|
|
2453
|
+
bytes[i] = value;
|
|
2454
|
+
}
|
|
2455
|
+
return bytes;
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
function solanaSubmitRpcUrl(flags, cluster, clusterApiUrl) {
|
|
2459
|
+
const rpc = getFlag(flags, ['rpc']);
|
|
2460
|
+
if (rpc !== undefined && rpc !== true && rpc !== '') return String(lastFlagValue(rpc));
|
|
2461
|
+
if (cluster === 'localnet') return 'http://127.0.0.1:8899';
|
|
2462
|
+
return clusterApiUrl(cluster);
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
async function submitSolanaMemoTransaction(flags, cluster, memoRef) {
|
|
2466
|
+
const keypairPath = resolve(String(requireFlag(flags, ['keypair'], 'keypair')));
|
|
2467
|
+
const secretKey = await readSolanaKeypair(keypairPath);
|
|
2468
|
+
const { Connection, Keypair, PublicKey, Transaction, TransactionInstruction, clusterApiUrl, sendAndConfirmTransaction } = await loadSolanaWeb3();
|
|
2469
|
+
let payer;
|
|
2470
|
+
try {
|
|
2471
|
+
payer = Keypair.fromSecretKey(secretKey);
|
|
2472
|
+
} catch {
|
|
2473
|
+
throw new Error('Solana --keypair could not be loaded as a signer.');
|
|
2474
|
+
}
|
|
2475
|
+
const connection = new Connection(solanaSubmitRpcUrl(flags, cluster, clusterApiUrl), 'confirmed');
|
|
2476
|
+
const memoBytes = Buffer.from(JSON.stringify(memoRef), 'utf8');
|
|
2477
|
+
const transaction = new Transaction().add(new TransactionInstruction({
|
|
2478
|
+
keys: [],
|
|
2479
|
+
programId: new PublicKey(SOLANA_MEMO_PROGRAM_ID),
|
|
2480
|
+
data: memoBytes,
|
|
2481
|
+
}));
|
|
2482
|
+
try {
|
|
2483
|
+
return await sendAndConfirmTransaction(connection, transaction, [payer], { commitment: 'confirmed' });
|
|
2484
|
+
} catch {
|
|
2485
|
+
throw new Error('Solana submission failed before a public-safe transaction signature was returned.');
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
export async function chainSubmitSolanaCommand(flags, io, positionalFile = undefined) {
|
|
2490
|
+
const inPath = resolve(String(requireFileArg(flags, ['file', 'in'], positionalFile, 'file')));
|
|
2491
|
+
const cluster = solanaSubmitCluster(flags);
|
|
2492
|
+
let artifact;
|
|
2493
|
+
try {
|
|
2494
|
+
artifact = await readJson(inPath);
|
|
2495
|
+
} catch {
|
|
2496
|
+
throw new Error('Unable to read a valid proof artifact JSON file.');
|
|
2497
|
+
}
|
|
2498
|
+
assertNoPrivateProofPayload(artifact);
|
|
2499
|
+
const [schema, validate] = chainArtifactValidator(artifact);
|
|
2500
|
+
const result = chainValidationResult(validate, artifact);
|
|
2501
|
+
if (result.ok !== true) throw new Error(result.errors?.join('; ') || 'Invalid proof-network artifact.');
|
|
2502
|
+
const memoRef = createSolanaProofMemoRef(schema, artifact, cluster);
|
|
2503
|
+
const execute = booleanFlag(flags, ['execute'], false);
|
|
2504
|
+
if (!execute) {
|
|
2505
|
+
print({
|
|
2506
|
+
ok: true,
|
|
2507
|
+
command: 'chain submit-solana',
|
|
2508
|
+
mode: 'dry-run',
|
|
2509
|
+
chain: 'solana',
|
|
2510
|
+
cluster,
|
|
2511
|
+
rpc_endpoint: solanaSubmitRpcLabel(flags, cluster),
|
|
2512
|
+
transaction_submitted: false,
|
|
2513
|
+
raw_memory_on_chain: false,
|
|
2514
|
+
artifact_type: schema,
|
|
2515
|
+
artifact_hash: memoRef.artifact_hash,
|
|
2516
|
+
proof_commitment: memoRef.proof_commitment,
|
|
2517
|
+
memo_program: SOLANA_MEMO_PROGRAM_ID,
|
|
2518
|
+
memo_ref: memoRef,
|
|
2519
|
+
would_submit: {
|
|
2520
|
+
instruction_count: 1,
|
|
2521
|
+
program: 'spl-memo',
|
|
2522
|
+
payload: 'memo_ref',
|
|
2523
|
+
},
|
|
2524
|
+
validation: result,
|
|
2525
|
+
explanation: solanaSubmitDryRunExplanation(),
|
|
2526
|
+
}, io);
|
|
2527
|
+
return 0;
|
|
2528
|
+
}
|
|
2529
|
+
const signature = await submitSolanaMemoTransaction(flags, cluster, memoRef);
|
|
2530
|
+
print({
|
|
2531
|
+
ok: true,
|
|
2532
|
+
command: 'chain submit-solana',
|
|
2533
|
+
mode: 'execute',
|
|
2534
|
+
chain: 'solana',
|
|
2535
|
+
cluster,
|
|
2536
|
+
rpc_endpoint: solanaSubmitRpcLabel(flags, cluster),
|
|
2537
|
+
transaction_submitted: true,
|
|
2538
|
+
raw_memory_on_chain: false,
|
|
2539
|
+
signature,
|
|
2540
|
+
artifact_type: schema,
|
|
2541
|
+
artifact_hash: memoRef.artifact_hash,
|
|
2542
|
+
proof_commitment: memoRef.proof_commitment,
|
|
2543
|
+
memo_program: SOLANA_MEMO_PROGRAM_ID,
|
|
2544
|
+
memo_ref: memoRef,
|
|
2545
|
+
validation: result,
|
|
2546
|
+
}, io);
|
|
2547
|
+
return 0;
|
|
2185
2548
|
}
|
|
2186
2549
|
|
|
2187
2550
|
export async function chainAnchorCommand(flags, io) {
|
|
@@ -2547,6 +2910,7 @@ function usage() {
|
|
|
2547
2910
|
'chain revoke',
|
|
2548
2911
|
'chain attest',
|
|
2549
2912
|
'chain verify',
|
|
2913
|
+
'chain submit-solana',
|
|
2550
2914
|
],
|
|
2551
2915
|
connector_options: {
|
|
2552
2916
|
'--bundle <path>': 'Absolute local Enigma vault bundle path rendered as ENIGMA_BUNDLE.',
|
|
@@ -2570,6 +2934,16 @@ function usage() {
|
|
|
2570
2934
|
'enigma status --bundle <path>': 'Show local Memory Passport counts, roots, owner display fields, connector readiness, and next commands.',
|
|
2571
2935
|
'enigma passport status --bundle <path>': 'Alias for enigma status.',
|
|
2572
2936
|
},
|
|
2937
|
+
init_options: {
|
|
2938
|
+
'--dry-run': 'Print the first-run plan without writing local artifacts or client configs.',
|
|
2939
|
+
'--bundle <path>': 'Bundle JSON to create. Defaults to .enigma/bundle.json.',
|
|
2940
|
+
'--out-dir <path>': 'Directory for context-pack.json, export.json, and verify-report.json. Defaults to the bundle directory.',
|
|
2941
|
+
'--client <id|auto>': `Client to plan; repeat or comma-separate. Use auto to plan installed/config-present clients, falling back to ${DEFAULT_SETUP_CLIENTS.join(', ')}.`,
|
|
2942
|
+
'--connect': 'Explicitly write selected client MCP configs; with default client selection, writes only installed/config-present client configs and skips missing configs.',
|
|
2943
|
+
'--memory-file <path>': 'Read local memory text from a file without echoing plaintext. Alias: --text-file.',
|
|
2944
|
+
'--memory-text <text>': 'Inline demo-only memory text. Avoid for private content because argv can be logged.',
|
|
2945
|
+
'--overwrite': 'Replace existing local first-run artifacts.',
|
|
2946
|
+
},
|
|
2573
2947
|
setup_options: {
|
|
2574
2948
|
'--bundle <path>': 'Bundle JSON to create. Defaults to .enigma/bundle.json.',
|
|
2575
2949
|
'--out-dir <path>': 'Directory for context-pack.json, export.json, and verify-report.json. Defaults to the bundle directory.',
|
|
@@ -2648,7 +3022,8 @@ function usage() {
|
|
|
2648
3022
|
revoke: 'enigma chain revoke --grant-hash <sha256:...> --reason <public-reason-code> [--revocation-ref <public-ref>] [--out <file>]',
|
|
2649
3023
|
attest: 'enigma chain attest (--report-hash <sha256:...> | --report-file <report.json>) --dataset-ref <sha256:...> --runner-ref <public-runner-ref> --package-ref <public-package-ref> [--score name=value] [--out <file>]',
|
|
2650
3024
|
verify: 'enigma chain verify --file <proof-artifact.json>',
|
|
2651
|
-
|
|
3025
|
+
submit_solana: 'enigma chain submit-solana --file <proof-artifact.json> --cluster <devnet|testnet|mainnet-beta|localnet> [--rpc <url>] [--execute --keypair <solana-keypair.json>]',
|
|
3026
|
+
boundary: 'Proof Network chain commands default to local planning and dry-run validation. submit-solana only submits a Solana Memo transaction when --execute is passed; it carries compact public-safe commitment/ref JSON, never raw memory or artifact bodies.',
|
|
2652
3027
|
},
|
|
2653
3028
|
relay_gateway_options: {
|
|
2654
3029
|
'--host <host>': 'Bind host. Defaults to 127.0.0.1.',
|
|
@@ -2679,7 +3054,7 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
2679
3054
|
const twoPartCommands = ['boundary', 'mcp', 'mesh', 'enterprise', 'capsule', 'relay', 'gateway', 'connect', 'disconnect', 'import', 'native-host', 'meter', 'settlement', 'chain', 'demo', 'passport'];
|
|
2680
3055
|
const flags = parseArgs(twoPartCommands.includes(command) ? argv.slice(2) : argv.slice(1));
|
|
2681
3056
|
const positionalFile = optionalPositional(argv[2]);
|
|
2682
|
-
if ((command === 'chain' && (!subcommand || subcommand === '--help' || subcommand === '-h' || flags.has('help'))) || ((flags.has('help') || argv.includes('-h')) && (command === 'setup' || command === 'test-drive' || command === 'search' || command === 'status' || (command === 'passport' && subcommand === 'status') || ((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model')))) {
|
|
3057
|
+
if ((command === 'chain' && (!subcommand || subcommand === '--help' || subcommand === '-h' || flags.has('help'))) || ((flags.has('help') || argv.includes('-h')) && (command === 'init' || command === 'setup' || command === 'test-drive' || command === 'search' || command === 'status' || (command === 'passport' && subcommand === 'status') || ((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model')))) {
|
|
2683
3058
|
print(usage(), io);
|
|
2684
3059
|
return 0;
|
|
2685
3060
|
}
|
|
@@ -2726,6 +3101,7 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
2726
3101
|
if (command === 'chain' && subcommand === 'revoke') return await chainRevokeCommand(flags, io);
|
|
2727
3102
|
if (command === 'chain' && subcommand === 'attest') return await chainAttestCommand(flags, io);
|
|
2728
3103
|
if (command === 'chain' && subcommand === 'verify') return await chainVerifyCommand(flags, io, positionalFile);
|
|
3104
|
+
if (command === 'chain' && subcommand === 'submit-solana') return await chainSubmitSolanaCommand(flags, io, positionalFile);
|
|
2729
3105
|
if (command === 'native-host' && subcommand === 'install-plan') return await nativeHostInstallPlanCommand(flags, io);
|
|
2730
3106
|
if (command === 'mesh' && subcommand === 'demo') return await meshDemoCommand(flags, io);
|
|
2731
3107
|
if (command === 'enterprise' && subcommand === 'demo') return await enterpriseDemoCommand(flags, io);
|