@neus/sdk 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/index.cjs CHANGED
@@ -430,9 +430,9 @@ function deriveDid(address, chainIdOrChain) {
430
430
  async function resolveDID(params, options = {}) {
431
431
  const endpointPath = options.endpoint || "/api/v1/profile/did/resolve";
432
432
  const apiUrl = typeof options.apiUrl === "string" ? options.apiUrl.trim() : "";
433
- const resolveEndpoint = (path2) => {
434
- if (!path2 || typeof path2 !== "string") return null;
435
- const trimmedPath = path2.trim();
433
+ const resolveEndpoint = (path) => {
434
+ if (!path || typeof path !== "string") return null;
435
+ const trimmedPath = path.trim();
436
436
  if (!trimmedPath) return null;
437
437
  if (/^https?:\/\//i.test(trimmedPath)) return trimmedPath;
438
438
  if (trimmedPath.startsWith("/")) {
@@ -491,9 +491,9 @@ async function resolveDID(params, options = {}) {
491
491
  async function standardizeVerificationRequest(params, options = {}) {
492
492
  const endpointPath = options.endpoint || "/api/v1/verification/standardize";
493
493
  const apiUrl = typeof options.apiUrl === "string" ? options.apiUrl.trim() : "";
494
- const resolveEndpoint = (path2) => {
495
- if (!path2 || typeof path2 !== "string") return null;
496
- const trimmedPath = path2.trim();
494
+ const resolveEndpoint = (path) => {
495
+ if (!path || typeof path !== "string") return null;
496
+ const trimmedPath = path.trim();
497
497
  if (!trimmedPath) return null;
498
498
  if (/^https?:\/\//i.test(trimmedPath)) return trimmedPath;
499
499
  if (trimmedPath.startsWith("/")) {
@@ -3004,7 +3004,6 @@ __export(index_exports, {
3004
3004
  MCP_INSTALL_CLIENTS: () => MCP_INSTALL_CLIENTS,
3005
3005
  MCP_INSTALL_HOSTS: () => MCP_INSTALL_HOSTS,
3006
3006
  MONTH: () => MONTH,
3007
- MOUNT_MANIFEST_RELATIVE: () => MOUNT_MANIFEST_RELATIVE,
3008
3007
  NEUS_AUTH_CLI: () => NEUS_AUTH_CLI,
3009
3008
  NEUS_AUTH_NPX: () => NEUS_AUTH_NPX,
3010
3009
  NEUS_CHECK_CLI: () => NEUS_CHECK_CLI,
@@ -3035,7 +3034,6 @@ __export(index_exports, {
3035
3034
  VerificationError: () => VerificationError,
3036
3035
  WEEK: () => WEEK,
3037
3036
  YEAR: () => YEAR,
3038
- applyRuntimeBundle: () => applyRuntimeBundle,
3039
3037
  buildAuthCommandForClient: () => buildAuthCommandForClient,
3040
3038
  buildCursorMcpInstallUrl: () => buildCursorMcpInstallUrl,
3041
3039
  buildNeusMcpHttpConfig: () => buildNeusMcpHttpConfig,
@@ -3045,9 +3043,6 @@ __export(index_exports, {
3045
3043
  buildSetupNpxOneLiner: () => buildSetupNpxOneLiner,
3046
3044
  buildVerificationRequest: () => buildVerificationRequest,
3047
3045
  buildVsCodeMcpInstallUrl: () => buildVsCodeMcpInstallUrl,
3048
- bundleToClaudeMd: () => bundleToClaudeMd,
3049
- bundleToCodexJson: () => bundleToCodexJson,
3050
- bundleToCursorRules: () => bundleToCursorRules,
3051
3046
  combineGates: () => combineGates,
3052
3047
  computeContentHash: () => computeContentHash,
3053
3048
  constructVerificationMessage: () => constructVerificationMessage,
@@ -3077,12 +3072,10 @@ __export(index_exports, {
3077
3072
  pickActiveDelegation: () => pickActiveDelegation,
3078
3073
  pickIdentity: () => pickIdentity,
3079
3074
  profileAgentToIdentitySeed: () => profileAgentToIdentitySeed,
3080
- readMountManifest: () => readMountManifest,
3081
3075
  resolveDID: () => resolveDID,
3082
3076
  resolveEffectiveRuntime: () => resolveEffectiveRuntime,
3083
3077
  resolveRuntimeBundleFromMcp: () => resolveRuntimeBundleFromMcp,
3084
3078
  resolveZkPassportConfig: () => resolveZkPassportConfig,
3085
- sanitizeAgentIdForFilename: () => sanitizeAgentIdForFilename,
3086
3079
  signMessage: () => signMessage,
3087
3080
  standardizeVerificationRequest: () => standardizeVerificationRequest,
3088
3081
  supportsMcpInstallDeeplink: () => supportsMcpInstallDeeplink,
@@ -3094,8 +3087,7 @@ __export(index_exports, {
3094
3087
  validateUniversalAddress: () => validateUniversalAddress,
3095
3088
  validateVerifierPayload: () => validateVerifierPayload,
3096
3089
  validateWalletAddress: () => validateWalletAddress,
3097
- withRetry: () => withRetry,
3098
- writeMountManifest: () => writeMountManifest
3090
+ withRetry: () => withRetry
3099
3091
  });
3100
3092
  module.exports = __toCommonJS(index_exports);
3101
3093
  init_client();
@@ -3164,7 +3156,7 @@ function capabilitiesToArray(caps) {
3164
3156
  return Object.entries(caps).filter(([, enabled]) => enabled === true).map(([key]) => String(key).trim()).filter(Boolean);
3165
3157
  }
3166
3158
  function isDelegationExpired(expiresAt) {
3167
- if (expiresAt === null || expiresAt === void 0 || expiresAt === 0) return false;
3159
+ if (expiresAt === null || expiresAt === 0) return false;
3168
3160
  const ms = Number(expiresAt);
3169
3161
  return Number.isFinite(ms) && ms > 0 && ms <= Date.now();
3170
3162
  }
@@ -3261,7 +3253,7 @@ function extractAgentContextFromProofs(proofs) {
3261
3253
  runtimePolicy: vvData.runtimePolicy && typeof vvData.runtimePolicy === "object" ? vvData.runtimePolicy : void 0,
3262
3254
  expiresAt: vvData.expiresAt ?? null,
3263
3255
  isExpired: isDelegationExpired(vvData.expiresAt),
3264
- maxSpend: vvData.maxSpend !== null && vvData.maxSpend !== void 0 ? String(vvData.maxSpend) : void 0,
3256
+ maxSpend: vvData.maxSpend !== null ? String(vvData.maxSpend) : void 0,
3265
3257
  instructions: vvData.instructions || null,
3266
3258
  skills: Array.isArray(vvData.skills) ? vvData.skills : [],
3267
3259
  provider: vvData.provider || vvData.modelProvider || null,
@@ -3546,168 +3538,6 @@ function evaluateMountFileHealth(manifest) {
3546
3538
  };
3547
3539
  }
3548
3540
 
3549
- // runtime-adapters.js
3550
- var import_node_fs = __toESM(require("node:fs"), 1);
3551
- var import_node_path = __toESM(require("node:path"), 1);
3552
- var MOUNT_MANIFEST_RELATIVE = import_node_path.default.join(".neus", "mount.json");
3553
- function sanitizeAgentIdForFilename(agentId) {
3554
- return String(agentId || "agent").trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "agent";
3555
- }
3556
- function bundleToCursorRules(bundle) {
3557
- const id = bundle.identity.agentId;
3558
- const label = bundle.identity.agentLabel || id;
3559
- const skillsBlock = (bundle.identity.skills || []).map((skill) => {
3560
- if (typeof skill === "string") return `- ${skill}`;
3561
- const labelText = skill.label || skill.id || "skill";
3562
- const kind = skill.kind || "skill";
3563
- const provider = skill.provider ? ` / ${skill.provider}` : "";
3564
- return `- ${labelText} (${kind}${provider})`;
3565
- }).join("\n");
3566
- const denied = (bundle.enforce.deniedActions || []).map((action) => `- ${action}`).join("\n");
3567
- const capabilities = (bundle.identity.capabilities || []).map((cap) => `- ${cap}`).join("\n");
3568
- const services = (bundle.identity.services || []).map((svc) => `- ${svc.name}: ${svc.endpoint}${svc.version ? ` (v${svc.version})` : ""}`).join("\n");
3569
- return `---
3570
- description: NEUS proof-backed agent \u2014 ${label}
3571
- globs:
3572
- alwaysApply: true
3573
- ---
3574
-
3575
- # NEUS Agent \u2014 ${label}
3576
-
3577
- You are **${label}** (\`${id}\`). This project mounted trust context from NEUS.
3578
-
3579
- ## Identity
3580
- ${bundle.identity.description || bundle.identity.instructions || "Follow the agent instructions below."}
3581
-
3582
- ## Instructions
3583
- ${bundle.identity.instructions || "Use NEUS MCP for trust checks before sensitive actions."}
3584
-
3585
- ## Capabilities
3586
- ${capabilities || "- General purpose"}
3587
-
3588
- ## Skills
3589
- ${skillsBlock || "- None configured"}
3590
-
3591
- ## Services
3592
- ${services || "- None configured"}
3593
-
3594
- ## Scoped policy
3595
- ${denied ? `Denied actions (do not perform without new approval):
3596
- ${denied}` : "- Follow delegation on file via NEUS MCP."}
3597
-
3598
- ## Trust workflow
3599
- 1. Call \`neus_context\` once per session when NEUS MCP is available.
3600
- 2. Trust before action: \`neus_proofs_check\` then \`neus_verify_or_guide\`.
3601
- 3. Do not invent qHashes, wallets, or receipt fields.
3602
- 4. Summarize NEUS outcomes as Trust Result \u2014 never dump raw tool JSON.
3603
-
3604
- ## Proof references
3605
- - Identity: ${bundle.trust.identityProofUrl}
3606
- ${bundle.trust.delegationProofUrl ? `- Delegation: ${bundle.trust.delegationProofUrl}` : "- Delegation: not on file \u2014 call `neus_agent_link` before acting as this agent."}
3607
- `;
3608
- }
3609
- function bundleToClaudeMd(bundle) {
3610
- const id = bundle.identity.agentId;
3611
- const label = bundle.identity.agentLabel || id;
3612
- return `# NEUS Agent \u2014 ${label}
3613
-
3614
- Mounted from NEUS Runtime Mount (\`${RUNTIME_MOUNT_SCHEMA}\`).
3615
-
3616
- ## Identity
3617
- - **Agent ID:** ${id}
3618
- - **Label:** ${label}
3619
-
3620
- ## Description
3621
- ${bundle.identity.description || "Proof-backed agent on NEUS Network."}
3622
-
3623
- ## Instructions
3624
- ${bundle.identity.instructions || "Use NEUS MCP before sensitive actions."}
3625
-
3626
- ## Trust receipts
3627
- - Identity: \`${bundle.trust.identityQHash}\` \u2014 ${bundle.trust.identityProofUrl}
3628
- ${bundle.trust.delegationQHash ? `- Delegation: \`${bundle.trust.delegationQHash}\` \u2014 ${bundle.trust.delegationProofUrl}` : ""}
3629
-
3630
- ## Policy
3631
- - Do not invent qHashes or verifier outcomes.
3632
- - Call \`neus_context\` once; use profile context when signed in.
3633
- `;
3634
- }
3635
- function bundleToCodexJson(bundle) {
3636
- return JSON.stringify(
3637
- {
3638
- schema: RUNTIME_MOUNT_SCHEMA,
3639
- name: bundle.identity.agentLabel,
3640
- agentId: bundle.identity.agentId,
3641
- agentWallet: bundle.identity.agentWallet,
3642
- description: bundle.identity.description,
3643
- instructions: bundle.identity.instructions,
3644
- capabilities: bundle.identity.capabilities,
3645
- skills: bundle.identity.skills,
3646
- services: bundle.identity.services,
3647
- effectiveRuntime: bundle.effectiveRuntime,
3648
- enforce: bundle.enforce,
3649
- trust: bundle.trust,
3650
- mountedAt: bundle.mountedAt
3651
- },
3652
- null,
3653
- 2
3654
- );
3655
- }
3656
- function readMountManifest(cwd) {
3657
- const manifestPath = import_node_path.default.join(cwd, MOUNT_MANIFEST_RELATIVE);
3658
- if (!import_node_fs.default.existsSync(manifestPath)) return null;
3659
- try {
3660
- const parsed = JSON.parse(import_node_fs.default.readFileSync(manifestPath, "utf8"));
3661
- return parsed?.schema === RUNTIME_MOUNT_SCHEMA ? parsed : null;
3662
- } catch {
3663
- return null;
3664
- }
3665
- }
3666
- function writeMountManifest(bundle, cwd) {
3667
- const dir = import_node_path.default.join(cwd, ".neus");
3668
- import_node_fs.default.mkdirSync(dir, { recursive: true });
3669
- const manifestPath = import_node_path.default.join(dir, "mount.json");
3670
- import_node_fs.default.writeFileSync(manifestPath, `${JSON.stringify(bundle, null, 2)}
3671
- `, "utf8");
3672
- return manifestPath;
3673
- }
3674
- function applyRuntimeBundle(flavor, bundle, cwd, options = {}) {
3675
- const dryRun = Boolean(options.dryRun);
3676
- const safeId = sanitizeAgentIdForFilename(bundle.identity.agentId);
3677
- const written = [];
3678
- const manifestPath = dryRun ? import_node_path.default.join(cwd, MOUNT_MANIFEST_RELATIVE) : writeMountManifest(bundle, cwd);
3679
- written.push(manifestPath);
3680
- if (flavor === "cursor") {
3681
- const rulesDir = import_node_path.default.join(cwd, ".cursor", "rules");
3682
- const rulesPath = import_node_path.default.join(rulesDir, `neus-agent-${safeId}.mdc`);
3683
- if (!dryRun) {
3684
- import_node_fs.default.mkdirSync(rulesDir, { recursive: true });
3685
- import_node_fs.default.writeFileSync(rulesPath, bundleToCursorRules(bundle), "utf8");
3686
- }
3687
- written.push(rulesPath);
3688
- return { flavor, written, primary: rulesPath, manifestPath };
3689
- }
3690
- if (flavor === "claude") {
3691
- const claudePath = import_node_path.default.join(cwd, ".claude", "NEUS_AGENT.md");
3692
- if (!dryRun) {
3693
- import_node_fs.default.mkdirSync(import_node_path.default.join(cwd, ".claude"), { recursive: true });
3694
- import_node_fs.default.writeFileSync(claudePath, bundleToClaudeMd(bundle), "utf8");
3695
- }
3696
- written.push(claudePath);
3697
- return { flavor, written, primary: claudePath, manifestPath };
3698
- }
3699
- if (flavor === "codex") {
3700
- const codexPath = import_node_path.default.join(cwd, ".neus", `codex-agent-${safeId}.json`);
3701
- if (!dryRun) {
3702
- import_node_fs.default.mkdirSync(import_node_path.default.join(cwd, ".neus"), { recursive: true });
3703
- import_node_fs.default.writeFileSync(codexPath, bundleToCodexJson(bundle), "utf8");
3704
- }
3705
- written.push(codexPath);
3706
- return { flavor, written, primary: codexPath, manifestPath };
3707
- }
3708
- throw new Error(`Unsupported runtime adapter: ${flavor}`);
3709
- }
3710
-
3711
3541
  // index.js
3712
3542
  init_errors();
3713
3543
 
@@ -3850,7 +3680,6 @@ var index_default = {
3850
3680
  MCP_INSTALL_CLIENTS,
3851
3681
  MCP_INSTALL_HOSTS,
3852
3682
  MONTH,
3853
- MOUNT_MANIFEST_RELATIVE,
3854
3683
  NEUS_AUTH_CLI,
3855
3684
  NEUS_AUTH_NPX,
3856
3685
  NEUS_CHECK_CLI,
@@ -3881,7 +3710,6 @@ var index_default = {
3881
3710
  VerificationError,
3882
3711
  WEEK,
3883
3712
  YEAR,
3884
- applyRuntimeBundle,
3885
3713
  buildAuthCommandForClient,
3886
3714
  buildCursorMcpInstallUrl,
3887
3715
  buildNeusMcpHttpConfig,
@@ -3891,9 +3719,6 @@ var index_default = {
3891
3719
  buildSetupNpxOneLiner,
3892
3720
  buildVerificationRequest,
3893
3721
  buildVsCodeMcpInstallUrl,
3894
- bundleToClaudeMd,
3895
- bundleToCodexJson,
3896
- bundleToCursorRules,
3897
3722
  combineGates,
3898
3723
  computeContentHash,
3899
3724
  constructVerificationMessage,
@@ -3922,12 +3747,10 @@ var index_default = {
3922
3747
  pickActiveDelegation,
3923
3748
  pickIdentity,
3924
3749
  profileAgentToIdentitySeed,
3925
- readMountManifest,
3926
3750
  resolveDID,
3927
3751
  resolveEffectiveRuntime,
3928
3752
  resolveRuntimeBundleFromMcp,
3929
3753
  resolveZkPassportConfig,
3930
- sanitizeAgentIdForFilename,
3931
3754
  signMessage,
3932
3755
  standardizeVerificationRequest,
3933
3756
  supportsMcpInstallDeeplink,
@@ -3939,6 +3762,5 @@ var index_default = {
3939
3762
  validateUniversalAddress,
3940
3763
  validateVerifierPayload,
3941
3764
  validateWalletAddress,
3942
- withRetry,
3943
- writeMountManifest
3765
+ withRetry
3944
3766
  });
@@ -54,7 +54,7 @@ function capabilitiesToArray(caps) {
54
54
  return Object.entries(caps).filter(([, enabled]) => enabled === true).map(([key]) => String(key).trim()).filter(Boolean);
55
55
  }
56
56
  function isDelegationExpired(expiresAt) {
57
- if (expiresAt === null || expiresAt === void 0 || expiresAt === 0) return false;
57
+ if (expiresAt === null || expiresAt === 0) return false;
58
58
  const ms = Number(expiresAt);
59
59
  return Number.isFinite(ms) && ms > 0 && ms <= Date.now();
60
60
  }
@@ -151,7 +151,7 @@ function extractAgentContextFromProofs(proofs) {
151
151
  runtimePolicy: vvData.runtimePolicy && typeof vvData.runtimePolicy === "object" ? vvData.runtimePolicy : void 0,
152
152
  expiresAt: vvData.expiresAt ?? null,
153
153
  isExpired: isDelegationExpired(vvData.expiresAt),
154
- maxSpend: vvData.maxSpend !== null && vvData.maxSpend !== void 0 ? String(vvData.maxSpend) : void 0,
154
+ maxSpend: vvData.maxSpend !== null ? String(vvData.maxSpend) : void 0,
155
155
  instructions: vvData.instructions || null,
156
156
  skills: Array.isArray(vvData.skills) ? vvData.skills : [],
157
157
  provider: vvData.provider || vvData.modelProvider || null,
@@ -0,0 +1,75 @@
1
+ /**
2
+ * NEUS CLI command strings — SSOT for docs, MCP context, product UI, and skills.
3
+ *
4
+ * Pattern (industry default):
5
+ * - Install once: `npm i -g @neus/sdk`
6
+ * - Daily use: `neus <command>` (short)
7
+ * - Zero-install try: `npx @neus/sdk <command>` (no global install)
8
+ */
9
+
10
+ export const NEUS_PKG = '@neus/sdk';
11
+
12
+ /** Recommended one-time install for builders using the CLI regularly. */
13
+ export const NEUS_INSTALL_CLI = `npm i -g ${NEUS_PKG}`;
14
+
15
+ /** Zero-install prefix — works without global install. */
16
+ export const NEUS_NPX = `npx ${NEUS_PKG}`;
17
+
18
+ /** Short commands (after `NEUS_INSTALL_CLI`). */
19
+ export const NEUS_SETUP_CLI = 'neus setup';
20
+ export const NEUS_AUTH_CLI = 'neus auth';
21
+ export const NEUS_CHECK_CLI = 'neus check';
22
+ export const NEUS_DOCTOR_CLI = 'neus doctor --live';
23
+ export const NEUS_EXAMPLES_CLI = 'neus examples';
24
+
25
+ /** One-shot copy-paste (no global install required). */
26
+ export const NEUS_SETUP_NPX = `${NEUS_NPX} setup`;
27
+ export const NEUS_AUTH_NPX = `${NEUS_NPX} auth`;
28
+ export const NEUS_CHECK_NPX = `${NEUS_NPX} check`;
29
+ export const NEUS_DOCTOR_NPX = `${NEUS_NPX} doctor --live`;
30
+ export const NEUS_EXAMPLES_NPX = `${NEUS_NPX} examples`;
31
+
32
+ /**
33
+ * @param {string} agentId
34
+ * @param {'cursor' | 'claude' | 'codex'} [host]
35
+ */
36
+ export function neusMountApply(agentId, host = 'cursor') {
37
+ const id = String(agentId || '').trim();
38
+ return `neus mount ${id} --apply ${host}`;
39
+ }
40
+
41
+ /**
42
+ * @param {string} agentId
43
+ * @param {'cursor' | 'claude' | 'codex'} [host]
44
+ */
45
+ export function neusMountApplyNpx(agentId, host = 'cursor') {
46
+ const id = String(agentId || '').trim();
47
+ return `${NEUS_NPX} mount ${id} --apply ${host}`;
48
+ }
49
+
50
+ /** Docs / landing quick start (installed path). */
51
+ export const NEUS_QUICKSTART_INSTALLED = `${NEUS_INSTALL_CLI}
52
+ ${NEUS_SETUP_CLI}
53
+ ${NEUS_AUTH_CLI}`;
54
+
55
+ /** Docs quick try (zero-install). */
56
+ export const NEUS_QUICKSTART_NPX = NEUS_SETUP_NPX;
57
+
58
+ /** Per-repo agent bind (after auth on the machine). */
59
+ export const NEUS_MOUNT_WORKFLOW = `${NEUS_AUTH_CLI}
60
+ neus mount <agentId> --apply cursor
61
+ ${NEUS_DOCTOR_CLI}`;
62
+
63
+ /**
64
+ * @param {string} subcommand
65
+ */
66
+ export function neusCmd(subcommand) {
67
+ return `neus ${String(subcommand || '').trim()}`;
68
+ }
69
+
70
+ /**
71
+ * @param {string} subcommand
72
+ */
73
+ export function neusNpx(subcommand) {
74
+ return `${NEUS_NPX} ${String(subcommand || '').trim()}`;
75
+ }
package/index.js CHANGED
@@ -72,16 +72,7 @@ export {
72
72
  evaluateMountFileHealth
73
73
  } from './runtime-mount.js';
74
74
 
75
- export {
76
- MOUNT_MANIFEST_RELATIVE,
77
- sanitizeAgentIdForFilename,
78
- bundleToCursorRules,
79
- bundleToClaudeMd,
80
- bundleToCodexJson,
81
- readMountManifest,
82
- writeMountManifest,
83
- applyRuntimeBundle
84
- } from './runtime-adapters.js';
75
+ // Node-only adapters (fs/path): import `@neus/sdk/runtime-adapters` — not re-exported here (Next/webpack safe).
85
76
 
86
77
  export {
87
78
  SDKError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neus/sdk",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "NEUS makes trust portable across the internet — so people, apps, and AI agents can prove what is real before access, payout, or execution.",
5
5
  "bin": {
6
6
  "neus": "cli/neus.mjs"
@@ -141,6 +141,7 @@
141
141
  },
142
142
  "files": [
143
143
  "cli/neus.mjs",
144
+ "cli-commands.js",
144
145
  "mcp-hosts.js",
145
146
  "index.js",
146
147
  "client.js",
@@ -148,6 +149,8 @@
148
149
  "errors.js",
149
150
  "gates.js",
150
151
  "sponsor.js",
152
+ "runtime-mount.js",
153
+ "runtime-adapters.js",
151
154
  "cjs/**",
152
155
  "widgets.cjs",
153
156
  "types.d.ts",
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Runtime Mount adapters — apply proof-backed bundles to host workspaces.
3
+ */
4
+
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { RUNTIME_MOUNT_SCHEMA } from './runtime-mount.js';
8
+
9
+ export const MOUNT_MANIFEST_RELATIVE = path.join('.neus', 'mount.json');
10
+
11
+ /**
12
+ * @param {string} agentId
13
+ */
14
+ export function sanitizeAgentIdForFilename(agentId) {
15
+ return String(agentId || 'agent')
16
+ .trim()
17
+ .toLowerCase()
18
+ .replace(/[^a-z0-9_-]+/g, '-')
19
+ .replace(/^-+|-+$/g, '')
20
+ .slice(0, 64) || 'agent';
21
+ }
22
+
23
+ /**
24
+ * @param {import('./runtime-mount.js').RuntimeBundle} bundle
25
+ */
26
+ export function bundleToCursorRules(bundle) {
27
+ const id = bundle.identity.agentId;
28
+ const label = bundle.identity.agentLabel || id;
29
+ const skillsBlock = (bundle.identity.skills || [])
30
+ .map(skill => {
31
+ if (typeof skill === 'string') return `- ${skill}`;
32
+ const labelText = skill.label || skill.id || 'skill';
33
+ const kind = skill.kind || 'skill';
34
+ const provider = skill.provider ? ` / ${skill.provider}` : '';
35
+ return `- ${labelText} (${kind}${provider})`;
36
+ })
37
+ .join('\n');
38
+
39
+ const denied = (bundle.enforce.deniedActions || []).map(action => `- ${action}`).join('\n');
40
+ const capabilities = (bundle.identity.capabilities || []).map(cap => `- ${cap}`).join('\n');
41
+ const services = (bundle.identity.services || [])
42
+ .map(svc => `- ${svc.name}: ${svc.endpoint}${svc.version ? ` (v${svc.version})` : ''}`)
43
+ .join('\n');
44
+
45
+ return `---
46
+ description: NEUS proof-backed agent — ${label}
47
+ globs:
48
+ alwaysApply: true
49
+ ---
50
+
51
+ # NEUS Agent — ${label}
52
+
53
+ You are **${label}** (\`${id}\`). This project mounted trust context from NEUS.
54
+
55
+ ## Identity
56
+ ${bundle.identity.description || bundle.identity.instructions || 'Follow the agent instructions below.'}
57
+
58
+ ## Instructions
59
+ ${bundle.identity.instructions || 'Use NEUS MCP for trust checks before sensitive actions.'}
60
+
61
+ ## Capabilities
62
+ ${capabilities || '- General purpose'}
63
+
64
+ ## Skills
65
+ ${skillsBlock || '- None configured'}
66
+
67
+ ## Services
68
+ ${services || '- None configured'}
69
+
70
+ ## Scoped policy
71
+ ${denied ? `Denied actions (do not perform without new approval):\n${denied}` : '- Follow delegation on file via NEUS MCP.'}
72
+
73
+ ## Trust workflow
74
+ 1. Call \`neus_context\` once per session when NEUS MCP is available.
75
+ 2. Trust before action: \`neus_proofs_check\` then \`neus_verify_or_guide\`.
76
+ 3. Do not invent qHashes, wallets, or receipt fields.
77
+ 4. Summarize NEUS outcomes as Trust Result — never dump raw tool JSON.
78
+
79
+ ## Proof references
80
+ - Identity: ${bundle.trust.identityProofUrl}
81
+ ${bundle.trust.delegationProofUrl ? `- Delegation: ${bundle.trust.delegationProofUrl}` : '- Delegation: not on file — call `neus_agent_link` before acting as this agent.'}
82
+ `;
83
+ }
84
+
85
+ /**
86
+ * @param {import('./runtime-mount.js').RuntimeBundle} bundle
87
+ */
88
+ export function bundleToClaudeMd(bundle) {
89
+ const id = bundle.identity.agentId;
90
+ const label = bundle.identity.agentLabel || id;
91
+ return `# NEUS Agent — ${label}
92
+
93
+ Mounted from NEUS Runtime Mount (\`${RUNTIME_MOUNT_SCHEMA}\`).
94
+
95
+ ## Identity
96
+ - **Agent ID:** ${id}
97
+ - **Label:** ${label}
98
+
99
+ ## Description
100
+ ${bundle.identity.description || 'Proof-backed agent on NEUS Network.'}
101
+
102
+ ## Instructions
103
+ ${bundle.identity.instructions || 'Use NEUS MCP before sensitive actions.'}
104
+
105
+ ## Trust receipts
106
+ - Identity: \`${bundle.trust.identityQHash}\` — ${bundle.trust.identityProofUrl}
107
+ ${bundle.trust.delegationQHash ? `- Delegation: \`${bundle.trust.delegationQHash}\` — ${bundle.trust.delegationProofUrl}` : ''}
108
+
109
+ ## Policy
110
+ - Do not invent qHashes or verifier outcomes.
111
+ - Call \`neus_context\` once; use profile context when signed in.
112
+ `;
113
+ }
114
+
115
+ /**
116
+ * @param {import('./runtime-mount.js').RuntimeBundle} bundle
117
+ */
118
+ export function bundleToCodexJson(bundle) {
119
+ return JSON.stringify(
120
+ {
121
+ schema: RUNTIME_MOUNT_SCHEMA,
122
+ name: bundle.identity.agentLabel,
123
+ agentId: bundle.identity.agentId,
124
+ agentWallet: bundle.identity.agentWallet,
125
+ description: bundle.identity.description,
126
+ instructions: bundle.identity.instructions,
127
+ capabilities: bundle.identity.capabilities,
128
+ skills: bundle.identity.skills,
129
+ services: bundle.identity.services,
130
+ effectiveRuntime: bundle.effectiveRuntime,
131
+ enforce: bundle.enforce,
132
+ trust: bundle.trust,
133
+ mountedAt: bundle.mountedAt
134
+ },
135
+ null,
136
+ 2
137
+ );
138
+ }
139
+
140
+ /**
141
+ * @param {string} cwd
142
+ */
143
+ export function readMountManifest(cwd) {
144
+ const manifestPath = path.join(cwd, MOUNT_MANIFEST_RELATIVE);
145
+ if (!fs.existsSync(manifestPath)) return null;
146
+ try {
147
+ const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
148
+ return parsed?.schema === RUNTIME_MOUNT_SCHEMA ? parsed : null;
149
+ } catch {
150
+ return null;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * @param {import('./runtime-mount.js').RuntimeBundle} bundle
156
+ * @param {string} cwd
157
+ */
158
+ export function writeMountManifest(bundle, cwd) {
159
+ const dir = path.join(cwd, '.neus');
160
+ fs.mkdirSync(dir, { recursive: true });
161
+ const manifestPath = path.join(dir, 'mount.json');
162
+ fs.writeFileSync(manifestPath, `${JSON.stringify(bundle, null, 2)}\n`, 'utf8');
163
+ return manifestPath;
164
+ }
165
+
166
+ /**
167
+ * @param {'cursor' | 'claude' | 'codex'} flavor
168
+ * @param {import('./runtime-mount.js').RuntimeBundle} bundle
169
+ * @param {string} cwd
170
+ * @param {{ dryRun?: boolean }} [options]
171
+ */
172
+ export function applyRuntimeBundle(flavor, bundle, cwd, options = {}) {
173
+ const dryRun = Boolean(options.dryRun);
174
+ const safeId = sanitizeAgentIdForFilename(bundle.identity.agentId);
175
+ const written = [];
176
+
177
+ const manifestPath = dryRun
178
+ ? path.join(cwd, MOUNT_MANIFEST_RELATIVE)
179
+ : writeMountManifest(bundle, cwd);
180
+ written.push(manifestPath);
181
+
182
+ if (flavor === 'cursor') {
183
+ const rulesDir = path.join(cwd, '.cursor', 'rules');
184
+ const rulesPath = path.join(rulesDir, `neus-agent-${safeId}.mdc`);
185
+ if (!dryRun) {
186
+ fs.mkdirSync(rulesDir, { recursive: true });
187
+ fs.writeFileSync(rulesPath, bundleToCursorRules(bundle), 'utf8');
188
+ }
189
+ written.push(rulesPath);
190
+ return { flavor, written, primary: rulesPath, manifestPath };
191
+ }
192
+
193
+ if (flavor === 'claude') {
194
+ const claudePath = path.join(cwd, '.claude', 'NEUS_AGENT.md');
195
+ if (!dryRun) {
196
+ fs.mkdirSync(path.join(cwd, '.claude'), { recursive: true });
197
+ fs.writeFileSync(claudePath, bundleToClaudeMd(bundle), 'utf8');
198
+ }
199
+ written.push(claudePath);
200
+ return { flavor, written, primary: claudePath, manifestPath };
201
+ }
202
+
203
+ if (flavor === 'codex') {
204
+ const codexPath = path.join(cwd, '.neus', `codex-agent-${safeId}.json`);
205
+ if (!dryRun) {
206
+ fs.mkdirSync(path.join(cwd, '.neus'), { recursive: true });
207
+ fs.writeFileSync(codexPath, bundleToCodexJson(bundle), 'utf8');
208
+ }
209
+ written.push(codexPath);
210
+ return { flavor, written, primary: codexPath, manifestPath };
211
+ }
212
+
213
+ throw new Error(`Unsupported runtime adapter: ${flavor}`);
214
+ }
@@ -0,0 +1,522 @@
1
+ /**
2
+ * Runtime Mount — proof-backed agent context bundle (neus.runtime-mount.v1).
3
+ * SSOT for CLI, integrators, and protocol neus_agent_mount response shape.
4
+ */
5
+
6
+ export const RUNTIME_MOUNT_SCHEMA = 'neus.runtime-mount.v1';
7
+
8
+ const PROOF_URL_BASE = 'https://neus.network/proof/';
9
+
10
+ /**
11
+ * @param {string | null | undefined} value
12
+ */
13
+ export function normalizeWallet(value) {
14
+ const wallet = String(value || '').trim().toLowerCase();
15
+ return /^0x[a-f0-9]{40}$/.test(wallet) ? wallet : '';
16
+ }
17
+
18
+ /**
19
+ * @param {unknown} value
20
+ */
21
+ function asString(value) {
22
+ const trimmed = String(value ?? '').trim();
23
+ return trimmed.length > 0 ? trimmed : '';
24
+ }
25
+
26
+ /**
27
+ * @param {unknown} value
28
+ * @returns {string[]}
29
+ */
30
+ function asStringArray(value) {
31
+ if (!Array.isArray(value)) return [];
32
+ return value.map(item => String(item || '').trim()).filter(Boolean);
33
+ }
34
+
35
+ /**
36
+ * @param {Record<string, unknown> | null | undefined} caps
37
+ */
38
+ function capabilitiesToArray(caps) {
39
+ if (Array.isArray(caps)) return asStringArray(caps);
40
+ if (!caps || typeof caps !== 'object') return [];
41
+ return Object.entries(caps)
42
+ .filter(([, enabled]) => enabled === true)
43
+ .map(([key]) => String(key).trim())
44
+ .filter(Boolean);
45
+ }
46
+
47
+ /**
48
+ * @param {number | null | undefined} expiresAt
49
+ */
50
+ export function isDelegationExpired(expiresAt) {
51
+ if (expiresAt === null || expiresAt === 0) return false;
52
+ const ms = Number(expiresAt);
53
+ return Number.isFinite(ms) && ms > 0 && ms <= Date.now();
54
+ }
55
+
56
+ /**
57
+ * @param {Array<Record<string, unknown>>} identities
58
+ * @param {{ agentId?: string, agentWallet?: string, identityQHash?: string }} selector
59
+ */
60
+ export function pickIdentity(identities, selector) {
61
+ const list = Array.isArray(identities) ? identities : [];
62
+ const qHash = asString(selector.identityQHash).toLowerCase();
63
+ if (qHash) {
64
+ return list.find(row => asString(row.qHash).toLowerCase() === qHash) || null;
65
+ }
66
+ const agentId = asString(selector.agentId).toLowerCase();
67
+ const agentWallet = normalizeWallet(selector.agentWallet);
68
+ if (agentId) {
69
+ const byId = list.filter(row => asString(row.agentId).toLowerCase() === agentId);
70
+ if (agentWallet) {
71
+ return byId.find(row => normalizeWallet(row.agentWallet) === agentWallet) || byId[0] || null;
72
+ }
73
+ return byId[0] || null;
74
+ }
75
+ if (agentWallet) {
76
+ return list.find(row => normalizeWallet(row.agentWallet) === agentWallet) || null;
77
+ }
78
+ return null;
79
+ }
80
+
81
+ /**
82
+ * @param {Array<Record<string, unknown>>} delegations
83
+ * @param {string} controllerWallet
84
+ * @param {string} agentWallet
85
+ * @param {string} agentId
86
+ */
87
+ export function pickActiveDelegation(delegations, controllerWallet, agentWallet, agentId) {
88
+ const list = Array.isArray(delegations) ? delegations : [];
89
+ const controller = normalizeWallet(controllerWallet);
90
+ const agent = normalizeWallet(agentWallet);
91
+ const id = asString(agentId).toLowerCase();
92
+ const candidates = list.filter(row => {
93
+ if (isDelegationExpired(row.expiresAt)) return false;
94
+ const rowAgent = normalizeWallet(row.agentWallet);
95
+ const rowController = normalizeWallet(row.controllerWallet);
96
+ if (agent && rowAgent && rowAgent !== agent) return false;
97
+ if (controller && rowController && rowController !== controller) return false;
98
+ if (id && row.agentId && asString(row.agentId).toLowerCase() !== id) return false;
99
+ return true;
100
+ });
101
+ return candidates[0] || null;
102
+ }
103
+
104
+ /**
105
+ * @param {Record<string, unknown> | null | undefined} identity
106
+ * @param {Record<string, unknown> | null | undefined} delegation
107
+ */
108
+ export function resolveEffectiveRuntime(identity, delegation) {
109
+ const delProvider = asString(delegation?.provider);
110
+ const delModel = asString(delegation?.model);
111
+ if (delProvider || delModel) {
112
+ return {
113
+ provider: delProvider || 'openai',
114
+ model: delModel || ''
115
+ };
116
+ }
117
+ const defaultRuntime =
118
+ identity?.defaultRuntime && typeof identity.defaultRuntime === 'object'
119
+ ? identity.defaultRuntime
120
+ : null;
121
+ const idProvider = asString(defaultRuntime?.provider);
122
+ const idModel = asString(defaultRuntime?.model);
123
+ if (idProvider || idModel) {
124
+ return {
125
+ provider: idProvider || 'openai',
126
+ model: idModel || ''
127
+ };
128
+ }
129
+ return null;
130
+ }
131
+
132
+ /**
133
+ * @param {unknown} proof
134
+ */
135
+ export function extractAgentContextFromProofs(proofs) {
136
+ const identities = [];
137
+ const delegations = [];
138
+ const list = Array.isArray(proofs) ? proofs : [];
139
+
140
+ for (const proof of list) {
141
+ const qHash = asString(proof?.qHash);
142
+ const verifiedVerifiers = Array.isArray(proof?.verifiedVerifiers) ? proof.verifiedVerifiers : [];
143
+ for (const vv of verifiedVerifiers) {
144
+ const verifierId = asString(vv?.verifierId);
145
+ const vvData = vv?.data && typeof vv.data === 'object' ? vv.data : {};
146
+ if (verifierId === 'agent-identity') {
147
+ identities.push({
148
+ qHash,
149
+ agentId: vvData.agentId || null,
150
+ agentWallet: vvData.agentWallet || null,
151
+ agentLabel: vvData.agentLabel || vvData.agentId || 'Agent',
152
+ agentType: vvData.agentType || 'agent',
153
+ description: vvData.description || null,
154
+ capabilities: capabilitiesToArray(vvData.capabilities),
155
+ skills: Array.isArray(vvData.skills) ? vvData.skills : [],
156
+ instructions: vvData.instructions || null,
157
+ services: Array.isArray(vvData.services) ? vvData.services : [],
158
+ defaultRuntime:
159
+ vvData.defaultRuntime && typeof vvData.defaultRuntime === 'object'
160
+ ? vvData.defaultRuntime
161
+ : undefined
162
+ });
163
+ }
164
+ if (verifierId === 'agent-delegation') {
165
+ delegations.push({
166
+ qHash,
167
+ controllerWallet: vvData.controllerWallet || null,
168
+ agentWallet: vvData.agentWallet || null,
169
+ agentId: vvData.agentId || null,
170
+ scope: vvData.scope || 'global',
171
+ allowedActions: asStringArray(vvData.allowedActions),
172
+ deniedActions: asStringArray(vvData.deniedActions),
173
+ runtimePolicy:
174
+ vvData.runtimePolicy && typeof vvData.runtimePolicy === 'object'
175
+ ? vvData.runtimePolicy
176
+ : undefined,
177
+ expiresAt: vvData.expiresAt ?? null,
178
+ isExpired: isDelegationExpired(vvData.expiresAt),
179
+ maxSpend: vvData.maxSpend !== null ? String(vvData.maxSpend) : undefined,
180
+ instructions: vvData.instructions || null,
181
+ skills: Array.isArray(vvData.skills) ? vvData.skills : [],
182
+ provider: vvData.provider || vvData.modelProvider || null,
183
+ model: vvData.model || null
184
+ });
185
+ }
186
+ }
187
+ }
188
+
189
+ return { identities, delegations };
190
+ }
191
+
192
+ /**
193
+ * @param {Record<string, unknown>} input
194
+ */
195
+ export function buildRuntimeBundle(input) {
196
+ const identity = input.identity || {};
197
+ const delegation = input.delegation || null;
198
+ const identityQHash = asString(input.identityQHash || identity.qHash);
199
+ const delegationQHash = delegation ? asString(input.delegationQHash || delegation.qHash) : null;
200
+ const agentId = asString(identity.agentId);
201
+ const agentWallet = normalizeWallet(identity.agentWallet);
202
+
203
+ if (!identityQHash || !agentId || !agentWallet) {
204
+ throw new Error('Runtime mount requires verified agent identity (agentId, agentWallet, identityQHash).');
205
+ }
206
+
207
+ const effectiveRuntime = resolveEffectiveRuntime(identity, delegation);
208
+ const deniedActions = delegation ? asStringArray(delegation.deniedActions) : [];
209
+ const allowedActions = delegation ? asStringArray(delegation.allowedActions) : undefined;
210
+ const requiresHumanApproval =
211
+ delegation?.runtimePolicy &&
212
+ typeof delegation.runtimePolicy === 'object' &&
213
+ delegation.runtimePolicy.requiresHumanApproval === true;
214
+
215
+ const capabilities = asStringArray(identity.capabilities);
216
+ const skills = Array.isArray(identity.skills) ? identity.skills : [];
217
+ const skillIds = skills
218
+ .map(skill =>
219
+ typeof skill === 'string' ? skill : asString(skill?.id || skill?.label)
220
+ )
221
+ .filter(Boolean);
222
+
223
+ const delegations = delegation ? [delegation] : [];
224
+ const activeDelegations = delegations.filter(row => !row.isExpired).length;
225
+
226
+ return {
227
+ schema: RUNTIME_MOUNT_SCHEMA,
228
+ mountedAt: new Date().toISOString(),
229
+ trust: {
230
+ identityQHash,
231
+ delegationQHash: delegationQHash || null,
232
+ identityProofUrl: `${PROOF_URL_BASE}${identityQHash}`,
233
+ delegationProofUrl: delegationQHash ? `${PROOF_URL_BASE}${delegationQHash}` : null
234
+ },
235
+ identity: {
236
+ agentId,
237
+ agentWallet,
238
+ agentLabel: asString(identity.agentLabel) || agentId,
239
+ agentType: asString(identity.agentType) || 'agent',
240
+ description: asString(identity.description) || undefined,
241
+ instructions: asString(identity.instructions) || undefined,
242
+ capabilities,
243
+ skills,
244
+ services: Array.isArray(identity.services) ? identity.services : undefined,
245
+ defaultRuntime:
246
+ identity.defaultRuntime && typeof identity.defaultRuntime === 'object'
247
+ ? identity.defaultRuntime
248
+ : undefined
249
+ },
250
+ delegation: delegation
251
+ ? {
252
+ controllerWallet: normalizeWallet(delegation.controllerWallet) || asString(delegation.controllerWallet),
253
+ scope: asString(delegation.scope) || undefined,
254
+ allowedActions,
255
+ deniedActions,
256
+ runtimePolicy: delegation.runtimePolicy,
257
+ expiresAt: delegation.expiresAt ?? null,
258
+ isExpired: Boolean(delegation.isExpired),
259
+ maxSpend: delegation.maxSpend,
260
+ instructions: asString(delegation.instructions) || undefined,
261
+ skills: Array.isArray(delegation.skills) ? delegation.skills : undefined,
262
+ provider: asString(delegation.provider) || undefined,
263
+ model: asString(delegation.model) || undefined
264
+ }
265
+ : null,
266
+ effectiveRuntime,
267
+ tools: Array.isArray(input.tools) ? input.tools : [],
268
+ secretBindings: Array.isArray(input.secretBindings) ? input.secretBindings : [],
269
+ memoryRefs: Array.isArray(input.memoryRefs) ? input.memoryRefs : undefined,
270
+ enforce: {
271
+ deniedActions,
272
+ ...(allowedActions?.length ? { allowedActions } : {}),
273
+ ...(requiresHumanApproval ? { requiresHumanApproval: true } : {})
274
+ },
275
+ contextPack: {
276
+ identityCount: 1,
277
+ delegationCount: delegations.length,
278
+ activeDelegations,
279
+ capabilitiesSummary: capabilities.slice(0, 32),
280
+ skillsSummary: skillIds.slice(0, 32)
281
+ }
282
+ };
283
+ }
284
+
285
+ /**
286
+ * @param {Record<string, unknown>} profileAgent
287
+ */
288
+ export function profileAgentToIdentitySeed(profileAgent) {
289
+ return {
290
+ agentId: profileAgent.agentId,
291
+ agentWallet: profileAgent.agentWallet,
292
+ agentLabel: profileAgent.agentLabel || profileAgent.name,
293
+ agentType: profileAgent.agentType || profileAgent.typeLabel,
294
+ description: profileAgent.description,
295
+ instructions: profileAgent.instructions,
296
+ capabilities: capabilitiesToArray(profileAgent.capabilities),
297
+ skills: Array.isArray(profileAgent.skills) ? profileAgent.skills : [],
298
+ services: Array.isArray(profileAgent.services) ? profileAgent.services : [],
299
+ identityQHash: profileAgent.identityQHash || profileAgent.qHash
300
+ };
301
+ }
302
+
303
+ /**
304
+ * @param {import('./runtime-mount.js').RuntimeBundle | Record<string, unknown>} value
305
+ */
306
+ export function isRuntimeBundle(value) {
307
+ return Boolean(value && typeof value === 'object' && value.schema === RUNTIME_MOUNT_SCHEMA);
308
+ }
309
+
310
+ /**
311
+ * Resolve mount via MCP (server tool first, then client assembly).
312
+ *
313
+ * @param {{
314
+ * callMcpTool: (args: { name: string, args?: Record<string, unknown>, accessKey?: string, sessionId?: string, signal?: AbortSignal }) => Promise<{ ok: boolean, payload?: unknown, error?: string }>,
315
+ * initializeMcp?: () => Promise<{ sessionId: string }>,
316
+ * accessKey: string,
317
+ * agentId?: string,
318
+ * agentWallet?: string,
319
+ * identityQHash?: string,
320
+ * signal?: AbortSignal
321
+ * }} input
322
+ */
323
+ export async function resolveRuntimeBundleFromMcp(input) {
324
+ const accessKey = asString(input.accessKey);
325
+ if (!accessKey) {
326
+ throw new Error('NEUS access key or authenticated MCP session is required for runtime mount.');
327
+ }
328
+
329
+ const selector = {
330
+ agentId: input.agentId,
331
+ agentWallet: input.agentWallet,
332
+ identityQHash: input.identityQHash
333
+ };
334
+ if (!selector.agentId && !selector.agentWallet && !selector.identityQHash) {
335
+ throw new Error('Provide agentId, agentWallet, or identityQHash.');
336
+ }
337
+
338
+ let sessionId = '';
339
+ if (input.initializeMcp) {
340
+ const init = await input.initializeMcp();
341
+ sessionId = init.sessionId || '';
342
+ }
343
+
344
+ const mountArgs = {
345
+ ...(selector.agentId ? { agentId: selector.agentId } : {}),
346
+ ...(selector.agentWallet ? { agentWallet: selector.agentWallet } : {}),
347
+ ...(selector.identityQHash ? { identityQHash: selector.identityQHash } : {})
348
+ };
349
+
350
+ const serverMount = await input.callMcpTool({
351
+ name: 'neus_agent_mount',
352
+ args: mountArgs,
353
+ accessKey,
354
+ sessionId,
355
+ signal: input.signal
356
+ });
357
+
358
+ if (serverMount.ok) {
359
+ const payload = serverMount.payload;
360
+ if (isRuntimeBundle(payload)) {
361
+ return /** @type {import('./runtime-mount.js').RuntimeBundle} */ (payload);
362
+ }
363
+ if (payload && typeof payload === 'object' && isRuntimeBundle(payload.data)) {
364
+ return /** @type {import('./runtime-mount.js').RuntimeBundle} */ (payload.data);
365
+ }
366
+ }
367
+
368
+ const me = await input.callMcpTool({
369
+ name: 'neus_me',
370
+ args: {},
371
+ accessKey,
372
+ sessionId,
373
+ signal: input.signal
374
+ });
375
+ if (!me.ok) {
376
+ throw new Error(me.error || 'Could not load profile context. Run `neus auth` and retry.');
377
+ }
378
+ const mePayload = /** @type {Record<string, unknown>} */ (me.payload || {});
379
+ if (mePayload.status === 'auth_required') {
380
+ throw new Error('Profile authentication required. Run `neus auth` or set NEUS_ACCESS_KEY.');
381
+ }
382
+
383
+ const principal = /** @type {Record<string, unknown>} */ (mePayload.principal || {});
384
+ const controllerWallet = normalizeWallet(principal.primaryAccount);
385
+ const profileAgents = Array.isArray(mePayload.agents) ? mePayload.agents : [];
386
+
387
+ let agentWallet = normalizeWallet(selector.agentWallet);
388
+ let agentId = asString(selector.agentId);
389
+
390
+ if (!agentWallet && agentId) {
391
+ const row = profileAgents.find(
392
+ row => asString(row.agentId).toLowerCase() === agentId.toLowerCase()
393
+ );
394
+ if (row) {
395
+ agentWallet = normalizeWallet(row.agentWallet);
396
+ }
397
+ }
398
+ if (!agentId && agentWallet) {
399
+ const row = profileAgents.find(row => normalizeWallet(row.agentWallet) === agentWallet);
400
+ if (row) agentId = asString(row.agentId);
401
+ }
402
+ if (!agentWallet && selector.identityQHash) {
403
+ const idProof = await input.callMcpTool({
404
+ name: 'neus_proofs_get',
405
+ args: { qHash: selector.identityQHash, verifierId: 'agent-identity' },
406
+ accessKey,
407
+ sessionId,
408
+ signal: input.signal
409
+ });
410
+ if (idProof.ok) {
411
+ const data = /** @type {Record<string, unknown>} */ (idProof.payload?.data || idProof.payload || {});
412
+ const proofs = Array.isArray(data.proofs) ? data.proofs : [];
413
+ const extracted = extractAgentContextFromProofs(proofs);
414
+ const identity = pickIdentity(extracted.identities, selector);
415
+ if (identity) {
416
+ agentWallet = normalizeWallet(identity.agentWallet);
417
+ agentId = asString(identity.agentId);
418
+ }
419
+ }
420
+ }
421
+
422
+ if (!agentWallet) {
423
+ throw new Error('Could not resolve agent wallet. Check agentId or link the agent on your profile.');
424
+ }
425
+
426
+ const [identityPage, delegationPage] = await Promise.all([
427
+ input.callMcpTool({
428
+ name: 'neus_proofs_get',
429
+ args: { identifier: agentWallet, verifierId: 'agent-identity', limit: 25 },
430
+ accessKey,
431
+ sessionId,
432
+ signal: input.signal
433
+ }),
434
+ controllerWallet
435
+ ? input.callMcpTool({
436
+ name: 'neus_proofs_get',
437
+ args: { identifier: controllerWallet, verifierId: 'agent-delegation', limit: 50 },
438
+ accessKey,
439
+ sessionId,
440
+ signal: input.signal
441
+ })
442
+ : Promise.resolve({ ok: false })
443
+ ]);
444
+
445
+ const identityProofs = identityPage.ok
446
+ ? /** @type {unknown[]} */ (
447
+ identityPage.payload?.data?.proofs || identityPage.payload?.proofs || []
448
+ )
449
+ : [];
450
+ const delegationProofs = delegationPage.ok
451
+ ? /** @type {unknown[]} */ (
452
+ delegationPage.payload?.data?.proofs || delegationPage.payload?.proofs || []
453
+ )
454
+ : [];
455
+
456
+ const idCtx = extractAgentContextFromProofs(identityProofs);
457
+ const delCtx = extractAgentContextFromProofs(delegationProofs);
458
+
459
+ let identity = pickIdentity(idCtx.identities, { ...selector, agentId, agentWallet });
460
+ if (!identity && profileAgents.length > 0) {
461
+ const row = profileAgents.find(
462
+ a =>
463
+ asString(a.agentId).toLowerCase() === agentId.toLowerCase() ||
464
+ normalizeWallet(a.agentWallet) === agentWallet
465
+ );
466
+ if (row) {
467
+ identity = { ...profileAgentToIdentitySeed(row), agentWallet, agentId: agentId || asString(row.agentId) };
468
+ }
469
+ }
470
+ if (!identity) {
471
+ throw new Error('Agent identity proof not found. Complete agent setup on neus.network first.');
472
+ }
473
+
474
+ const delegation = pickActiveDelegation(
475
+ delCtx.delegations,
476
+ controllerWallet,
477
+ agentWallet,
478
+ agentId || asString(identity.agentId)
479
+ );
480
+
481
+ return buildRuntimeBundle({
482
+ identity,
483
+ delegation,
484
+ identityQHash: asString(identity.qHash || selector.identityQHash),
485
+ delegationQHash: delegation ? asString(delegation.qHash) : null,
486
+ tools: [],
487
+ secretBindings: []
488
+ });
489
+ }
490
+
491
+ /**
492
+ * @param {import('./runtime-mount.js').RuntimeBundle | Record<string, unknown> | null | undefined} manifest
493
+ */
494
+ export function evaluateMountFileHealth(manifest) {
495
+ if (!manifest || manifest.schema !== RUNTIME_MOUNT_SCHEMA) {
496
+ return {
497
+ mountFileValid: false,
498
+ missingDelegation: true,
499
+ delegationExpired: false,
500
+ needsRefresh: true,
501
+ reason: 'missing_or_invalid'
502
+ };
503
+ }
504
+
505
+ const delegationQHash = asString(manifest.trust?.delegationQHash);
506
+ const missingDelegation = !delegationQHash;
507
+ const expiresAt = manifest.delegation?.expiresAt;
508
+ const delegationExpired =
509
+ Boolean(manifest.delegation?.isExpired) || isDelegationExpired(expiresAt);
510
+
511
+ return {
512
+ mountFileValid: true,
513
+ missingDelegation,
514
+ delegationExpired,
515
+ needsRefresh: missingDelegation || delegationExpired,
516
+ reason: delegationExpired
517
+ ? 'delegation_expired'
518
+ : missingDelegation
519
+ ? 'delegation_missing'
520
+ : null
521
+ };
522
+ }