@neus/sdk 1.1.7 → 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/mcp-hosts.js CHANGED
@@ -3,11 +3,40 @@
3
3
  * Browser-safe: no Node-only APIs except the Buffer fallback for non-browser tests.
4
4
  */
5
5
 
6
+ import {
7
+ NEUS_AUTH_CLI,
8
+ NEUS_INSTALL_CLI,
9
+ NEUS_NPX,
10
+ NEUS_SETUP_NPX,
11
+ neusCmd,
12
+ } from './cli-commands.js';
13
+
14
+ export {
15
+ NEUS_PKG,
16
+ NEUS_INSTALL_CLI,
17
+ NEUS_NPX,
18
+ NEUS_SETUP_CLI,
19
+ NEUS_SETUP_NPX,
20
+ NEUS_AUTH_CLI,
21
+ NEUS_CHECK_CLI,
22
+ NEUS_DOCTOR_CLI,
23
+ NEUS_EXAMPLES_CLI,
24
+ NEUS_CHECK_NPX,
25
+ NEUS_AUTH_NPX,
26
+ NEUS_DOCTOR_NPX,
27
+ NEUS_EXAMPLES_NPX,
28
+ NEUS_QUICKSTART_INSTALLED,
29
+ NEUS_QUICKSTART_NPX,
30
+ NEUS_MOUNT_WORKFLOW,
31
+ neusMountApply,
32
+ neusMountApplyNpx,
33
+ neusCmd,
34
+ neusNpx,
35
+ } from './cli-commands.js';
36
+
6
37
  export const NEUS_MCP_SERVER_NAME = 'neus';
7
38
  export const NEUS_MCP_URL = 'https://mcp.neus.network/mcp';
8
- export const NEUS_SETUP_CLI = 'npx -y -p @neus/sdk neus setup';
9
- export const NEUS_AUTH_CLI = 'npx -y -p @neus/sdk neus auth';
10
- export const NEUS_MCP_SETUP_DOCS_URL = 'https://docs.neus.network/mcp/ide-plugin';
39
+ export const NEUS_MCP_SETUP_DOCS_URL = 'https://docs.neus.network/mcp/setup';
11
40
 
12
41
  /** CLI `neus setup --client` values. */
13
42
  export const MCP_INSTALL_CLIENTS = ['claude', 'codex', 'cursor', 'vscode'];
@@ -18,13 +47,13 @@ export const MCP_INSTALL_HOSTS = ['cursor', 'claude', 'codex'];
18
47
  export const IDE_HOST_LABELS = {
19
48
  cursor: 'Cursor',
20
49
  claude: 'Claude Code',
21
- codex: 'Codex'
50
+ codex: 'Codex',
22
51
  };
23
52
 
24
53
  export const IDE_HOST_BRAND_LOGOS = {
25
54
  cursor: '/images/brandLogos/cursor.svg',
26
55
  claude: '/images/brandLogos/anthropic.svg',
27
- codex: '/images/brandLogos/openai.svg'
56
+ codex: '/images/brandLogos/openai.svg',
28
57
  };
29
58
 
30
59
  /**
@@ -36,7 +65,7 @@ export function buildNeusMcpHttpConfig(accessKey) {
36
65
  return {
37
66
  type: 'http',
38
67
  url: NEUS_MCP_URL,
39
- ...(key ? { headers: { Authorization: `Bearer ${key}` } } : {})
68
+ ...(key ? { headers: { Authorization: `Bearer ${key}` } } : {}),
40
69
  };
41
70
  }
42
71
 
@@ -69,7 +98,7 @@ export function buildCursorMcpInstallUrl(accessKey) {
69
98
  export function buildVsCodeMcpInstallUrl(accessKey) {
70
99
  const payload = {
71
100
  name: NEUS_MCP_SERVER_NAME,
72
- ...buildNeusMcpHttpConfig(accessKey)
101
+ ...buildNeusMcpHttpConfig(accessKey),
73
102
  };
74
103
  return `vscode:mcp/install?${encodeURIComponent(JSON.stringify(payload))}`;
75
104
  }
@@ -80,12 +109,13 @@ export function buildVsCodeMcpInstallUrl(accessKey) {
80
109
  */
81
110
  export function buildAuthCommandForClient(client) {
82
111
  if (client === 'codex') {
83
- return `${NEUS_AUTH_CLI} --client codex`;
112
+ return neusCmd(`auth --client codex`);
84
113
  }
85
114
  return NEUS_AUTH_CLI;
86
115
  }
87
116
 
88
117
  /**
118
+ * Copy-paste block for Profile / IDE onboarding (install + setup + auth).
89
119
  * @param {'claude' | 'codex' | 'cursor' | 'vscode'} client
90
120
  * @param {string | null | undefined} accessKey
91
121
  * @returns {string}
@@ -93,10 +123,13 @@ export function buildAuthCommandForClient(client) {
93
123
  export function buildSetupCommandForClient(client, accessKey) {
94
124
  const key = String(accessKey || '').trim();
95
125
  const setup = key
96
- ? `${NEUS_SETUP_CLI} --client ${client} --access-key ${key}`
97
- : `${NEUS_SETUP_CLI} --client ${client}`;
98
- if (key) return setup;
99
- return `${setup}\n${buildAuthCommandForClient(client)}`;
126
+ ? neusCmd(`setup --client ${client} --access-key ${key}`)
127
+ : neusCmd(`setup --client ${client}`);
128
+ if (key) {
129
+ return `${NEUS_INSTALL_CLI}\n${setup}`;
130
+ }
131
+ const auth = buildAuthCommandForClient(client);
132
+ return `${NEUS_INSTALL_CLI}\n${setup}\n${auth}`;
100
133
  }
101
134
 
102
135
  /**
@@ -108,6 +141,15 @@ export function buildSetupCommandForHost(host, accessKey) {
108
141
  return buildSetupCommandForClient(host, accessKey);
109
142
  }
110
143
 
144
+ /**
145
+ * Zero-install one-liner for landing pages and copy buttons.
146
+ * @param {'claude' | 'codex' | 'cursor' | 'vscode'} [client]
147
+ */
148
+ export function buildSetupNpxOneLiner(client) {
149
+ if (!client) return NEUS_SETUP_NPX;
150
+ return `${NEUS_NPX} setup --client ${client}`;
151
+ }
152
+
111
153
  /**
112
154
  * Cursor supports MCP install deeplinks; Codex uses CLI, not VS Code deeplinks.
113
155
  * @param {'cursor' | 'claude' | 'codex'} host
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neus/sdk",
3
- "version": "1.1.7",
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"
@@ -31,10 +31,22 @@
31
31
  "import": "./gates.js",
32
32
  "require": "./cjs/gates.cjs"
33
33
  },
34
+ "./cli-commands": {
35
+ "import": "./cli-commands.js",
36
+ "require": "./cjs/cli-commands.cjs"
37
+ },
34
38
  "./mcp-hosts": {
35
39
  "import": "./mcp-hosts.js",
36
40
  "require": "./cjs/mcp-hosts.cjs"
37
41
  },
42
+ "./runtime-mount": {
43
+ "import": "./runtime-mount.js",
44
+ "require": "./cjs/runtime-mount.cjs"
45
+ },
46
+ "./runtime-adapters": {
47
+ "import": "./runtime-adapters.js",
48
+ "require": "./cjs/runtime-adapters.cjs"
49
+ },
38
50
  "./widgets": {
39
51
  "types": "./types.d.ts",
40
52
  "import": "./widgets/index.js",
@@ -54,7 +66,7 @@
54
66
  "format": "prettier --write \"**/*.js\"",
55
67
  "build": "npm run build:widgets && npm run build:cjs",
56
68
  "build:widgets": "npx esbuild widgets/verify-gate/VerifyGate.jsx widgets/verify-gate/ProofBadge.jsx --bundle --platform=browser --format=esm --outdir=widgets/verify-gate/dist --jsx=automatic --legal-comments=none --external:react --external:react-dom --external:react/jsx-runtime --external:@neus/sdk/client",
57
- "build:cjs": "npx esbuild index.js client.js utils.js errors.js gates.js mcp-hosts.js --bundle --platform=node --format=cjs --outdir=cjs --out-extension:.js=.cjs --legal-comments=none --external:ethers --external:@zkpassport/sdk --external:react --external:react-dom --external:react/jsx-runtime",
69
+ "build:cjs": "npx esbuild index.js client.js utils.js errors.js gates.js cli-commands.js mcp-hosts.js runtime-mount.js runtime-adapters.js --bundle --platform=node --format=cjs --outdir=cjs --out-extension:.js=.cjs --legal-comments=none --external:ethers --external:@zkpassport/sdk --external:react --external:react-dom --external:react/jsx-runtime",
58
70
  "prepack": "npm run build",
59
71
  "prepublishOnly": "npm run lint && npm test && npm run build"
60
72
  },
@@ -129,6 +141,7 @@
129
141
  },
130
142
  "files": [
131
143
  "cli/neus.mjs",
144
+ "cli-commands.js",
132
145
  "mcp-hosts.js",
133
146
  "index.js",
134
147
  "client.js",
@@ -136,6 +149,8 @@
136
149
  "errors.js",
137
150
  "gates.js",
138
151
  "sponsor.js",
152
+ "runtime-mount.js",
153
+ "runtime-adapters.js",
139
154
  "cjs/**",
140
155
  "widgets.cjs",
141
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
+ }