@zhixuan92/multi-model-agent 3.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 (169) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/cli/index.d.ts +61 -0
  4. package/dist/cli/index.d.ts.map +1 -0
  5. package/dist/cli/index.js +252 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/cli/install-skill.d.ts +158 -0
  8. package/dist/cli/install-skill.d.ts.map +1 -0
  9. package/dist/cli/install-skill.js +425 -0
  10. package/dist/cli/install-skill.js.map +1 -0
  11. package/dist/cli/print-token.d.ts +18 -0
  12. package/dist/cli/print-token.d.ts.map +1 -0
  13. package/dist/cli/print-token.js +60 -0
  14. package/dist/cli/print-token.js.map +1 -0
  15. package/dist/cli/serve.d.ts +44 -0
  16. package/dist/cli/serve.d.ts.map +1 -0
  17. package/dist/cli/serve.js +61 -0
  18. package/dist/cli/serve.js.map +1 -0
  19. package/dist/cli/status.d.ts +49 -0
  20. package/dist/cli/status.d.ts.map +1 -0
  21. package/dist/cli/status.js +155 -0
  22. package/dist/cli/status.js.map +1 -0
  23. package/dist/http/async-dispatch.d.ts +32 -0
  24. package/dist/http/async-dispatch.d.ts.map +1 -0
  25. package/dist/http/async-dispatch.js +53 -0
  26. package/dist/http/async-dispatch.js.map +1 -0
  27. package/dist/http/auth.d.ts +26 -0
  28. package/dist/http/auth.d.ts.map +1 -0
  29. package/dist/http/auth.js +64 -0
  30. package/dist/http/auth.js.map +1 -0
  31. package/dist/http/cwd-validator.d.ts +11 -0
  32. package/dist/http/cwd-validator.d.ts.map +1 -0
  33. package/dist/http/cwd-validator.js +115 -0
  34. package/dist/http/cwd-validator.js.map +1 -0
  35. package/dist/http/errors.d.ts +4 -0
  36. package/dist/http/errors.d.ts.map +1 -0
  37. package/dist/http/errors.js +9 -0
  38. package/dist/http/errors.js.map +1 -0
  39. package/dist/http/execution-context.d.ts +15 -0
  40. package/dist/http/execution-context.d.ts.map +1 -0
  41. package/dist/http/execution-context.js +35 -0
  42. package/dist/http/execution-context.js.map +1 -0
  43. package/dist/http/handler-deps.d.ts +16 -0
  44. package/dist/http/handler-deps.d.ts.map +1 -0
  45. package/dist/http/handler-deps.js +2 -0
  46. package/dist/http/handler-deps.js.map +1 -0
  47. package/dist/http/handlers/control/batch.d.ts +24 -0
  48. package/dist/http/handlers/control/batch.d.ts.map +1 -0
  49. package/dist/http/handlers/control/batch.js +81 -0
  50. package/dist/http/handlers/control/batch.js.map +1 -0
  51. package/dist/http/handlers/control/clarifications.d.ts +19 -0
  52. package/dist/http/handlers/control/clarifications.d.ts.map +1 -0
  53. package/dist/http/handlers/control/clarifications.js +58 -0
  54. package/dist/http/handlers/control/clarifications.js.map +1 -0
  55. package/dist/http/handlers/control/context-blocks.d.ts +22 -0
  56. package/dist/http/handlers/control/context-blocks.d.ts.map +1 -0
  57. package/dist/http/handlers/control/context-blocks.js +88 -0
  58. package/dist/http/handlers/control/context-blocks.js.map +1 -0
  59. package/dist/http/handlers/introspection/health.d.ts +13 -0
  60. package/dist/http/handlers/introspection/health.d.ts.map +1 -0
  61. package/dist/http/handlers/introspection/health.js +17 -0
  62. package/dist/http/handlers/introspection/health.js.map +1 -0
  63. package/dist/http/handlers/introspection/status.d.ts +26 -0
  64. package/dist/http/handlers/introspection/status.d.ts.map +1 -0
  65. package/dist/http/handlers/introspection/status.js +136 -0
  66. package/dist/http/handlers/introspection/status.js.map +1 -0
  67. package/dist/http/handlers/introspection/tools-list.d.ts +9 -0
  68. package/dist/http/handlers/introspection/tools-list.d.ts.map +1 -0
  69. package/dist/http/handlers/introspection/tools-list.js +28 -0
  70. package/dist/http/handlers/introspection/tools-list.js.map +1 -0
  71. package/dist/http/handlers/tools/audit.d.ts +4 -0
  72. package/dist/http/handlers/tools/audit.d.ts.map +1 -0
  73. package/dist/http/handlers/tools/audit.js +39 -0
  74. package/dist/http/handlers/tools/audit.js.map +1 -0
  75. package/dist/http/handlers/tools/debug.d.ts +4 -0
  76. package/dist/http/handlers/tools/debug.d.ts.map +1 -0
  77. package/dist/http/handlers/tools/debug.js +39 -0
  78. package/dist/http/handlers/tools/debug.js.map +1 -0
  79. package/dist/http/handlers/tools/delegate.d.ts +4 -0
  80. package/dist/http/handlers/tools/delegate.d.ts.map +1 -0
  81. package/dist/http/handlers/tools/delegate.js +57 -0
  82. package/dist/http/handlers/tools/delegate.js.map +1 -0
  83. package/dist/http/handlers/tools/execute-plan.d.ts +4 -0
  84. package/dist/http/handlers/tools/execute-plan.d.ts.map +1 -0
  85. package/dist/http/handlers/tools/execute-plan.js +39 -0
  86. package/dist/http/handlers/tools/execute-plan.js.map +1 -0
  87. package/dist/http/handlers/tools/retry.d.ts +4 -0
  88. package/dist/http/handlers/tools/retry.d.ts.map +1 -0
  89. package/dist/http/handlers/tools/retry.js +52 -0
  90. package/dist/http/handlers/tools/retry.js.map +1 -0
  91. package/dist/http/handlers/tools/review.d.ts +4 -0
  92. package/dist/http/handlers/tools/review.d.ts.map +1 -0
  93. package/dist/http/handlers/tools/review.js +39 -0
  94. package/dist/http/handlers/tools/review.js.map +1 -0
  95. package/dist/http/handlers/tools/verify.d.ts +4 -0
  96. package/dist/http/handlers/tools/verify.d.ts.map +1 -0
  97. package/dist/http/handlers/tools/verify.js +39 -0
  98. package/dist/http/handlers/tools/verify.js.map +1 -0
  99. package/dist/http/loopback.d.ts +17 -0
  100. package/dist/http/loopback.d.ts.map +1 -0
  101. package/dist/http/loopback.js +43 -0
  102. package/dist/http/loopback.js.map +1 -0
  103. package/dist/http/middleware/body-reader.d.ts +16 -0
  104. package/dist/http/middleware/body-reader.d.ts.map +1 -0
  105. package/dist/http/middleware/body-reader.js +44 -0
  106. package/dist/http/middleware/body-reader.js.map +1 -0
  107. package/dist/http/project-registry.d.ts +54 -0
  108. package/dist/http/project-registry.d.ts.map +1 -0
  109. package/dist/http/project-registry.js +132 -0
  110. package/dist/http/project-registry.js.map +1 -0
  111. package/dist/http/router.d.ts +14 -0
  112. package/dist/http/router.d.ts.map +1 -0
  113. package/dist/http/router.js +41 -0
  114. package/dist/http/router.js.map +1 -0
  115. package/dist/http/server.d.ts +16 -0
  116. package/dist/http/server.d.ts.map +1 -0
  117. package/dist/http/server.js +235 -0
  118. package/dist/http/server.js.map +1 -0
  119. package/dist/http/types.d.ts +9 -0
  120. package/dist/http/types.d.ts.map +1 -0
  121. package/dist/http/types.js +2 -0
  122. package/dist/http/types.js.map +1 -0
  123. package/dist/index.d.ts +2 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +2 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/install/claude-code.d.ts +43 -0
  128. package/dist/install/claude-code.d.ts.map +1 -0
  129. package/dist/install/claude-code.js +65 -0
  130. package/dist/install/claude-code.js.map +1 -0
  131. package/dist/install/codex-cli.d.ts +39 -0
  132. package/dist/install/codex-cli.d.ts.map +1 -0
  133. package/dist/install/codex-cli.js +318 -0
  134. package/dist/install/codex-cli.js.map +1 -0
  135. package/dist/install/cursor.d.ts +72 -0
  136. package/dist/install/cursor.d.ts.map +1 -0
  137. package/dist/install/cursor.js +81 -0
  138. package/dist/install/cursor.js.map +1 -0
  139. package/dist/install/gemini-cli.d.ts +66 -0
  140. package/dist/install/gemini-cli.d.ts.map +1 -0
  141. package/dist/install/gemini-cli.js +111 -0
  142. package/dist/install/gemini-cli.js.map +1 -0
  143. package/dist/install/include-utils.d.ts +27 -0
  144. package/dist/install/include-utils.d.ts.map +1 -0
  145. package/dist/install/include-utils.js +90 -0
  146. package/dist/install/include-utils.js.map +1 -0
  147. package/dist/install/manifest.d.ts +90 -0
  148. package/dist/install/manifest.d.ts.map +1 -0
  149. package/dist/install/manifest.js +200 -0
  150. package/dist/install/manifest.js.map +1 -0
  151. package/dist/openapi.d.ts +15 -0
  152. package/dist/openapi.d.ts.map +1 -0
  153. package/dist/openapi.js +314 -0
  154. package/dist/openapi.js.map +1 -0
  155. package/dist/skills/_shared/auth.md +32 -0
  156. package/dist/skills/_shared/error-handling.md +31 -0
  157. package/dist/skills/_shared/polling.md +40 -0
  158. package/dist/skills/_shared/response-shape.md +46 -0
  159. package/dist/skills/mma-audit/SKILL.md +55 -0
  160. package/dist/skills/mma-clarifications/SKILL.md +68 -0
  161. package/dist/skills/mma-context-blocks/SKILL.md +69 -0
  162. package/dist/skills/mma-debug/SKILL.md +59 -0
  163. package/dist/skills/mma-delegate/SKILL.md +63 -0
  164. package/dist/skills/mma-execute-plan/SKILL.md +63 -0
  165. package/dist/skills/mma-retry/SKILL.md +54 -0
  166. package/dist/skills/mma-review/SKILL.md +55 -0
  167. package/dist/skills/mma-verify/SKILL.md +57 -0
  168. package/dist/skills/multi-model-agent/SKILL.md +55 -0
  169. package/package.json +60 -0
@@ -0,0 +1,235 @@
1
+ import { createServer } from 'node:http';
2
+ import { readFileSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { join, dirname } from 'node:path';
5
+ import { Router } from './router.js';
6
+ import { sendError } from './errors.js';
7
+ import { readBody } from './middleware/body-reader.js';
8
+ import { loadToken, validateAuthHeader } from './auth.js';
9
+ import { validateCwd } from './cwd-validator.js';
10
+ import { isLoopbackAddress } from './loopback.js';
11
+ /** Server package version — read once at module load time from package.json. */
12
+ function readServerVersion() {
13
+ try {
14
+ const thisDir = dirname(fileURLToPath(import.meta.url));
15
+ // Walk up from src/http/ to packages/server/
16
+ const pkgPath = join(thisDir, '..', '..', 'package.json');
17
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
18
+ return pkg.version ?? '0.0.0';
19
+ }
20
+ catch {
21
+ return '0.0.0';
22
+ }
23
+ }
24
+ const SERVER_VERSION = readServerVersion();
25
+ /** Routes where the loopback guard is enforced. */
26
+ const LOOPBACK_ONLY_PATHS = new Set(['/health', '/status']);
27
+ /** Routes that do NOT require bearer auth. */
28
+ const AUTH_EXEMPT_PATHS = new Set(['/health']);
29
+ /** Routes that require a `cwd` query parameter (validated by cwd-validator middleware). */
30
+ const CWD_REQUIRED_PATHS = new Set([
31
+ '/delegate', '/audit', '/review', '/verify', '/debug', '/execute-plan', '/retry',
32
+ '/context-blocks',
33
+ ]);
34
+ /**
35
+ * Registers tool handlers (POST /delegate, /audit, /review, /verify, /debug, /execute-plan, /retry).
36
+ * Imported dynamically to avoid circular-dependency issues and to keep startServer lean.
37
+ */
38
+ async function registerToolHandlers(router, config, batchRegistry, projectRegistry) {
39
+ const { buildDelegateHandler } = await import('./handlers/tools/delegate.js');
40
+ const { buildAuditHandler } = await import('./handlers/tools/audit.js');
41
+ const { buildReviewHandler } = await import('./handlers/tools/review.js');
42
+ const { buildVerifyHandler } = await import('./handlers/tools/verify.js');
43
+ const { buildDebugHandler } = await import('./handlers/tools/debug.js');
44
+ const { buildExecutePlanHandler } = await import('./handlers/tools/execute-plan.js');
45
+ const { buildRetryHandler } = await import('./handlers/tools/retry.js');
46
+ const { createDiagnosticLogger } = await import('@zhixuan92/multi-model-agent-core');
47
+ const logger = createDiagnosticLogger({ enabled: false });
48
+ // For tool handlers, we need MultiModelConfig which is part of ServerConfig only
49
+ // when the full mmagent.config.json is loaded. In test/minimal configs that only
50
+ // have `server:`, we create a stub config. Real CLI startup will load full config.
51
+ // Cast through unknown to avoid type gymnastics here; validation happens in schema.
52
+ const multiModelConfig = config.agents
53
+ ? config
54
+ : undefined;
55
+ if (!multiModelConfig) {
56
+ // Server started with server-only config (e.g. tests): register stubs that return 503
57
+ for (const [method, path] of [
58
+ ['POST', '/delegate'], ['POST', '/audit'], ['POST', '/review'],
59
+ ['POST', '/verify'], ['POST', '/debug'], ['POST', '/execute-plan'], ['POST', '/retry'],
60
+ ]) {
61
+ router.register(method, path, (_req, res, _params, _ctx) => {
62
+ sendError(res, 503, 'no_agent_config', 'Server started without agent configuration; provide a full mmagent.config.json');
63
+ });
64
+ }
65
+ return;
66
+ }
67
+ const deps = {
68
+ config: multiModelConfig,
69
+ logger,
70
+ projectRegistry,
71
+ batchRegistry,
72
+ };
73
+ router.register('POST', '/delegate', buildDelegateHandler(deps));
74
+ router.register('POST', '/audit', buildAuditHandler(deps));
75
+ router.register('POST', '/review', buildReviewHandler(deps));
76
+ router.register('POST', '/verify', buildVerifyHandler(deps));
77
+ router.register('POST', '/debug', buildDebugHandler(deps));
78
+ router.register('POST', '/execute-plan', buildExecutePlanHandler(deps));
79
+ router.register('POST', '/retry', buildRetryHandler(deps));
80
+ }
81
+ /**
82
+ * Registers control handlers (GET /batch/:batchId, POST/DELETE /context-blocks,
83
+ * POST /clarifications/confirm).
84
+ */
85
+ async function registerControlHandlers(router, config, batchRegistry, projectRegistry) {
86
+ const { buildBatchHandler } = await import('./handlers/control/batch.js');
87
+ const { buildCreateContextBlockHandler, buildDeleteContextBlockHandler } = await import('./handlers/control/context-blocks.js');
88
+ const { buildClarificationsHandler } = await import('./handlers/control/clarifications.js');
89
+ router.register('GET', '/batch/:batchId', buildBatchHandler({ batchRegistry }));
90
+ router.register('POST', '/context-blocks', buildCreateContextBlockHandler({ projectRegistry, config }));
91
+ router.register('DELETE', '/context-blocks/:blockId', buildDeleteContextBlockHandler({ projectRegistry }));
92
+ router.register('POST', '/clarifications/confirm', buildClarificationsHandler({ batchRegistry }));
93
+ }
94
+ export async function startServer(config) {
95
+ const token = loadToken(config.server.auth.tokenFile);
96
+ const router = new Router();
97
+ // ── Create shared registries ───────────────────────────────────────────────
98
+ const { BatchRegistry } = await import('@zhixuan92/multi-model-agent-core');
99
+ const { ProjectRegistry } = await import('./project-registry.js');
100
+ const batchRegistry = new BatchRegistry({
101
+ batchTtlMs: config.server.limits.batchTtlMs,
102
+ clarificationTimeoutMs: config.server.limits.clarificationTimeoutMs,
103
+ });
104
+ const projectRegistry = new ProjectRegistry({
105
+ cap: config.server.limits.projectCap,
106
+ idleEvictionMs: config.server.limits.idleProjectTimeoutMs,
107
+ evictionIntervalMs: Math.min(config.server.limits.idleProjectTimeoutMs, 60_000),
108
+ });
109
+ // GET /health — lightweight liveness probe (extracted to handler module)
110
+ const { buildHealthHandler } = await import('./handlers/introspection/health.js');
111
+ router.register('GET', '/health', buildHealthHandler());
112
+ // Register tool handlers (Phase 6)
113
+ await registerToolHandlers(router, config, batchRegistry, projectRegistry);
114
+ // Register control handlers (Phase 7)
115
+ await registerControlHandlers(router, config, batchRegistry, projectRegistry);
116
+ // GET /status — operator introspection (registered after registries are ready)
117
+ // Capture serverStartedAt now (after all setup, before listen) so uptimeMs reflects
118
+ // time since the server was fully initialised.
119
+ const serverStartedAt = Date.now();
120
+ const { buildStatusHandler } = await import('./handlers/introspection/status.js');
121
+ router.register('GET', '/status', buildStatusHandler({
122
+ batchRegistry,
123
+ projectRegistry,
124
+ serverStartedAt,
125
+ bind: config.server.bind,
126
+ version: SERVER_VERSION,
127
+ }));
128
+ // GET /tools — OpenAPI 3.0 document (auth required, NOT loopback-gated)
129
+ const { buildToolsHandler } = await import('./handlers/introspection/tools-list.js');
130
+ router.register('GET', '/tools', buildToolsHandler());
131
+ const server = createServer((req, res) => {
132
+ void handleRequest(router, token, req, res, config);
133
+ });
134
+ await new Promise((resolve) => {
135
+ server.listen(config.server.port, config.server.bind, resolve);
136
+ });
137
+ const addr = server.address();
138
+ const port = addr.port;
139
+ const serverAddress = typeof addr === 'object' && addr !== null ? addr.address ?? null : null;
140
+ return {
141
+ port,
142
+ serverAddress,
143
+ stop: () => new Promise((resolve) => server.close(() => resolve())),
144
+ batchRegistry,
145
+ projectRegistry,
146
+ serverStartedAt,
147
+ };
148
+ }
149
+ const BODY_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
150
+ async function handleRequest(router, token, req, res, cfg) {
151
+ const method = req.method ?? 'GET';
152
+ const rawUrl = req.url ?? '/';
153
+ // ── Step 1: Body size cap (for methods that carry a body) ──────────────────
154
+ let rawBody;
155
+ if (BODY_METHODS.has(method)) {
156
+ const result = await readBody(req, cfg.server.limits.maxBodyBytes);
157
+ if (!result.ok) {
158
+ // Send 413 then close; include Connection: close so the client knows
159
+ res.writeHead(413, { 'content-type': 'application/json', 'connection': 'close' });
160
+ res.end(JSON.stringify({ error: { code: 'payload_too_large', message: `Request body exceeds the ${cfg.server.limits.maxBodyBytes}-byte limit` } }), () => { req.socket?.destroy(); });
161
+ return;
162
+ }
163
+ rawBody = result.body;
164
+ }
165
+ // ── Step 2: Route match (404 not_found / 405 method_not_allowed) ──────────
166
+ const match = router.match(method, rawUrl);
167
+ if (!match) {
168
+ const allowed = router.methodsFor(rawUrl);
169
+ if (allowed.length > 0) {
170
+ sendError(res, 405, 'method_not_allowed', `Method ${method} not allowed`, { allowed });
171
+ }
172
+ else {
173
+ sendError(res, 404, 'not_found', `Unknown path ${rawUrl.split('?')[0]}`);
174
+ }
175
+ return;
176
+ }
177
+ // ── Step 3: Loopback guard for /health and /status ────────────────────────
178
+ const pathname = rawUrl.split('?')[0];
179
+ if (LOOPBACK_ONLY_PATHS.has(pathname)) {
180
+ const remoteAddr = req.socket?.remoteAddress;
181
+ if (!isLoopbackAddress(remoteAddr)) {
182
+ sendError(res, 403, 'loopback_only', 'This endpoint is only accessible from the loopback interface');
183
+ return;
184
+ }
185
+ }
186
+ // ── Step 4: Auth (bearer token) — skip for /health ───────────────────────
187
+ if (!AUTH_EXEMPT_PATHS.has(pathname)) {
188
+ const header = req.headers['authorization'];
189
+ const authResult = validateAuthHeader(header, token);
190
+ if (!authResult.ok) {
191
+ sendError(res, 401, 'unauthorized', 'Valid Bearer token required');
192
+ return;
193
+ }
194
+ }
195
+ // ── Step 5: JSON parse → ctx.body ────────────────────────────────────────
196
+ let parsedBody;
197
+ if (rawBody !== undefined && rawBody.length > 0) {
198
+ try {
199
+ parsedBody = JSON.parse(rawBody.toString('utf8'));
200
+ }
201
+ catch {
202
+ sendError(res, 400, 'invalid_json', 'Request body is not valid JSON');
203
+ return;
204
+ }
205
+ }
206
+ // ── Step 6: cwd query param → validate → ctx.cwd ─────────────────────────
207
+ // cwd is required for tool routes and context-block routes.
208
+ // /batch/:batchId and /clarifications/confirm do NOT require cwd.
209
+ let cwdValue;
210
+ const urlObj = new URL(rawUrl, 'http://localhost');
211
+ // Match against pathname prefix patterns for cwd-required routes
212
+ const requiresCwd = CWD_REQUIRED_PATHS.has(pathname) ||
213
+ pathname === '/context-blocks' ||
214
+ /^\/context-blocks\//.test(pathname);
215
+ if (requiresCwd) {
216
+ const cwdParam = urlObj.searchParams.get('cwd') ?? undefined;
217
+ const cwdResult = validateCwd(cwdParam);
218
+ if (!cwdResult.ok) {
219
+ const statusCode = cwdResult.error === 'forbidden_cwd' ? 403 : 400;
220
+ sendError(res, statusCode, cwdResult.error, cwdResult.message);
221
+ return;
222
+ }
223
+ cwdValue = cwdResult.canonicalCwd;
224
+ }
225
+ // ── Steps 7-9: Zod validation, project registry, and handler run ──────────
226
+ // These happen inside each handler (Phase 6+).
227
+ const ctx = {
228
+ url: urlObj,
229
+ cwd: cwdValue,
230
+ body: parsedBody,
231
+ authed: !AUTH_EXEMPT_PATHS.has(pathname),
232
+ };
233
+ await match.handler(req, res, match.params, ctx);
234
+ }
235
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/http/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ServerResponse } from 'node:http';
2
+ export interface RequestContext {
3
+ url: URL;
4
+ cwd?: string;
5
+ body?: unknown;
6
+ authed: boolean;
7
+ }
8
+ export type Handler = (ctx: RequestContext, res: ServerResponse, params: Record<string, string>) => Promise<void> | void;
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/http/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/http/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Options for installing a Claude Code skill.
3
+ */
4
+ export interface ClaudeCodeInstallOpts {
5
+ /** Human-readable name of the skill (used in file path). */
6
+ skillName: string;
7
+ /**
8
+ * Raw skill content. May contain `@include _shared/<file>.md` directives
9
+ * which are inlined before writing.
10
+ */
11
+ content: string;
12
+ /**
13
+ * Home directory — replaces `os.homedir()` in all file operations.
14
+ * Must NOT default to `os.homedir()`.
15
+ */
16
+ homeDir: string;
17
+ /** Root of the skills directory for @include resolution. */
18
+ skillsRoot: string;
19
+ }
20
+ /**
21
+ * Write (or overwrite) the SKILL.md file for a Claude Code skill.
22
+ *
23
+ * Target path: `<homeDir>/.claude/skills/<skillName>/SKILL.md`
24
+ *
25
+ * @param opts Installation options (see `ClaudeCodeInstallOpts`).
26
+ */
27
+ export declare function installClaudeCode(opts: ClaudeCodeInstallOpts): void;
28
+ /**
29
+ * Uninstall a Claude Code skill by removing its directory.
30
+ *
31
+ * Target: `<homeDir>/.claude/skills/<skillName>/`
32
+ *
33
+ * Security: `skillName` is validated against the expected skills directory
34
+ * boundary to prevent path traversal (e.g. `../other-dir`). If `skillName`
35
+ * resolves outside the skills directory, the function is a no-op.
36
+ *
37
+ * This is also a no-op when the directory does not exist (no error is thrown).
38
+ *
39
+ * @param skillName Name of the skill to uninstall.
40
+ * @param homeDir Home directory where the skill directory lives.
41
+ */
42
+ export declare function uninstallClaudeCode(skillName: string, homeDir: string): void;
43
+ //# sourceMappingURL=claude-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"AAsBA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAUnE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAe5E"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Claude Code skill writer for install-skill.
3
+ *
4
+ * Writes each skill's SKILL.md to `<homeDir>/.claude/skills/<skillName>/SKILL.md`.
5
+ *
6
+ * Before writing, inlines any `@include _shared/<file>.md` directives found in
7
+ * the content. The directive line is replaced with the full content of the
8
+ * corresponding shared file sourced from `<skillsRoot>/_shared/<file>.md`.
9
+ * The `@include` directive is NOT preserved in the written file.
10
+ *
11
+ * If a referenced shared file is missing (ENOENT):
12
+ * - A warning is logged to stderr.
13
+ * - The include line is removed from the output (not preserved).
14
+ * - Processing continues for remaining content.
15
+ *
16
+ * @module
17
+ */
18
+ import fs from 'node:fs';
19
+ import path from 'node:path';
20
+ import { inlineIncludes } from './include-utils.js';
21
+ /**
22
+ * Write (or overwrite) the SKILL.md file for a Claude Code skill.
23
+ *
24
+ * Target path: `<homeDir>/.claude/skills/<skillName>/SKILL.md`
25
+ *
26
+ * @param opts Installation options (see `ClaudeCodeInstallOpts`).
27
+ */
28
+ export function installClaudeCode(opts) {
29
+ const { skillName, content, homeDir, skillsRoot } = opts;
30
+ // Inline @include directives before writing
31
+ const inlinedContent = inlineIncludes('Claude Code skill writer', content, skillsRoot);
32
+ // Determine target path: <homeDir>/.claude/skills/<skillName>/SKILL.md
33
+ const skillDir = path.join(homeDir, '.claude', 'skills', skillName);
34
+ fs.mkdirSync(skillDir, { recursive: true });
35
+ fs.writeFileSync(path.join(skillDir, 'SKILL.md'), inlinedContent, 'utf-8');
36
+ }
37
+ /**
38
+ * Uninstall a Claude Code skill by removing its directory.
39
+ *
40
+ * Target: `<homeDir>/.claude/skills/<skillName>/`
41
+ *
42
+ * Security: `skillName` is validated against the expected skills directory
43
+ * boundary to prevent path traversal (e.g. `../other-dir`). If `skillName`
44
+ * resolves outside the skills directory, the function is a no-op.
45
+ *
46
+ * This is also a no-op when the directory does not exist (no error is thrown).
47
+ *
48
+ * @param skillName Name of the skill to uninstall.
49
+ * @param homeDir Home directory where the skill directory lives.
50
+ */
51
+ export function uninstallClaudeCode(skillName, homeDir) {
52
+ const skillsBase = path.resolve(homeDir, '.claude', 'skills');
53
+ // Security: validate skillName does not escape the skills directory.
54
+ // Normalize skillName and verify the resolved path stays within the base.
55
+ const normalizedName = path.normalize(skillName);
56
+ const resolvedSkillDir = path.resolve(skillsBase, normalizedName);
57
+ const baseResolved = skillsBase + path.sep;
58
+ if (!resolvedSkillDir.startsWith(baseResolved)) {
59
+ // skillName traversal attempt — no-op rather than throwing, matching
60
+ // the "no error when directory does not exist" behaviour.
61
+ return;
62
+ }
63
+ fs.rmSync(resolvedSkillDir, { recursive: true, force: true });
64
+ }
65
+ //# sourceMappingURL=claude-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAsBpD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA2B;IAC3D,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAEzD,4CAA4C;IAC5C,MAAM,cAAc,GAAG,cAAc,CAAC,0BAA0B,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAEvF,uEAAuE;IACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACpE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,OAAe;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAE9D,qEAAqE;IACrE,0EAA0E;IAC1E,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC;IAC3C,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/C,qEAAqE;QACrE,0DAA0D;QAC1D,OAAO;IACT,CAAC;IAED,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,39 @@
1
+ export interface CodexCliInstallOpts {
2
+ /** Human-readable name of the skill (used in warning messages). */
3
+ skillName: string;
4
+ /** Raw skill content (may contain @include directives). */
5
+ content: string;
6
+ /**
7
+ * Home directory — replaces `os.homedir()` in all file operations.
8
+ * Must NOT default to `os.homedir()`.
9
+ */
10
+ homeDir: string;
11
+ /** Root of the skills directory for @include resolution. */
12
+ skillsRoot: string;
13
+ }
14
+ /**
15
+ * Write (or overwrite) the managed block in the Codex CLI's AGENTS.md.
16
+ *
17
+ * The algorithm:
18
+ * 1. Inline @include directives.
19
+ * 2. Read existing file if present.
20
+ * 3. Determine new content: create / append / replace.
21
+ * 4. Write to disk.
22
+ *
23
+ * @throws If the AGENTS.md file exists but cannot be read.
24
+ * @throws If the AGENTS.md path is a directory.
25
+ */
26
+ export declare function installCodexCli(opts: CodexCliInstallOpts): void;
27
+ /**
28
+ * Remove the managed block (including markers) from AGENTS.md.
29
+ *
30
+ * Behaviour:
31
+ * - File does not exist → no-op.
32
+ * - File has no managed block markers → no-op (file unchanged).
33
+ * - File has managed block → remove it; write remaining content back.
34
+ * - Remaining content is empty or whitespace-only → delete the file.
35
+ *
36
+ * @throws On filesystem errors other than ENOENT when reading/writing.
37
+ */
38
+ export declare function uninstallCodexCli(homeDir: string): void;
39
+ //# sourceMappingURL=codex-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-cli.d.ts","sourceRoot":"","sources":["../../src/install/codex-cli.ts"],"names":[],"mappings":"AAgDA,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAmLD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAiE/D;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CA2CvD"}