@lamplitisles/dsh-nanocodex 0.1.0-beta.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 +65 -0
- package/NOTICE +2 -0
- package/README.md +182 -0
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/cordis.patch.yml +52 -0
- package/dist/index.d.ts +435 -0
- package/dist/index.js +3405 -0
- package/dist/standard-preset.d.ts +7 -0
- package/dist/standard-preset.js +25 -0
- package/engine-release.json +14 -0
- package/package.json +119 -0
- package/presets/standard/agent.cordis.yml +6 -0
- package/presets/standard/preset.yml +2 -0
- package/vendor/nanocodex/README.md +1344 -0
- package/vendor/nanocodex/actions/events.d.mts +10 -0
- package/vendor/nanocodex/actions/events.mjs +163 -0
- package/vendor/nanocodex/actions/index.d.mts +13 -0
- package/vendor/nanocodex/actions/index.mjs +35 -0
- package/vendor/nanocodex/actions/session.d.mts +66 -0
- package/vendor/nanocodex/actions/session.mjs +59 -0
- package/vendor/nanocodex/actions/turn.d.mts +59 -0
- package/vendor/nanocodex/actions/turn.mjs +37 -0
- package/vendor/nanocodex/actions/voice.d.mts +22 -0
- package/vendor/nanocodex/actions/voice.mjs +50 -0
- package/vendor/nanocodex/browser/Agent.d.mts +55 -0
- package/vendor/nanocodex/browser/Agent.mjs +11 -0
- package/vendor/nanocodex/browser/ChatGptSubscription.d.mts +7 -0
- package/vendor/nanocodex/browser/ChatGptSubscription.mjs +19 -0
- package/vendor/nanocodex/browser/InlineAgent.mjs +266 -0
- package/vendor/nanocodex/browser/Transport.d.mts +74 -0
- package/vendor/nanocodex/browser/Transport.mjs +61 -0
- package/vendor/nanocodex/browser/Voice.d.mts +71 -0
- package/vendor/nanocodex/browser/Voice.mjs +291 -0
- package/vendor/nanocodex/browser/VoiceSession.mjs +688 -0
- package/vendor/nanocodex/browser/WorkerAgent.d.mts +65 -0
- package/vendor/nanocodex/browser/WorkerAgent.mjs +1472 -0
- package/vendor/nanocodex/browser/agent.worker.mjs +3 -0
- package/vendor/nanocodex/browser/config.d.mts +36 -0
- package/vendor/nanocodex/browser/config.mjs +439 -0
- package/vendor/nanocodex/browser/engine.mjs +13 -0
- package/vendor/nanocodex/browser/harness.mjs +55 -0
- package/vendor/nanocodex/browser/host.d.mts +83 -0
- package/vendor/nanocodex/browser/host.mjs +555 -0
- package/vendor/nanocodex/browser/hostManagedWebSocket.d.mts +14 -0
- package/vendor/nanocodex/browser/hostManagedWebSocket.mjs +110 -0
- package/vendor/nanocodex/browser/index.d.mts +92 -0
- package/vendor/nanocodex/browser/index.mjs +23 -0
- package/vendor/nanocodex/browser/indexeddb-durability-store.mjs +197 -0
- package/vendor/nanocodex/browser/workspace.d.mts +16 -0
- package/vendor/nanocodex/browser/workspace.mjs +107 -0
- package/vendor/nanocodex/cloud/Client.d.mts +83 -0
- package/vendor/nanocodex/cloud/Client.mjs +231 -0
- package/vendor/nanocodex/cloud/Decorator.d.mts +31 -0
- package/vendor/nanocodex/cloud/Decorator.mjs +37 -0
- package/vendor/nanocodex/cloud/Dialog.d.mts +113 -0
- package/vendor/nanocodex/cloud/Dialog.mjs +366 -0
- package/vendor/nanocodex/cloud/Errors.d.mts +22 -0
- package/vendor/nanocodex/cloud/Errors.mjs +39 -0
- package/vendor/nanocodex/cloud/Principal.d.mts +26 -0
- package/vendor/nanocodex/cloud/Principal.mjs +88 -0
- package/vendor/nanocodex/cloud/RemoteProvider.mjs +88 -0
- package/vendor/nanocodex/cloud/Transport.d.mts +47 -0
- package/vendor/nanocodex/cloud/Transport.mjs +454 -0
- package/vendor/nanocodex/cloud/actions/account.d.mts +9 -0
- package/vendor/nanocodex/cloud/actions/account.mjs +19 -0
- package/vendor/nanocodex/cloud/actions/agent.d.mts +18 -0
- package/vendor/nanocodex/cloud/actions/agent.mjs +428 -0
- package/vendor/nanocodex/cloud/actions/connection.d.mts +133 -0
- package/vendor/nanocodex/cloud/actions/connection.mjs +580 -0
- package/vendor/nanocodex/cloud/actions/grant.d.mts +10 -0
- package/vendor/nanocodex/cloud/actions/grant.mjs +12 -0
- package/vendor/nanocodex/cloud/actions/index.d.mts +7 -0
- package/vendor/nanocodex/cloud/actions/index.mjs +7 -0
- package/vendor/nanocodex/cloud/actions/machineUsd.d.mts +23 -0
- package/vendor/nanocodex/cloud/actions/machineUsd.mjs +37 -0
- package/vendor/nanocodex/cloud/actions/model.d.mts +12 -0
- package/vendor/nanocodex/cloud/actions/model.mjs +50 -0
- package/vendor/nanocodex/cloud/actions/mpp.d.mts +28 -0
- package/vendor/nanocodex/cloud/actions/mpp.mjs +39 -0
- package/vendor/nanocodex/cloud/index.d.mts +30 -0
- package/vendor/nanocodex/cloud/index.mjs +9 -0
- package/vendor/nanocodex/cloud/internal.mjs +533 -0
- package/vendor/nanocodex/cloud/mercator.mjs +108 -0
- package/vendor/nanocodex/cloud/server/HostPrincipal.d.mts +34 -0
- package/vendor/nanocodex/cloud/server/HostPrincipal.mjs +202 -0
- package/vendor/nanocodex/cloud/server/index.d.mts +1 -0
- package/vendor/nanocodex/cloud/server/index.mjs +1 -0
- package/vendor/nanocodex/cloud/types.d.mts +211 -0
- package/vendor/nanocodex/cloudflare/Agent.d.mts +133 -0
- package/vendor/nanocodex/cloudflare/Agent.mjs +811 -0
- package/vendor/nanocodex/cloudflare/egress-subject.mjs +19 -0
- package/vendor/nanocodex/cloudflare/egress.d.mts +41 -0
- package/vendor/nanocodex/cloudflare/egress.mjs +119 -0
- package/vendor/nanocodex/cloudflare/event-socket.mjs +316 -0
- package/vendor/nanocodex/cloudflare/index.d.mts +7 -0
- package/vendor/nanocodex/cloudflare/index.mjs +6 -0
- package/vendor/nanocodex/host/Agent.d.mts +55 -0
- package/vendor/nanocodex/host/Agent.mjs +1 -0
- package/vendor/nanocodex/host/index.d.mts +82 -0
- package/vendor/nanocodex/host/index.mjs +10 -0
- package/vendor/nanocodex/index.d.mts +81 -0
- package/vendor/nanocodex/index.mjs +12 -0
- package/vendor/nanocodex/internal.mjs +1275 -0
- package/vendor/nanocodex/managed/Agent.d.mts +380 -0
- package/vendor/nanocodex/managed/Agent.mjs +1694 -0
- package/vendor/nanocodex/managed/ManagedError.d.mts +9 -0
- package/vendor/nanocodex/managed/ManagedError.mjs +8 -0
- package/vendor/nanocodex/managed/README.md +241 -0
- package/vendor/nanocodex/managed/Voice.mjs +202 -0
- package/vendor/nanocodex/managed/index.d.mts +20 -0
- package/vendor/nanocodex/managed/index.mjs +2 -0
- package/vendor/nanocodex/managed/internal.mjs +119 -0
- package/vendor/nanocodex/node/Agent.d.mts +50 -0
- package/vendor/nanocodex/node/Agent.mjs +203 -0
- package/vendor/nanocodex/node/ChatGptSubscription.d.mts +9 -0
- package/vendor/nanocodex/node/ChatGptSubscription.mjs +17 -0
- package/vendor/nanocodex/node/Transport.d.mts +44 -0
- package/vendor/nanocodex/node/Transport.mjs +46 -0
- package/vendor/nanocodex/node/host.mjs +731 -0
- package/vendor/nanocodex/node/index.d.mts +73 -0
- package/vendor/nanocodex/node/index.mjs +17 -0
- package/vendor/nanocodex/node/workspace.d.mts +10 -0
- package/vendor/nanocodex/node/workspace.mjs +198 -0
- package/vendor/nanocodex/package.json +200 -0
- package/vendor/nanocodex/pkg-node/nanocodex.d.ts +675 -0
- package/vendor/nanocodex/pkg-node/nanocodex.js +2628 -0
- package/vendor/nanocodex/pkg-node/nanocodex_bg.wasm.d.ts +105 -0
- package/vendor/nanocodex/pkg-node/package.json +1 -0
- package/vendor/nanocodex/pkg-web/.nanocodex-bindgen-stamp +6 -0
- package/vendor/nanocodex/pkg-web/nanocodex-build.json +1 -0
- package/vendor/nanocodex/pkg-web/nanocodex.d.ts +805 -0
- package/vendor/nanocodex/pkg-web/nanocodex.js +2714 -0
- package/vendor/nanocodex/pkg-web/nanocodex_bg.js +2615 -0
- package/vendor/nanocodex/pkg-web/nanocodex_bg.wasm +0 -0
- package/vendor/nanocodex/pkg-web/nanocodex_bg.wasm.d.ts +105 -0
- package/vendor/nanocodex/pkg-web/nanocodex_worker.js +9 -0
- package/vendor/nanocodex/pkg-web/package.json +1 -0
- package/vendor/nanocodex/runtime/chatgpt-subscription.mjs +212 -0
- package/vendor/nanocodex/runtime/cloudflare-durability-store.d.mts +26 -0
- package/vendor/nanocodex/runtime/cloudflare-durability-store.mjs +168 -0
- package/vendor/nanocodex/runtime/code-evaluator.worker.mjs +137 -0
- package/vendor/nanocodex/runtime/code-runtime.mjs +1 -0
- package/vendor/nanocodex/runtime/durability-store.d.mts +85 -0
- package/vendor/nanocodex/runtime/durability-store.mjs +631 -0
- package/vendor/nanocodex/runtime/durability.mjs +153 -0
- package/vendor/nanocodex/runtime/managed-transport.mjs +460 -0
- package/vendor/nanocodex/runtime/mcp-runtime.mjs +534 -0
- package/vendor/nanocodex/runtime/postgres-durability-store.d.mts +64 -0
- package/vendor/nanocodex/runtime/postgres-durability-store.mjs +532 -0
- package/vendor/nanocodex/runtime/quickjs-evaluator.d.mts +17 -0
- package/vendor/nanocodex/runtime/quickjs-evaluator.mjs +236 -0
- package/vendor/nanocodex/runtime/responses-transport.mjs +22 -0
- package/vendor/nanocodex/runtime/subagents.d.mts +107 -0
- package/vendor/nanocodex/runtime/subagents.mjs +54 -0
- package/vendor/nanocodex/runtime/subscription-store.d.mts +8 -0
- package/vendor/nanocodex/runtime/subscription-store.mjs +42 -0
- package/vendor/nanocodex/runtime/tempo-provider.d.mts +125 -0
- package/vendor/nanocodex/runtime/tempo-provider.mjs +264 -0
- package/vendor/nanocodex/runtime/tool-configuration.mjs +1 -0
- package/vendor/nanocodex/runtime/tool-router.mjs +1 -0
- package/vendor/nanocodex/runtime/utf8.mjs +1 -0
- package/vendor/nanocodex/runtime/worker-evaluator.mjs +162 -0
- package/vendor/nanocodex/runtime/workspace.d.mts +1 -0
- package/vendor/nanocodex/runtime/workspace.mjs +1 -0
- package/vendor/nanocodex/tools/Tools.d.mts +56 -0
- package/vendor/nanocodex/tools/Tools.mjs +136 -0
- package/vendor/nanocodex/tools/artifact.d.mts +1 -0
- package/vendor/nanocodex/tools/artifact.mjs +1 -0
- package/vendor/nanocodex/tools/attachment.mjs +1 -0
- package/vendor/nanocodex/tools/bash.d.mts +1 -0
- package/vendor/nanocodex/tools/bash.mjs +1 -0
- package/vendor/nanocodex/tools/browser/accountInfo.mjs +795 -0
- package/vendor/nanocodex/tools/browser/browserBuffer.mjs +18 -0
- package/vendor/nanocodex/tools/browser/browserCompiler.mjs +155 -0
- package/vendor/nanocodex/tools/browser/browserEgress.mjs +161 -0
- package/vendor/nanocodex/tools/browser/browserPython.mjs +133 -0
- package/vendor/nanocodex/tools/browser/browserShell.mjs +1075 -0
- package/vendor/nanocodex/tools/browser/browserSprintf.mjs +4 -0
- package/vendor/nanocodex/tools/browser/browserSsh.mjs +201 -0
- package/vendor/nanocodex/tools/browser/browserZlib.mjs +136 -0
- package/vendor/nanocodex/tools/browser/compiler.worker.mjs +160 -0
- package/vendor/nanocodex/tools/browser/devTunnelsSshBrowser.mjs +13 -0
- package/vendor/nanocodex/tools/browser/index.d.mts +209 -0
- package/vendor/nanocodex/tools/browser/index.mjs +174 -0
- package/vendor/nanocodex/tools/browser/opfsGit.mjs +248 -0
- package/vendor/nanocodex/tools/browser/python.worker.mjs +114 -0
- package/vendor/nanocodex/tools/browser/threadGit.mjs +197 -0
- package/vendor/nanocodex/tools/browser/unsupportedNodeRsa.mjs +5 -0
- package/vendor/nanocodex/tools/browser/workspace.mjs +83 -0
- package/vendor/nanocodex/tools/dataset.d.mts +1 -0
- package/vendor/nanocodex/tools/dataset.mjs +1 -0
- package/vendor/nanocodex/tools/datasetContract.mjs +1 -0
- package/vendor/nanocodex/tools/datasetEngine.mjs +1 -0
- package/vendor/nanocodex/tools/hostedCatalog.d.mts +1 -0
- package/vendor/nanocodex/tools/hostedCatalog.mjs +1 -0
- package/vendor/nanocodex/tools/index.d.mts +49 -0
- package/vendor/nanocodex/tools/index.mjs +19 -0
- package/vendor/nanocodex/tools/namedTool.mjs +1 -0
- package/vendor/nanocodex/tools/repository-workspace.d.mts +1 -0
- package/vendor/nanocodex/tools/repository-workspace.mjs +1 -0
- package/vendor/nanocodex/tools/ssh.d.mts +1 -0
- package/vendor/nanocodex/tools/ssh.mjs +1 -0
- package/vendor/nanocodex/tools/standard.mjs +1 -0
- package/vendor/nanocodex/tools/standardDescriptions.mjs +1 -0
- package/vendor/nanocodex/types.d.mts +663 -0
- package/vendor/nanocodex/wasm.d.mts +4 -0
- package/vendor/nanocodex/worker/ChatGptSubscription.d.mts +9 -0
- package/vendor/nanocodex/worker/ChatGptSubscription.mjs +29 -0
- package/vendor/nanocodex/worker/index.d.mts +18 -0
- package/vendor/nanocodex/worker/index.mjs +5 -0
- package/vendor/nanocodex-tools/README.md +65 -0
- package/vendor/nanocodex-tools/dist/hosted/app-tool-catalog.d.ts +7 -0
- package/vendor/nanocodex-tools/dist/hosted/app-tool-catalog.js +14 -0
- package/vendor/nanocodex-tools/dist/hosted/broker-core.d.ts +172 -0
- package/vendor/nanocodex-tools/dist/hosted/broker-core.js +1278 -0
- package/vendor/nanocodex-tools/dist/hosted/index.d.ts +3 -0
- package/vendor/nanocodex-tools/dist/hosted/index.js +3 -0
- package/vendor/nanocodex-tools/dist/hosted/protocol.d.ts +120 -0
- package/vendor/nanocodex-tools/dist/hosted/protocol.js +415 -0
- package/vendor/nanocodex-tools/dist/index.d.ts +19 -0
- package/vendor/nanocodex-tools/dist/index.js +14 -0
- package/vendor/nanocodex-tools/dist/memory.d.ts +204 -0
- package/vendor/nanocodex-tools/dist/memory.js +411 -0
- package/vendor/nanocodex-tools/dist/namespace.d.ts +87 -0
- package/vendor/nanocodex-tools/dist/namespace.js +338 -0
- package/vendor/nanocodex-tools/dist/repository-archive.d.ts +4 -0
- package/vendor/nanocodex-tools/dist/repository-archive.js +104 -0
- package/vendor/nanocodex-tools/dist/runtime.d.ts +30 -0
- package/vendor/nanocodex-tools/dist/runtime.js +37 -0
- package/vendor/nanocodex-tools/dist/session.d.ts +167 -0
- package/vendor/nanocodex-tools/dist/session.js +286 -0
- package/vendor/nanocodex-tools/dist/shell.d.ts +51 -0
- package/vendor/nanocodex-tools/dist/shell.js +553 -0
- package/vendor/nanocodex-tools/dist/ssh.d.ts +29 -0
- package/vendor/nanocodex-tools/dist/ssh.js +66 -0
- package/vendor/nanocodex-tools/dist/workspace.d.ts +45 -0
- package/vendor/nanocodex-tools/dist/workspace.js +237 -0
- package/vendor/nanocodex-tools/package.json +122 -0
- package/vendor/nanocodex-tools/runtime/code-runtime.mjs +817 -0
- package/vendor/nanocodex-tools/runtime/tool-configuration.mjs +50 -0
- package/vendor/nanocodex-tools/runtime/tool-router.mjs +730 -0
- package/vendor/nanocodex-tools/runtime/utf8.d.mts +2 -0
- package/vendor/nanocodex-tools/runtime/utf8.mjs +25 -0
- package/vendor/nanocodex-tools/tools/artifact.d.mts +69 -0
- package/vendor/nanocodex-tools/tools/artifact.mjs +270 -0
- package/vendor/nanocodex-tools/tools/attachment.mjs +603 -0
- package/vendor/nanocodex-tools/tools/bash.d.mts +90 -0
- package/vendor/nanocodex-tools/tools/bash.mjs +742 -0
- package/vendor/nanocodex-tools/tools/dataset.d.mts +9 -0
- package/vendor/nanocodex-tools/tools/dataset.mjs +47 -0
- package/vendor/nanocodex-tools/tools/datasetContract.mjs +54 -0
- package/vendor/nanocodex-tools/tools/datasetEngine.mjs +1167 -0
- package/vendor/nanocodex-tools/tools/execution-contract.d.mts +5 -0
- package/vendor/nanocodex-tools/tools/execution-contract.mjs +63 -0
- package/vendor/nanocodex-tools/tools/hostedCatalog.d.mts +20 -0
- package/vendor/nanocodex-tools/tools/hostedCatalog.mjs +67 -0
- package/vendor/nanocodex-tools/tools/hostedMachine.d.mts +10 -0
- package/vendor/nanocodex-tools/tools/hostedMachine.mjs +56 -0
- package/vendor/nanocodex-tools/tools/just-bash-browser.d.mts +1 -0
- package/vendor/nanocodex-tools/tools/just-bash-browser.mjs +1 -0
- package/vendor/nanocodex-tools/tools/namedTool.d.mts +3 -0
- package/vendor/nanocodex-tools/tools/namedTool.mjs +3 -0
- package/vendor/nanocodex-tools/tools/nodeProcess.d.mts +10 -0
- package/vendor/nanocodex-tools/tools/nodeProcess.mjs +314 -0
- package/vendor/nanocodex-tools/tools/processOutput.mjs +56 -0
- package/vendor/nanocodex-tools/tools/repository-workspace.d.mts +55 -0
- package/vendor/nanocodex-tools/tools/repository-workspace.mjs +397 -0
- package/vendor/nanocodex-tools/tools/ssh.d.mts +56 -0
- package/vendor/nanocodex-tools/tools/ssh.mjs +503 -0
- package/vendor/nanocodex-tools/tools/standard.mjs +458 -0
- package/vendor/nanocodex-tools/tools/standardDescriptions.mjs +3 -0
- package/vendor/nanocodex-tools/tools/types.d.mts +83 -0
- package/vendor/nanocodex-tools/tools/workspace.d.mts +25 -0
- package/vendor/nanocodex-tools/tools/workspace.mjs +282 -0
- package/vendor/nanocodex-tools/tools/x.d.mts +30 -0
- package/vendor/nanocodex-tools/tools/x.mjs +91 -0
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import {
|
|
2
|
+
connectionRequestFromGrant,
|
|
3
|
+
connectionFromWire,
|
|
4
|
+
connectionMatchesRequest,
|
|
5
|
+
reconnectRequestFromConnection,
|
|
6
|
+
} from "../internal.mjs";
|
|
7
|
+
import { InvalidResponseError } from "../Errors.mjs";
|
|
8
|
+
import {
|
|
9
|
+
hostedAppToolCatalog,
|
|
10
|
+
hostedToolCatalogDigest,
|
|
11
|
+
} from "../../tools/hostedCatalog.mjs";
|
|
12
|
+
|
|
13
|
+
const CLOUD_ACCOUNT_PROVIDERS = Object.freeze([
|
|
14
|
+
"github",
|
|
15
|
+
"gmail",
|
|
16
|
+
"gdrive",
|
|
17
|
+
"gcalendar",
|
|
18
|
+
"gtasks",
|
|
19
|
+
"gdocs",
|
|
20
|
+
"gsheets",
|
|
21
|
+
"gslides",
|
|
22
|
+
"gcontacts",
|
|
23
|
+
"slack",
|
|
24
|
+
"x",
|
|
25
|
+
"chatgpt",
|
|
26
|
+
]);
|
|
27
|
+
const CONNECTOR_RESOURCE_PREFIX = "urn:nanocodex:connector:";
|
|
28
|
+
const CONNECTORS_RESOURCE_PREFIX = "urn:nanocodex:connectors:";
|
|
29
|
+
const APP_RESOURCE_PREFIX = "urn:nanocodex:app:";
|
|
30
|
+
const APP_ORIGIN_RESOURCE_PREFIX = "urn:nanocodex:origin:";
|
|
31
|
+
const APP_TOOL_CATALOG_RESOURCE_PREFIX = "urn:nanocodex:app-tool-catalog:sha256:";
|
|
32
|
+
const HOSTED_AUTHORIZATION_RESOURCE = "urn:nanocodex:authorization:hosted";
|
|
33
|
+
const HOST_PRINCIPAL_EXCHANGE_RESOURCE_PREFIX = "urn:nanocodex:host-principal:exchange:";
|
|
34
|
+
const HOST_PRINCIPAL_ID = /^[A-Za-z0-9_-]{43}$/;
|
|
35
|
+
const MPP_RESOURCE_PREFIX = "urn:nanocodex:mpp:";
|
|
36
|
+
const MCP_CONNECTION_ID = /^[A-Za-z0-9_-]{43}$/;
|
|
37
|
+
const MCP_CONNECTION_RESOURCE_PREFIX = "urn:nanocodex:mcp:";
|
|
38
|
+
const MCP_FOCUS_RESOURCE_PREFIX = "urn:nanocodex:mcp-focus:";
|
|
39
|
+
const AGENT_VISIBILITY_RESOURCES = Object.freeze({
|
|
40
|
+
finalMessages: "urn:nanocodex:agent:output:final",
|
|
41
|
+
actionSummaries: "urn:nanocodex:agent:output:actions",
|
|
42
|
+
conversationHistory: "urn:nanocodex:agent:history:read",
|
|
43
|
+
rawTraces: "urn:nanocodex:agent:trace:read",
|
|
44
|
+
});
|
|
45
|
+
const AGENT_VISIBILITY_RESOURCE_PREFIX = "urn:nanocodex:agent:visibility:";
|
|
46
|
+
const AGENT_CONVERSATION_RESOURCE_PREFIX = "urn:nanocodex:agent:conversation:";
|
|
47
|
+
const AGENT_CONVERSATION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
48
|
+
const AGENT_VISIBILITY_NAMES = Object.freeze({
|
|
49
|
+
finalMessages: "reply",
|
|
50
|
+
actionSummaries: "actions",
|
|
51
|
+
conversationHistory: "history",
|
|
52
|
+
rawTraces: "traces",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export async function connect(client, options) {
|
|
56
|
+
options ??= {};
|
|
57
|
+
const permission = options.permission ?? "agent.run";
|
|
58
|
+
if (typeof permission !== "string" || permission.length === 0) throw new TypeError("connect permission must be a non-empty string");
|
|
59
|
+
const requestedConnectors = normalizeCloudAccounts(options.capabilities?.cloudAccounts);
|
|
60
|
+
const agentVisibility = normalizeAgentVisibility(options.capabilities?.agent);
|
|
61
|
+
const authorization = options.authorization ?? (client.principal ? "hosted" : "access_key");
|
|
62
|
+
if (authorization !== "access_key" && authorization !== "hosted") {
|
|
63
|
+
throw new TypeError("connect authorization must be access_key or hosted");
|
|
64
|
+
}
|
|
65
|
+
if (client.principal && authorization !== "hosted") {
|
|
66
|
+
throw new TypeError("host principal connections require hosted authorization");
|
|
67
|
+
}
|
|
68
|
+
if (client.principal && options.capabilities?.authorizeAccessKey !== undefined) {
|
|
69
|
+
throw new TypeError("host principal connections cannot request access-key or MPP authority");
|
|
70
|
+
}
|
|
71
|
+
const appToolCatalog = hostedAppToolCatalog(options.tools ?? []);
|
|
72
|
+
const appToolCatalogDigest = appToolCatalog.length === 0
|
|
73
|
+
? undefined
|
|
74
|
+
: await hostedToolCatalogDigest(appToolCatalog);
|
|
75
|
+
const conversationId = normalizeAgentConversationId(options.conversationId);
|
|
76
|
+
const mcpConnections = normalizeMcpConnections(options.mcpConnections ?? []);
|
|
77
|
+
const focusMcpConnectionId = normalizeMcpFocus(options.focusMcpConnectionId, mcpConnections);
|
|
78
|
+
const exactRequest = connectionRequestFromGrant({
|
|
79
|
+
connectors: requestedConnectors,
|
|
80
|
+
mcpConnections,
|
|
81
|
+
permission,
|
|
82
|
+
visibility: agentVisibility,
|
|
83
|
+
authorization,
|
|
84
|
+
...(appToolCatalogDigest ? { appToolCatalogDigest } : {}),
|
|
85
|
+
...(conversationId ? { conversationId } : {}),
|
|
86
|
+
});
|
|
87
|
+
const baseAuth = withConnectionResources(
|
|
88
|
+
options.capabilities?.auth ?? client.auth,
|
|
89
|
+
client.appId,
|
|
90
|
+
client.appOrigin,
|
|
91
|
+
requestedConnectors,
|
|
92
|
+
agentVisibility,
|
|
93
|
+
mcpConnections,
|
|
94
|
+
focusMcpConnectionId,
|
|
95
|
+
conversationId,
|
|
96
|
+
authorization,
|
|
97
|
+
appToolCatalogDigest,
|
|
98
|
+
);
|
|
99
|
+
if (client.principal
|
|
100
|
+
&& baseAuth.resources.some((resource) => resource.startsWith(MPP_RESOURCE_PREFIX))) {
|
|
101
|
+
throw new TypeError("host principal connections cannot request access-key or MPP authority");
|
|
102
|
+
}
|
|
103
|
+
const principalExchange = client.principal
|
|
104
|
+
? await client.principal.create({ resources: baseAuth.resources, signal: options.signal })
|
|
105
|
+
: undefined;
|
|
106
|
+
const auth = principalExchange
|
|
107
|
+
? withHostPrincipalExchange(baseAuth, principalExchange.token)
|
|
108
|
+
: baseAuth;
|
|
109
|
+
const walletAuth = delegateAuthVerification(auth);
|
|
110
|
+
if (!principalExchange) client.dialog.showWallet?.();
|
|
111
|
+
let connected = false;
|
|
112
|
+
try {
|
|
113
|
+
if (!principalExchange) await client.dialog.waitForWallet?.();
|
|
114
|
+
const activeAccount = authorization === "access_key" && !client.principal
|
|
115
|
+
? activeAccountAddress(client.provider)
|
|
116
|
+
: undefined;
|
|
117
|
+
const reusable = activeAccount
|
|
118
|
+
? await registeredAccessKey(client, activeAccount, options.signal)
|
|
119
|
+
: undefined;
|
|
120
|
+
// Reuse only keys already registered with the Connect control plane. Older
|
|
121
|
+
// browser-only keys are replaced in this same passkey ceremony, after which
|
|
122
|
+
// both the private signer and public grant record remain durable.
|
|
123
|
+
const authorizeAccessKey = authorization === "hosted"
|
|
124
|
+
? undefined
|
|
125
|
+
: options.capabilities?.authorizeAccessKey
|
|
126
|
+
?? (reusable
|
|
127
|
+
? undefined
|
|
128
|
+
: freshAccessKeyAuthorization(client.accessKey?.authorize));
|
|
129
|
+
const result = await client.provider.request({
|
|
130
|
+
method: "wallet_connect",
|
|
131
|
+
params: [{
|
|
132
|
+
chainId: "0x1079",
|
|
133
|
+
capabilities: {
|
|
134
|
+
...(walletAuth ? { auth: walletAuth } : {}),
|
|
135
|
+
...(authorizeAccessKey ? { authorizeAccessKey: serializeAuthorizeAccessKey(authorizeAccessKey) } : {}),
|
|
136
|
+
},
|
|
137
|
+
}],
|
|
138
|
+
...(!principalExchange && mcpConnections.length === 0 ? {} : {
|
|
139
|
+
context: {
|
|
140
|
+
...(principalExchange ? { hostPrincipal: principalExchange } : {}),
|
|
141
|
+
...(mcpConnections.length === 0 ? {} : {
|
|
142
|
+
requestedMcpConnections: mcpConnections.map(({ id, name }) => ({
|
|
143
|
+
id,
|
|
144
|
+
name,
|
|
145
|
+
status: "authorization_required",
|
|
146
|
+
})),
|
|
147
|
+
}),
|
|
148
|
+
...(focusMcpConnectionId ? { focusMcpConnection: focusMcpConnectionId } : {}),
|
|
149
|
+
},
|
|
150
|
+
}),
|
|
151
|
+
});
|
|
152
|
+
const account = result.accounts?.[0];
|
|
153
|
+
if (!account) throw new Error("Nanocodex Connect returned no account");
|
|
154
|
+
const hostPrincipalId = principalExchange
|
|
155
|
+
? account.principal?.kind === "host" && HOST_PRINCIPAL_ID.test(account.principal?.id)
|
|
156
|
+
? account.principal.id
|
|
157
|
+
: undefined
|
|
158
|
+
: undefined;
|
|
159
|
+
if (principalExchange && !hostPrincipalId) {
|
|
160
|
+
throw new Error("Nanocodex Connect returned no host principal");
|
|
161
|
+
}
|
|
162
|
+
if (!principalExchange && typeof account.address !== "string") {
|
|
163
|
+
throw new Error("Nanocodex Connect returned no wallet account");
|
|
164
|
+
}
|
|
165
|
+
const approvalId = account.capabilities?.auth?.approval_id;
|
|
166
|
+
if (typeof approvalId !== "string" || approvalId.length === 0) {
|
|
167
|
+
throw new Error("Nanocodex Connect returned no signed approval identifier");
|
|
168
|
+
}
|
|
169
|
+
const keyAuthorization = account.capabilities?.keyAuthorization;
|
|
170
|
+
const preflightKeyMatchesAccount = reusable
|
|
171
|
+
&& typeof activeAccount === "string"
|
|
172
|
+
&& activeAccount.toLowerCase() === account.address.toLowerCase();
|
|
173
|
+
const reusedAccessKey = authorization === "hosted"
|
|
174
|
+
? undefined
|
|
175
|
+
: keyAuthorization
|
|
176
|
+
? undefined
|
|
177
|
+
: preflightKeyMatchesAccount
|
|
178
|
+
? reusable
|
|
179
|
+
: await registeredAccessKey(client, account.address, options.signal);
|
|
180
|
+
if (authorization === "access_key" && !keyAuthorization && !reusedAccessKey) {
|
|
181
|
+
throw new Error("Nanocodex Connect returned no new or reusable access key");
|
|
182
|
+
}
|
|
183
|
+
const wire = await client.request({
|
|
184
|
+
method: "POST",
|
|
185
|
+
path: "/v1/connections",
|
|
186
|
+
body: {
|
|
187
|
+
app_id: client.appId,
|
|
188
|
+
...(hostPrincipalId
|
|
189
|
+
? { principal: { kind: "host", id: hostPrincipalId } }
|
|
190
|
+
: { account_address: account.address }),
|
|
191
|
+
approval_id: approvalId,
|
|
192
|
+
authorization_mode: authorization,
|
|
193
|
+
...(authorization === "hosted" ? {} : keyAuthorization ? {
|
|
194
|
+
key_authorization: keyAuthorization,
|
|
195
|
+
signed_key_authorization: account.capabilities?.personalSign?.keyAuthorization,
|
|
196
|
+
} : {
|
|
197
|
+
reuse_access_key: reusedAccessKey,
|
|
198
|
+
}),
|
|
199
|
+
permission,
|
|
200
|
+
...(requestedConnectors.length === 0 ? {} : { requested_connectors: requestedConnectors }),
|
|
201
|
+
...(mcpConnections.length === 0
|
|
202
|
+
? {}
|
|
203
|
+
: { requested_mcp_connections: mcpConnections.map(({ id }) => id) }),
|
|
204
|
+
...(appToolCatalogDigest ? { requested_app_tool_catalog_digest: appToolCatalogDigest } : {}),
|
|
205
|
+
},
|
|
206
|
+
signal: options.signal,
|
|
207
|
+
});
|
|
208
|
+
const grantToken = wire?.grant_token;
|
|
209
|
+
if (typeof grantToken !== "string" || grantToken.length === 0) {
|
|
210
|
+
throw new Error("Nanocodex Connect returned no grant-scoped session");
|
|
211
|
+
}
|
|
212
|
+
const connection = connectionFromWire(wire);
|
|
213
|
+
if (!connectionMatchesRequest(connection, exactRequest)) {
|
|
214
|
+
throw new InvalidResponseError("Nanocodex Connect returned a grant outside the exact approved request");
|
|
215
|
+
}
|
|
216
|
+
if (hostPrincipalId && connection.principal?.id !== hostPrincipalId) {
|
|
217
|
+
throw new InvalidResponseError("Nanocodex Connect returned a different host principal");
|
|
218
|
+
}
|
|
219
|
+
if (!hostPrincipalId && connection.principal) {
|
|
220
|
+
throw new InvalidResponseError("Nanocodex Connect replaced the wallet account with a host principal");
|
|
221
|
+
}
|
|
222
|
+
client._setSession({
|
|
223
|
+
grantId: connection.grant.id,
|
|
224
|
+
token: grantToken,
|
|
225
|
+
connection: sessionConnectionWire(wire),
|
|
226
|
+
...(principalExchange ? { resources: baseAuth.resources } : {}),
|
|
227
|
+
});
|
|
228
|
+
connected = true;
|
|
229
|
+
return connection;
|
|
230
|
+
} finally {
|
|
231
|
+
// The host stays covered until the grant session is committed. React owns
|
|
232
|
+
// manual closure from a layout effect so its connected tree is committed
|
|
233
|
+
// before the modal disappears; imperative callers retain automatic close.
|
|
234
|
+
if (!connected || options.dialog?.close !== "manual") {
|
|
235
|
+
client.dialog.hideWallet?.();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// The Nanocodex wallet host owns the complete SIWE ceremony so it can keep
|
|
241
|
+
// the authenticated session in the iframe while the user resolves requested
|
|
242
|
+
// connectors. Omitting `verify` here also prevents the forwarding Provider
|
|
243
|
+
// from replaying the wallet host's one-time challenge after approval.
|
|
244
|
+
function delegateAuthVerification(auth) {
|
|
245
|
+
if (!auth || typeof auth === "string") return auth;
|
|
246
|
+
const { verify: _verify, ...forwarded } = auth;
|
|
247
|
+
return forwarded;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function normalizeCloudAccounts(cloudAccounts) {
|
|
251
|
+
if (!cloudAccounts || typeof cloudAccounts !== "object" || Array.isArray(cloudAccounts)) return [];
|
|
252
|
+
return CLOUD_ACCOUNT_PROVIDERS.filter((provider) => cloudAccounts[provider] === true);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function normalizeAgentVisibility(agent) {
|
|
256
|
+
const rawTraces = agent?.rawTraces === true;
|
|
257
|
+
return Object.freeze({
|
|
258
|
+
finalMessages: rawTraces || agent?.finalMessages !== false,
|
|
259
|
+
actionSummaries: rawTraces || agent?.actionSummaries !== false,
|
|
260
|
+
conversationHistory: rawTraces || agent?.conversationHistory === true,
|
|
261
|
+
rawTraces,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function normalizeAgentConversationId(value) {
|
|
266
|
+
if (value === undefined) return undefined;
|
|
267
|
+
if (typeof value !== "string" || !AGENT_CONVERSATION_ID.test(value)) {
|
|
268
|
+
throw new TypeError("conversationId must be a lowercase UUIDv4");
|
|
269
|
+
}
|
|
270
|
+
return value;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function normalizeMcpConnections(value) {
|
|
274
|
+
if (!Array.isArray(value) || value.length > 16) {
|
|
275
|
+
throw new TypeError("mcpConnections must be an array of at most 16 pre-registered connections");
|
|
276
|
+
}
|
|
277
|
+
const ids = new Set();
|
|
278
|
+
return Object.freeze(value.map((connection) => {
|
|
279
|
+
if (!connection || typeof connection !== "object"
|
|
280
|
+
|| typeof connection.id !== "string" || !MCP_CONNECTION_ID.test(connection.id)
|
|
281
|
+
|| typeof connection.name !== "string" || connection.name.length < 1
|
|
282
|
+
|| connection.name.length > 256 || connection.name.trim() !== connection.name
|
|
283
|
+
|| ids.has(connection.id)) {
|
|
284
|
+
throw new TypeError("mcpConnections must contain unique opaque 43-character IDs and bounded display names");
|
|
285
|
+
}
|
|
286
|
+
ids.add(connection.id);
|
|
287
|
+
return Object.freeze({ id: connection.id, name: connection.name });
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function normalizeMcpFocus(value, connections) {
|
|
292
|
+
if (value === undefined) return undefined;
|
|
293
|
+
if (typeof value !== "string" || !MCP_CONNECTION_ID.test(value)
|
|
294
|
+
|| !connections.some(({ id }) => id === value)) {
|
|
295
|
+
throw new TypeError("focusMcpConnectionId must identify one requested MCP connection");
|
|
296
|
+
}
|
|
297
|
+
return value;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function withConnectionResources(
|
|
301
|
+
auth,
|
|
302
|
+
appId,
|
|
303
|
+
appOrigin,
|
|
304
|
+
requestedConnectors,
|
|
305
|
+
agentVisibility,
|
|
306
|
+
mcpConnections,
|
|
307
|
+
focusMcpConnectionId,
|
|
308
|
+
conversationId,
|
|
309
|
+
authorization,
|
|
310
|
+
appToolCatalogDigest,
|
|
311
|
+
) {
|
|
312
|
+
const configured = typeof auth === "object" && auth !== null
|
|
313
|
+
? (auth.resources ?? []).filter((resource) =>
|
|
314
|
+
!Object.values(AGENT_VISIBILITY_RESOURCES).includes(resource)
|
|
315
|
+
&& !resource.startsWith(AGENT_VISIBILITY_RESOURCE_PREFIX)
|
|
316
|
+
&& !resource.startsWith(AGENT_CONVERSATION_RESOURCE_PREFIX)
|
|
317
|
+
&& !resource.startsWith(CONNECTOR_RESOURCE_PREFIX)
|
|
318
|
+
&& !resource.startsWith(CONNECTORS_RESOURCE_PREFIX)
|
|
319
|
+
&& !resource.startsWith(MCP_CONNECTION_RESOURCE_PREFIX)
|
|
320
|
+
&& !resource.startsWith(MCP_FOCUS_RESOURCE_PREFIX)
|
|
321
|
+
&& !resource.startsWith(APP_RESOURCE_PREFIX)
|
|
322
|
+
&& !resource.startsWith(APP_ORIGIN_RESOURCE_PREFIX)
|
|
323
|
+
&& !resource.startsWith(APP_TOOL_CATALOG_RESOURCE_PREFIX)
|
|
324
|
+
&& !resource.startsWith(HOST_PRINCIPAL_EXCHANGE_RESOURCE_PREFIX)
|
|
325
|
+
&& resource !== HOSTED_AUTHORIZATION_RESOURCE)
|
|
326
|
+
: [];
|
|
327
|
+
const visibility = Object.entries(AGENT_VISIBILITY_NAMES)
|
|
328
|
+
.filter(([name]) => agentVisibility[name])
|
|
329
|
+
.map(([, value]) => value);
|
|
330
|
+
const resources = [...new Set([
|
|
331
|
+
...configured,
|
|
332
|
+
`${APP_RESOURCE_PREFIX}${encodeURIComponent(appId)}`,
|
|
333
|
+
...(appOrigin ? [`${APP_ORIGIN_RESOURCE_PREFIX}${encodeURIComponent(appOrigin)}`] : []),
|
|
334
|
+
...(requestedConnectors.length === 0
|
|
335
|
+
? []
|
|
336
|
+
: [`${CONNECTORS_RESOURCE_PREFIX}${requestedConnectors.join(",")}`]),
|
|
337
|
+
...(visibility.length === 0
|
|
338
|
+
? []
|
|
339
|
+
: [`${AGENT_VISIBILITY_RESOURCE_PREFIX}${visibility.join(",")}`]),
|
|
340
|
+
...(conversationId ? [`${AGENT_CONVERSATION_RESOURCE_PREFIX}${conversationId}`] : []),
|
|
341
|
+
...(authorization === "hosted" ? [HOSTED_AUTHORIZATION_RESOURCE] : []),
|
|
342
|
+
...(appToolCatalogDigest
|
|
343
|
+
? [`${APP_TOOL_CATALOG_RESOURCE_PREFIX}${appToolCatalogDigest.slice(2)}`]
|
|
344
|
+
: []),
|
|
345
|
+
...mcpConnections.map(({ id }) => `${MCP_CONNECTION_RESOURCE_PREFIX}${id}`),
|
|
346
|
+
...(focusMcpConnectionId ? [`${MCP_FOCUS_RESOURCE_PREFIX}${focusMcpConnectionId}`] : []),
|
|
347
|
+
])];
|
|
348
|
+
if (typeof auth === "string") return { url: auth, resources };
|
|
349
|
+
return { ...auth, resources };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function withHostPrincipalExchange(auth, token) {
|
|
353
|
+
if (!HOST_PRINCIPAL_ID.test(token)) {
|
|
354
|
+
throw new TypeError("host principal returned an invalid exchange token");
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
...auth,
|
|
358
|
+
resources: [
|
|
359
|
+
...auth.resources.filter((resource) => !resource.startsWith(HOST_PRINCIPAL_EXCHANGE_RESOURCE_PREFIX)),
|
|
360
|
+
`${HOST_PRINCIPAL_EXCHANGE_RESOURCE_PREFIX}${token}`,
|
|
361
|
+
],
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function reusableAccessKeys(provider, accountAddress) {
|
|
366
|
+
const records = provider?.store?.getState?.().accessKeys;
|
|
367
|
+
if (!Array.isArray(records)) return undefined;
|
|
368
|
+
const now = Math.floor(Date.now() / 1000);
|
|
369
|
+
const matching = records.filter((record) =>
|
|
370
|
+
record
|
|
371
|
+
&& typeof record === "object"
|
|
372
|
+
&& typeof record.address === "string"
|
|
373
|
+
&& typeof record.expiry === "number"
|
|
374
|
+
&& record.expiry > now
|
|
375
|
+
&& typeof record.access === "string"
|
|
376
|
+
&& record.access.toLowerCase() === accountAddress.toLowerCase()
|
|
377
|
+
&& Number(record.chainId) === 4217
|
|
378
|
+
);
|
|
379
|
+
const channelAuthorities = persistedChannelAuthorities(accountAddress);
|
|
380
|
+
matching.sort((left, right) => {
|
|
381
|
+
const leftOwnsChannel = channelAuthorities.has(left.address.toLowerCase()) ? 1 : 0;
|
|
382
|
+
const rightOwnsChannel = channelAuthorities.has(right.address.toLowerCase()) ? 1 : 0;
|
|
383
|
+
return rightOwnsChannel - leftOwnsChannel || right.expiry - left.expiry;
|
|
384
|
+
});
|
|
385
|
+
return matching.map((selected) => ({ key_id: selected.address, expiry: selected.expiry }));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function activeAccountAddress(provider) {
|
|
389
|
+
const state = provider?.store?.getState?.();
|
|
390
|
+
const account = state?.accounts?.[state.activeAccount ?? 0];
|
|
391
|
+
return typeof account?.address === "string" ? account.address : undefined;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async function isRegisteredAccessKey(client, accountAddress, keyId, signal) {
|
|
395
|
+
try {
|
|
396
|
+
const value = await client.request({
|
|
397
|
+
method: "GET",
|
|
398
|
+
path: `/v1/access-keys/${accountAddress}/${keyId}?app_id=${encodeURIComponent(client.appId)}`,
|
|
399
|
+
signal,
|
|
400
|
+
});
|
|
401
|
+
return value?.registered === true;
|
|
402
|
+
} catch {
|
|
403
|
+
// Registration discovery is only an optimization. If it is unavailable,
|
|
404
|
+
// create a fresh authorization in the one passkey ceremony and fail closed.
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async function registeredAccessKey(client, accountAddress, signal) {
|
|
410
|
+
for (const candidate of reusableAccessKeys(client.provider, accountAddress)) {
|
|
411
|
+
if (await isRegisteredAccessKey(client, accountAddress, candidate.key_id, signal)) {
|
|
412
|
+
return candidate;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return undefined;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function freshAccessKeyAuthorization(authorization) {
|
|
419
|
+
if (!authorization || typeof authorization !== "object") return authorization;
|
|
420
|
+
const { reuse: _reuse, ...fresh } = authorization;
|
|
421
|
+
return fresh;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function persistedChannelAuthorities(accountAddress) {
|
|
425
|
+
const authorities = new Set();
|
|
426
|
+
if (typeof localStorage === "undefined") return authorities;
|
|
427
|
+
const prefix = `nanocodex:connect:mpp:${accountAddress.toLowerCase()}:`;
|
|
428
|
+
for (const name of Object.keys(localStorage)) {
|
|
429
|
+
if (!name.startsWith(prefix) || !name.includes(":chan:")) continue;
|
|
430
|
+
try {
|
|
431
|
+
const snapshot = JSON.parse(localStorage.getItem(name));
|
|
432
|
+
const authority = snapshot?.descriptor?.authorizedSigner;
|
|
433
|
+
if (typeof authority === "string") authorities.add(authority.toLowerCase());
|
|
434
|
+
} catch {
|
|
435
|
+
// Ignore unrelated or corrupt browser storage; the MPP store owns its
|
|
436
|
+
// eventual validation and will fail closed if selected directly.
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return authorities;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function serializeAuthorizeAccessKey(value) {
|
|
443
|
+
const { limits, scopes, ...authorization } = value;
|
|
444
|
+
if (limits !== undefined && (!Array.isArray(limits) || limits.length === 0)) {
|
|
445
|
+
throw new TypeError("access-key limits must contain at least one explicit spending constraint");
|
|
446
|
+
}
|
|
447
|
+
if (scopes !== undefined && !Array.isArray(scopes)) {
|
|
448
|
+
throw new TypeError("access-key scopes must be an array when provided");
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
...authorization,
|
|
452
|
+
...(value.chainId === undefined ? {} : { chainId: toHex(value.chainId) }),
|
|
453
|
+
...(limits === undefined ? {} : {
|
|
454
|
+
limits: limits.map((limit) => ({
|
|
455
|
+
...limit,
|
|
456
|
+
limit: toHex(limit.limit),
|
|
457
|
+
})),
|
|
458
|
+
}),
|
|
459
|
+
...(scopes === undefined ? {} : { scopes }),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function toHex(value) {
|
|
464
|
+
return `0x${BigInt(value).toString(16)}`;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export async function disconnect(client, options = {}) {
|
|
468
|
+
const session = client._captureSession?.();
|
|
469
|
+
client._clearSession();
|
|
470
|
+
if (!session) return;
|
|
471
|
+
await session.request({
|
|
472
|
+
method: "POST",
|
|
473
|
+
path: "/v1/connections/disconnect",
|
|
474
|
+
signal: options.signal,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export async function reconnect(client, options = {}) {
|
|
479
|
+
const session = client._getSession();
|
|
480
|
+
if (!session) return undefined;
|
|
481
|
+
const retainedAuthorization = session.connection?.authorization_mode
|
|
482
|
+
?? (session.connection?.access_key ? "access_key" : undefined);
|
|
483
|
+
const authorization = options.authorization
|
|
484
|
+
?? (retainedAuthorization === "access_key" || retainedAuthorization === "hosted"
|
|
485
|
+
? retainedAuthorization
|
|
486
|
+
: (client.principal ? "hosted" : "access_key"));
|
|
487
|
+
if (client.principal && authorization !== "hosted") {
|
|
488
|
+
client._clearSession();
|
|
489
|
+
throw new TypeError("host principal connections require hosted authorization");
|
|
490
|
+
}
|
|
491
|
+
const appToolCatalog = hostedAppToolCatalog(options.tools ?? []);
|
|
492
|
+
const requestOptions = {
|
|
493
|
+
...options,
|
|
494
|
+
authorization,
|
|
495
|
+
appToolCatalogDigest: appToolCatalog.length === 0
|
|
496
|
+
? undefined
|
|
497
|
+
: await hostedToolCatalogDigest(appToolCatalog),
|
|
498
|
+
};
|
|
499
|
+
let retainedRequest;
|
|
500
|
+
let retained;
|
|
501
|
+
if (session.connection) {
|
|
502
|
+
try {
|
|
503
|
+
retained = connectionFromWire(session.connection);
|
|
504
|
+
if (retained.grant.id.toLowerCase() !== session.grantId.toLowerCase()
|
|
505
|
+
|| !connectionMatchesRequest(retained, requestOptions)) {
|
|
506
|
+
client._clearSession();
|
|
507
|
+
return undefined;
|
|
508
|
+
}
|
|
509
|
+
retainedRequest = reconnectRequestFromConnection(retained);
|
|
510
|
+
} catch {
|
|
511
|
+
// A legacy or corrupt projection can still be validated against the live
|
|
512
|
+
// grant. Current sessions always retain a complete exact projection.
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (client.principal) {
|
|
516
|
+
if (!retained?.principal || !Array.isArray(session.resources) || session.resources.length === 0) {
|
|
517
|
+
client._clearSession();
|
|
518
|
+
return undefined;
|
|
519
|
+
}
|
|
520
|
+
} else if (retained?.principal) {
|
|
521
|
+
client._clearSession();
|
|
522
|
+
return undefined;
|
|
523
|
+
}
|
|
524
|
+
let principalExchange;
|
|
525
|
+
if (client.principal) {
|
|
526
|
+
try {
|
|
527
|
+
principalExchange = await client.principal.create({
|
|
528
|
+
resources: session.resources,
|
|
529
|
+
signal: options.signal,
|
|
530
|
+
});
|
|
531
|
+
} catch (error) {
|
|
532
|
+
client._clearSession();
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
client._setSessionToken(session.token);
|
|
537
|
+
try {
|
|
538
|
+
const wire = await client.request({
|
|
539
|
+
// POST makes browsers attach their caller Origin. A simple cross-origin
|
|
540
|
+
// GET from an extension can omit Origin even when the app ID header is set.
|
|
541
|
+
method: "POST",
|
|
542
|
+
path: `/v1/grants/${session.grantId}/reconnect`,
|
|
543
|
+
...(principalExchange ? { body: { host_principal_exchange: principalExchange.token } } : {}),
|
|
544
|
+
signal: options.signal,
|
|
545
|
+
});
|
|
546
|
+
const connection = connectionFromWire(wire);
|
|
547
|
+
if (connection.grant.status !== "active"
|
|
548
|
+
|| connection.grant.expiresAt <= Math.floor(Date.now() / 1_000)) {
|
|
549
|
+
client._clearSession();
|
|
550
|
+
return undefined;
|
|
551
|
+
}
|
|
552
|
+
if (retained?.principal && connection.principal?.id !== retained.principal.id) {
|
|
553
|
+
client._clearSession();
|
|
554
|
+
return undefined;
|
|
555
|
+
}
|
|
556
|
+
if (!connectionMatchesRequest(connection, requestOptions)
|
|
557
|
+
|| (retainedRequest && !connectionMatchesRequest(connection, retainedRequest))) {
|
|
558
|
+
client._clearSession();
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
client._setSession({
|
|
562
|
+
grantId: session.grantId,
|
|
563
|
+
token: typeof wire?.grant_token === "string" && wire.grant_token
|
|
564
|
+
? wire.grant_token
|
|
565
|
+
: session.token,
|
|
566
|
+
connection: sessionConnectionWire(wire),
|
|
567
|
+
...(principalExchange ? { resources: session.resources } : {}),
|
|
568
|
+
});
|
|
569
|
+
return connection;
|
|
570
|
+
} catch (error) {
|
|
571
|
+
client._setSessionToken(undefined);
|
|
572
|
+
if (error?.status === 401 || error?.status === 403) client._clearSession();
|
|
573
|
+
throw error;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function sessionConnectionWire(wire) {
|
|
578
|
+
const { grant_token: _grantToken, ...connection } = wire;
|
|
579
|
+
return connection;
|
|
580
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Client } from "../Client.mjs";
|
|
2
|
+
import type { Grant, Hex } from "../types.mjs";
|
|
3
|
+
|
|
4
|
+
export declare namespace revoke {
|
|
5
|
+
type Options = Readonly<{ grantId: Hex; signal?: AbortSignal | undefined }>;
|
|
6
|
+
type ReturnType = Promise<Grant>;
|
|
7
|
+
type ErrorType = Error;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function revoke(client: Client, options: revoke.Options): revoke.ReturnType;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { grantFromWire } from "../internal.mjs";
|
|
2
|
+
|
|
3
|
+
export async function revoke(client, options) {
|
|
4
|
+
if (!options?.grantId) throw new TypeError("revoke requires grantId");
|
|
5
|
+
const grant = grantFromWire(await client.request({
|
|
6
|
+
method: "POST",
|
|
7
|
+
path: `/v1/grants/${options.grantId}/revoke`,
|
|
8
|
+
signal: options.signal,
|
|
9
|
+
}));
|
|
10
|
+
client._clearSession();
|
|
11
|
+
return grant;
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * as account from "./account.mjs";
|
|
2
|
+
export * as agent from "./agent.mjs";
|
|
3
|
+
export * as connection from "./connection.mjs";
|
|
4
|
+
export * as grant from "./grant.mjs";
|
|
5
|
+
export * as machineUsd from "./machineUsd.mjs";
|
|
6
|
+
export * as model from "./model.mjs";
|
|
7
|
+
export * as mpp from "./mpp.mjs";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * as account from "./account.mjs";
|
|
2
|
+
export * as agent from "./agent.mjs";
|
|
3
|
+
export * as connection from "./connection.mjs";
|
|
4
|
+
export * as grant from "./grant.mjs";
|
|
5
|
+
export * as machineUsd from "./machineUsd.mjs";
|
|
6
|
+
export * as model from "./model.mjs";
|
|
7
|
+
export * as mpp from "./mpp.mjs";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Client } from "../Client.mjs";
|
|
2
|
+
import type { Hex, MachineUsdConfig, MachineUsdFunding } from "../types.mjs";
|
|
3
|
+
|
|
4
|
+
export declare namespace getConfig {
|
|
5
|
+
type Options = Readonly<{ signal?: AbortSignal | undefined }>;
|
|
6
|
+
type ReturnType = Promise<MachineUsdConfig>;
|
|
7
|
+
type ErrorType = Error;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getConfig(client: Client, options?: getConfig.Options | undefined): getConfig.ReturnType;
|
|
11
|
+
|
|
12
|
+
export declare namespace fund {
|
|
13
|
+
type Options = Readonly<{
|
|
14
|
+
grantId: Hex;
|
|
15
|
+
accountAddress: Hex;
|
|
16
|
+
usdAmountCents: number;
|
|
17
|
+
signal?: AbortSignal | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
type ReturnType = Promise<MachineUsdFunding>;
|
|
20
|
+
type ErrorType = Error;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function fund(client: Client, options: fund.Options): fund.ReturnType;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { fundResultFromWire, machineUsdConfigFromWire } from "../internal.mjs";
|
|
2
|
+
|
|
3
|
+
export async function getConfig(client, options = {}) {
|
|
4
|
+
return machineUsdConfigFromWire(await client.request({
|
|
5
|
+
method: "GET",
|
|
6
|
+
path: "/v1/machine-usd/config",
|
|
7
|
+
signal: options.signal,
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function fund(client, options) {
|
|
12
|
+
if (!options?.grantId) throw new TypeError("fund requires grantId");
|
|
13
|
+
if (!Number.isSafeInteger(options.usdAmountCents)) {
|
|
14
|
+
throw new TypeError("fund requires an integer usdAmountCents");
|
|
15
|
+
}
|
|
16
|
+
const config = await getConfig(client, { signal: options.signal });
|
|
17
|
+
if (!config.onrampEnabled) throw new Error("The MACH onramp is unavailable");
|
|
18
|
+
if (options.usdAmountCents < config.minUsdAmountCents || options.usdAmountCents > config.maxUsdAmountCents) {
|
|
19
|
+
throw new RangeError(`MACH amount must be from ${config.minUsdAmountCents} through ${config.maxUsdAmountCents} cents`);
|
|
20
|
+
}
|
|
21
|
+
const approval = await client.dialog.open(Object.freeze({
|
|
22
|
+
id: crypto.randomUUID(),
|
|
23
|
+
type: "machineUsdFund",
|
|
24
|
+
grantId: options.grantId,
|
|
25
|
+
accountAddress: options.accountAddress,
|
|
26
|
+
usdAmountCents: options.usdAmountCents,
|
|
27
|
+
tokenAddress: config.tokenAddress,
|
|
28
|
+
chainId: config.chainId,
|
|
29
|
+
apiUrl: client.transport.baseUrl.replace(/\/+$/, ""),
|
|
30
|
+
stripePublishableKey: config.stripePublishableKey,
|
|
31
|
+
}));
|
|
32
|
+
return fundResultFromWire(await client.request({
|
|
33
|
+
method: "GET",
|
|
34
|
+
path: `/v1/grants/${options.grantId}/mpp/balance`,
|
|
35
|
+
signal: options.signal,
|
|
36
|
+
}).then((connection) => ({ order: approval.order, connection })), client);
|
|
37
|
+
}
|