enigma-memory 0.1.18 → 0.1.22
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 +76 -24
- package/apps/cli/bin/enigma-desktop.mjs +140 -0
- package/apps/cli/bin/enigma-terminal.mjs +78 -0
- package/apps/cli/bin/enigma.mjs +1923 -285
- package/apps/desktop/electron-main.cjs +217 -0
- package/apps/desktop/package.json +12 -0
- package/apps/desktop/src/app.js +264 -7
- package/apps/desktop/src/index.html +3514 -1373
- package/apps/desktop/src/launch-electron.mjs +51 -0
- package/apps/desktop/src/server.mjs +2914 -0
- package/apps/desktop/src/styles.css +2972 -260
- package/apps/desktop/src/zk-browser-prove.mjs +53 -0
- package/apps/desktop/src/zk-state.mjs +1789 -0
- package/apps/gateway/bin/enigma-gateway.mjs +102 -5
- package/apps/gateway/src/server.mjs +271 -8
- package/apps/ios/EnigmaCore/Package.swift +12 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/EnigmaAPIClient.swift +227 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/Models.swift +278 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/PKCE.swift +96 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/PrivacyMinimizer.swift +187 -0
- package/apps/ios/EnigmaCore/Sources/EnigmaCore/ToolModels.swift +129 -0
- package/apps/ios/EnigmaCore/Tests/EnigmaCoreTests/EnigmaCoreTests.swift +42 -0
- package/apps/ios/EnigmaIOS/Enigma/AppModel.swift +346 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AccentColor.colorset/Contents.json +12 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/Contents.json +11 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/EnigmaAppIcon.png +0 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/Contents.json +3 -0
- package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/LaunchBackground.colorset/Contents.json +12 -0
- package/apps/ios/EnigmaIOS/Enigma/ChatView.swift +181 -0
- package/apps/ios/EnigmaIOS/Enigma/CouncilView.swift +78 -0
- package/apps/ios/EnigmaIOS/Enigma/CreateView.swift +152 -0
- package/apps/ios/EnigmaIOS/Enigma/EnigmaApp.swift +52 -0
- package/apps/ios/EnigmaIOS/Enigma/Info.plist +52 -0
- package/apps/ios/EnigmaIOS/Enigma/NaturalLanguagePrivacyTagger.swift +26 -0
- package/apps/ios/EnigmaIOS/Enigma/OAuthClient.swift +321 -0
- package/apps/ios/EnigmaIOS/Enigma/OnboardingView.swift +105 -0
- package/apps/ios/EnigmaIOS/Enigma/PrivateVaultView.swift +275 -0
- package/apps/ios/EnigmaIOS/Enigma/SecureStore.swift +76 -0
- package/apps/ios/EnigmaIOS/Enigma/SettingsView.swift +60 -0
- package/apps/ios/EnigmaIOS/Enigma/Theme.swift +80 -0
- package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/project.pbxproj +211 -0
- package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/xcshareddata/xcschemes/Enigma.xcscheme +23 -0
- package/apps/native-host/README.md +19 -8
- package/apps/native-host/bin/enigma-native-host.mjs +229 -13
- package/apps/relay/bin/enigma-relay.mjs +103 -5
- package/apps/relay/src/federation-runtime.mjs +618 -0
- package/apps/relay/src/server.mjs +310 -9
- package/apps/verifier/bin/enigma-verify.mjs +327 -11
- package/cortex-v3/circuits/build/intent_vk_bytes.json +35 -0
- package/cortex-v3/circuits/build/sale_vk_bytes.json +35 -0
- package/cortex-v3/circuits/build/vk_bytes.json +32 -0
- package/cortex-v3/proving-assets.json +64 -0
- package/cortex-v3/zk/BUILD-CONTRACT.md +87 -0
- package/cortex-v3/zk/action-transition-vk.json +119 -0
- package/cortex-v3/zk/alias-adversarial.test.mjs +220 -0
- package/cortex-v3/zk/groth16-verify-child.mjs +17 -0
- package/cortex-v3/zk/intent-witness.mjs +365 -0
- package/cortex-v3/zk/intent-witness.test.mjs +485 -0
- package/cortex-v3/zk/proving-assets.mjs +203 -0
- package/cortex-v3/zk/sale-witness.mjs +783 -0
- package/cortex-v3/zk/sale-witness.test.mjs +784 -0
- package/cortex-v3/zk/sealed-sale-release-vk.json +119 -0
- package/cortex-v3/zk/settlement-evidence.mjs +722 -0
- package/cortex-v3/zk/setup-intent.mjs +688 -0
- package/cortex-v3/zk/setup-sale.mjs +666 -0
- package/cortex-v3/zk/setup.mjs +594 -0
- package/cortex-v3/zk/witness.mjs +184 -0
- package/cortex-v3/zk/zk-codec.mjs +232 -0
- package/cortex-v3/zk/zk-codec.test.mjs +293 -0
- package/cortex-v3/zk/zk-settle.mjs +370 -0
- package/cortex-v3/zk/zk-tree.mjs +256 -0
- package/cortex-v3/zk/zk-tree.test.mjs +419 -0
- package/deploy/docker-compose.local-production-simulation.yml +36 -0
- package/docs/browser-extension-install.md +8 -6
- package/docs/client-connectors.md +15 -11
- package/docs/developer-ecosystem.md +15 -13
- package/docs/enigma-memory-ready-conformance.md +11 -9
- package/docs/install-anywhere.md +61 -28
- package/docs/installers-and-desktop.md +8 -7
- package/docs/novelty-invention-candidates.md +161 -161
- package/docs/proof-network-claim-boundaries.md +320 -318
- package/examples/01-quickstart-agent/index.mjs +49 -0
- package/examples/01_agent_memory_quickstart.mjs +57 -0
- package/examples/02-multi-agent-swarm/index.mjs +57 -0
- package/examples/02_cross_model_passport.mjs +64 -0
- package/examples/03-langchain-memory/index.mjs +41 -0
- package/examples/03_poseidon_commitment_verification.mjs +71 -0
- package/examples/04-python-trading-agent/trader.py +49 -0
- package/examples/README.md +27 -0
- package/examples/ci/github-actions.yml +7 -2
- package/package.json +142 -11
- package/packages/adapters/PACKAGE_CONTRACT.md +1 -1
- package/packages/connectors/src/index.js +196 -4
- package/packages/connectors/swarm-router.mjs +168 -0
- package/packages/core/src/index.js +248 -1
- package/packages/core/src/version.mjs +7 -0
- package/packages/dev-tools/package.json +19 -0
- package/packages/dev-tools/src/index.js +4 -0
- package/packages/dev-tools/src/memory-benchmark-suite.js +112 -0
- package/packages/dev-tools/src/swarm-simulator.js +101 -0
- package/packages/dev-tools/src/vault-inspector.js +114 -0
- package/packages/dev-tools/src/vector-benchmark.js +100 -0
- package/packages/developer-platform/src/access-credentials.js +341 -0
- package/packages/developer-platform/src/http.js +132 -0
- package/packages/developer-platform/src/index.js +4 -0
- package/packages/developer-platform/src/usage-http.js +60 -0
- package/packages/developer-platform/src/usage.js +295 -0
- package/packages/enclave-runtime/attestation.mjs +159 -0
- package/packages/enclave-runtime/index.mjs +47 -0
- package/packages/enclave-runtime/session-manager.mjs +253 -0
- package/packages/enclave-runtime/zeroization-proof.mjs +227 -0
- package/packages/enigma-reflex/package.json +14 -0
- package/packages/enigma-reflex/src/index.js +204 -0
- package/packages/enigma-reflex/training/generate-dataset.mjs +40 -0
- package/packages/enigma-reflex/training/requirements.txt +8 -0
- package/packages/enigma-reflex/training/train.py +314 -0
- package/packages/enigma-weave/LICENSE +22 -0
- package/packages/enigma-weave/UPSTREAM.json +21 -0
- package/packages/enigma-weave/package.json +14 -0
- package/packages/enigma-weave/src/index.js +286 -0
- package/packages/hosted-cloud/src/index.js +80 -5
- package/packages/importers/src/index.js +432 -0
- package/packages/inference-runtime/src/browser.js +401 -0
- package/packages/inference-runtime/src/chat.js +265 -0
- package/packages/inference-runtime/src/code.js +407 -0
- package/packages/inference-runtime/src/contracts.js +162 -0
- package/packages/inference-runtime/src/http.js +232 -0
- package/packages/inference-runtime/src/image.js +186 -0
- package/packages/inference-runtime/src/index.js +10 -0
- package/packages/inference-runtime/src/model-router.js +320 -0
- package/packages/inference-runtime/src/platform.js +125 -0
- package/packages/inference-runtime/src/privacy.js +400 -0
- package/packages/inference-runtime/src/video.js +253 -0
- package/packages/mcp-server/README.md +22 -6
- package/packages/mcp-server/bin/enigma-mcp.mjs +2 -1
- package/packages/mcp-server/src/index.js +1418 -105
- package/packages/mcp-server/src/oauth.js +561 -0
- package/packages/mcp-server/src/private-handoff.js +84 -0
- package/packages/mcp-server/src/remote-http.js +273 -0
- package/packages/mcp-server/src/remote-policy.js +72 -0
- package/packages/mcp-server/swarm-bridge.mjs +361 -0
- package/packages/mesh/index.d.ts +283 -0
- package/packages/mesh/package.json +23 -0
- package/packages/mesh/src/crypto.js +189 -0
- package/packages/mesh/src/federation-packets.js +353 -0
- package/packages/mesh/src/gossip.js +311 -0
- package/packages/mesh/src/index.js +6 -0
- package/packages/mesh/src/protocol.js +255 -0
- package/packages/mesh/src/router.js +279 -0
- package/packages/mesh/src/transport.js +306 -0
- package/packages/passport/src/index.js +426 -1
- package/packages/private-economy/src/credits-http.js +100 -0
- package/packages/private-economy/src/credits.js +447 -0
- package/packages/private-economy/src/index.js +5 -0
- package/packages/private-economy/src/payments-http.js +120 -0
- package/packages/private-economy/src/payments.js +509 -0
- package/packages/private-economy/src/x402.js +346 -0
- package/packages/proof-network/PACKAGE_CONTRACT.md +21 -0
- package/packages/rag/index.d.ts +182 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/THIRD_PARTY_LICENSES.txt +207 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/config.json +25 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/sha256-manifest.json +28 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +30686 -0
- package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +15 -0
- package/packages/rag/package.json +27 -0
- package/packages/rag/src/blinded-search.js +109 -0
- package/packages/rag/src/bm25.js +169 -0
- package/packages/rag/src/embeddings.js +459 -0
- package/packages/rag/src/hybrid.js +76 -0
- package/packages/rag/src/index.js +38 -0
- package/packages/rag/src/reranker.js +61 -0
- package/packages/rag/src/research.js +107 -0
- package/packages/rag/src/vector-store.js +430 -0
- package/packages/rag/src/verify-model-artifacts.mjs +4 -0
- package/packages/sdk/index.d.ts +760 -0
- package/packages/sdk/package.json +33 -0
- package/packages/sdk/python/README.md +24 -0
- package/packages/sdk/python/enigma_sdk.py +250 -0
- package/packages/sdk/python/pyproject.toml +34 -0
- package/packages/sdk/python/requirements.txt +1 -0
- package/packages/sdk/python/setup.py +20 -0
- package/packages/sdk/src/federation/capability-grant.js +389 -0
- package/packages/sdk/src/federation/federation-router.js +360 -0
- package/packages/sdk/src/federation/ghostmesh-bridge.js +497 -0
- package/packages/sdk/src/federation/index.js +3 -0
- package/packages/sdk/src/index.js +1796 -0
- package/packages/sdk/src/intelligence/contradiction.js +337 -0
- package/packages/sdk/src/intelligence/decision-engine.js +155 -0
- package/packages/sdk/src/intelligence/index.js +4 -0
- package/packages/sdk/src/intelligence/ontology.js +122 -0
- package/packages/sdk/src/intelligence/temporal.js +123 -0
- package/packages/sdk/src/market-client.js +142 -0
- package/packages/sdk/src/mesh-client.js +110 -0
- package/packages/sdk/src/middleware/index.js +3 -0
- package/packages/sdk/src/middleware/langchain.js +159 -0
- package/packages/sdk/src/middleware/llamaindex.js +101 -0
- package/packages/sdk/src/middleware/vercel-ai.js +112 -0
- package/packages/sdk/src/rag-client.js +85 -0
- package/packages/sdk/src/swarm-orchestrator.js +260 -0
- package/packages/settlement/PACKAGE_CONTRACT.md +1 -1
- package/packages/snapcompact/THIRD_PARTY_LICENSES.txt +40 -0
- package/packages/snapcompact/assets/8x13-latin1.bdf +3837 -0
- package/packages/snapcompact/index.d.ts +284 -0
- package/packages/snapcompact/package.json +25 -0
- package/packages/snapcompact/src/index.js +716 -0
- package/packages/storage/PACKAGE_CONTRACT.md +1 -1
- package/packages/terminal-console/animations.mjs +240 -0
- package/packages/terminal-console/auto-anchor.mjs +220 -0
- package/packages/terminal-console/banner.mjs +91 -0
- package/packages/terminal-console/commands.mjs +459 -0
- package/packages/terminal-console/delegation.mjs +152 -0
- package/packages/terminal-console/index.mjs +5 -0
- package/packages/terminal-console/outbox.mjs +143 -0
- package/packages/terminal-console/phantom-bridge.mjs +637 -0
- package/packages/terminal-console/repl.mjs +136 -0
- package/packages/terminal-console/signer-store.mjs +130 -0
- package/packages/terminal-console/solana-rpc.mjs +214 -0
- package/packages/terminal-console/solana-transport.mjs +189 -0
- package/packages/terminal-tui/dashboard.mjs +214 -0
- package/packages/terminal-tui/index.mjs +28 -0
- package/packages/terminal-tui/merkle-tree-renderer.mjs +268 -0
- package/packages/terminal-tui/telemetry-hud.mjs +137 -0
- package/packages/vault/index.d.ts +449 -0
- package/packages/vault/package.json +27 -0
- package/packages/vault/src/e2ee.mjs +393 -0
- package/packages/vault/src/enclave.js +481 -0
- package/packages/vault/src/erasure.js +207 -0
- package/packages/vault/src/index.js +1018 -155
- package/packages/vault/src/persistence.js +307 -0
- package/packages/vault/src/poseidon.js +354 -0
- package/packages/vault/src/receipt.js +459 -0
- package/scripts/benchmark-optical-context.mjs +166 -0
- package/scripts/bootstrap-enigma.mjs +502 -0
- package/scripts/build-edge-backend-workers.mjs +20 -5
- package/scripts/build-goal-completion-audit.mjs +72 -25
- package/scripts/build-hosted-api-key-lifecycle.mjs +26 -8
- package/scripts/build-hosted-customer-lifecycle.mjs +20 -3
- package/scripts/build-hosted-probe-worker.mjs +19 -4
- package/scripts/build-installer-assets.mjs +41 -21
- package/scripts/build-operator-evidence-starter.mjs +59 -1
- package/scripts/build-production-backend-env-kit.mjs +2 -0
- package/scripts/build-production-unblocker.mjs +3 -0
- package/scripts/check.mjs +17 -3
- package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
- package/scripts/install-enigma-local.mjs +18 -5
- package/scripts/release-audit.mjs +65 -109
- package/scripts/release-provenance.mjs +6 -0
- package/scripts/run-backend-readiness-smoke.mjs +112 -10
- package/scripts/scan-secrets.mjs +1 -0
- package/scripts/simulate-production-env.mjs +7 -2
- package/scripts/validate-hosted-backend-live.mjs +112 -1
- package/specs/antibody-pack-v1.schema.json +95 -0
- package/specs/antigen-envelope-v1.schema.json +81 -0
- package/specs/boundary-manifest-v1.schema.json +35 -35
- package/specs/capsule-v1.schema.json +55 -55
- package/specs/claim-boundary-manifest-v1.schema.json +22 -22
- package/specs/claim-ledger-v1.schema.json +291 -0
- package/specs/context-passport-v1.schema.json +59 -0
- package/specs/deletion-tombstone-v1.schema.json +26 -26
- package/specs/evidence-packet-v1.schema.json +177 -0
- package/specs/hosted-backend-live-evidence-v1.schema.json +72 -3
- package/specs/immune-scan-report-v1.schema.json +112 -0
- package/specs/lifecycle-receipt-log-v1.schema.json +67 -0
- package/specs/memory-atom-v1.schema.json +59 -0
- package/specs/memory-event-v1.schema.json +42 -42
- package/specs/passport-v1.schema.json +50 -50
- package/specs/proof-of-non-use-v1.schema.json +65 -0
- package/specs/quarantine-record-v1.schema.json +126 -0
- package/specs/receipt-v1.schema.json +61 -61
- package/specs/state-checkpoint-v1.schema.json +37 -37
- package/specs/trust-bundle-v1.schema.json +56 -56
- package/specs/trust-card-v1.schema.json +119 -0
- package/docs/proof-network-launch-plan.md +0 -421
- package/packages/metering/PACKAGE_CONTRACT.md +0 -20
- package/scripts/build-ai-orchestration-plan.mjs +0 -248
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// Enigma Sovereign Terminal — Dedicated Electron Desktop Application Window
|
|
2
|
+
// Owns the dynamic localhost server and the enigma:// private-session protocol.
|
|
3
|
+
|
|
4
|
+
const { app, BrowserWindow, shell, safeStorage } = require('electron');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const { pathToFileURL } = require('node:url');
|
|
7
|
+
|
|
8
|
+
const PROTOCOL_SCHEME = 'enigma';
|
|
9
|
+
const TEST_MODE = process.env.ENIGMA_ELECTRON_HANDOFF_TEST === '1';
|
|
10
|
+
const HANDOFF_MODULE_URL = pathToFileURL(
|
|
11
|
+
path.join(__dirname, '..', '..', 'packages', 'mcp-server', 'src', 'private-handoff.js')
|
|
12
|
+
).href;
|
|
13
|
+
|
|
14
|
+
let mainWindow = null;
|
|
15
|
+
let desktopServerInstance = null;
|
|
16
|
+
let desktopServerInfo = null;
|
|
17
|
+
let pendingHandoffUrl = process.env.ENIGMA_ELECTRON_HANDOFF_TEST_URL || findHandoffArgument(process.argv);
|
|
18
|
+
let protocolRegistered = false;
|
|
19
|
+
|
|
20
|
+
function findHandoffArgument(argv) {
|
|
21
|
+
return Array.isArray(argv)
|
|
22
|
+
? argv.find((value) => typeof value === 'string' && value.toLowerCase().startsWith('enigma://private')) || null
|
|
23
|
+
: null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function registerPrivateProtocol() {
|
|
27
|
+
if (process.defaultApp && process.argv[1]) {
|
|
28
|
+
protocolRegistered = app.setAsDefaultProtocolClient(
|
|
29
|
+
PROTOCOL_SCHEME,
|
|
30
|
+
process.execPath,
|
|
31
|
+
[path.resolve(process.argv[1])]
|
|
32
|
+
);
|
|
33
|
+
} else {
|
|
34
|
+
protocolRegistered = app.setAsDefaultProtocolClient(PROTOCOL_SCHEME);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function closeDesktopServer() {
|
|
39
|
+
const instance = desktopServerInstance;
|
|
40
|
+
desktopServerInstance = null;
|
|
41
|
+
desktopServerInfo = null;
|
|
42
|
+
if (instance) await instance.close();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function workspaceUrlForHandoff(protocolUrl) {
|
|
46
|
+
if (!desktopServerInfo) throw new Error('Enigma desktop server is not ready.');
|
|
47
|
+
const { createWorkspaceUrlFromProtocol } = await import(HANDOFF_MODULE_URL);
|
|
48
|
+
return createWorkspaceUrlFromProtocol(protocolUrl, desktopServerInfo.url);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function openPrivateHandoff(protocolUrl) {
|
|
52
|
+
if (!protocolUrl) return;
|
|
53
|
+
pendingHandoffUrl = protocolUrl;
|
|
54
|
+
if (!app.isReady()) return;
|
|
55
|
+
if (!mainWindow || mainWindow.isDestroyed() || !desktopServerInfo) {
|
|
56
|
+
await createMainWindow();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const target = await workspaceUrlForHandoff(protocolUrl);
|
|
60
|
+
pendingHandoffUrl = null;
|
|
61
|
+
await mainWindow.loadURL(target);
|
|
62
|
+
if (mainWindow.isMinimized()) mainWindow.restore();
|
|
63
|
+
mainWindow.show();
|
|
64
|
+
mainWindow.focus();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function verifyElectronHandoff() {
|
|
68
|
+
const state = await mainWindow.webContents.executeJavaScript(`
|
|
69
|
+
new Promise((resolve, reject) => {
|
|
70
|
+
const startedAt = Date.now();
|
|
71
|
+
const inspect = () => {
|
|
72
|
+
const route = document.querySelector('#workspaceRouteSelect');
|
|
73
|
+
const active = document.querySelector('.workspace-view.active');
|
|
74
|
+
if (active?.dataset.workspaceView === 'chat' && route && !route.disabled && route.value) {
|
|
75
|
+
resolve({
|
|
76
|
+
href: location.href,
|
|
77
|
+
activeTab: document.querySelector('.nav-tab-btn.active')?.id || null,
|
|
78
|
+
activeView: active.dataset.workspaceView,
|
|
79
|
+
selectedRoute: route.selectedOptions[0]?.textContent || null,
|
|
80
|
+
externalScripts: Array.from(document.scripts).map((script) => script.src).filter(Boolean),
|
|
81
|
+
sessionStorageEntries: sessionStorage.length
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (Date.now() - startedAt > 8000) {
|
|
86
|
+
reject(new Error('Workspace route did not become ready.'));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
setTimeout(inspect, 50);
|
|
90
|
+
};
|
|
91
|
+
inspect();
|
|
92
|
+
})
|
|
93
|
+
`);
|
|
94
|
+
console.log('ENIGMA_ELECTRON_HANDOFF ' + JSON.stringify({
|
|
95
|
+
...state,
|
|
96
|
+
dynamicPort: desktopServerInfo.port,
|
|
97
|
+
protocolRegistered,
|
|
98
|
+
}));
|
|
99
|
+
await closeDesktopServer();
|
|
100
|
+
if (mainWindow && !mainWindow.isDestroyed()) mainWindow.destroy();
|
|
101
|
+
app.exit(0);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function createMainWindow() {
|
|
105
|
+
if (mainWindow && !mainWindow.isDestroyed()) return mainWindow;
|
|
106
|
+
const { createDesktopServer } = await import('./src/server.mjs');
|
|
107
|
+
const defaultUserDataBundle = process.env.ENIGMA_BUNDLE_PATH
|
|
108
|
+
|| path.join(app.getPath('userData'), 'vault', 'bundle.json');
|
|
109
|
+
|
|
110
|
+
let serverOptions;
|
|
111
|
+
if (TEST_MODE) {
|
|
112
|
+
serverOptions = {
|
|
113
|
+
port: 0,
|
|
114
|
+
inMemoryOnly: true,
|
|
115
|
+
modelAdapters: [{
|
|
116
|
+
id: 'electron-handoff-fixture',
|
|
117
|
+
provider: 'Enigma Electron',
|
|
118
|
+
models: ['enigma-code'],
|
|
119
|
+
async invoke(input) {
|
|
120
|
+
return { text: `Electron handoff fixture: ${input.prompt}` };
|
|
121
|
+
},
|
|
122
|
+
}],
|
|
123
|
+
};
|
|
124
|
+
} else {
|
|
125
|
+
if (!safeStorage.isEncryptionAvailable()) {
|
|
126
|
+
throw new Error('OS secure storage unavailable; refusing to start with weak host-bound key custody.');
|
|
127
|
+
}
|
|
128
|
+
serverOptions = {
|
|
129
|
+
port: 0,
|
|
130
|
+
bundlePath: defaultUserDataBundle,
|
|
131
|
+
safeStorage,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
desktopServerInstance = createDesktopServer(serverOptions);
|
|
136
|
+
desktopServerInfo = await desktopServerInstance.listen();
|
|
137
|
+
mainWindow = new BrowserWindow({
|
|
138
|
+
width: 1240,
|
|
139
|
+
height: 780,
|
|
140
|
+
minWidth: 900,
|
|
141
|
+
minHeight: 600,
|
|
142
|
+
show: !TEST_MODE,
|
|
143
|
+
backgroundColor: '#07090e',
|
|
144
|
+
title: 'Enigma Sovereign AI Memory Terminal',
|
|
145
|
+
autoHideMenuBar: true,
|
|
146
|
+
webPreferences: {
|
|
147
|
+
nodeIntegration: false,
|
|
148
|
+
contextIsolation: true,
|
|
149
|
+
sandbox: true,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
|
154
|
+
if (url.toLowerCase().startsWith('enigma://private')) {
|
|
155
|
+
openPrivateHandoff(url).catch(() => {});
|
|
156
|
+
} else {
|
|
157
|
+
shell.openExternal(url);
|
|
158
|
+
}
|
|
159
|
+
return { action: 'deny' };
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const target = pendingHandoffUrl
|
|
163
|
+
? await workspaceUrlForHandoff(pendingHandoffUrl)
|
|
164
|
+
: desktopServerInfo.url;
|
|
165
|
+
pendingHandoffUrl = null;
|
|
166
|
+
await mainWindow.loadURL(target);
|
|
167
|
+
|
|
168
|
+
mainWindow.on('closed', async () => {
|
|
169
|
+
mainWindow = null;
|
|
170
|
+
await closeDesktopServer();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (TEST_MODE) await verifyElectronHandoff();
|
|
174
|
+
return mainWindow;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!TEST_MODE) registerPrivateProtocol();
|
|
178
|
+
const hasSingleInstanceLock = app.requestSingleInstanceLock();
|
|
179
|
+
if (!hasSingleInstanceLock) {
|
|
180
|
+
app.quit();
|
|
181
|
+
} else {
|
|
182
|
+
app.on('second-instance', (_event, argv) => {
|
|
183
|
+
const handoffUrl = findHandoffArgument(argv);
|
|
184
|
+
if (handoffUrl) {
|
|
185
|
+
openPrivateHandoff(handoffUrl).catch(() => {});
|
|
186
|
+
} else if (mainWindow && !mainWindow.isDestroyed()) {
|
|
187
|
+
if (mainWindow.isMinimized()) mainWindow.restore();
|
|
188
|
+
mainWindow.show();
|
|
189
|
+
mainWindow.focus();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
app.on('open-url', (event, url) => {
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
if (typeof url === 'string' && url.toLowerCase().startsWith('enigma://private')) {
|
|
196
|
+
openPrivateHandoff(url).catch(() => {});
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
app.whenReady()
|
|
201
|
+
.then(() => createMainWindow())
|
|
202
|
+
.catch((error) => {
|
|
203
|
+
console.error(`Enigma desktop startup failed: ${error.message}`);
|
|
204
|
+
app.exit(1);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
app.on('activate', () => {
|
|
208
|
+
if (BrowserWindow.getAllWindows().length === 0) {
|
|
209
|
+
createMainWindow().catch(() => {});
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
app.on('window-all-closed', async () => {
|
|
215
|
+
await closeDesktopServer();
|
|
216
|
+
if (process.platform !== 'darwin') app.quit();
|
|
217
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "enigma-desktop-app",
|
|
3
|
+
"version": "0.1.22",
|
|
4
|
+
"description": "Enigma Sovereign AI Memory Terminal Dedicated Desktop Application",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "electron-main.cjs",
|
|
7
|
+
"private": true,
|
|
8
|
+
"scripts": {
|
|
9
|
+
"start": "electron electron-main.cjs",
|
|
10
|
+
"build": "node src/launch-electron.mjs"
|
|
11
|
+
}
|
|
12
|
+
}
|
package/apps/desktop/src/app.js
CHANGED
|
@@ -17,6 +17,7 @@ export const DESKTOP_SCREENS = Object.freeze([
|
|
|
17
17
|
const CLIENT_TEMPLATES = Object.freeze([
|
|
18
18
|
Object.freeze({ id: 'claude-desktop', name: 'Claude Desktop', kind: 'mcp-client' }),
|
|
19
19
|
Object.freeze({ id: 'cursor', name: 'Cursor', kind: 'mcp-client' }),
|
|
20
|
+
Object.freeze({ id: 'kimi-k3', name: 'Kimi K3', kind: 'mcp-client' }),
|
|
20
21
|
Object.freeze({ id: 'vscode', name: 'VS Code', kind: 'mcp-client' }),
|
|
21
22
|
Object.freeze({ id: 'browser-bridge', name: 'Browser bridge', kind: 'extension' })
|
|
22
23
|
]);
|
|
@@ -76,6 +77,21 @@ export function createDesktopState(options = {}) {
|
|
|
76
77
|
clients: [],
|
|
77
78
|
memories: [],
|
|
78
79
|
search: { query: '', results: [] },
|
|
80
|
+
agentTurn: {
|
|
81
|
+
status: 'idle',
|
|
82
|
+
adapters: [],
|
|
83
|
+
adapter_id: '',
|
|
84
|
+
provider: '',
|
|
85
|
+
model: '',
|
|
86
|
+
context_refs: [],
|
|
87
|
+
receipt_refs: [],
|
|
88
|
+
memory_id: '',
|
|
89
|
+
result_preview: '',
|
|
90
|
+
error_code: '',
|
|
91
|
+
error_message: '',
|
|
92
|
+
completed_at: '',
|
|
93
|
+
note: 'Agent turns execute only through an explicitly configured provider/model adapter.'
|
|
94
|
+
},
|
|
79
95
|
verifier: {
|
|
80
96
|
status: 'idle',
|
|
81
97
|
evidence: [],
|
|
@@ -95,6 +111,17 @@ export function createDesktopState(options = {}) {
|
|
|
95
111
|
peers: 0,
|
|
96
112
|
relays: 0,
|
|
97
113
|
last_witness_at: '',
|
|
114
|
+
federation: {
|
|
115
|
+
started: false,
|
|
116
|
+
scope: '',
|
|
117
|
+
destination_hex: '',
|
|
118
|
+
transport_id: '',
|
|
119
|
+
listen_port: null,
|
|
120
|
+
registered_peers: 0,
|
|
121
|
+
active_grants: 0,
|
|
122
|
+
pending_queries: 0,
|
|
123
|
+
persisted: false
|
|
124
|
+
},
|
|
98
125
|
note: 'Mesh status is local telemetry until matched to witness receipts.'
|
|
99
126
|
},
|
|
100
127
|
enterprise: {
|
|
@@ -141,8 +168,18 @@ export function desktopReducer(state = createDesktopState(), action = {}) {
|
|
|
141
168
|
return importBundleState(state, action);
|
|
142
169
|
case 'bundle/export':
|
|
143
170
|
return exportBundleState(state, action);
|
|
171
|
+
case 'agent/adapters':
|
|
172
|
+
return setAgentAdaptersState(state, action);
|
|
173
|
+
case 'agent/turn-started':
|
|
174
|
+
return startAgentTurnState(state, action);
|
|
175
|
+
case 'agent/turn-completed':
|
|
176
|
+
return completeAgentTurnState(state, action);
|
|
177
|
+
case 'agent/turn-failed':
|
|
178
|
+
return failAgentTurnState(state, action);
|
|
144
179
|
case 'mesh/update':
|
|
145
180
|
return updateMeshState(state, action);
|
|
181
|
+
case 'mesh/federation-update':
|
|
182
|
+
return updateFederationState(state, action);
|
|
146
183
|
case 'enterprise/update':
|
|
147
184
|
return updateEnterpriseState(state, action);
|
|
148
185
|
case 'draft/set':
|
|
@@ -167,6 +204,7 @@ export function renderDesktopModel(state = createDesktopState()) {
|
|
|
167
204
|
vault: state.vault.status,
|
|
168
205
|
mcp: state.mcp.status,
|
|
169
206
|
clients: connectedClients.length,
|
|
207
|
+
agentTurn: state.agentTurn.status,
|
|
170
208
|
memories: activeMemories.length,
|
|
171
209
|
deleted: deletedMemories.length,
|
|
172
210
|
verifier: verifierOk ? 'shape-clean' : state.verifier.status,
|
|
@@ -187,6 +225,28 @@ export function renderDesktopModel(state = createDesktopState()) {
|
|
|
187
225
|
],
|
|
188
226
|
memories: state.memories.map(renderMemoryRow)
|
|
189
227
|
},
|
|
228
|
+
agentTurn: {
|
|
229
|
+
title: 'Operational agent turn',
|
|
230
|
+
status: state.agentTurn.status,
|
|
231
|
+
adapters: state.agentTurn.adapters.map((adapter) => ({
|
|
232
|
+
...adapter,
|
|
233
|
+
models: adapter.models.slice()
|
|
234
|
+
})),
|
|
235
|
+
selection: {
|
|
236
|
+
adapter_id: state.agentTurn.adapter_id,
|
|
237
|
+
provider: state.agentTurn.provider,
|
|
238
|
+
model: state.agentTurn.model
|
|
239
|
+
},
|
|
240
|
+
context_refs: state.agentTurn.context_refs.map((ref) => ({ ...ref })),
|
|
241
|
+
receipt_refs: state.agentTurn.receipt_refs.map((ref) => ({ ...ref })),
|
|
242
|
+
memory_id: state.agentTurn.memory_id,
|
|
243
|
+
result_preview: state.agentTurn.result_preview,
|
|
244
|
+
error: state.agentTurn.error_code
|
|
245
|
+
? { code: state.agentTurn.error_code, message: state.agentTurn.error_message }
|
|
246
|
+
: null,
|
|
247
|
+
completed_at: state.agentTurn.completed_at,
|
|
248
|
+
note: state.agentTurn.note
|
|
249
|
+
},
|
|
190
250
|
mcp: {
|
|
191
251
|
title: 'MCP server status',
|
|
192
252
|
status: state.mcp.status,
|
|
@@ -230,6 +290,7 @@ export function renderDesktopModel(state = createDesktopState()) {
|
|
|
230
290
|
peers: state.mesh.peers,
|
|
231
291
|
relays: state.mesh.relays,
|
|
232
292
|
last_witness_at: state.mesh.last_witness_at,
|
|
293
|
+
federation: { ...state.mesh.federation },
|
|
233
294
|
note: state.mesh.note
|
|
234
295
|
},
|
|
235
296
|
enterprise: {
|
|
@@ -268,6 +329,22 @@ export function searchMemories(query, options = {}) {
|
|
|
268
329
|
return { ...options, query, type: 'memory/search' };
|
|
269
330
|
}
|
|
270
331
|
|
|
332
|
+
export function setAgentAdapters(adapters = []) {
|
|
333
|
+
return { adapters, type: 'agent/adapters' };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export function startAgentTurn(selection = {}, options = {}) {
|
|
337
|
+
return { ...options, selection, type: 'agent/turn-started' };
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function completeAgentTurn(turn = {}, options = {}) {
|
|
341
|
+
return { ...options, turn, type: 'agent/turn-completed' };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export function failAgentTurn(error = {}, options = {}) {
|
|
345
|
+
return { ...options, error, type: 'agent/turn-failed' };
|
|
346
|
+
}
|
|
347
|
+
|
|
271
348
|
export function verifyReceipts(input = {}, options = {}) {
|
|
272
349
|
return { ...options, input, type: 'receipts/verify' };
|
|
273
350
|
}
|
|
@@ -292,6 +369,10 @@ export function updateMeshStatus(mesh = {}, options = {}) {
|
|
|
292
369
|
return { ...options, mesh, type: 'mesh/update' };
|
|
293
370
|
}
|
|
294
371
|
|
|
372
|
+
export function updateFederationStatus(federation = {}, options = {}) {
|
|
373
|
+
return { ...options, federation, type: 'mesh/federation-update' };
|
|
374
|
+
}
|
|
375
|
+
|
|
295
376
|
export function updateEnterpriseStatus(enterprise = {}, options = {}) {
|
|
296
377
|
return { ...options, enterprise, type: 'enterprise/update' };
|
|
297
378
|
}
|
|
@@ -316,6 +397,10 @@ export const desktopActions = Object.freeze({
|
|
|
316
397
|
removeMemory: deleteMemory,
|
|
317
398
|
searchMemories,
|
|
318
399
|
searchMemory: searchMemories,
|
|
400
|
+
setAgentAdapters,
|
|
401
|
+
startAgentTurn,
|
|
402
|
+
completeAgentTurn,
|
|
403
|
+
failAgentTurn,
|
|
319
404
|
verifyReceipts,
|
|
320
405
|
verifyReceiptOutput: verifyReceipts,
|
|
321
406
|
connectClient,
|
|
@@ -326,6 +411,7 @@ export const desktopActions = Object.freeze({
|
|
|
326
411
|
exportBundle,
|
|
327
412
|
exportDesktopBundle: exportBundle,
|
|
328
413
|
updateMeshStatus,
|
|
414
|
+
updateFederationStatus,
|
|
329
415
|
updateEnterpriseStatus,
|
|
330
416
|
selectDesktopScreen,
|
|
331
417
|
setDesktopDraft
|
|
@@ -360,6 +446,10 @@ export const desktopApi = Object.freeze({
|
|
|
360
446
|
removeMemory,
|
|
361
447
|
searchMemories,
|
|
362
448
|
searchMemory,
|
|
449
|
+
setAgentAdapters,
|
|
450
|
+
startAgentTurn,
|
|
451
|
+
completeAgentTurn,
|
|
452
|
+
failAgentTurn,
|
|
363
453
|
verifyReceipts,
|
|
364
454
|
verifyReceiptOutput,
|
|
365
455
|
connectClient,
|
|
@@ -368,7 +458,10 @@ export const desktopApi = Object.freeze({
|
|
|
368
458
|
importBundle,
|
|
369
459
|
importDesktopBundle,
|
|
370
460
|
exportBundle,
|
|
371
|
-
exportDesktopBundle
|
|
461
|
+
exportDesktopBundle,
|
|
462
|
+
updateMeshStatus,
|
|
463
|
+
updateFederationStatus,
|
|
464
|
+
updateEnterpriseStatus
|
|
372
465
|
});
|
|
373
466
|
|
|
374
467
|
if (typeof globalThis !== 'undefined') {
|
|
@@ -605,6 +698,7 @@ function importBundleState(state, action) {
|
|
|
605
698
|
evidence: state.verifier.evidence.concat(importedVerifierEvidence),
|
|
606
699
|
errors: state.verifier.errors.concat(importedVerifierEvidence.flatMap((item) => item.errors.map((error) => `${item.receipt_id || `receipt[${item.index}]`}: ${error}`)))
|
|
607
700
|
} : state.verifier,
|
|
701
|
+
|
|
608
702
|
importExport: { ...state.importExport, import_status: 'imported', import_errors: [] },
|
|
609
703
|
vault: {
|
|
610
704
|
...state.vault,
|
|
@@ -616,6 +710,136 @@ function importBundleState(state, action) {
|
|
|
616
710
|
}
|
|
617
711
|
});
|
|
618
712
|
}
|
|
713
|
+
function setAgentAdaptersState(state, action) {
|
|
714
|
+
const adapters = Array.isArray(action.adapters)
|
|
715
|
+
? action.adapters
|
|
716
|
+
.map((adapter) => ({
|
|
717
|
+
id: cleanString(adapter?.id),
|
|
718
|
+
provider: cleanString(adapter?.provider),
|
|
719
|
+
models: normalizeStringList(adapter?.models)
|
|
720
|
+
}))
|
|
721
|
+
.filter((adapter) => adapter.id && adapter.provider && adapter.models.length > 0)
|
|
722
|
+
: [];
|
|
723
|
+
return bump({
|
|
724
|
+
...state,
|
|
725
|
+
agentTurn: {
|
|
726
|
+
...state.agentTurn,
|
|
727
|
+
adapters
|
|
728
|
+
},
|
|
729
|
+
notice: adapters.length > 0
|
|
730
|
+
? `${adapters.length} configured model adapter${adapters.length === 1 ? '' : 's'} available.`
|
|
731
|
+
: 'No provider/model adapter is configured; agent turns fail closed.'
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function startAgentTurnState(state, action) {
|
|
736
|
+
const selection = action.selection && typeof action.selection === 'object'
|
|
737
|
+
? action.selection
|
|
738
|
+
: {};
|
|
739
|
+
return bump({
|
|
740
|
+
...state,
|
|
741
|
+
activeScreen: 'vault',
|
|
742
|
+
agentTurn: {
|
|
743
|
+
...state.agentTurn,
|
|
744
|
+
status: 'running',
|
|
745
|
+
adapter_id: cleanString(selection.adapterId ?? selection.adapter_id),
|
|
746
|
+
provider: cleanString(selection.provider),
|
|
747
|
+
model: cleanString(selection.model),
|
|
748
|
+
context_refs: [],
|
|
749
|
+
receipt_refs: [],
|
|
750
|
+
memory_id: '',
|
|
751
|
+
result_preview: '',
|
|
752
|
+
error_code: '',
|
|
753
|
+
error_message: '',
|
|
754
|
+
completed_at: ''
|
|
755
|
+
},
|
|
756
|
+
notice: 'Executing authenticated retrieval → provider invocation → encrypted persistence.'
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
function completeAgentTurnState(state, action) {
|
|
761
|
+
const turn = action.turn && typeof action.turn === 'object' ? action.turn : {};
|
|
762
|
+
const adapter = turn.adapter && typeof turn.adapter === 'object' ? turn.adapter : {};
|
|
763
|
+
const contextRefs = Array.isArray(turn.context?.refs)
|
|
764
|
+
? turn.context.refs.map((ref) => ({ ...ref }))
|
|
765
|
+
: [];
|
|
766
|
+
const receiptRefs = Array.isArray(turn.receiptRefs)
|
|
767
|
+
? turn.receiptRefs.map((ref) => ({ ...ref }))
|
|
768
|
+
: [];
|
|
769
|
+
const completedAt = cleanString(action.now) || INITIAL_NOW;
|
|
770
|
+
return bump({
|
|
771
|
+
...state,
|
|
772
|
+
activeScreen: 'vault',
|
|
773
|
+
agentTurn: {
|
|
774
|
+
...state.agentTurn,
|
|
775
|
+
status: 'completed',
|
|
776
|
+
adapter_id: cleanString(adapter.id) || state.agentTurn.adapter_id,
|
|
777
|
+
provider: cleanString(adapter.provider) || state.agentTurn.provider,
|
|
778
|
+
model: cleanString(adapter.model) || state.agentTurn.model,
|
|
779
|
+
context_refs: contextRefs,
|
|
780
|
+
receipt_refs: receiptRefs,
|
|
781
|
+
memory_id: cleanString(turn.memory?.id),
|
|
782
|
+
result_preview: clamp(modelResultText(turn.result), 240),
|
|
783
|
+
error_code: '',
|
|
784
|
+
error_message: '',
|
|
785
|
+
completed_at: completedAt
|
|
786
|
+
},
|
|
787
|
+
notice: `Agent turn completed with ${contextRefs.length} context ref${contextRefs.length === 1 ? '' : 's'} and ${receiptRefs.length} receipt ref${receiptRefs.length === 1 ? '' : 's'}.`
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function failAgentTurnState(state, action) {
|
|
792
|
+
const error = action.error && typeof action.error === 'object' ? action.error : {};
|
|
793
|
+
return bump({
|
|
794
|
+
...state,
|
|
795
|
+
activeScreen: 'vault',
|
|
796
|
+
agentTurn: {
|
|
797
|
+
...state.agentTurn,
|
|
798
|
+
status: 'failed',
|
|
799
|
+
error_code: cleanString(error.code) || 'AGENT_TURN_FAILED',
|
|
800
|
+
error_message: cleanString(error.message) || 'Agent turn failed',
|
|
801
|
+
completed_at: cleanString(action.now) || INITIAL_NOW
|
|
802
|
+
},
|
|
803
|
+
notice: cleanString(error.message) || 'Agent turn failed closed.'
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
function updateFederationState(state, action) {
|
|
808
|
+
const federation = action.federation && typeof action.federation === 'object'
|
|
809
|
+
? action.federation
|
|
810
|
+
: {};
|
|
811
|
+
const endpoint = federation.endpoint && typeof federation.endpoint === 'object'
|
|
812
|
+
? federation.endpoint
|
|
813
|
+
: {};
|
|
814
|
+
const transport = federation.transport && typeof federation.transport === 'object'
|
|
815
|
+
? federation.transport
|
|
816
|
+
: {};
|
|
817
|
+
return bump({
|
|
818
|
+
...state,
|
|
819
|
+
activeScreen: 'mesh',
|
|
820
|
+
mesh: {
|
|
821
|
+
...state.mesh,
|
|
822
|
+
federation: {
|
|
823
|
+
started: federation.started === true,
|
|
824
|
+
scope: cleanString(federation.scope),
|
|
825
|
+
destination_hex: cleanString(endpoint.destinationHex),
|
|
826
|
+
transport_id: cleanString(transport.id),
|
|
827
|
+
listen_port: normalizePort(transport.listenPort),
|
|
828
|
+
registered_peers: Array.isArray(federation.registeredPeers)
|
|
829
|
+
? federation.registeredPeers.length
|
|
830
|
+
: 0,
|
|
831
|
+
active_grants: Array.isArray(federation.activeGrantIds)
|
|
832
|
+
? federation.activeGrantIds.length
|
|
833
|
+
: 0,
|
|
834
|
+
pending_queries: normalizeNonNegativeInteger(federation.pendingQueries, 0),
|
|
835
|
+
persisted: federation.persisted === true
|
|
836
|
+
}
|
|
837
|
+
},
|
|
838
|
+
notice: federation.started === true
|
|
839
|
+
? 'Encrypted, signed GhostMesh federation bridge is running.'
|
|
840
|
+
: 'GhostMesh federation bridge is configured but stopped.'
|
|
841
|
+
});
|
|
842
|
+
}
|
|
619
843
|
|
|
620
844
|
function exportBundleState(state, action) {
|
|
621
845
|
const now = cleanString(action.now) || INITIAL_NOW;
|
|
@@ -1012,6 +1236,21 @@ function screenLabel(screen) {
|
|
|
1012
1236
|
case 'enterprise': return 'Enterprise';
|
|
1013
1237
|
default: return screen;
|
|
1014
1238
|
}
|
|
1239
|
+
|
|
1240
|
+
}
|
|
1241
|
+
function modelResultText(result) {
|
|
1242
|
+
if (typeof result === 'string') return result;
|
|
1243
|
+
if (!result || typeof result !== 'object') return '';
|
|
1244
|
+
for (const key of ['text', 'outputText', 'output_text', 'content']) {
|
|
1245
|
+
if (typeof result[key] === 'string') return result[key];
|
|
1246
|
+
}
|
|
1247
|
+
if (Array.isArray(result.content)) {
|
|
1248
|
+
return result.content
|
|
1249
|
+
.map((part) => typeof part === 'string' ? part : part?.text)
|
|
1250
|
+
.filter((part) => typeof part === 'string')
|
|
1251
|
+
.join('');
|
|
1252
|
+
}
|
|
1253
|
+
return '';
|
|
1015
1254
|
}
|
|
1016
1255
|
|
|
1017
1256
|
function cleanString(value) {
|
|
@@ -1102,13 +1341,14 @@ function renderHtml(model, state) {
|
|
|
1102
1341
|
${renderMetric('MCP', model.summary.mcp)}
|
|
1103
1342
|
${renderMetric('Clients', model.summary.clients)}
|
|
1104
1343
|
${renderMetric('Receipt inspector', model.summary.verifier)}
|
|
1344
|
+
${renderMetric('Agent turn', model.summary.agentTurn)}
|
|
1105
1345
|
</dl>
|
|
1106
1346
|
</header>
|
|
1107
1347
|
<nav class="screen-nav" aria-label="Desktop screens">
|
|
1108
1348
|
${model.navigation.map((item) => `<button class="screen-tab${item.active ? ' is-active' : ''}" type="button" data-screen="${escapeHtml(item.id)}">${escapeHtml(item.label)}</button>`).join('')}
|
|
1109
1349
|
</nav>
|
|
1110
1350
|
<main>
|
|
1111
|
-
${renderVaultScreen(model.screens.vault, state)}
|
|
1351
|
+
${renderVaultScreen(model.screens.vault, model.screens.agentTurn, state)}
|
|
1112
1352
|
${renderMcpScreen(model.screens.mcp)}
|
|
1113
1353
|
${renderClientsScreen(model.screens.clients)}
|
|
1114
1354
|
${renderImportExportScreen(model.screens.importExport, state)}
|
|
@@ -1127,13 +1367,19 @@ function renderScreen(id, title, body) {
|
|
|
1127
1367
|
return `<section class="screen-card" id="screen-${escapeHtml(id)}"><div class="screen-heading"><p>${escapeHtml(screenLabel(id))}</p><h2>${escapeHtml(title)}</h2></div>${body}</section>`;
|
|
1128
1368
|
}
|
|
1129
1369
|
|
|
1130
|
-
function renderVaultScreen(screen, state) {
|
|
1370
|
+
function renderVaultScreen(screen, agentTurn, state) {
|
|
1131
1371
|
const memories = screen.memories.length ? screen.memories.map((memory) => `
|
|
1132
1372
|
<li class="memory-row${memory.deleted ? ' is-deleted' : ''}">
|
|
1133
1373
|
<div><strong>${escapeHtml(memory.descriptor)}</strong><span>${escapeHtml(memory.address)}</span></div>
|
|
1134
1374
|
<code>${escapeHtml(memory.body_fingerprint)}</code>
|
|
1135
1375
|
<button type="button" data-delete-memory="${escapeHtml(memory.address)}" ${memory.deleted ? 'disabled' : ''}>Delete + prove</button>
|
|
1136
1376
|
</li>`).join('') : '<li class="empty-row">No memory descriptors yet.</li>';
|
|
1377
|
+
const contextRefs = agentTurn.context_refs.length
|
|
1378
|
+
? escapeHtml(JSON.stringify(agentTurn.context_refs, null, 2))
|
|
1379
|
+
: 'No context refs observed.';
|
|
1380
|
+
const receiptRefs = agentTurn.receipt_refs.length
|
|
1381
|
+
? escapeHtml(JSON.stringify(agentTurn.receipt_refs, null, 2))
|
|
1382
|
+
: 'No receipt refs observed.';
|
|
1137
1383
|
|
|
1138
1384
|
return renderScreen('vault', screen.title, `
|
|
1139
1385
|
<div class="two-column">
|
|
@@ -1155,6 +1401,19 @@ function renderVaultScreen(screen, state) {
|
|
|
1155
1401
|
<button type="submit">Remember descriptor</button>
|
|
1156
1402
|
</form>
|
|
1157
1403
|
</div>
|
|
1404
|
+
<div class="panel status-panel">
|
|
1405
|
+
<span class="status-pill">${escapeHtml(agentTurn.status)}</span>
|
|
1406
|
+
<h3>${escapeHtml(agentTurn.title)}</h3>
|
|
1407
|
+
<p>${escapeHtml(agentTurn.note)}</p>
|
|
1408
|
+
<dl class="detail-list">
|
|
1409
|
+
${renderMetric('Adapter', agentTurn.selection.adapter_id || 'not configured')}
|
|
1410
|
+
${renderMetric('Provider', agentTurn.selection.provider || 'not configured')}
|
|
1411
|
+
${renderMetric('Model', agentTurn.selection.model || 'not configured')}
|
|
1412
|
+
${renderMetric('Persisted memory', agentTurn.memory_id || 'not observed')}
|
|
1413
|
+
</dl>
|
|
1414
|
+
<h4>Context refs</h4><pre>${contextRefs}</pre>
|
|
1415
|
+
<h4>Receipt refs</h4><pre>${receiptRefs}</pre>
|
|
1416
|
+
</div>
|
|
1158
1417
|
<form class="inline-form" data-form="search">
|
|
1159
1418
|
<label>Search descriptors <input name="query" value="${escapeHtml(state.search.query)}" placeholder="tag, address, fingerprint"></label>
|
|
1160
1419
|
<button type="submit">Search</button>
|
|
@@ -1224,7 +1483,8 @@ function renderDeleteProveScreen(screen) {
|
|
|
1224
1483
|
}
|
|
1225
1484
|
|
|
1226
1485
|
function renderMeshScreen(screen) {
|
|
1227
|
-
|
|
1486
|
+
const federation = screen.federation;
|
|
1487
|
+
return renderScreen('mesh', screen.title, `<div class="panel status-panel"><span class="status-pill">${escapeHtml(screen.status)}</span><p>${escapeHtml(screen.note)}</p><dl class="detail-list">${renderMetric('Peers', screen.peers)}${renderMetric('Relays', screen.relays)}${renderMetric('Last witness', screen.last_witness_at || 'not observed')}${renderMetric('Federation bridge', federation.started ? 'running' : 'stopped')}${renderMetric('Federation scope', federation.scope || 'not initialized')}${renderMetric('Local bridge port', federation.listen_port || 'not listening')}${renderMetric('Registered federation peers', federation.registered_peers)}${renderMetric('Active grants', federation.active_grants)}${renderMetric('Pending queries', federation.pending_queries)}${renderMetric('Encrypted state', federation.persisted ? 'persistent' : 'ephemeral')}</dl></div>`);
|
|
1228
1488
|
}
|
|
1229
1489
|
|
|
1230
1490
|
function renderEnterpriseScreen(screen) {
|
|
@@ -1249,9 +1509,6 @@ function wireDesktopEvents(root, state, dispatch) {
|
|
|
1249
1509
|
case 'stop-mcp':
|
|
1250
1510
|
dispatch(stopMcp({ now }));
|
|
1251
1511
|
break;
|
|
1252
|
-
case 'mesh-online':
|
|
1253
|
-
dispatch(updateMeshStatus({ status: 'online', peers: 3, relays: 1, last_witness_at: now }, { now }));
|
|
1254
|
-
break;
|
|
1255
1512
|
case 'enterprise-demo':
|
|
1256
1513
|
dispatch(updateEnterpriseStatus({ status: 'configured', tenant_id: 'tenant_local', policy_id: 'policy_desktop', siem: 'ready' }, { now }));
|
|
1257
1514
|
break;
|