@agentsmarket/cli 0.1.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.
Files changed (59) hide show
  1. package/README.md +91 -0
  2. package/dist/commands/balance.d.ts +1 -0
  3. package/dist/commands/balance.js +20 -0
  4. package/dist/commands/balance.js.map +1 -0
  5. package/dist/commands/call.d.ts +1 -0
  6. package/dist/commands/call.js +64 -0
  7. package/dist/commands/call.js.map +1 -0
  8. package/dist/commands/info.d.ts +11 -0
  9. package/dist/commands/info.js +60 -0
  10. package/dist/commands/info.js.map +1 -0
  11. package/dist/commands/init.d.ts +12 -0
  12. package/dist/commands/init.js +80 -0
  13. package/dist/commands/init.js.map +1 -0
  14. package/dist/commands/install.d.ts +15 -0
  15. package/dist/commands/install.js +75 -0
  16. package/dist/commands/install.js.map +1 -0
  17. package/dist/commands/mcp.d.ts +14 -0
  18. package/dist/commands/mcp.js +275 -0
  19. package/dist/commands/mcp.js.map +1 -0
  20. package/dist/commands/publish.d.ts +1 -0
  21. package/dist/commands/publish.js +97 -0
  22. package/dist/commands/publish.js.map +1 -0
  23. package/dist/commands/rate.d.ts +8 -0
  24. package/dist/commands/rate.js +24 -0
  25. package/dist/commands/rate.js.map +1 -0
  26. package/dist/commands/refund.d.ts +7 -0
  27. package/dist/commands/refund.js +38 -0
  28. package/dist/commands/refund.js.map +1 -0
  29. package/dist/commands/register.d.ts +6 -0
  30. package/dist/commands/register.js +55 -0
  31. package/dist/commands/register.js.map +1 -0
  32. package/dist/commands/rename.d.ts +7 -0
  33. package/dist/commands/rename.js +33 -0
  34. package/dist/commands/rename.js.map +1 -0
  35. package/dist/commands/scan.d.ts +35 -0
  36. package/dist/commands/scan.js +193 -0
  37. package/dist/commands/scan.js.map +1 -0
  38. package/dist/commands/search.d.ts +4 -0
  39. package/dist/commands/search.js +29 -0
  40. package/dist/commands/search.js.map +1 -0
  41. package/dist/index.d.ts +15 -0
  42. package/dist/index.js +115 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/lib/config.d.ts +37 -0
  45. package/dist/lib/config.js +112 -0
  46. package/dist/lib/config.js.map +1 -0
  47. package/dist/lib/http.d.ts +25 -0
  48. package/dist/lib/http.js +105 -0
  49. package/dist/lib/http.js.map +1 -0
  50. package/dist/lib/keys.d.ts +69 -0
  51. package/dist/lib/keys.js +85 -0
  52. package/dist/lib/keys.js.map +1 -0
  53. package/dist/lib/payment-keys.d.ts +25 -0
  54. package/dist/lib/payment-keys.js +55 -0
  55. package/dist/lib/payment-keys.js.map +1 -0
  56. package/dist/lib/payment.d.ts +27 -0
  57. package/dist/lib/payment.js +123 -0
  58. package/dist/lib/payment.js.map +1 -0
  59. package/package.json +36 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * `agentsmarket scan <SKILL.md>` — security scan before publishing.
3
+ *
4
+ * Checks for common attack patterns in AI agent skills:
5
+ * - Prompt injection (override system instructions, ignore safety)
6
+ * - Data exfiltration (hidden URLs, webhook posts, env var access)
7
+ * - Hidden/obfuscated content (base64 blobs, eval/Function, encoded strings)
8
+ * - Dangerous commands (rm -rf, curl|bash, fs access)
9
+ * - Credential harvesting (API_KEY, SECRET, TOKEN patterns)
10
+ *
11
+ * Returns a 0-100 safety score. Exit code 0 if score >= 70 (publish).
12
+ * Exit code 1 if score < 70 (warnings — review before publishing).
13
+ *
14
+ * Differentiation vs competitors:
15
+ * - skills.sh / Agensi: third-party audits POST-publish (passive)
16
+ * - Gen Digital Agent Trust Hub / Snyk ToxicSkills / Socket: external scanners
17
+ * for ONE marketplace (Composio/Smithery only)
18
+ * - agentsmarket scan: marketplace-integrated PRE-publish gate, real-time,
19
+ * free, open source. Runs in CLI before skill hits the server.
20
+ */
21
+ import { readFileSync } from 'node:fs';
22
+ const PATTERNS = [
23
+ // CRITICAL: prompt injection
24
+ {
25
+ severity: 'critical', category: 'prompt-injection',
26
+ regex: /ignore\s+(all\s+)?previous\s+instructions/i,
27
+ message: 'Tries to override previous instructions',
28
+ },
29
+ {
30
+ severity: 'critical', category: 'prompt-injection',
31
+ regex: /disregard\s+(all\s+)?(prior|previous|above)\s+(instructions|rules|context)/i,
32
+ message: 'Tries to disregard prior rules or context',
33
+ },
34
+ {
35
+ severity: 'critical', category: 'prompt-injection',
36
+ regex: /system\s*prompt|reveal\s+system|show\s+system\s+prompt/i,
37
+ message: 'References or attempts to extract system prompt',
38
+ },
39
+ {
40
+ severity: 'critical', category: 'prompt-injection',
41
+ regex: /you\s+are\s+now\s+[a-z_]+|act\s+as\s+(an?\s+)?unrestricted/i,
42
+ message: 'Tries to override persona or remove restrictions',
43
+ },
44
+ // HIGH: data exfiltration
45
+ {
46
+ severity: 'high', category: 'exfiltration',
47
+ regex: /\b(fetch|axios|got|request)\s*\([^)]*\$\{?[A-Z_][A-Z0-9_]*\}?/,
48
+ message: 'Sends server-side env var via HTTP request',
49
+ },
50
+ {
51
+ severity: 'high', category: 'exfiltration',
52
+ regex: /\b(webhook\.site|requestbin|pipedream|burpcollaborator)\b/i,
53
+ message: 'Uses known exfiltration testing service',
54
+ },
55
+ {
56
+ severity: 'high', category: 'exfiltration',
57
+ regex: /https?:\/\/[^\s]*\$\{?[A-Z_]/i,
58
+ message: 'Embeds env var in URL (possible data exfiltration)',
59
+ },
60
+ // HIGH: hidden/obfuscated content
61
+ {
62
+ severity: 'high', category: 'obfuscation',
63
+ regex: /\beval\s*\(/,
64
+ message: 'Uses eval() (code execution risk)',
65
+ },
66
+ {
67
+ severity: 'high', category: 'obfuscation',
68
+ regex: /\bnew\s+Function\s*\(/,
69
+ message: 'Uses new Function() (code execution risk)',
70
+ },
71
+ {
72
+ severity: 'high', category: 'obfuscation',
73
+ regex: /\batob\s*\(\s*[A-Za-z0-9+/=]{100,}\s*\)/,
74
+ message: 'Decodes large base64 blob (possible hidden payload)',
75
+ },
76
+ // HIGH: credential harvesting
77
+ {
78
+ severity: 'high', category: 'credentials',
79
+ regex: /(API[_-]?KEY|SECRET[_-]?KEY|ACCESS[_-]?TOKEN|PRIVATE[_-]?KEY)\s*[:=]/i,
80
+ message: 'Contains hardcoded credential pattern',
81
+ },
82
+ {
83
+ severity: 'high', category: 'credentials',
84
+ regex: /\b(aws|github|gcp|azure|slack|openai|anthropic)[_-]?(token|key|secret)\s*[:=]/i,
85
+ message: 'Contains provider-specific credential',
86
+ },
87
+ // MEDIUM: dangerous commands
88
+ {
89
+ severity: 'medium', category: 'dangerous-cmd',
90
+ regex: /\brm\s+-rf?\s+\//,
91
+ message: 'Recursive delete from root',
92
+ },
93
+ {
94
+ severity: 'medium', category: 'dangerous-cmd',
95
+ regex: /\bcurl\s+[^|]+\|\s*(bash|sh)\b/,
96
+ message: 'Pipes curl output to shell (RCE risk)',
97
+ },
98
+ {
99
+ severity: 'medium', category: 'dangerous-cmd',
100
+ regex: /~\/\.ssh|\/etc\/passwd|\/etc\/shadow/,
101
+ message: 'References sensitive file paths',
102
+ },
103
+ // LOW: style issues
104
+ {
105
+ severity: 'low', category: 'style',
106
+ regex: /TODO|FIXME|XXX/i,
107
+ message: 'Unfinished code markers in skill',
108
+ },
109
+ ];
110
+ const SCORE_BY_SEVERITY = {
111
+ critical: -40,
112
+ high: -15,
113
+ medium: -5,
114
+ low: -1,
115
+ };
116
+ function findLineNumber(content, matchIndex) {
117
+ return content.slice(0, matchIndex).split('\n').length;
118
+ }
119
+ export function scanContent(content, path) {
120
+ const findings = [];
121
+ for (const pattern of PATTERNS) {
122
+ let match;
123
+ const regex = new RegExp(pattern.regex.source, pattern.regex.flags + 'g');
124
+ while ((match = regex.exec(content)) !== null) {
125
+ findings.push({
126
+ severity: pattern.severity,
127
+ category: pattern.category,
128
+ message: pattern.message,
129
+ line: findLineNumber(content, match.index),
130
+ });
131
+ if (match[0].length === 0)
132
+ regex.lastIndex++;
133
+ }
134
+ }
135
+ const deductions = findings.reduce((sum, f) => sum + SCORE_BY_SEVERITY[f.severity], 0);
136
+ const score = Math.max(0, Math.min(100, 100 + deductions));
137
+ let recommendation = 'publish';
138
+ if (score < 50)
139
+ recommendation = 'block';
140
+ else if (score < 70)
141
+ recommendation = 'review';
142
+ return { path, score, findings, recommendation };
143
+ }
144
+ export async function scanCommand(filePath) {
145
+ let content;
146
+ try {
147
+ content = readFileSync(filePath, 'utf-8');
148
+ }
149
+ catch (err) {
150
+ console.error(`✗ Cannot read ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
151
+ process.exit(2);
152
+ }
153
+ const result = scanContent(content, filePath);
154
+ const color = (s, code) => `\x1b[${code}m${s}\x1b[0m`;
155
+ const red = (s) => color(s, 31);
156
+ const yellow = (s) => color(s, 33);
157
+ const green = (s) => color(s, 32);
158
+ const gray = (s) => color(s, 90);
159
+ console.log(`\nScanning ${result.path}…\n`);
160
+ const bySev = { critical: [], high: [], medium: [], low: [] };
161
+ for (const f of result.findings)
162
+ bySev[f.severity].push(f);
163
+ if (result.findings.length === 0) {
164
+ console.log(green(' ✓ No issues found. Safe to publish.'));
165
+ }
166
+ else {
167
+ for (const [sev, list] of Object.entries(bySev)) {
168
+ if (list.length === 0)
169
+ continue;
170
+ const label = sev === 'critical' ? red(sev.toUpperCase()) :
171
+ sev === 'high' ? color(sev, 91) :
172
+ sev === 'medium' ? yellow(sev) :
173
+ gray(sev);
174
+ console.log(` ${label} (${list.length})`);
175
+ for (const f of list) {
176
+ const where = f.line ? gray(`L${f.line}`) : '';
177
+ console.log(` [${f.category}] ${f.message} ${where}`);
178
+ }
179
+ }
180
+ }
181
+ const scoreLabel = result.score >= 90 ? green(`${result.score}/100`) :
182
+ result.score >= 70 ? yellow(`${result.score}/100`) :
183
+ red(`${result.score}/100`);
184
+ console.log(`\nSafety score: ${scoreLabel}`);
185
+ const recLabel = result.recommendation === 'publish' ? green('✓ PUBLISH') :
186
+ result.recommendation === 'review' ? yellow('⚠ REVIEW before publishing') :
187
+ red('✗ BLOCK — do not publish');
188
+ console.log(`Recommendation: ${recLabel}\n`);
189
+ if (result.recommendation !== 'publish') {
190
+ process.exit(1);
191
+ }
192
+ }
193
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function searchCommand(query: string, opts?: {
2
+ freeOnly?: boolean;
3
+ limit?: number;
4
+ }): Promise<void>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * `agentsmarket search <query>` — browse the marketplace.
3
+ */
4
+ import { authedFetch } from '../lib/http.js';
5
+ export async function searchCommand(query, opts = {}) {
6
+ const params = new URLSearchParams();
7
+ params.set('q', query);
8
+ if (opts.freeOnly)
9
+ params.set('free', 'true');
10
+ if (opts.limit)
11
+ params.set('limit', String(opts.limit));
12
+ const path = `/v1/skills?${params.toString()}`;
13
+ const res = await authedFetch('GET', path, undefined, { requireAuth: false });
14
+ const data = await res.json();
15
+ if (data.skills.length === 0) {
16
+ console.log(`No skills found matching "${query}".`);
17
+ return;
18
+ }
19
+ console.log(`Found ${data.count} skill(s) matching "${query}":\n`);
20
+ for (const s of data.skills) {
21
+ const price = s.is_free ? 'FREE' : `$${(s.price_usdt / 1_000_000).toFixed(3)} USDT`;
22
+ const tags = s.tags.length ? `[${s.tags.join(', ')}]` : '';
23
+ console.log(` ${s.id}`);
24
+ console.log(` ${s.name} — ${price} (${s.invocation_count} invocations) ${tags}`);
25
+ console.log(` ${s.description.slice(0, 120)}${s.description.length > 120 ? '...' : ''}`);
26
+ console.log(` by ${s.author_agent_id}\n`);
27
+ }
28
+ }
29
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAc,MAAM,gBAAgB,CAAC;AAazD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa,EAAE,OAA+C,EAAE;IAClG,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvB,IAAI,IAAI,CAAC,QAAQ;QAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAExD,MAAM,IAAI,GAAG,cAAc,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC/C,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAwC,CAAC;IAEpE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,IAAI,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,KAAK,uBAAuB,KAAK,MAAM,CAAC,CAAC;IACnE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QACpF,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC,gBAAgB,iBAAiB,IAAI,EAAE,CAAC,CAAC;QACpF,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5F,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * agentsmarket CLI entry point.
4
+ *
5
+ * Commands:
6
+ * init Generate Ed25519 agent keypair (one-time setup)
7
+ * info Show current agent identity and status
8
+ * search Browse the marketplace for skills
9
+ * call Invoke a skill (handles signing + payment)
10
+ * publish Publish your own skill (from SKILL.md)
11
+ * balance Show current wallet balance in USDT
12
+ *
13
+ * More info: https://agentsmarket.world
14
+ */
15
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * agentsmarket CLI entry point.
4
+ *
5
+ * Commands:
6
+ * init Generate Ed25519 agent keypair (one-time setup)
7
+ * info Show current agent identity and status
8
+ * search Browse the marketplace for skills
9
+ * call Invoke a skill (handles signing + payment)
10
+ * publish Publish your own skill (from SKILL.md)
11
+ * balance Show current wallet balance in USDT
12
+ *
13
+ * More info: https://agentsmarket.world
14
+ */
15
+ import { Command } from 'commander';
16
+ import { initCommand } from './commands/init.js';
17
+ import { infoCommand } from './commands/info.js';
18
+ import { registerCommand } from './commands/register.js';
19
+ import { searchCommand } from './commands/search.js';
20
+ import { callCommand } from './commands/call.js';
21
+ import { publishCommand } from './commands/publish.js';
22
+ import { rateCommand } from './commands/rate.js';
23
+ import { mcpCommand } from './commands/mcp.js';
24
+ import { balanceCommand } from './commands/balance.js';
25
+ import { scanCommand } from './commands/scan.js';
26
+ import { refundCommand } from './commands/refund.js';
27
+ import { installCommand } from './commands/install.js';
28
+ import { renameCommand } from './commands/rename.js';
29
+ const program = new Command();
30
+ program
31
+ .name('agentsmarket')
32
+ .description('CLI for agentsmarket.world — manage your AI agent identity, wallet, and skill invocations.\n' +
33
+ 'Generate an Ed25519 keypair, sign messages, browse and invoke skills from the marketplace.')
34
+ .version('0.1.0');
35
+ program
36
+ .command('init')
37
+ .description('Generate a new Ed25519 agent keypair, save it locally, and register on server')
38
+ .action(initCommand);
39
+ program
40
+ .command('register')
41
+ .description('Re-register the current agent on the marketplace server')
42
+ .action(registerCommand);
43
+ program
44
+ .command('info')
45
+ .description('Show current agent identity, network, and config locations')
46
+ .action(infoCommand);
47
+ program
48
+ .command('search <query>')
49
+ .description('Browse the marketplace for skills matching a query')
50
+ .option('--free', 'only show free skills')
51
+ .option('--limit <n>', 'max number of results', '20')
52
+ .action(async (query, opts) => {
53
+ await searchCommand(query, {
54
+ freeOnly: !!opts.free,
55
+ limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
56
+ });
57
+ });
58
+ program
59
+ .command('call <skill_id>')
60
+ .description('Invoke a skill by ID (handles signing + payment automatically)')
61
+ .action(async (skillId) => {
62
+ await callCommand(skillId, {});
63
+ });
64
+ program
65
+ .command('publish <path>')
66
+ .description('Publish a SKILL.md to the marketplace (parses YAML frontmatter)')
67
+ .action(async (filePath) => {
68
+ await publishCommand(filePath);
69
+ });
70
+ program
71
+ .command('rate <skill_id> <rating>')
72
+ .description('Rate a purchased skill (1-5). Requires prior purchase within 30 days.')
73
+ .option('-c, --comment <text>', 'optional comment (max 1000 chars)')
74
+ .action(async (skillId, rating, opts) => {
75
+ await rateCommand(skillId, rating, { comment: opts.comment });
76
+ });
77
+ program
78
+ .command('mcp')
79
+ .description('Run agentsmarket as an MCP server (stdio). Use to expose marketplace tools to Claude Code, OpenCode, Cursor, Codex CLI, etc.')
80
+ .action(async () => {
81
+ await mcpCommand();
82
+ });
83
+ program
84
+ .command('scan <path>')
85
+ .description('Scan a SKILL.md file for security issues before publishing (prompt injection, exfiltration, obfuscation, dangerous commands). Exit 0 if safe to publish.')
86
+ .action(async (filePath) => {
87
+ await scanCommand(filePath);
88
+ });
89
+ program
90
+ .command('refund <purchase_id>')
91
+ .description('Refund a recent purchase if output was too short (<100 chars) and within 24h window. Phase 1 buyer protection.')
92
+ .action(async (purchaseId) => {
93
+ await refundCommand(purchaseId);
94
+ });
95
+ program
96
+ .command('install <skill_id>')
97
+ .description('Download a skill\'s SKILL.md and write it to your agent\'s skill directory (auto-detected). MCP-first: LLMs/agents should call install_skill MCP tool instead, since they know where they live.')
98
+ .action(async (skillId) => {
99
+ await installCommand(skillId);
100
+ });
101
+ program
102
+ .command('rename <display_name>')
103
+ .description('Set human-readable name for current agent (max 80 chars). Shown in skill listings + author profile.')
104
+ .action(async (newName) => {
105
+ await renameCommand(newName);
106
+ });
107
+ program
108
+ .command('balance')
109
+ .description('Show current wallet balance in USDT')
110
+ .action(balanceCommand);
111
+ program.parseAsync(process.argv).catch((err) => {
112
+ console.error('✗ ' + (err instanceof Error ? err.message : String(err)));
113
+ process.exit(1);
114
+ });
115
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Config file management for agentsmarket CLI.
3
+ *
4
+ * Stores agent identity + network preference in ~/.config/agentsmarket/
5
+ *
6
+ * MVP: file-based storage with 0700 dir / 0600 file permissions.
7
+ * Production: migrate to OS keychain (macOS Keychain / Linux libsecret /
8
+ * Windows Credential Manager) via @napi-rs/keyring.
9
+ */
10
+ export type Network = 'base-sepolia' | 'base-mainnet';
11
+ export interface Config {
12
+ /** Ed25519 public key, base64url-encoded, with "ed25519:" prefix. */
13
+ agent_id: string;
14
+ /** secp256k1 payment address (0x-prefixed). Used for EIP-3009 USDC payments. */
15
+ payment_address: string;
16
+ /** Blockchain network. MVP: only base-sepolia supported. */
17
+ network: Network;
18
+ /** ISO 8601 timestamp of agent creation. */
19
+ created_at: string;
20
+ }
21
+ /** Returns ~/.config/agentsmarket (platform-correct home dir). */
22
+ export declare function getConfigDir(): string;
23
+ export declare function getKeyPath(): string;
24
+ export declare function getPaymentKeyPath(): string;
25
+ export declare function getConfigPath(): string;
26
+ /** Returns existing config or null. */
27
+ export declare function loadConfig(): Config | null;
28
+ /** Save config file with 0600 permissions. Creates parent dir if needed. */
29
+ export declare function saveConfig(config: Config): void;
30
+ /** Save private key with 0600 permissions. */
31
+ export declare function savePrivateKey(pem: string): void;
32
+ /** Save secp256k1 payment key with 0600 permissions. */
33
+ export declare function savePaymentKey(pem: string): void;
34
+ export declare function loadPaymentKeyPem(): string;
35
+ export declare function configExists(): boolean;
36
+ export declare function keyExists(): boolean;
37
+ export declare function paymentKeyExists(): boolean;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Config file management for agentsmarket CLI.
3
+ *
4
+ * Stores agent identity + network preference in ~/.config/agentsmarket/
5
+ *
6
+ * MVP: file-based storage with 0700 dir / 0600 file permissions.
7
+ * Production: migrate to OS keychain (macOS Keychain / Linux libsecret /
8
+ * Windows Credential Manager) via @napi-rs/keyring.
9
+ */
10
+ import * as fs from 'node:fs';
11
+ import * as path from 'node:path';
12
+ import * as os from 'node:os';
13
+ const CONFIG_DIR_NAME = 'agentsmarket';
14
+ const KEY_FILE_NAME = 'agent.key';
15
+ const PAYMENT_KEY_FILE_NAME = 'payment.key';
16
+ const CONFIG_FILE_NAME = 'config.json';
17
+ /** Returns ~/.config/agentsmarket (platform-correct home dir). */
18
+ export function getConfigDir() {
19
+ const home = os.homedir();
20
+ if (process.platform === 'win32') {
21
+ return path.join(home, 'AppData', 'Roaming', CONFIG_DIR_NAME);
22
+ }
23
+ if (process.platform === 'darwin') {
24
+ return path.join(home, 'Library', 'Application Support', CONFIG_DIR_NAME);
25
+ }
26
+ // Linux / Unix — XDG default
27
+ const xdgConfig = process.env.XDG_CONFIG_HOME ?? path.join(home, '.config');
28
+ return path.join(xdgConfig, CONFIG_DIR_NAME);
29
+ }
30
+ export function getKeyPath() {
31
+ return path.join(getConfigDir(), KEY_FILE_NAME);
32
+ }
33
+ export function getPaymentKeyPath() {
34
+ return path.join(getConfigDir(), PAYMENT_KEY_FILE_NAME);
35
+ }
36
+ export function getConfigPath() {
37
+ return path.join(getConfigDir(), CONFIG_FILE_NAME);
38
+ }
39
+ /** Returns existing config or null. */
40
+ export function loadConfig() {
41
+ try {
42
+ const content = fs.readFileSync(getConfigPath(), 'utf-8');
43
+ const parsed = JSON.parse(content);
44
+ if (typeof parsed.agent_id !== 'string' || !parsed.agent_id.startsWith('ed25519:')) {
45
+ return null;
46
+ }
47
+ if (typeof parsed.payment_address !== 'string' || !/^0x[0-9a-fA-F]{40}$/.test(parsed.payment_address)) {
48
+ return null;
49
+ }
50
+ if (parsed.network !== 'base-sepolia' && parsed.network !== 'base-mainnet') {
51
+ return null;
52
+ }
53
+ if (typeof parsed.created_at !== 'string') {
54
+ return null;
55
+ }
56
+ return parsed;
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ /** Save config file with 0600 permissions. Creates parent dir if needed. */
63
+ export function saveConfig(config) {
64
+ const dir = getConfigDir();
65
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
66
+ setPermissions(dir, 0o700);
67
+ const configPath = getConfigPath();
68
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
69
+ setPermissions(configPath, 0o600);
70
+ }
71
+ /** Save private key with 0600 permissions. */
72
+ export function savePrivateKey(pem) {
73
+ const dir = getConfigDir();
74
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
75
+ setPermissions(dir, 0o700);
76
+ const keyPath = getKeyPath();
77
+ fs.writeFileSync(keyPath, pem, { mode: 0o600 });
78
+ setPermissions(keyPath, 0o600);
79
+ }
80
+ /** Save secp256k1 payment key with 0600 permissions. */
81
+ export function savePaymentKey(pem) {
82
+ const dir = getConfigDir();
83
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
84
+ setPermissions(dir, 0o700);
85
+ const keyPath = getPaymentKeyPath();
86
+ fs.writeFileSync(keyPath, pem, { mode: 0o600 });
87
+ setPermissions(keyPath, 0o600);
88
+ }
89
+ export function loadPaymentKeyPem() {
90
+ return fs.readFileSync(getPaymentKeyPath(), 'utf-8');
91
+ }
92
+ export function configExists() {
93
+ return fs.existsSync(getConfigPath());
94
+ }
95
+ export function keyExists() {
96
+ return fs.existsSync(getKeyPath());
97
+ }
98
+ export function paymentKeyExists() {
99
+ return fs.existsSync(getPaymentKeyPath());
100
+ }
101
+ /** Set file permissions — best-effort on Windows (chmod doesn't fully apply). */
102
+ function setPermissions(path, mode) {
103
+ if (process.platform === 'win32')
104
+ return;
105
+ try {
106
+ fs.chmodSync(path, mode);
107
+ }
108
+ catch {
109
+ // Ignore — best effort
110
+ }
111
+ }
112
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Authenticated HTTP client for the marketplace server.
3
+ *
4
+ * Signs every request with the agent's Ed25519 key per server protocol:
5
+ * Headers:
6
+ * X-Agent-ID: ed25519:...
7
+ * X-Signature: base64(64-byte Ed25519 sig)
8
+ * X-Timestamp: unix ms (within 5 min drift)
9
+ * Message: METHOD\nPATH\nTIMESTAMP\nSHA256(BODY)
10
+ */
11
+ export declare class HttpError extends Error {
12
+ readonly status: number;
13
+ readonly code: string;
14
+ constructor(status: number, code: string, message: string);
15
+ }
16
+ /** Make an authenticated request to the marketplace server. */
17
+ export declare function authedFetch(method: string, path: string, body?: unknown, opts?: {
18
+ baseUrl?: string;
19
+ requireAuth?: boolean;
20
+ }): Promise<Response>;
21
+ /** Convenience: authed JSON request, returns parsed body. */
22
+ export declare function authedJson<T>(method: string, path: string, body?: unknown, opts?: {
23
+ baseUrl?: string;
24
+ requireAuth?: boolean;
25
+ }): Promise<T>;