anpm-io 1.0.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 (139) hide show
  1. package/README.md +174 -0
  2. package/dist/commands/access.d.ts +2 -0
  3. package/dist/commands/access.js +90 -0
  4. package/dist/commands/adopt.d.ts +2 -0
  5. package/dist/commands/adopt.js +177 -0
  6. package/dist/commands/changelog.d.ts +2 -0
  7. package/dist/commands/changelog.js +67 -0
  8. package/dist/commands/check-update.d.ts +2 -0
  9. package/dist/commands/check-update.js +76 -0
  10. package/dist/commands/config.d.ts +2 -0
  11. package/dist/commands/config.js +84 -0
  12. package/dist/commands/create.d.ts +2 -0
  13. package/dist/commands/create.js +227 -0
  14. package/dist/commands/deploy-record.d.ts +2 -0
  15. package/dist/commands/deploy-record.js +93 -0
  16. package/dist/commands/deploy.d.ts +2 -0
  17. package/dist/commands/deploy.js +284 -0
  18. package/dist/commands/diff.d.ts +2 -0
  19. package/dist/commands/diff.js +92 -0
  20. package/dist/commands/feedback.d.ts +2 -0
  21. package/dist/commands/feedback.js +71 -0
  22. package/dist/commands/grant.d.ts +33 -0
  23. package/dist/commands/grant.js +190 -0
  24. package/dist/commands/hub.d.ts +2 -0
  25. package/dist/commands/hub.js +171 -0
  26. package/dist/commands/init.d.ts +13 -0
  27. package/dist/commands/init.js +172 -0
  28. package/dist/commands/install.d.ts +2 -0
  29. package/dist/commands/install.js +626 -0
  30. package/dist/commands/join.d.ts +6 -0
  31. package/dist/commands/join.js +90 -0
  32. package/dist/commands/link.d.ts +2 -0
  33. package/dist/commands/link.js +112 -0
  34. package/dist/commands/list.d.ts +2 -0
  35. package/dist/commands/list.js +144 -0
  36. package/dist/commands/login.d.ts +7 -0
  37. package/dist/commands/login.js +235 -0
  38. package/dist/commands/orgs.d.ts +10 -0
  39. package/dist/commands/orgs.js +128 -0
  40. package/dist/commands/outdated.d.ts +2 -0
  41. package/dist/commands/outdated.js +70 -0
  42. package/dist/commands/package.d.ts +57 -0
  43. package/dist/commands/package.js +569 -0
  44. package/dist/commands/ping.d.ts +2 -0
  45. package/dist/commands/ping.js +40 -0
  46. package/dist/commands/publish.d.ts +98 -0
  47. package/dist/commands/publish.js +899 -0
  48. package/dist/commands/run.d.ts +2 -0
  49. package/dist/commands/run.js +249 -0
  50. package/dist/commands/search.d.ts +2 -0
  51. package/dist/commands/search.js +57 -0
  52. package/dist/commands/status.d.ts +2 -0
  53. package/dist/commands/status.js +159 -0
  54. package/dist/commands/uninstall.d.ts +2 -0
  55. package/dist/commands/uninstall.js +132 -0
  56. package/dist/commands/update.d.ts +2 -0
  57. package/dist/commands/update.js +171 -0
  58. package/dist/commands/versions.d.ts +2 -0
  59. package/dist/commands/versions.js +44 -0
  60. package/dist/index.d.ts +2 -0
  61. package/dist/index.js +91 -0
  62. package/dist/lib/agent-status.d.ts +23 -0
  63. package/dist/lib/agent-status.js +127 -0
  64. package/dist/lib/ai-tools.d.ts +34 -0
  65. package/dist/lib/ai-tools.js +104 -0
  66. package/dist/lib/anpm-config.d.ts +39 -0
  67. package/dist/lib/anpm-config.js +112 -0
  68. package/dist/lib/api.d.ts +24 -0
  69. package/dist/lib/api.js +151 -0
  70. package/dist/lib/auto-detect.d.ts +30 -0
  71. package/dist/lib/auto-detect.js +112 -0
  72. package/dist/lib/cloud-providers/anthropic.d.ts +19 -0
  73. package/dist/lib/cloud-providers/anthropic.js +200 -0
  74. package/dist/lib/cloud-providers/package-mapper.d.ts +9 -0
  75. package/dist/lib/cloud-providers/package-mapper.js +34 -0
  76. package/dist/lib/cloud-providers/provider.d.ts +60 -0
  77. package/dist/lib/cloud-providers/provider.js +7 -0
  78. package/dist/lib/command-adapter.d.ts +41 -0
  79. package/dist/lib/command-adapter.js +188 -0
  80. package/dist/lib/config.d.ts +50 -0
  81. package/dist/lib/config.js +274 -0
  82. package/dist/lib/contact-format.d.ts +7 -0
  83. package/dist/lib/contact-format.js +23 -0
  84. package/dist/lib/device-hash.d.ts +1 -0
  85. package/dist/lib/device-hash.js +16 -0
  86. package/dist/lib/error-report.d.ts +5 -0
  87. package/dist/lib/error-report.js +28 -0
  88. package/dist/lib/git-installer.d.ts +16 -0
  89. package/dist/lib/git-installer.js +97 -0
  90. package/dist/lib/git-operations.d.ts +38 -0
  91. package/dist/lib/git-operations.js +183 -0
  92. package/dist/lib/hub-notify.d.ts +9 -0
  93. package/dist/lib/hub-notify.js +66 -0
  94. package/dist/lib/install-source.d.ts +33 -0
  95. package/dist/lib/install-source.js +98 -0
  96. package/dist/lib/installer.d.ts +40 -0
  97. package/dist/lib/installer.js +358 -0
  98. package/dist/lib/local-installer.d.ts +15 -0
  99. package/dist/lib/local-installer.js +73 -0
  100. package/dist/lib/lockfile.d.ts +13 -0
  101. package/dist/lib/lockfile.js +42 -0
  102. package/dist/lib/manifest.d.ts +65 -0
  103. package/dist/lib/manifest.js +113 -0
  104. package/dist/lib/migration.d.ts +10 -0
  105. package/dist/lib/migration.js +91 -0
  106. package/dist/lib/paths.d.ts +10 -0
  107. package/dist/lib/paths.js +22 -0
  108. package/dist/lib/preamble.d.ts +22 -0
  109. package/dist/lib/preamble.js +133 -0
  110. package/dist/lib/relay-config.d.ts +13 -0
  111. package/dist/lib/relay-config.js +46 -0
  112. package/dist/lib/requires-suggest.d.ts +23 -0
  113. package/dist/lib/requires-suggest.js +295 -0
  114. package/dist/lib/setup-command.d.ts +6 -0
  115. package/dist/lib/setup-command.js +72 -0
  116. package/dist/lib/slug.d.ts +24 -0
  117. package/dist/lib/slug.js +100 -0
  118. package/dist/lib/step-tracker.d.ts +8 -0
  119. package/dist/lib/step-tracker.js +28 -0
  120. package/dist/lib/storage.d.ts +6 -0
  121. package/dist/lib/storage.js +23 -0
  122. package/dist/lib/update-cache.d.ts +2 -0
  123. package/dist/lib/update-cache.js +51 -0
  124. package/dist/lib/version-check.d.ts +10 -0
  125. package/dist/lib/version-check.js +75 -0
  126. package/dist/mcp/server.d.ts +3 -0
  127. package/dist/mcp/server.js +112 -0
  128. package/dist/postinstall.d.ts +8 -0
  129. package/dist/postinstall.js +41 -0
  130. package/dist/prompts/_error-handling.md +38 -0
  131. package/dist/prompts/create.md +170 -0
  132. package/dist/prompts/explore.md +30 -0
  133. package/dist/prompts/index.d.ts +3 -0
  134. package/dist/prompts/index.js +22 -0
  135. package/dist/relay-compat.d.ts +2 -0
  136. package/dist/relay-compat.js +7 -0
  137. package/dist/types.d.ts +118 -0
  138. package/dist/types.js +2 -0
  139. package/package.json +51 -0
package/README.md ADDED
@@ -0,0 +1,174 @@
1
+ # relay
2
+
3
+ **The package manager for AI agents.**
4
+
5
+ Write once, run on any harness. One command install. Built-in usage analytics.
6
+
7
+ ```bash
8
+ npx relayax-cli install @gstack/code-review
9
+ ```
10
+
11
+ ```
12
+ ╭──────────────────────────────────────────────╮
13
+ │ │
14
+ │ relay — AI agent distribution for humans │
15
+ │ and machines. │
16
+ │ │
17
+ │ ✓ installed @gstack/code-review (v2.1.0) │
18
+ │ 3 skills, 1 agent ready │
19
+ │ │
20
+ ╰──────────────────────────────────────────────╯
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Why
26
+
27
+ AI agents are stuck in silos. You build an agent for Claude Code — it doesn't work on OpenClaw. You share it on GitHub — no one knows it exists. You have no idea if anyone actually uses it.
28
+
29
+ **Relay fixes this.**
30
+
31
+ | Problem | Relay |
32
+ |---|---|
33
+ | Agents locked to one harness | Cross-harness compatibility (Claude, OpenClaw, nanoclaw) |
34
+ | No distribution channel | `relay install` — one command, done |
35
+ | Zero feedback from users | Built-in analytics — see which skills get used |
36
+
37
+ ---
38
+
39
+ ## Quick Start
40
+
41
+ ```bash
42
+ # Install an agent — no setup required
43
+ npx relayax-cli install @author/agent-name
44
+
45
+ # Or install globally
46
+ npm i -g relayax-cli
47
+ relay install @author/agent-name
48
+ ```
49
+
50
+ That's it. The agent is ready in your `.relay/agents/` directory, compatible with your harness.
51
+
52
+ ---
53
+
54
+ ## For Agent Builders
55
+
56
+ ```bash
57
+ # Publish your agent to the registry
58
+ relay publish
59
+
60
+ # See who's using it
61
+ relay status --analytics
62
+ ```
63
+
64
+ Relay tracks skill-level usage out of the box. No extra setup. You'll know exactly which skills land and which don't — so you can ship better agents, faster.
65
+
66
+ ### Package Format
67
+
68
+ ```yaml
69
+ # team.yaml
70
+ name: code-review
71
+ version: 2.1.0
72
+ harness:
73
+ - claude
74
+ - openclaw
75
+ - nanoclaw
76
+ agents:
77
+ - name: reviewer
78
+ type: passive
79
+ skills:
80
+ - name: review-pr
81
+ - name: security-check
82
+ - name: style-lint
83
+ ```
84
+
85
+ One spec. Every harness.
86
+
87
+ ---
88
+
89
+ ## Commands
90
+
91
+ | Command | What it does |
92
+ |---|---|
93
+ | `relay install <name>` | Install an agent |
94
+ | `relay search <keyword>` | Find agents in the registry |
95
+ | `relay publish` | Publish your agent |
96
+ | `relay list` | List installed agents |
97
+ | `relay status` | Check environment + analytics |
98
+ | `relay update` | Update agents to latest |
99
+ | `relay uninstall <name>` | Remove an agent |
100
+ | `relay diff <name>` | See what changed between versions |
101
+
102
+ All output is JSON by default (for AI agents). Add `--pretty` for human-readable format.
103
+
104
+ ---
105
+
106
+ ## How It Works
107
+
108
+ ```
109
+ relay install @team/agent
110
+
111
+ ╭──────────┴──────────╮
112
+ │ Relay Registry │
113
+ │ (relay.ax cloud) │
114
+ ╰──────────┬──────────╯
115
+
116
+ ╭──────────┴──────────╮
117
+ │ relay agent spec │
118
+ │ (universal format) │
119
+ ╰──┬───────┬───────┬──╯
120
+ │ │ │
121
+ ┌─────┴─┐ ┌──┴───┐ ┌─┴──────┐
122
+ │Claude │ │Open │ │nano │
123
+ │ Code │ │Claw │ │claw │
124
+ └───────┘ └──────┘ └────────┘
125
+ ```
126
+
127
+ Relay resolves the right format for your harness automatically. Builders write one spec, users install with one command.
128
+
129
+ ---
130
+
131
+ ## AI-Native
132
+
133
+ Relay is built for AI agents as first-class users. The CLI outputs structured JSON so agents can search, install, and manage other agents autonomously.
134
+
135
+ ```bash
136
+ # An agent searching for tools
137
+ relay search "database migration" | jq '.results[].slug'
138
+
139
+ # An agent installing what it needs
140
+ relay install @tools/db-migrate
141
+ # → {"status":"ok","agent":"db-migrate","skills":["migrate","rollback","seed"]}
142
+ ```
143
+
144
+ Relay also ships as an **MCP server**, so any MCP-compatible agent can use it directly:
145
+
146
+ ```bash
147
+ relay mcp
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Open Core
153
+
154
+ The CLI and agent spec are open source (MIT). Build agents, publish them, self-host your own registry — no vendor lock-in.
155
+
156
+ [relay.ax](https://relayax.com) provides the hosted registry with:
157
+ - Private agent hosting
158
+ - Organization management & access control
159
+ - Usage analytics dashboard
160
+ - Enterprise SSO & audit logs
161
+
162
+ ---
163
+
164
+ ## Community
165
+
166
+ - [25+ production agents](https://relayax.com) ready to install
167
+ - [Builder docs](https://relayax.com/docs) for creating your own
168
+ - [Discord](#) for help and discussion
169
+
170
+ ---
171
+
172
+ <p align="center">
173
+ <sub>Built by <a href="https://relayax.com">RelayAX</a></sub>
174
+ </p>
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerAccess(program: Command): void;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerAccess = registerAccess;
4
+ const commander_1 = require("commander");
5
+ const config_js_1 = require("../lib/config.js");
6
+ async function claimAccess(slug, code) {
7
+ const token = await (0, config_js_1.getValidToken)();
8
+ if (!token) {
9
+ throw new Error('LOGIN_REQUIRED');
10
+ }
11
+ const res = await fetch(`${config_js_1.API_URL}/api/agents/${slug}/claim-access`, {
12
+ method: 'POST',
13
+ headers: {
14
+ 'Content-Type': 'application/json',
15
+ Authorization: `Bearer ${token}`,
16
+ },
17
+ body: JSON.stringify({ code }),
18
+ signal: AbortSignal.timeout(10000),
19
+ });
20
+ const body = (await res.json().catch(() => ({})));
21
+ if (!res.ok) {
22
+ const errCode = body.error ?? String(res.status);
23
+ switch (errCode) {
24
+ case 'INVALID_LINK':
25
+ throw new Error('초대 링크가 유효하지 않거나 만료되었습니다.');
26
+ case 'NOT_FOUND':
27
+ throw new Error('에이전트를 찾을 수 없습니다.');
28
+ case 'UNAUTHORIZED':
29
+ throw new Error('LOGIN_REQUIRED');
30
+ default:
31
+ throw new Error(body.message ?? `접근 권한 요청 실패 (${res.status})`);
32
+ }
33
+ }
34
+ return body;
35
+ }
36
+ function registerAccess(program) {
37
+ program
38
+ .command('access <slug>')
39
+ .description('초대 코드로 에이전트에 접근 권한을 얻고 바로 설치합니다')
40
+ .requiredOption('--code <code>', '에이전트 초대 코드')
41
+ .action(async (slug, opts) => {
42
+ const json = program.opts().json ?? false;
43
+ try {
44
+ const result = await claimAccess(slug, opts.code);
45
+ if (!result.success || !result.agent) {
46
+ throw new Error('서버 응답이 올바르지 않습니다.');
47
+ }
48
+ const agentSlug = result.agent.slug;
49
+ if (json) {
50
+ console.log(JSON.stringify({ status: 'ok', agent: result.agent }));
51
+ }
52
+ else {
53
+ console.log(`\x1b[32m접근 권한이 부여되었습니다: ${result.agent.name}\x1b[0m`);
54
+ console.log(`\x1b[33m에이전트를 설치합니다: anpm install ${agentSlug}\x1b[0m\n`);
55
+ }
56
+ // Automatically install the agent
57
+ const { registerInstall } = await import('./install.js');
58
+ const subProgram = new commander_1.Command();
59
+ subProgram.option('--json', '구조화된 JSON 출력');
60
+ if (json)
61
+ subProgram.setOptionValue('json', true);
62
+ registerInstall(subProgram);
63
+ await subProgram.parseAsync(['node', 'relay', 'install', agentSlug]);
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : String(err);
67
+ if (message === 'LOGIN_REQUIRED') {
68
+ if (json) {
69
+ console.error(JSON.stringify({
70
+ error: 'LOGIN_REQUIRED',
71
+ message: '로그인이 필요합니다. anpm login을 먼저 실행하세요.',
72
+ fix: 'anpm login 실행 후 재시도하세요.',
73
+ }));
74
+ }
75
+ else {
76
+ console.error('\x1b[31m오류: 로그인이 필요합니다.\x1b[0m');
77
+ console.error(' anpm login을 먼저 실행하세요.');
78
+ }
79
+ process.exit(1);
80
+ }
81
+ if (json) {
82
+ console.error(JSON.stringify({ error: 'ACCESS_FAILED', message, fix: '접근 링크 코드를 확인하거나 에이전트 제작자에게 문의하세요.' }));
83
+ }
84
+ else {
85
+ console.error(`\x1b[31m오류: ${message}\x1b[0m`);
86
+ }
87
+ process.exit(1);
88
+ }
89
+ });
90
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerAdopt(program: Command): void;
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerAdopt = registerAdopt;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const config_js_1 = require("../lib/config.js");
11
+ const paths_js_1 = require("../lib/paths.js");
12
+ const installer_js_1 = require("../lib/installer.js");
13
+ const agent_status_js_1 = require("../lib/agent-status.js");
14
+ function registerAdopt(program) {
15
+ program
16
+ .command('adopt [path]')
17
+ .description('Adopt unmanaged skills into anpm management')
18
+ .option('--all', 'Adopt all unmanaged skills')
19
+ .option('--global', 'Adopt to global scope')
20
+ .option('--project <dir>', 'Project root path')
21
+ .option('--yes', 'Skip confirmation prompts')
22
+ .action(async (inputPath, opts) => {
23
+ const json = program.opts().json ?? false;
24
+ const projectPath = (0, paths_js_1.resolveProjectPath)(opts.project);
25
+ const scope = opts.global ? 'global' : 'local';
26
+ try {
27
+ if (opts.all) {
28
+ // Adopt all unmanaged content
29
+ const unmanaged = (0, agent_status_js_1.findUnmanagedContent)(projectPath);
30
+ if (unmanaged.length === 0) {
31
+ if (json)
32
+ console.log(JSON.stringify({ status: 'ok', message: 'All content is already managed by anpm' }));
33
+ else
34
+ console.log('\x1b[32m✓\x1b[0m All content is already managed by anpm.');
35
+ return;
36
+ }
37
+ if (!json) {
38
+ console.log(`\nFound ${unmanaged.length} unmanaged item(s):\n`);
39
+ for (const item of unmanaged) {
40
+ console.log(` ${item.type}/${item.name} \x1b[90m(${item.harness})\x1b[0m`);
41
+ }
42
+ }
43
+ if (!opts.yes && !json) {
44
+ const { confirm } = await import('@inquirer/prompts');
45
+ const ok = await confirm({ message: `Adopt all ${unmanaged.length} items?`, default: true });
46
+ if (!ok) {
47
+ process.exit(0);
48
+ }
49
+ }
50
+ let adopted = 0;
51
+ for (const item of unmanaged) {
52
+ try {
53
+ await adoptSingle(item.path, item.name, scope, projectPath, json);
54
+ adopted++;
55
+ }
56
+ catch (err) {
57
+ const msg = err instanceof Error ? err.message : String(err);
58
+ if (!json)
59
+ console.error(` \x1b[33m⚠️ Skipping ${item.name}: ${msg}\x1b[0m`);
60
+ }
61
+ }
62
+ if (json)
63
+ console.log(JSON.stringify({ status: 'ok', adopted }));
64
+ else
65
+ console.log(`\n\x1b[32m✓\x1b[0m Adopted ${adopted} item(s).`);
66
+ return;
67
+ }
68
+ // Single path adopt
69
+ if (!inputPath) {
70
+ console.error('Usage: anpm adopt <path> or anpm adopt --all');
71
+ process.exit(1);
72
+ }
73
+ const absPath = path_1.default.resolve(inputPath);
74
+ if (!fs_1.default.existsSync(absPath)) {
75
+ throw new Error(`Path not found: ${absPath}`);
76
+ }
77
+ // Check if already a relay symlink
78
+ try {
79
+ if (fs_1.default.lstatSync(absPath).isSymbolicLink()) {
80
+ const target = fs_1.default.readlinkSync(absPath);
81
+ if (target.includes('.relay/agents/')) {
82
+ if (json)
83
+ console.log(JSON.stringify({ status: 'ok', message: 'Already managed by anpm' }));
84
+ else
85
+ console.log(`\x1b[32m✓\x1b[0m Already managed by anpm.`);
86
+ return;
87
+ }
88
+ }
89
+ }
90
+ catch { /* not a symlink */ }
91
+ const name = path_1.default.basename(absPath);
92
+ await adoptSingle(absPath, name, scope, projectPath, json);
93
+ if (json) {
94
+ console.log(JSON.stringify({ status: 'ok', slug: `adopted/${name}` }));
95
+ }
96
+ else {
97
+ console.log(`\n\x1b[32m✓ Adopted ${name}\x1b[0m`);
98
+ console.log(` Now managed by anpm and deployed to all detected harnesses.`);
99
+ }
100
+ }
101
+ catch (err) {
102
+ const message = err instanceof Error ? err.message : String(err);
103
+ if (json)
104
+ console.error(JSON.stringify({ error: 'ADOPT_FAILED', message }));
105
+ else
106
+ console.error(`\x1b[31m✖ ${message}\x1b[0m`);
107
+ process.exit(1);
108
+ }
109
+ });
110
+ }
111
+ async function adoptSingle(sourcePath, name, scope, projectPath, json) {
112
+ const baseDir = scope === 'global'
113
+ ? path_1.default.join(os_1.default.homedir(), '.relay', 'agents', 'local', name)
114
+ : path_1.default.join(projectPath, '.relay', 'agents', 'local', name);
115
+ // Detect what type of content this is (skill, command, rule)
116
+ // by looking at the parent directory name
117
+ const parentDir = path_1.default.basename(path_1.default.dirname(sourcePath));
118
+ const contentType = ['skills', 'commands', 'rules', 'agents'].includes(parentDir) ? parentDir : 'skills';
119
+ const destDir = path_1.default.join(baseDir, contentType, name);
120
+ // Safety: copy first, then symlink, then delete original
121
+ // 1. Copy to .relay/agents/
122
+ fs_1.default.mkdirSync(destDir, { recursive: true });
123
+ copyDirRecursive(sourcePath, destDir);
124
+ // 2. Verify copy exists
125
+ if (!fs_1.default.existsSync(destDir)) {
126
+ throw new Error(`Copy failed: ${destDir}`);
127
+ }
128
+ // 3. Remove original and replace with symlink
129
+ if (fs_1.default.lstatSync(sourcePath).isDirectory()) {
130
+ fs_1.default.rmSync(sourcePath, { recursive: true, force: true });
131
+ }
132
+ else {
133
+ fs_1.default.unlinkSync(sourcePath);
134
+ }
135
+ const relativeSrc = path_1.default.relative(path_1.default.dirname(sourcePath), destDir);
136
+ fs_1.default.symlinkSync(relativeSrc, sourcePath);
137
+ // 4. Deploy to other harnesses
138
+ const deploy = await (0, installer_js_1.deploySymlinks)(baseDir, scope, projectPath);
139
+ for (const w of deploy.warnings) {
140
+ if (!json)
141
+ console.error(`\x1b[33m${w}\x1b[0m`);
142
+ }
143
+ // 5. Record in installed.json
144
+ const slug = `adopted/${name}`;
145
+ const record = {
146
+ version: '0.0.0',
147
+ installed_at: new Date().toISOString(),
148
+ files: [baseDir],
149
+ deploy_scope: scope,
150
+ deployed_symlinks: [sourcePath, ...deploy.symlinks],
151
+ source: `adopted:${sourcePath}`,
152
+ };
153
+ if (scope === 'global') {
154
+ const installed = (0, config_js_1.loadGlobalInstalled)();
155
+ installed[slug] = record;
156
+ (0, config_js_1.saveGlobalInstalled)(installed);
157
+ }
158
+ else {
159
+ const installed = (0, config_js_1.loadInstalled)();
160
+ installed[slug] = record;
161
+ (0, config_js_1.saveInstalled)(installed);
162
+ }
163
+ }
164
+ function copyDirRecursive(src, dest) {
165
+ const stat = fs_1.default.statSync(src);
166
+ if (stat.isDirectory()) {
167
+ fs_1.default.mkdirSync(dest, { recursive: true });
168
+ for (const entry of fs_1.default.readdirSync(src, { withFileTypes: true })) {
169
+ if (entry.name.startsWith('.'))
170
+ continue;
171
+ copyDirRecursive(path_1.default.join(src, entry.name), path_1.default.join(dest, entry.name));
172
+ }
173
+ }
174
+ else {
175
+ fs_1.default.copyFileSync(src, dest);
176
+ }
177
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerChangelog(program: Command): void;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerChangelog = registerChangelog;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const js_yaml_1 = __importDefault(require("js-yaml"));
10
+ function registerChangelog(program) {
11
+ const changelog = program
12
+ .command('changelog')
13
+ .description('에이전트 패키지의 changelog를 관리합니다');
14
+ changelog
15
+ .command('add')
16
+ .description('relay.yaml에 changelog 엔트리를 추가합니다')
17
+ .argument('[message]', 'changelog 메시지 (없으면 에디터에서 입력)')
18
+ .action(async (message) => {
19
+ const yamlPath = path_1.default.resolve('relay.yaml');
20
+ if (!fs_1.default.existsSync(yamlPath)) {
21
+ console.error('relay.yaml을 찾을 수 없습니다. 에이전트 패키지 디렉토리에서 실행하세요.');
22
+ process.exit(1);
23
+ }
24
+ const content = fs_1.default.readFileSync(yamlPath, 'utf-8');
25
+ const doc = js_yaml_1.default.load(content) ?? {};
26
+ if (!message) {
27
+ // Read from stdin if piped, otherwise prompt
28
+ const readline = await import('readline');
29
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
30
+ message = await new Promise((resolve) => {
31
+ rl.question('Changelog 메시지: ', (answer) => {
32
+ rl.close();
33
+ resolve(answer);
34
+ });
35
+ });
36
+ }
37
+ if (!message || message.trim() === '') {
38
+ console.error('changelog 메시지가 비어있습니다.');
39
+ process.exit(1);
40
+ }
41
+ const version = String(doc.version ?? '1.0.0');
42
+ const date = new Date().toISOString().split('T')[0];
43
+ const entry = `## v${version} (${date})\n\n- ${message.trim()}`;
44
+ const existing = doc.changelog ? String(doc.changelog) : '';
45
+ doc.changelog = existing ? `${entry}\n\n${existing}` : entry;
46
+ fs_1.default.writeFileSync(yamlPath, js_yaml_1.default.dump(doc, { lineWidth: -1, noRefs: true }), 'utf-8');
47
+ console.log(`\x1b[32m✓\x1b[0m changelog 추가됨 (v${version})`);
48
+ console.log(` ${message.trim()}`);
49
+ });
50
+ changelog
51
+ .command('show')
52
+ .description('현재 relay.yaml의 changelog를 표시합니다')
53
+ .action(() => {
54
+ const yamlPath = path_1.default.resolve('relay.yaml');
55
+ if (!fs_1.default.existsSync(yamlPath)) {
56
+ console.error('relay.yaml을 찾을 수 없습니다.');
57
+ process.exit(1);
58
+ }
59
+ const content = fs_1.default.readFileSync(yamlPath, 'utf-8');
60
+ const doc = js_yaml_1.default.load(content) ?? {};
61
+ if (!doc.changelog) {
62
+ console.log('changelog가 없습니다. `anpm changelog add "메시지"`로 추가하세요.');
63
+ return;
64
+ }
65
+ console.log(String(doc.changelog));
66
+ });
67
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerCheckUpdate(program: Command): void;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerCheckUpdate = registerCheckUpdate;
4
+ const version_check_js_1 = require("../lib/version-check.js");
5
+ const slug_js_1 = require("../lib/slug.js");
6
+ function registerCheckUpdate(program) {
7
+ program
8
+ .command('check-update [slug]')
9
+ .description('CLI 및 설치된 에이전트의 업데이트를 확인합니다')
10
+ .option('--quiet', '업데이트가 있을 때만 머신 리더블 출력')
11
+ .option('--force', '캐시를 무시하고 강제 체크')
12
+ .action(async (slug, opts) => {
13
+ const quiet = opts.quiet ?? false;
14
+ const force = opts.force ?? false;
15
+ // CLI version check
16
+ const cliResult = await (0, version_check_js_1.checkCliVersion)(force);
17
+ if (cliResult) {
18
+ if (quiet) {
19
+ console.log(`CLI_UPGRADE_AVAILABLE ${cliResult.current} ${cliResult.latest}`);
20
+ }
21
+ else {
22
+ console.log(`\n\x1b[33m⚠ anpm v${cliResult.latest} available\x1b[0m (현재 v${cliResult.current})`);
23
+ console.log(` 실행: npm update -g relayax-cli\n`);
24
+ }
25
+ }
26
+ // Agent version check
27
+ if (slug) {
28
+ // Resolve to scoped slug
29
+ let scopedSlug;
30
+ if ((0, slug_js_1.isScopedSlug)(slug)) {
31
+ scopedSlug = slug;
32
+ }
33
+ else {
34
+ try {
35
+ const parsed = await (0, slug_js_1.resolveSlug)(slug);
36
+ scopedSlug = parsed.full;
37
+ }
38
+ catch {
39
+ scopedSlug = slug;
40
+ }
41
+ }
42
+ const agentResult = await (0, version_check_js_1.checkAgentVersion)(scopedSlug, force);
43
+ if (agentResult) {
44
+ if (quiet) {
45
+ const byAuthor = agentResult.author ? ` ${agentResult.author}` : '';
46
+ console.log(`AGENT_UPGRADE_AVAILABLE ${slug} ${agentResult.current} ${agentResult.latest}${byAuthor}`);
47
+ }
48
+ else {
49
+ const byAuthor = agentResult.author ? ` \x1b[90m(by @${agentResult.author})\x1b[0m` : '';
50
+ console.log(`\x1b[33m⚠ ${slug} v${agentResult.latest} available\x1b[0m${byAuthor} (현재 v${agentResult.current})`);
51
+ console.log(` 실행: anpm update ${slug}`);
52
+ }
53
+ }
54
+ else if (!quiet && !cliResult) {
55
+ console.log('모든 것이 최신 상태입니다.');
56
+ }
57
+ }
58
+ else {
59
+ const agentResults = await (0, version_check_js_1.checkAllAgents)(force);
60
+ for (const result of agentResults) {
61
+ if (quiet) {
62
+ const byAuthor = result.author ? ` ${result.author}` : '';
63
+ console.log(`AGENT_UPGRADE_AVAILABLE ${result.slug} ${result.current} ${result.latest}${byAuthor}`);
64
+ }
65
+ else {
66
+ const byAuthor = result.author ? ` \x1b[90m(by @${result.author})\x1b[0m` : '';
67
+ console.log(`\x1b[33m⚠ ${result.slug} v${result.latest} available\x1b[0m${byAuthor} (현재 v${result.current})`);
68
+ console.log(` 실행: anpm update ${result.slug}`);
69
+ }
70
+ }
71
+ if (!quiet && !cliResult && agentResults.length === 0) {
72
+ console.log('모든 것이 최신 상태입니다.');
73
+ }
74
+ }
75
+ });
76
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerConfig(program: Command): void;