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
@@ -0,0 +1,171 @@
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.registerUpdate = registerUpdate;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const os_1 = __importDefault(require("os"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const api_js_1 = require("../lib/api.js");
11
+ const storage_js_1 = require("../lib/storage.js");
12
+ const git_operations_js_1 = require("../lib/git-operations.js");
13
+ const installer_js_1 = require("../lib/installer.js");
14
+ const config_js_1 = require("../lib/config.js");
15
+ const slug_js_1 = require("../lib/slug.js");
16
+ const preamble_js_1 = require("../lib/preamble.js");
17
+ const paths_js_1 = require("../lib/paths.js");
18
+ function registerUpdate(program) {
19
+ program
20
+ .command('update <slug>')
21
+ .description('설치된 에이전트를 최신 버전으로 업데이트합니다')
22
+ .option('--path <install_path>', '설치 경로 지정 (기본: ./.claude)')
23
+ .option('--code <code>', '초대 코드 (비공개 에이전트 업데이트 시 필요)')
24
+ .action(async (slugInput, opts) => {
25
+ const json = program.opts().json ?? false;
26
+ const tempDir = (0, storage_js_1.makeTempDir)();
27
+ const projectPath = (0, paths_js_1.resolveProjectPath)(opts.path);
28
+ try {
29
+ // Resolve scoped slug
30
+ const localInstalled = (0, config_js_1.loadInstalled)();
31
+ const globalInstalled = (0, config_js_1.loadGlobalInstalled)();
32
+ let slug;
33
+ if ((0, slug_js_1.isScopedSlug)(slugInput)) {
34
+ slug = slugInput;
35
+ }
36
+ else {
37
+ const parsed = await (0, slug_js_1.resolveSlug)(slugInput);
38
+ slug = parsed.full;
39
+ }
40
+ // Find current entry (check both registries)
41
+ const currentEntry = localInstalled[slug] ?? globalInstalled[slug];
42
+ const currentVersion = currentEntry?.version ?? null;
43
+ const currentScope = globalInstalled[slug] ? 'global'
44
+ : currentEntry?.deploy_scope ?? 'global';
45
+ // Fetch latest agent metadata
46
+ const agent = await (0, api_js_1.fetchAgentInfo)(slug);
47
+ const latestVersion = agent.version;
48
+ if (currentVersion && currentVersion === latestVersion) {
49
+ if (json) {
50
+ console.log(JSON.stringify({ status: 'up-to-date', slug, version: latestVersion }));
51
+ }
52
+ else {
53
+ console.log(`이미 최신 버전입니다 (${slug} v${latestVersion})`);
54
+ }
55
+ return;
56
+ }
57
+ // Visibility check
58
+ const visibility = agent.visibility ?? 'public';
59
+ if (visibility === 'internal') {
60
+ const token = await (0, config_js_1.getValidToken)();
61
+ if (!token) {
62
+ console.error('이 에이전트는 Org 멤버만 업데이트할 수 있습니다. `anpm login`을 먼저 실행하세요.');
63
+ process.exit(1);
64
+ }
65
+ }
66
+ // Clean up old symlinks (new) and deployed_files (legacy migration)
67
+ if (currentEntry?.deployed_symlinks && currentEntry.deployed_symlinks.length > 0) {
68
+ (0, installer_js_1.removeSymlinks)(currentEntry.deployed_symlinks);
69
+ }
70
+ if (currentEntry?.deployed_files && currentEntry.deployed_files.length > 0) {
71
+ (0, installer_js_1.uninstallAgent)(currentEntry.deployed_files);
72
+ }
73
+ // Determine agent directory
74
+ const parsedSlug = (0, slug_js_1.parseSlug)(slug);
75
+ const owner = parsedSlug?.owner ?? 'unknown';
76
+ const name = parsedSlug?.name ?? slug;
77
+ const agentDir = currentScope === 'global'
78
+ ? path_1.default.join(os_1.default.homedir(), '.relay', 'agents', owner, name)
79
+ : path_1.default.join(projectPath, '.relay', 'agents', owner, name);
80
+ // Download & extract: prefer git, fallback to tar.gz
81
+ if (agent.git_url && fs_1.default.existsSync(path_1.default.join(agentDir, '.git'))) {
82
+ // Existing git clone — fetch + checkout latest tag
83
+ (0, git_operations_js_1.checkGitInstalled)();
84
+ (0, git_operations_js_1.gitFetch)(agentDir);
85
+ const latestTag = (0, git_operations_js_1.gitLatestTag)(agentDir);
86
+ if (latestTag) {
87
+ (0, git_operations_js_1.gitCheckout)(agentDir, latestTag);
88
+ }
89
+ }
90
+ else if (agent.git_url) {
91
+ // No existing clone — fresh git clone
92
+ (0, git_operations_js_1.checkGitInstalled)();
93
+ await (0, storage_js_1.clonePackage)(agent.git_url, agentDir);
94
+ }
95
+ else {
96
+ throw new Error('이 에이전트는 재설치가 필요합니다. anpm install로 다시 설치하세요.');
97
+ }
98
+ // Inject preamble
99
+ (0, preamble_js_1.injectPreambleToAgent)(agentDir, slug);
100
+ // Deploy symlinks (always — handles migration from legacy deployed_files)
101
+ const deploy = await (0, installer_js_1.deploySymlinks)(agentDir, currentScope, projectPath);
102
+ // Update installed.json
103
+ const installRecord = {
104
+ agent_id: agent.id,
105
+ version: latestVersion,
106
+ installed_at: new Date().toISOString(),
107
+ files: [agentDir],
108
+ deploy_scope: currentScope,
109
+ deployed_symlinks: deploy.symlinks,
110
+ };
111
+ if (currentScope === 'global') {
112
+ globalInstalled[slug] = installRecord;
113
+ (0, config_js_1.saveGlobalInstalled)(globalInstalled);
114
+ // Clean up local entry if migrating
115
+ if (localInstalled[slug]) {
116
+ delete localInstalled[slug];
117
+ (0, config_js_1.saveInstalled)(localInstalled);
118
+ }
119
+ }
120
+ else {
121
+ localInstalled[slug] = installRecord;
122
+ (0, config_js_1.saveInstalled)(localInstalled);
123
+ }
124
+ // Report
125
+ await (0, api_js_1.reportInstall)(agent.id, slug, latestVersion);
126
+ const result = {
127
+ status: 'updated',
128
+ slug,
129
+ from_version: currentVersion,
130
+ version: latestVersion,
131
+ scope: currentScope,
132
+ symlinks: deploy.symlinks.length,
133
+ };
134
+ if (json) {
135
+ console.log(JSON.stringify(result));
136
+ }
137
+ else {
138
+ const fromLabel = currentVersion ? `v${currentVersion} → ` : '';
139
+ console.log(`\n\x1b[32m✓ ${agent.name} ${fromLabel}v${latestVersion} 업데이트 완료\x1b[0m`);
140
+ console.log(` 위치: \x1b[36m${agentDir}\x1b[0m`);
141
+ console.log(` symlink: ${deploy.symlinks.length}개`);
142
+ // Show changelog
143
+ try {
144
+ const versions = await (0, api_js_1.fetchAgentVersions)(slug);
145
+ const thisVersion = versions.find((v) => v.version === latestVersion);
146
+ if (thisVersion?.changelog) {
147
+ console.log(`\n \x1b[90m── Changelog ──────────────────────────────\x1b[0m`);
148
+ for (const line of thisVersion.changelog.split('\n').slice(0, 5)) {
149
+ console.log(` ${line}`);
150
+ }
151
+ console.log(` \x1b[90m───────────────────────────────────────────\x1b[0m`);
152
+ }
153
+ }
154
+ catch {
155
+ // Non-critical
156
+ }
157
+ // Requires check
158
+ const requiresResults = (0, installer_js_1.checkRequires)(agentDir);
159
+ (0, installer_js_1.printRequiresCheck)(requiresResults);
160
+ }
161
+ }
162
+ catch (err) {
163
+ const message = err instanceof Error ? err.message : String(err);
164
+ console.error(JSON.stringify({ error: 'UPDATE_FAILED', message, fix: 'npm update -g relayax-cli로 수동 업데이트하세요.' }));
165
+ process.exit(1);
166
+ }
167
+ finally {
168
+ (0, storage_js_1.removeTempDir)(tempDir);
169
+ }
170
+ });
171
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerVersions(program: Command): void;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerVersions = registerVersions;
4
+ const api_js_1 = require("../lib/api.js");
5
+ const slug_js_1 = require("../lib/slug.js");
6
+ function registerVersions(program) {
7
+ program
8
+ .command('versions <slug>')
9
+ .description('에이전트 버전 목록과 릴리즈 노트를 확인합니다')
10
+ .action(async (slugInput) => {
11
+ const json = program.opts().json ?? false;
12
+ try {
13
+ const resolved = await (0, slug_js_1.resolveSlug)(slugInput);
14
+ const versions = await (0, api_js_1.fetchAgentVersions)(resolved.full);
15
+ if (json) {
16
+ console.log(JSON.stringify({ slug: resolved.full, versions }));
17
+ return;
18
+ }
19
+ if (versions.length === 0) {
20
+ console.log(`\n${resolved.full} 버전 이력이 없습니다.`);
21
+ return;
22
+ }
23
+ console.log(`\n\x1b[1m${resolved.full} 버전 이력\x1b[0m (${versions.length}개):\n`);
24
+ for (const v of versions) {
25
+ const date = new Date(v.created_at).toLocaleDateString('ko-KR');
26
+ console.log(` \x1b[36mv${v.version}\x1b[0m (${date})`);
27
+ if (v.changelog) {
28
+ console.log(` \x1b[90m${v.changelog}\x1b[0m`);
29
+ }
30
+ }
31
+ console.log(`\n\x1b[33m 특정 버전 설치: anpm install ${resolved.full}@<version>\x1b[0m`);
32
+ }
33
+ catch (err) {
34
+ const message = err instanceof Error ? err.message : String(err);
35
+ if (json) {
36
+ console.error(JSON.stringify({ error: 'VERSIONS_FAILED', message }));
37
+ }
38
+ else {
39
+ console.error(`\x1b[31m오류: ${message}\x1b[0m`);
40
+ }
41
+ process.exit(1);
42
+ }
43
+ });
44
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_js_1 = require("./commands/init.js");
6
+ const create_js_1 = require("./commands/create.js");
7
+ const status_js_1 = require("./commands/status.js");
8
+ const search_js_1 = require("./commands/search.js");
9
+ const install_js_1 = require("./commands/install.js");
10
+ const list_js_1 = require("./commands/list.js");
11
+ const uninstall_js_1 = require("./commands/uninstall.js");
12
+ const package_js_1 = require("./commands/package.js");
13
+ const publish_js_1 = require("./commands/publish.js");
14
+ const login_js_1 = require("./commands/login.js");
15
+ const update_js_1 = require("./commands/update.js");
16
+ const outdated_js_1 = require("./commands/outdated.js");
17
+ const check_update_js_1 = require("./commands/check-update.js");
18
+ const changelog_js_1 = require("./commands/changelog.js");
19
+ const join_js_1 = require("./commands/join.js");
20
+ const orgs_js_1 = require("./commands/orgs.js");
21
+ const deploy_record_js_1 = require("./commands/deploy-record.js");
22
+ const ping_js_1 = require("./commands/ping.js");
23
+ const access_js_1 = require("./commands/access.js");
24
+ const grant_js_1 = require("./commands/grant.js");
25
+ const versions_js_1 = require("./commands/versions.js");
26
+ const diff_js_1 = require("./commands/diff.js");
27
+ const feedback_js_1 = require("./commands/feedback.js");
28
+ const link_js_1 = require("./commands/link.js");
29
+ const config_js_1 = require("./commands/config.js");
30
+ const adopt_js_1 = require("./commands/adopt.js");
31
+ const run_js_1 = require("./commands/run.js");
32
+ const deploy_js_1 = require("./commands/deploy.js");
33
+ const server_js_1 = require("./mcp/server.js");
34
+ const migration_js_1 = require("./lib/migration.js");
35
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
36
+ const pkg = require('../package.json');
37
+ const program = new commander_1.Command();
38
+ program
39
+ .name('anpm')
40
+ .description('anpm — the agent package manager')
41
+ .version(pkg.version)
42
+ .option('--json', '구조화된 JSON 출력');
43
+ (0, init_js_1.registerInit)(program);
44
+ (0, create_js_1.registerCreate)(program);
45
+ (0, status_js_1.registerStatus)(program);
46
+ (0, search_js_1.registerSearch)(program);
47
+ (0, install_js_1.registerInstall)(program);
48
+ (0, list_js_1.registerList)(program);
49
+ (0, uninstall_js_1.registerUninstall)(program);
50
+ (0, package_js_1.registerPackage)(program);
51
+ (0, publish_js_1.registerPublish)(program);
52
+ (0, login_js_1.registerLogin)(program);
53
+ (0, update_js_1.registerUpdate)(program);
54
+ (0, outdated_js_1.registerOutdated)(program);
55
+ (0, check_update_js_1.registerCheckUpdate)(program);
56
+ (0, changelog_js_1.registerChangelog)(program);
57
+ (0, join_js_1.registerJoin)(program);
58
+ (0, orgs_js_1.registerOrgs)(program);
59
+ (0, deploy_record_js_1.registerDeployRecord)(program);
60
+ (0, ping_js_1.registerPing)(program);
61
+ (0, access_js_1.registerAccess)(program);
62
+ (0, grant_js_1.registerGrant)(program);
63
+ (0, versions_js_1.registerVersions)(program);
64
+ (0, diff_js_1.registerDiff)(program);
65
+ (0, feedback_js_1.registerFeedback)(program);
66
+ (0, link_js_1.registerLink)(program);
67
+ (0, config_js_1.registerConfig)(program);
68
+ (0, adopt_js_1.registerAdopt)(program);
69
+ (0, run_js_1.registerRun)(program);
70
+ (0, deploy_js_1.registerDeploy)(program);
71
+ program
72
+ .command('mcp')
73
+ .description('MCP 서버 모드로 실행합니다 (stdio transport)')
74
+ .action(async () => {
75
+ await (0, server_js_1.startMcpServer)();
76
+ });
77
+ // 모든 명령 실행 전 마이그레이션 + 버전 표시
78
+ program.hook('preAction', (_thisCommand, actionCommand) => {
79
+ const isJson = program.opts().json ?? false;
80
+ const isMcp = actionCommand.name() === 'mcp';
81
+ // 마이그레이션은 항상 실행 (mcp 제외)
82
+ if (!isMcp) {
83
+ (0, migration_js_1.migrateGlobalDir)();
84
+ (0, migration_js_1.migrateProjectDir)(process.env.RELAY_PROJECT_PATH ?? process.cwd());
85
+ }
86
+ // 버전 표시는 TTY + non-json만
87
+ if (!isJson && !isMcp && process.stderr.isTTY) {
88
+ process.stderr.write(`\x1b[2manpm v${pkg.version}\x1b[0m\n`);
89
+ }
90
+ });
91
+ program.parse();
@@ -0,0 +1,23 @@
1
+ export interface AgentStatusEntry {
2
+ slug: string;
3
+ source: string;
4
+ version: string;
5
+ scope: 'global' | 'local';
6
+ status: 'active' | 'broken' | 'unknown';
7
+ harnesses: string[];
8
+ symlinkCount: number;
9
+ brokenSymlinks: string[];
10
+ }
11
+ /**
12
+ * Get detailed status of all installed agents with harness mapping.
13
+ */
14
+ export declare function getAgentStatusEntries(): AgentStatusEntry[];
15
+ /**
16
+ * Scan harness directories for unmanaged (non-relay) content.
17
+ */
18
+ export declare function findUnmanagedContent(projectPath: string): {
19
+ harness: string;
20
+ type: string;
21
+ name: string;
22
+ path: string;
23
+ }[];
@@ -0,0 +1,127 @@
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.getAgentStatusEntries = getAgentStatusEntries;
7
+ exports.findUnmanagedContent = findUnmanagedContent;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const os_1 = __importDefault(require("os"));
11
+ const config_js_1 = require("./config.js");
12
+ const ai_tools_js_1 = require("./ai-tools.js");
13
+ /**
14
+ * Get detailed status of all installed agents with harness mapping.
15
+ */
16
+ function getAgentStatusEntries() {
17
+ const { global: globalInstalled, local: localInstalled } = (0, config_js_1.loadMergedInstalled)();
18
+ const entries = [];
19
+ function processRegistry(registry, scope) {
20
+ for (const [slug, info] of Object.entries(registry)) {
21
+ const symlinks = info.deployed_symlinks ?? [];
22
+ const broken = [];
23
+ const harnessSet = new Set();
24
+ for (const link of symlinks) {
25
+ if (!isSymlink(link)) {
26
+ broken.push(link);
27
+ }
28
+ else {
29
+ // Extract harness name from path
30
+ const harnessName = extractHarnessName(link);
31
+ if (harnessName)
32
+ harnessSet.add(harnessName);
33
+ }
34
+ }
35
+ entries.push({
36
+ slug,
37
+ source: info.source ?? 'registry',
38
+ version: info.version,
39
+ scope: (info.deploy_scope ?? scope),
40
+ status: broken.length > 0 ? 'broken' : symlinks.length > 0 ? 'active' : 'unknown',
41
+ harnesses: Array.from(harnessSet),
42
+ symlinkCount: symlinks.length - broken.length,
43
+ brokenSymlinks: broken,
44
+ });
45
+ }
46
+ }
47
+ processRegistry(globalInstalled, 'global');
48
+ processRegistry(localInstalled, 'local');
49
+ return entries;
50
+ }
51
+ /**
52
+ * Scan harness directories for unmanaged (non-relay) content.
53
+ */
54
+ function findUnmanagedContent(projectPath) {
55
+ const unmanaged = [];
56
+ const homeDir = os_1.default.homedir();
57
+ const contentDirs = ['skills', 'commands', 'rules', 'agents'];
58
+ for (const tool of ai_tools_js_1.AI_TOOLS) {
59
+ // Check both global and local harness dirs
60
+ const dirs = [
61
+ { base: path_1.default.join(homeDir, tool.skillsDir), scope: 'global' },
62
+ { base: path_1.default.join(projectPath, tool.skillsDir), scope: 'local' },
63
+ ];
64
+ for (const { base } of dirs) {
65
+ for (const contentType of contentDirs) {
66
+ const dir = path_1.default.join(base, contentType);
67
+ if (!fs_1.default.existsSync(dir))
68
+ continue;
69
+ for (const entry of fs_1.default.readdirSync(dir, { withFileTypes: true })) {
70
+ if (entry.name.startsWith('.'))
71
+ continue;
72
+ if (entry.name === 'relay')
73
+ continue; // skip relay's own dir
74
+ const entryPath = path_1.default.join(dir, entry.name);
75
+ // If it's not a symlink pointing into .relay/agents/, it's unmanaged
76
+ if (!isRelaySymlink(entryPath)) {
77
+ unmanaged.push({
78
+ harness: tool.name,
79
+ type: contentType,
80
+ name: entry.name,
81
+ path: entryPath,
82
+ });
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ // Deduplicate by path
89
+ const seen = new Set();
90
+ return unmanaged.filter((item) => {
91
+ if (seen.has(item.path))
92
+ return false;
93
+ seen.add(item.path);
94
+ return true;
95
+ });
96
+ }
97
+ function isSymlink(p) {
98
+ try {
99
+ const stat = fs_1.default.lstatSync(p);
100
+ if (!stat.isSymbolicLink())
101
+ return false;
102
+ // Also check if target exists
103
+ return fs_1.default.existsSync(p);
104
+ }
105
+ catch {
106
+ return false;
107
+ }
108
+ }
109
+ function isRelaySymlink(p) {
110
+ try {
111
+ if (!fs_1.default.lstatSync(p).isSymbolicLink())
112
+ return false;
113
+ const target = fs_1.default.readlinkSync(p);
114
+ return target.includes('.relay/agents/') || target.includes('.relay\\agents\\');
115
+ }
116
+ catch {
117
+ return false;
118
+ }
119
+ }
120
+ function extractHarnessName(symlinkPath) {
121
+ for (const tool of ai_tools_js_1.AI_TOOLS) {
122
+ if (symlinkPath.includes(tool.skillsDir)) {
123
+ return tool.name;
124
+ }
125
+ }
126
+ return undefined;
127
+ }
@@ -0,0 +1,34 @@
1
+ export interface AITool {
2
+ name: string;
3
+ value: string;
4
+ skillsDir: string;
5
+ }
6
+ /**
7
+ * Agent Skills 표준을 지원하는 에이전트 CLI 목록.
8
+ * @fission-ai/openspec의 AI_TOOLS에서 차용.
9
+ */
10
+ export declare const AI_TOOLS: AITool[];
11
+ /**
12
+ * 프로젝트 디렉토리에서 에이전트 CLI 디렉토리를 감지한다.
13
+ */
14
+ export declare function detectAgentCLIs(projectPath: string): AITool[];
15
+ /**
16
+ * 홈 디렉토리에서 글로벌 에이전트 CLI 디렉토리를 감지한다.
17
+ * ~/{skillsDir}/ 가 존재하는 CLI를 반환.
18
+ */
19
+ export declare function detectGlobalCLIs(home?: string): AITool[];
20
+ export type ContentType = 'skill' | 'agent' | 'command' | 'rule';
21
+ export interface ContentItem {
22
+ name: string;
23
+ type: ContentType;
24
+ /** 소스 디렉토리 기준 상대 경로 (예: skills/code-review) */
25
+ relativePath: string;
26
+ }
27
+ /**
28
+ * 프로젝트 로컬 소스의 개별 스킬/에이전트/커맨드/룰 항목을 반환한다.
29
+ */
30
+ export declare function scanLocalItems(projectPath: string, tool: AITool): ContentItem[];
31
+ /**
32
+ * 글로벌 홈 디렉토리 소스의 개별 스킬/에이전트/커맨드/룰 항목을 반환한다.
33
+ */
34
+ export declare function scanGlobalItems(tool: AITool, home?: string): ContentItem[];
@@ -0,0 +1,104 @@
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.AI_TOOLS = void 0;
7
+ exports.detectAgentCLIs = detectAgentCLIs;
8
+ exports.detectGlobalCLIs = detectGlobalCLIs;
9
+ exports.scanLocalItems = scanLocalItems;
10
+ exports.scanGlobalItems = scanGlobalItems;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const os_1 = __importDefault(require("os"));
13
+ const path_1 = __importDefault(require("path"));
14
+ /**
15
+ * Agent Skills 표준을 지원하는 에이전트 CLI 목록.
16
+ * @fission-ai/openspec의 AI_TOOLS에서 차용.
17
+ */
18
+ exports.AI_TOOLS = [
19
+ { name: 'Amazon Q Developer', value: 'amazon-q', skillsDir: '.amazonq' },
20
+ { name: 'Antigravity', value: 'antigravity', skillsDir: '.agent' },
21
+ { name: 'Auggie', value: 'auggie', skillsDir: '.augment' },
22
+ { name: 'Claude Code', value: 'claude', skillsDir: '.claude' },
23
+ { name: 'Cline', value: 'cline', skillsDir: '.cline' },
24
+ { name: 'Codex', value: 'codex', skillsDir: '.codex' },
25
+ { name: 'CodeBuddy', value: 'codebuddy', skillsDir: '.codebuddy' },
26
+ { name: 'Continue', value: 'continue', skillsDir: '.continue' },
27
+ { name: 'CoStrict', value: 'costrict', skillsDir: '.cospec' },
28
+ { name: 'Crush', value: 'crush', skillsDir: '.crush' },
29
+ { name: 'Cursor', value: 'cursor', skillsDir: '.cursor' },
30
+ { name: 'Factory Droid', value: 'factory', skillsDir: '.factory' },
31
+ { name: 'Gemini CLI', value: 'gemini', skillsDir: '.gemini' },
32
+ { name: 'GitHub Copilot', value: 'github-copilot', skillsDir: '.github' },
33
+ { name: 'Hermes Agent', value: 'hermes', skillsDir: '.hermes' },
34
+ { name: 'iFlow', value: 'iflow', skillsDir: '.iflow' },
35
+ { name: 'Kilo Code', value: 'kilocode', skillsDir: '.kilocode' },
36
+ { name: 'Kiro', value: 'kiro', skillsDir: '.kiro' },
37
+ { name: 'OpenClaw', value: 'openclaw', skillsDir: '.openclaw' },
38
+ { name: 'OpenCode', value: 'opencode', skillsDir: '.opencode' },
39
+ { name: 'Pi', value: 'pi', skillsDir: '.pi' },
40
+ { name: 'Qoder', value: 'qoder', skillsDir: '.qoder' },
41
+ { name: 'Qwen Code', value: 'qwen', skillsDir: '.qwen' },
42
+ { name: 'RooCode', value: 'roocode', skillsDir: '.roo' },
43
+ { name: 'Trae', value: 'trae', skillsDir: '.trae' },
44
+ { name: 'Windsurf', value: 'windsurf', skillsDir: '.windsurf' },
45
+ ];
46
+ /**
47
+ * 프로젝트 디렉토리에서 에이전트 CLI 디렉토리를 감지한다.
48
+ */
49
+ function detectAgentCLIs(projectPath) {
50
+ return exports.AI_TOOLS.filter((tool) => fs_1.default.existsSync(path_1.default.join(projectPath, tool.skillsDir)));
51
+ }
52
+ /**
53
+ * 홈 디렉토리에서 글로벌 에이전트 CLI 디렉토리를 감지한다.
54
+ * ~/{skillsDir}/ 가 존재하는 CLI를 반환.
55
+ */
56
+ function detectGlobalCLIs(home) {
57
+ const homeDir = home ?? os_1.default.homedir();
58
+ return exports.AI_TOOLS.filter((tool) => fs_1.default.existsSync(path_1.default.join(homeDir, tool.skillsDir)));
59
+ }
60
+ const CONTENT_DIRS = [
61
+ { dir: 'skills', type: 'skill' },
62
+ { dir: 'agents', type: 'agent' },
63
+ { dir: 'commands', type: 'command' },
64
+ { dir: 'rules', type: 'rule' },
65
+ ];
66
+ const EXCLUDE_SUBDIRS = ['relay'];
67
+ /**
68
+ * 소스 디렉토리(basePath) 안의 skills/, agents/, commands/, rules/에서
69
+ * 개별 항목을 스캔하여 반환한다.
70
+ */
71
+ function scanItemsIn(basePath) {
72
+ const items = [];
73
+ for (const { dir, type } of CONTENT_DIRS) {
74
+ const fullDir = path_1.default.join(basePath, dir);
75
+ if (!fs_1.default.existsSync(fullDir))
76
+ continue;
77
+ for (const entry of fs_1.default.readdirSync(fullDir, { withFileTypes: true })) {
78
+ if (entry.name.startsWith('.'))
79
+ continue;
80
+ if (entry.isDirectory() && EXCLUDE_SUBDIRS.includes(entry.name))
81
+ continue;
82
+ items.push({
83
+ name: entry.name.replace(/\.\w+$/, ''), // 파일이면 확장자 제거
84
+ type,
85
+ relativePath: path_1.default.join(dir, entry.name),
86
+ });
87
+ }
88
+ }
89
+ return items;
90
+ }
91
+ /**
92
+ * 프로젝트 로컬 소스의 개별 스킬/에이전트/커맨드/룰 항목을 반환한다.
93
+ */
94
+ function scanLocalItems(projectPath, tool) {
95
+ const basePath = path_1.default.join(projectPath, tool.skillsDir);
96
+ return scanItemsIn(basePath);
97
+ }
98
+ /**
99
+ * 글로벌 홈 디렉토리 소스의 개별 스킬/에이전트/커맨드/룰 항목을 반환한다.
100
+ */
101
+ function scanGlobalItems(tool, home) {
102
+ const basePath = path_1.default.join(home ?? os_1.default.homedir(), tool.skillsDir);
103
+ return scanItemsIn(basePath);
104
+ }
@@ -0,0 +1,39 @@
1
+ export interface ProviderConfig {
2
+ api_key?: string;
3
+ default_model?: string;
4
+ }
5
+ export interface AnpmConfig {
6
+ registry?: string;
7
+ locale?: string;
8
+ providers?: {
9
+ anthropic?: ProviderConfig;
10
+ [provider: string]: ProviderConfig | undefined;
11
+ };
12
+ [key: string]: unknown;
13
+ }
14
+ /** @deprecated Use AnpmConfig */
15
+ export type RelayConfig = AnpmConfig;
16
+ export declare const CONFIG_DEFAULTS: AnpmConfig;
17
+ export declare function loadConfig(): AnpmConfig;
18
+ export declare function saveConfig(config: AnpmConfig): void;
19
+ export declare function deleteConfigKey(key: string): void;
20
+ /**
21
+ * Get the registry URL from config, with fallback to default.
22
+ */
23
+ export declare function getRegistryUrl(): string;
24
+ /**
25
+ * Resolve provider API key with priority:
26
+ * 1. explicit flag (--api-key)
27
+ * 2. environment variable (ANTHROPIC_API_KEY etc.)
28
+ * 3. config.json providers section
29
+ */
30
+ export declare function resolveProviderApiKey(provider: string, flagValue?: string): string | undefined;
31
+ /**
32
+ * Mask an API key for display: sk-ant-xxx...xxxx
33
+ */
34
+ export declare function maskApiKey(key: string): string;
35
+ /**
36
+ * Set a nested config key using dot notation.
37
+ * e.g. "provider.anthropic.api-key" → config.providers.anthropic.api_key
38
+ */
39
+ export declare function setNestedConfigKey(dotPath: string, value: string): void;