@obov/mext 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/build.js +16 -2
  2. package/dist/build.js.map +1 -1
  3. package/dist/cli/args.js +1 -2
  4. package/dist/cli/args.js.map +1 -1
  5. package/dist/cli/build.js +22 -2
  6. package/dist/cli/build.js.map +1 -1
  7. package/dist/cli/dev-server.js +3 -2
  8. package/dist/cli/dev-server.js.map +1 -1
  9. package/dist/cli/dev.d.ts +6 -0
  10. package/dist/cli/dev.js +4 -4
  11. package/dist/cli/dev.js.map +1 -1
  12. package/dist/cli/main.js +2 -0
  13. package/dist/cli/main.js.map +1 -1
  14. package/dist/cli/media.d.ts +19 -0
  15. package/dist/cli/media.js +77 -0
  16. package/dist/cli/media.js.map +1 -0
  17. package/dist/cli/run.js +5 -0
  18. package/dist/cli/run.js.map +1 -1
  19. package/dist/cli/serve.d.ts +10 -0
  20. package/dist/cli/serve.js +114 -0
  21. package/dist/cli/serve.js.map +1 -0
  22. package/dist/client/index.d.ts +2 -1
  23. package/dist/client/index.js.map +1 -1
  24. package/dist/client/runner.js +3 -0
  25. package/dist/client/runner.js.map +1 -1
  26. package/dist/client/typed.d.ts +3 -1
  27. package/dist/client/typed.js +39 -3
  28. package/dist/client/typed.js.map +1 -1
  29. package/dist/client/types.d.ts +31 -2
  30. package/dist/client/types.js.map +1 -1
  31. package/dist/config.d.ts +17 -0
  32. package/dist/config.js +36 -1
  33. package/dist/config.js.map +1 -1
  34. package/dist/content.d.ts +65 -0
  35. package/dist/content.js +99 -0
  36. package/dist/content.js.map +1 -0
  37. package/dist/index.d.ts +3 -1
  38. package/dist/index.js +1 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/invoke.d.ts +4 -0
  41. package/dist/invoke.js +12 -5
  42. package/dist/invoke.js.map +1 -1
  43. package/dist/manifest.d.ts +6 -1
  44. package/dist/manifest.js.map +1 -1
  45. package/dist/mcp/constants.d.ts +2 -0
  46. package/dist/mcp/constants.js +2 -0
  47. package/dist/mcp/constants.js.map +1 -1
  48. package/dist/mcp/dispatch.d.ts +9 -3
  49. package/dist/mcp/dispatch.js +10 -4
  50. package/dist/mcp/dispatch.js.map +1 -1
  51. package/dist/mcp/host.d.ts +14 -0
  52. package/dist/mcp/host.js +48 -0
  53. package/dist/mcp/host.js.map +1 -0
  54. package/dist/mcp/http.d.ts +22 -5
  55. package/dist/mcp/http.js +125 -18
  56. package/dist/mcp/http.js.map +1 -1
  57. package/dist/mcp/index.d.ts +1 -0
  58. package/dist/mcp/index.js +1 -0
  59. package/dist/mcp/index.js.map +1 -1
  60. package/dist/mcp/tasks.js +1 -1
  61. package/dist/mcp/tasks.js.map +1 -1
  62. package/dist/remote/client.d.ts +24 -1
  63. package/dist/remote/client.js +177 -53
  64. package/dist/remote/client.js.map +1 -1
  65. package/dist/remote/index.d.ts +1 -1
  66. package/dist/remote/index.js.map +1 -1
  67. package/dist/route.d.ts +40 -2
  68. package/dist/route.js +128 -8
  69. package/dist/route.js.map +1 -1
  70. package/dist/start.js +3 -2
  71. package/dist/start.js.map +1 -1
  72. package/dist/version-constant.d.ts +1 -1
  73. package/dist/version-constant.js +1 -1
  74. package/dist/version-constant.js.map +1 -1
  75. package/package.json +1 -1
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { createServer } from "node:http";
7
7
  import { relative } from "node:path";
8
- import { loadConfig, mcpDeclarations, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from "../config.js";
8
+ import { httpServerOptions, loadConfig, mcpDeclarations, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from "../config.js";
9
9
  import { loadProjectInstrumentation } from "../instrumentation.js";
10
10
  import { createMcpHttpHandler } from "../mcp/http.js";
11
11
  import { loadPromptSet, withPrompts } from "../prompt.js";
@@ -57,10 +57,11 @@ async function main() {
57
57
  ...(config.auth ? { auth: config.auth } : {}),
58
58
  ...(config.tools ? { tools: config.tools } : {}),
59
59
  ...(config.oauth ? { oauth: config.oauth } : {}),
60
+ ...(config.routes ? { routeDefaults: config.routes } : {}),
60
61
  ...(routes.length > 0 ? { routes } : {}),
61
62
  ...mcpDeclarations(config),
62
63
  audit: tapped.audit,
63
- server: config.server?.allowedOrigins ? { allowedOrigins: config.server.allowedOrigins } : {},
64
+ server: httpServerOptions(config),
64
65
  onerror: (error) => process.stderr.write(`mcp: ${error.message}\n`),
65
66
  });
66
67
  const server = createServer(listener);
@@ -1 +1 @@
1
- {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../src/cli/dev-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mext dev 의 서버 자식 프로세스 엔트리 (cli/dev.ts 가 fork). 직접 실행하지 않는다.\n * cwd 의 mext.config.ts · commands/ 를 로드해 127.0.0.1 임의 포트에서 MCP HTTP 처리기를 띄우고 IPC 로 보고한다.\n * 요청은 감독 프로세스 (부모) 가 받아 이 포트로 중계한다. 부모 IPC 가 끊기면 종료.\n */\nimport { createServer } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport { relative } from \"node:path\"\nimport type { AuditEvent } from \"../audit.ts\"\nimport { loadConfig, mcpDeclarations, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from \"../config.ts\"\nimport { loadProjectInstrumentation } from \"../instrumentation.ts\"\nimport { createMcpHttpHandler } from \"../mcp/http.ts\"\nimport { loadPromptSet, withPrompts } from \"../prompt.ts\"\nimport { loadResourceSet, withResources } from \"../resource.ts\"\nimport { loadRoutes } from \"../route.ts\"\nimport { loadRegistry } from \"../scan.ts\"\nimport { resolveTypesPath, writeTypes } from \"../typegen.ts\"\nimport { tapAudit } from \"./dev-tap.ts\"\n\n/** 자식 → 부모 */\nexport type DevChildMessage =\n | { type: \"error\"; message: string }\n /** 감사 tap (spec §10): 호출 1건의 감사 이벤트 */\n | { type: \"audit\"; event: AuditEvent }\n| {\n type: \"config\"\n commandsDir: string\n routesDir: string\n /** 감시 대상 (§10). resources/ · prompts/ */\n resourcesDir: string\n promptsDir: string\n server: { host?: string; port?: number }\n }\n | { type: \"ready\"; port: number; commands: number }\n | { type: \"error\"; message: string }\n\n/** 부모 → 자식. retire = 새 자식으로 교체됨 (listen 스트림을 닫고 진행 중 요청은 끝까지), shutdown = 종료 */\nexport type DevParentMessage = { type: \"shutdown\" } | { type: \"retire\" }\n\nconst send = (message: DevChildMessage): Promise<void> =>\n new Promise((resolve) => {\n if (!process.connected) return resolve()\n process.send!(message, undefined, {}, () => resolve())\n })\n\n// 터미널 Ctrl-C 는 프로세스 그룹 전체에 간다. 종료는 부모가 정한다 (shutdown · IPC 끊김)\nprocess.on(\"SIGINT\", () => {})\nprocess.on(\"disconnect\", () => process.exit(0))\n\nasync function main(): Promise<void> {\n const cwd = process.cwd()\n // register() = 명령어 · config import 전\n const instrumentation = await loadProjectInstrumentation(cwd)\n const config = await loadConfig(cwd)\n const commandsDir = resolveCommandsDir(cwd, config)\n const routesDir = resolveRoutesDir(cwd, config)\n const resourcesDir = resolveResourcesDir(cwd, config)\n const promptsDir = resolvePromptsDir(cwd, config)\n await send({\n type: \"config\",\n commandsDir,\n routesDir,\n resourcesDir,\n promptsDir,\n server: {\n ...(config.server?.host !== undefined ? { host: config.server.host } : {}),\n ...(config.server?.port !== undefined ? { port: config.server.port } : {}),\n },\n })\n const registry = withPrompts(\n withResources(await loadRegistry(commandsDir), await loadResourceSet(resourcesDir)),\n await loadPromptSet(promptsDir),\n )\n const routes = await loadRoutes(routesDir)\n generateTypes(cwd, config.types, commandsDir)\n // 감사 tap: 모든 호출의 이벤트를 감독 프로세스로 (전달을 기다리지 않는다). 프로젝트 audit 설정의 동작은 그대로\n const tapped = tapAudit(registry, config.audit, (event) => {\n if (process.connected) process.send!({ type: \"audit\", event } satisfies DevChildMessage, undefined, {}, () => {})\n })\n const listener = createMcpHttpHandler({\n registry: tapped.registry,\n instrumentation,\n ...(config.app ? { app: config.app } : {}),\n ...(config.auth ? { auth: config.auth } : {}),\n ...(config.tools ? { tools: config.tools } : {}),\n ...(config.oauth ? { oauth: config.oauth } : {}),\n ...(routes.length > 0 ? { routes } : {}),\n ...mcpDeclarations(config),\n audit: tapped.audit,\n server: config.server?.allowedOrigins ? { allowedOrigins: config.server.allowedOrigins } : {},\n onerror: (error) => process.stderr.write(`mcp: ${error.message}\\n`),\n })\n const server = createServer(listener)\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(0, \"127.0.0.1\", () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n process.on(\"message\", (message: DevParentMessage) => {\n if (message?.type === \"retire\") void listener.closeSubscriptions()\n if (message?.type !== \"shutdown\") return\n void listener.close().finally(() => {\n server.closeAllConnections()\n server.close(() => process.exit(0))\n })\n })\n await send({ type: \"ready\", port: (server.address() as AddressInfo).port, commands: registry.commands.size })\n}\n\nmain().catch(async (error: unknown) => {\n await send({ type: \"error\", message: describeLoadError(error) })\n process.exit(1)\n})\n\n/** 명령어 타입 생성 (config.types, specs/client.md §4). 실패 = stderr 1줄 (서버는 계속) */\nfunction generateTypes(cwd: string, types: boolean | string | undefined, commandsDir: string): void {\n const out = resolveTypesPath(cwd, types)\n if (out === undefined) return\n try {\n if (writeTypes(commandsDir, out).changed) process.stderr.write(`mext dev: wrote ${relative(cwd, out) || out}\\n`)\n } catch (error) {\n process.stderr.write(`mext dev: cannot write command types (${error instanceof Error ? error.message : String(error)})\\n`)\n }\n}\n\n/** SyntaxError 는 stack 첫 줄들에 파일 위치가 있다 (ESM 파싱 오류). 그 외는 message (MextBuildError = issue 목록) */\nfunction describeLoadError(error: unknown): string {\n if (error instanceof SyntaxError && error.stack) {\n const at = error.stack.indexOf(\"\\n at \")\n return (at < 0 ? error.stack : error.stack.slice(0, at)).trim()\n }\n return error instanceof Error ? error.message : String(error)\n}\n"]}
1
+ {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../src/cli/dev-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * mext dev 의 서버 자식 프로세스 엔트리 (cli/dev.ts 가 fork). 직접 실행하지 않는다.\n * cwd 의 mext.config.ts · commands/ 를 로드해 127.0.0.1 임의 포트에서 MCP HTTP 처리기를 띄우고 IPC 로 보고한다.\n * 요청은 감독 프로세스 (부모) 가 받아 이 포트로 중계한다. 부모 IPC 가 끊기면 종료.\n */\nimport { createServer } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport { relative } from \"node:path\"\nimport type { AuditEvent } from \"../audit.ts\"\nimport { httpServerOptions, loadConfig, mcpDeclarations, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from \"../config.ts\"\nimport { loadProjectInstrumentation } from \"../instrumentation.ts\"\nimport { createMcpHttpHandler } from \"../mcp/http.ts\"\nimport { loadPromptSet, withPrompts } from \"../prompt.ts\"\nimport { loadResourceSet, withResources } from \"../resource.ts\"\nimport { loadRoutes } from \"../route.ts\"\nimport { loadRegistry } from \"../scan.ts\"\nimport { resolveTypesPath, writeTypes } from \"../typegen.ts\"\nimport { tapAudit } from \"./dev-tap.ts\"\n\n/** 자식 → 부모 */\nexport type DevChildMessage =\n | { type: \"error\"; message: string }\n /** 감사 tap (spec §10): 호출 1건의 감사 이벤트 */\n | { type: \"audit\"; event: AuditEvent }\n| {\n type: \"config\"\n commandsDir: string\n routesDir: string\n /** 감시 대상 (§10). resources/ · prompts/ */\n resourcesDir: string\n promptsDir: string\n server: { host?: string; port?: number }\n }\n | { type: \"ready\"; port: number; commands: number }\n | { type: \"error\"; message: string }\n\n/** 부모 → 자식. retire = 새 자식으로 교체됨 (listen 스트림을 닫고 진행 중 요청은 끝까지), shutdown = 종료 */\nexport type DevParentMessage = { type: \"shutdown\" } | { type: \"retire\" }\n\nconst send = (message: DevChildMessage): Promise<void> =>\n new Promise((resolve) => {\n if (!process.connected) return resolve()\n process.send!(message, undefined, {}, () => resolve())\n })\n\n// 터미널 Ctrl-C 는 프로세스 그룹 전체에 간다. 종료는 부모가 정한다 (shutdown · IPC 끊김)\nprocess.on(\"SIGINT\", () => {})\nprocess.on(\"disconnect\", () => process.exit(0))\n\nasync function main(): Promise<void> {\n const cwd = process.cwd()\n // register() = 명령어 · config import 전\n const instrumentation = await loadProjectInstrumentation(cwd)\n const config = await loadConfig(cwd)\n const commandsDir = resolveCommandsDir(cwd, config)\n const routesDir = resolveRoutesDir(cwd, config)\n const resourcesDir = resolveResourcesDir(cwd, config)\n const promptsDir = resolvePromptsDir(cwd, config)\n await send({\n type: \"config\",\n commandsDir,\n routesDir,\n resourcesDir,\n promptsDir,\n server: {\n ...(config.server?.host !== undefined ? { host: config.server.host } : {}),\n ...(config.server?.port !== undefined ? { port: config.server.port } : {}),\n },\n })\n const registry = withPrompts(\n withResources(await loadRegistry(commandsDir), await loadResourceSet(resourcesDir)),\n await loadPromptSet(promptsDir),\n )\n const routes = await loadRoutes(routesDir)\n generateTypes(cwd, config.types, commandsDir)\n // 감사 tap: 모든 호출의 이벤트를 감독 프로세스로 (전달을 기다리지 않는다). 프로젝트 audit 설정의 동작은 그대로\n const tapped = tapAudit(registry, config.audit, (event) => {\n if (process.connected) process.send!({ type: \"audit\", event } satisfies DevChildMessage, undefined, {}, () => {})\n })\n const listener = createMcpHttpHandler({\n registry: tapped.registry,\n instrumentation,\n ...(config.app ? { app: config.app } : {}),\n ...(config.auth ? { auth: config.auth } : {}),\n ...(config.tools ? { tools: config.tools } : {}),\n ...(config.oauth ? { oauth: config.oauth } : {}),\n ...(config.routes ? { routeDefaults: config.routes } : {}),\n ...(routes.length > 0 ? { routes } : {}),\n ...mcpDeclarations(config),\n audit: tapped.audit,\n server: httpServerOptions(config),\n onerror: (error) => process.stderr.write(`mcp: ${error.message}\\n`),\n })\n const server = createServer(listener)\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(0, \"127.0.0.1\", () => {\n server.off(\"error\", reject)\n resolve()\n })\n })\n process.on(\"message\", (message: DevParentMessage) => {\n if (message?.type === \"retire\") void listener.closeSubscriptions()\n if (message?.type !== \"shutdown\") return\n void listener.close().finally(() => {\n server.closeAllConnections()\n server.close(() => process.exit(0))\n })\n })\n await send({ type: \"ready\", port: (server.address() as AddressInfo).port, commands: registry.commands.size })\n}\n\nmain().catch(async (error: unknown) => {\n await send({ type: \"error\", message: describeLoadError(error) })\n process.exit(1)\n})\n\n/** 명령어 타입 생성 (config.types, specs/client.md §4). 실패 = stderr 1줄 (서버는 계속) */\nfunction generateTypes(cwd: string, types: boolean | string | undefined, commandsDir: string): void {\n const out = resolveTypesPath(cwd, types)\n if (out === undefined) return\n try {\n if (writeTypes(commandsDir, out).changed) process.stderr.write(`mext dev: wrote ${relative(cwd, out) || out}\\n`)\n } catch (error) {\n process.stderr.write(`mext dev: cannot write command types (${error instanceof Error ? error.message : String(error)})\\n`)\n }\n}\n\n/** SyntaxError 는 stack 첫 줄들에 파일 위치가 있다 (ESM 파싱 오류). 그 외는 message (MextBuildError = issue 목록) */\nfunction describeLoadError(error: unknown): string {\n if (error instanceof SyntaxError && error.stack) {\n const at = error.stack.indexOf(\"\\n at \")\n return (at < 0 ? error.stack : error.stack.slice(0, at)).trim()\n }\n return error instanceof Error ? error.message : String(error)\n}\n"]}
package/dist/cli/dev.d.ts CHANGED
@@ -17,5 +17,11 @@ interface DevArgs {
17
17
  }
18
18
  /** 반환 문자열 = 사용법 오류 메시지 */
19
19
  export declare function parseDevArgs(argv: readonly string[]): DevArgs | string;
20
+ /**
21
+ * stdio (mext dev --stdio · mext serve --stdio): stdout = MCP 메시지만. D4: 이 프로세스의 그 외 stdout 쓰기 (console.log · process.stdout.write) 는
22
+ * 명령어 import 전부터 종료까지 stderr 로 돌린다. stdin EOF = 연결 종료 → 바로 반환 (bin 이 exit).
23
+ * 감시 · 잠금 없음: MCP 클라이언트가 프로세스를 소유 · 재실행한다
24
+ */
25
+ export declare function sourceStdio(io: CliIo, prog?: string): Promise<number>;
20
26
  export declare function devHelp(): string;
21
27
  export {};
package/dist/cli/dev.js CHANGED
@@ -35,7 +35,7 @@ export async function devCommand(argv, io) {
35
35
  return EXIT.ok;
36
36
  }
37
37
  if (parsed.stdio)
38
- return stdio(io);
38
+ return sourceStdio(io);
39
39
  return supervise(parsed, io);
40
40
  }
41
41
  /** 반환 문자열 = 사용법 오류 메시지 */
@@ -75,11 +75,11 @@ export function parseDevArgs(argv) {
75
75
  }
76
76
  /* ---------------------------------------------------------------- stdio */
77
77
  /**
78
- * stdio: stdout = MCP 메시지만. D4: 이 프로세스의 그 외 stdout 쓰기 (console.log · process.stdout.write) 는
78
+ * stdio (mext dev --stdio · mext serve --stdio): stdout = MCP 메시지만. D4: 이 프로세스의 그 외 stdout 쓰기 (console.log · process.stdout.write) 는
79
79
  * 명령어 import 전부터 종료까지 stderr 로 돌린다. stdin EOF = 연결 종료 → 바로 반환 (bin 이 exit).
80
80
  * 감시 · 잠금 없음: MCP 클라이언트가 프로세스를 소유 · 재실행한다
81
81
  */
82
- async function stdio(io) {
82
+ export async function sourceStdio(io, prog = DEV_PROG) {
83
83
  const redirect = io.stdout === process.stdout ? redirectStdout() : undefined;
84
84
  const wire = redirect?.wire ?? writerStream(io.stdout);
85
85
  try {
@@ -112,7 +112,7 @@ async function stdio(io) {
112
112
  return io.signal?.aborted ? EXIT.interrupted : EXIT.ok;
113
113
  }
114
114
  catch (error) {
115
- io.stderr.write(formatError(error, DEV_PROG));
115
+ io.stderr.write(formatError(error, prog));
116
116
  return exitCodeOf(error);
117
117
  }
118
118
  // redirect 는 원복하지 않는다: 종료 중 남은 핸들러 출력도 stdout 에 섞이지 않게 (프로세스는 곧 exit)
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { fork, type ChildProcess } from \"node:child_process\"\nimport { existsSync, watch, type FSWatcher } from \"node:fs\"\nimport { createServer, request as httpRequest, type IncomingMessage, type Server, type ServerResponse } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport { basename, dirname, extname, relative, resolve } from \"node:path\"\nimport { Writable } from \"node:stream\"\nimport { fileURLToPath } from \"node:url\"\nimport {\n CONFIG_FILE,\n loadConfig,\n mcpStdioDeclarations,\n resolveCommandsDir,\n resolveLocalPrincipal,\n resolvePromptsDir,\n resolveResourcesDir,\n} from \"../config.ts\"\nimport { DEFAULT_HOST, DEFAULT_PORT, MCP_PATH } from \"../mcp/constants.ts\"\nimport { loadProjectInstrumentation } from \"../instrumentation.ts\"\nimport { redirectStdout, serveMcpStdio } from \"../mcp/stdio.ts\"\nimport { loadPromptSet, withPrompts } from \"../prompt.ts\"\nimport { loadResourceSet, withResources } from \"../resource.ts\"\nimport { loadRegistry } from \"../scan.ts\"\nimport { createDevAuditHub, newAuditToken, type DevAuditHub } from \"./dev-audit.ts\"\nimport { acquireDevLock, releaseDevLock, updateDevLock, type DevLock } from \"./dev-lock.ts\"\nimport type { DevChildMessage, DevParentMessage } from \"./dev-server.ts\"\nimport { table } from \"./help.ts\"\nimport type { CliIo, CliWriter } from \"./io.ts\"\nimport { EXIT, exitCodeOf, formatError } from \"./output.ts\"\n\nexport const DEV_PROG = \"mext dev\"\n\n/** 감시 대상 프로젝트 루트 파일 (commandsDir/** 와 함께) */\nexport const DEV_WATCHED_ROOT_FILES: readonly string[] = [CONFIG_FILE, \"instrumentation.ts\"]\n\n/** 파일 변경 → 재시작 debounce (ms) */\nexport const DEV_DEBOUNCE_MS = 100\n\n/**\n * mext dev [--port <n>] [--host <h>] 개발 HTTP 서버. 감독 프로세스 + 서버 자식 (파일 변경 시 교체)\n * mext dev --stdio stdio 서버 (감시 없음, 같은 프로세스)\n */\nexport async function devCommand(argv: readonly string[], io: CliIo): Promise<number> {\n const parsed = parseDevArgs(argv)\n if (typeof parsed === \"string\") {\n io.stderr.write(`error: ${parsed}\\nRun \"${DEV_PROG} --help\" for usage.\\n`)\n return EXIT.usage\n }\n if (parsed.help) {\n io.stdout.write(devHelp())\n return EXIT.ok\n }\n if (parsed.stdio) return stdio(io)\n return supervise(parsed, io)\n}\n\ninterface DevArgs {\n help: boolean\n stdio: boolean\n port?: number\n host?: string\n}\n\n/** 반환 문자열 = 사용법 오류 메시지 */\nexport function parseDevArgs(argv: readonly string[]): DevArgs | string {\n const args: DevArgs = { help: false, stdio: false }\n for (let i = 0; i < argv.length; i++) {\n const tok = argv[i]!\n if (tok === \"--help\" || tok === \"-h\") {\n args.help = true\n continue\n }\n if (tok === \"--stdio\") {\n args.stdio = true\n continue\n }\n if (!tok.startsWith(\"--\")) return `unexpected argument \"${tok}\"`\n const eq = tok.indexOf(\"=\")\n const name = eq < 0 ? tok.slice(2) : tok.slice(2, eq)\n if (name !== \"port\" && name !== \"host\") return `unknown flag --${name}`\n const value = eq < 0 ? argv[++i] : tok.slice(eq + 1)\n if (value === undefined || value === \"\") return `--${name} requires a value`\n if (name === \"port\") {\n const port = Number(value)\n if (!Number.isInteger(port) || port < 0 || port > 65_535) return `--port must be an integer between 0 and 65535`\n args.port = port\n } else args.host = value\n }\n if (args.stdio && (args.port !== undefined || args.host !== undefined)) return \"--port and --host do not apply to --stdio\"\n return args\n}\n\n/* ---------------------------------------------------------------- stdio */\n\n/**\n * stdio: stdout = MCP 메시지만. D4: 이 프로세스의 그 외 stdout 쓰기 (console.log · process.stdout.write) 는\n * 명령어 import 전부터 종료까지 stderr 로 돌린다. stdin EOF = 연결 종료 → 바로 반환 (bin 이 exit).\n * 감시 · 잠금 없음: MCP 클라이언트가 프로세스를 소유 · 재실행한다\n */\nasync function stdio(io: CliIo): Promise<number> {\n const redirect = io.stdout === process.stdout ? redirectStdout() : undefined\n const wire = redirect?.wire ?? writerStream(io.stdout)\n try {\n const instrumentation = await loadProjectInstrumentation(io.cwd)\n const config = await loadConfig(io.cwd)\n const registry = withPrompts(\n withResources(await loadRegistry(resolveCommandsDir(io.cwd, config)), await loadResourceSet(resolveResourcesDir(io.cwd, config))),\n await loadPromptSet(resolvePromptsDir(io.cwd, config)),\n )\n const principal = await resolveLocalPrincipal(config, \"stdio\")\n const server = serveMcpStdio({\n registry,\n instrumentation,\n principal,\n ...(config.app ? { app: config.app } : {}),\n ...(config.tools ? { tools: config.tools } : {}),\n ...mcpStdioDeclarations(config),\n stdin: io.stdin,\n stdout: wire,\n onerror: (error) => io.stderr.write(`mcp: ${error.message}\\n`),\n })\n const onAbort = (): void => void server.close()\n if (io.signal?.aborted) onAbort()\n io.signal?.addEventListener(\"abort\", onAbort, { once: true })\n // SIGTERM (MCP 클라이언트 종료) = close → cleanup 후 exit 0. 실제 프로세스 stdio 일 때만\n if (redirect) process.once(\"SIGTERM\", onAbort)\n await server.closed\n io.signal?.removeEventListener(\"abort\", onAbort)\n if (redirect) process.off(\"SIGTERM\", onAbort)\n return io.signal?.aborted ? EXIT.interrupted : EXIT.ok\n } catch (error) {\n io.stderr.write(formatError(error, DEV_PROG))\n return exitCodeOf(error)\n }\n // redirect 는 원복하지 않는다: 종료 중 남은 핸들러 출력도 stdout 에 섞이지 않게 (프로세스는 곧 exit)\n}\n\n/** 주입된 CliWriter (테스트) → transport 용 Writable */\nfunction writerStream(writer: CliWriter): Writable {\n return new Writable({\n write(chunk: Buffer | string, _encoding, callback) {\n writer.write(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"))\n callback()\n },\n })\n}\n\n/* ---------------------------------------------------------------- HTTP 감독 프로세스 */\n\n/**\n * 감독 프로세스 (이 프로세스) 는 사용자 코드를 import 하지 않는다. listen 소켓 · HTTP 연결을 쥐고\n * 요청마다 현재 서버 자식 (dev-server.ts, 127.0.0.1 임의 포트) 으로 중계한다.\n * 파일 변경 → 새 자식 fork → ready 후 전환, 이전 자식은 진행 중 요청이 끝나면 종료.\n * D2: 재시작 중 (새 자식 준비 전) 들어온 요청은 대기 후 새 자식이 처리. 새 자식 로드 실패 = 이전 자식이 처리\n */\nasync function supervise(args: DevArgs, io: CliIo): Promise<number> {\n const cwd = resolve(io.cwd)\n const log = (line: string): void => void io.stderr.write(`${DEV_PROG}: ${line}\\n`)\n\n // 감사 tap (spec §10): 실행마다 새 토큰. 잠금 파일에만 적는다 (출력하지 않는다)\n const auditToken = newAuditToken()\n let lock: DevLock\n try {\n const got = acquireDevLock(cwd, null, auditToken)\n if (\"running\" in got) {\n const where = got.running.url ? `at ${got.running.url}` : \"(starting)\"\n io.stderr.write(\n `error: ${DEV_PROG} is already running ${where} (PID ${got.running.pid}).\\n` +\n \"Stop it first, or connect to that server.\\n\",\n )\n return EXIT.error\n }\n lock = got.acquired\n } catch (error) {\n io.stderr.write(formatError(error, DEV_PROG))\n return EXIT.error\n }\n const onExit = (): void => releaseDevLock(cwd)\n process.on(\"exit\", onExit)\n\n const supervisor = new DevSupervisor(cwd, log, createDevAuditHub(auditToken))\n try {\n const first = await supervisor.start()\n const host = args.host ?? first?.host ?? DEFAULT_HOST\n const port = args.port ?? first?.port ?? DEFAULT_PORT\n const url = await supervisor.listen(host, port)\n lock = { ...lock, url }\n updateDevLock(cwd, lock)\n io.stderr.write(`MCP dev server (Streamable HTTP) listening on ${url}\\n`)\n supervisor.watchFiles()\n // SIGINT (io.signal) 까지 실행\n await new Promise<void>((done) => {\n if (io.signal?.aborted) return done()\n io.signal?.addEventListener(\"abort\", () => done(), { once: true })\n })\n return EXIT.ok\n } catch (error) {\n io.stderr.write(formatError(error, DEV_PROG))\n return exitCodeOf(error)\n } finally {\n await supervisor.close()\n releaseDevLock(cwd)\n process.off(\"exit\", onExit)\n }\n}\n\ninterface ServerChild {\n seq: number\n proc: ChildProcess\n /** ready 후 자식의 127.0.0.1 포트 */\n port?: number\n inflight: number\n retiring: boolean\n startedAt: number\n}\n\n/** 자식 엔트리. tsc 빌드 (.js) · 원본 (.ts) 모두 이 모듈과 같은 확장자 */\nconst CHILD_ENTRY = fileURLToPath(new URL(`./dev-server${extname(fileURLToPath(import.meta.url))}`, import.meta.url))\n\n/** 요청 · 응답에서 중계하지 않는 hop-by-hop 헤더 */\nconst HOP_HEADERS = new Set([\"connection\", \"keep-alive\", \"proxy-connection\", \"upgrade\", \"te\", \"trailer\"])\n\nclass DevSupervisor {\n private readonly cwd: string\n private readonly log: (line: string) => void\n private server: Server | undefined\n private current: ServerChild | undefined\n private pending: ServerChild | undefined\n private readonly retired = new Set<ServerChild>()\n /** 새 자식 준비 전까지 대기 중인 요청 (D2) */\n private queue: (() => void)[] = []\n /** 자식이 하나도 없을 때의 로드 오류 (요청에 구조화 오류로 응답) */\n private loadError: string | undefined\n private commandsDir: string\n /** routes/ · resources/ · prompts/ (선택, §10 · §12.3 · §12.4). 없으면 생성 감지만 */\n private optionalDirs: readonly string[]\n private bound: { host: string; port: number } | undefined\n private warnedServerChange = false\n private seq = 0\n private closing = false\n private watchers = new Map<string, FSWatcher>()\n private debounce: NodeJS.Timeout | undefined\n private changed = new Set<string>()\n private firstConfig: ((server: { host?: string; port?: number } | undefined) => void) | undefined\n /** 감사 tap: 자식이 넘긴 이벤트 보관 · endpoint */\n private readonly audit: DevAuditHub\n\n constructor(cwd: string, log: (line: string) => void, audit: DevAuditHub) {\n this.cwd = cwd\n this.log = log\n this.audit = audit\n this.commandsDir = resolve(cwd, \"commands\")\n this.optionalDirs = [\"routes\", \"resources\", \"prompts\"].map((name) => resolve(cwd, name))\n }\n\n /** 첫 자식 fork. 자식이 보고한 config.server (host · port) 반환. config 로드 실패 = undefined */\n start(): Promise<{ host?: string; port?: number } | undefined> {\n return new Promise((done) => {\n this.firstConfig = done\n this.spawn()\n })\n }\n\n async listen(host: string, port: number): Promise<string> {\n const server = createServer((req, res) => this.dispatch(req, res))\n this.server = server\n await new Promise<void>((done, reject) => {\n server.once(\"error\", reject)\n server.listen(port, host, () => {\n server.off(\"error\", reject)\n done()\n })\n })\n const address = server.address() as AddressInfo\n this.bound = { host, port }\n const shown = host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host\n return `http://${shown}:${address.port}${MCP_PATH}`\n }\n\n /* -------------------------------------------------------------- 자식 수명 */\n\n private spawn(): void {\n if (this.closing) return\n if (this.pending) this.stop(this.pending)\n const child: ServerChild = {\n seq: ++this.seq,\n proc: fork(CHILD_ENTRY, [], {\n cwd: this.cwd,\n // node --test 의 실행 옵션은 자식에 넘기지 않는다 (--conditions 등은 유지)\n execArgv: process.execArgv.filter((a) => !a.startsWith(\"--test\")),\n stdio: [\"ignore\", \"inherit\", \"inherit\", \"ipc\"],\n }),\n inflight: 0,\n retiring: false,\n startedAt: Date.now(),\n }\n this.pending = child\n let failed = false\n child.proc.on(\"message\", (message: DevChildMessage) => {\n if (message.type === \"config\") this.onConfig(child, message)\n else if (message.type === \"ready\") this.onReady(child, message.port, message.commands)\n else if (message.type === \"audit\") this.audit.push(message.event)\n else if (message.type === \"error\") {\n failed = true\n this.onLoadFailed(child, message.message)\n }\n })\n child.proc.on(\"error\", (error) => {\n if (!failed) this.onLoadFailed(child, error.message)\n failed = true\n })\n child.proc.on(\"exit\", (code, signal) => {\n this.retired.delete(child)\n if (this.pending === child && !failed) {\n failed = true\n this.onLoadFailed(child, `server process exited (${signal ?? `code ${code}`}) before it was ready`)\n } else if (this.current === child) {\n this.current = undefined\n if (this.closing) return\n this.log(`server process exited unexpectedly (${signal ?? `code ${code}`}); restarting`)\n this.spawn()\n }\n })\n }\n\n private onConfig(child: ServerChild, message: Extract<DevChildMessage, { type: \"config\" }>): void {\n if (child !== this.pending) return\n if (this.firstConfig) {\n this.firstConfig(message.server)\n this.firstConfig = undefined\n } else if (\n this.bound &&\n !this.warnedServerChange &&\n ((message.server.host !== undefined && message.server.host !== this.bound.host) ||\n (message.server.port !== undefined && message.server.port !== this.bound.port))\n ) {\n this.warnedServerChange = true\n this.log(\"server.host / server.port changes in mext.config.ts apply after restarting mext dev\")\n }\n const optionalDirs = [message.routesDir, message.resourcesDir, message.promptsDir]\n if (message.commandsDir !== this.commandsDir || optionalDirs.some((dir, i) => dir !== this.optionalDirs[i])) {\n this.commandsDir = message.commandsDir\n this.optionalDirs = optionalDirs\n if (this.watchers.size > 0) this.watchFiles()\n }\n }\n\n private onReady(child: ServerChild, port: number, commands: number): void {\n if (child !== this.pending) return\n const previous = this.current\n child.port = port\n this.pending = undefined\n this.current = child\n this.loadError = undefined\n const ms = Date.now() - child.startedAt\n this.log(`${previous ? \"reloaded\" : \"ready\"} (${commands} command${commands === 1 ? \"\" : \"s\"}, ${ms}ms)`)\n if (previous) this.retire(previous)\n this.flush()\n // commands/ 가 없던 상태에서 생겼으면 감시 시작\n if (this.watchers.size > 0 && !this.watchers.has(this.commandsDir)) this.watchFiles()\n else if (this.watchers.size > 0 && this.optionalDirs.some((dir) => !this.watchers.has(dir) && existsSync(dir))) this.watchFiles()\n }\n\n private onLoadFailed(child: ServerChild, message: string): void {\n if (child !== this.pending) return\n this.pending = undefined\n if (this.firstConfig) {\n this.firstConfig(undefined)\n this.firstConfig = undefined\n }\n if (this.current) {\n this.log(`reload failed; still serving the previous version. Fix the error and save to retry.\\n${indent(message)}`)\n } else {\n this.loadError = message\n this.log(`load failed; requests return an error until the next change.\\n${indent(message)}`)\n }\n this.flush()\n }\n\n /** 진행 중 요청이 끝나면 종료. subscriptions/listen 스트림은 끝나지 않으므로 자식이 완료 result 후 닫는다 (§12.5) */\n private retire(child: ServerChild): void {\n child.retiring = true\n this.retired.add(child)\n if (child.inflight === 0) this.stop(child)\n else if (child.proc.connected) child.proc.send({ type: \"retire\" } satisfies DevParentMessage, () => {})\n }\n\n private stop(child: ServerChild): void {\n if (child.proc.exitCode !== null || child.proc.signalCode !== null) return\n // 준비 전 (로드 중) 자식은 shutdown 메시지를 처리하지 않는다\n if (child.port !== undefined && child.proc.connected) {\n child.proc.send({ type: \"shutdown\" } satisfies DevParentMessage, () => {})\n } else child.proc.kill(\"SIGTERM\")\n setTimeout(() => {\n if (child.proc.exitCode === null && child.proc.signalCode === null) child.proc.kill(\"SIGKILL\")\n }, 3_000).unref()\n }\n\n /* -------------------------------------------------------------- 요청 중계 */\n\n private dispatch(req: IncomingMessage, res: ServerResponse): void {\n // 감사 tap endpoint = 감독 프로세스가 직접 응답 (자식으로 중계하지 않는다. 재시작 중에도 응답)\n if (this.audit.handle(req, res)) return\n if (this.pending) {\n this.queue.push(() => this.dispatch(req, res))\n return\n }\n const child = this.current\n if (child?.port !== undefined) return this.proxy(child, req, res)\n this.sendUnavailable(req, res, this.loadError ?? \"the server process is not running\")\n }\n\n private flush(): void {\n const queued = this.queue\n this.queue = []\n for (const run of queued) run()\n }\n\n private proxy(child: ServerChild, req: IncomingMessage, res: ServerResponse): void {\n // 대기 중 클라이언트가 끊은 요청\n if (res.destroyed || req.destroyed) return\n child.inflight++\n let finished = false\n const done = (): void => {\n if (finished) return\n finished = true\n child.inflight--\n if (child.retiring && child.inflight === 0) this.stop(child)\n }\n const headers: Record<string, string | string[]> = {}\n for (const [name, value] of Object.entries(req.headers)) {\n if (value !== undefined && !HOP_HEADERS.has(name)) headers[name] = value\n }\n const upstream = httpRequest({\n host: \"127.0.0.1\",\n port: child.port,\n method: req.method,\n path: req.url,\n headers,\n agent: false,\n })\n upstream.on(\"response\", (up) => {\n const out: Record<string, string | string[]> = {}\n for (const [name, value] of Object.entries(up.headers)) {\n if (value !== undefined && !HOP_HEADERS.has(name)) out[name] = value\n }\n res.writeHead(up.statusCode ?? 502, out)\n res.flushHeaders()\n up.pipe(res)\n up.on(\"error\", () => res.destroy())\n up.on(\"aborted\", () => res.destroy())\n })\n upstream.on(\"error\", (error) => {\n if (res.headersSent) res.destroy()\n else if (!res.destroyed) {\n sendJson(res, 502, rpcError(-32_603, `mext dev: server process did not respond (${error.message}).`))\n }\n done()\n })\n // 클라이언트 연결 종료 (SSE 취소 포함) = 자식으로의 요청도 닫아 ctx.signal abort\n res.on(\"close\", () => {\n if (!res.writableFinished) upstream.destroy()\n done()\n })\n req.pipe(upstream)\n }\n\n /** 자식 없음 (로드 실패) = 503 + JSON-RPC 오류. MCP 엔드포인트 외 경로도 같은 응답 */\n private sendUnavailable(req: IncomingMessage, res: ServerResponse, message: string): void {\n const chunks: Buffer[] = []\n let size = 0\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length\n if (size <= 1024 * 1024) chunks.push(chunk)\n })\n req.on(\"end\", () => {\n const text =\n \"mext dev: the project failed to load. Fix the error and save; the server reloads automatically.\\n\" + message\n sendJson(res, 503, rpcError(-32_603, text, { loadError: message }, requestId(Buffer.concat(chunks))))\n })\n }\n\n /* -------------------------------------------------------------- 파일 감시 */\n\n /** commandsDir · routes · resources · prompts (recursive) + 프로젝트 루트 (mext.config.ts · instrumentation.ts · 폴더 생성 · 삭제) */\n watchFiles(): void {\n if (this.closing) return\n for (const w of this.watchers.values()) w.close()\n this.watchers.clear()\n const rootNames = new Set(DEV_WATCHED_ROOT_FILES)\n if (dirname(this.commandsDir) === this.cwd) rootNames.add(basename(this.commandsDir))\n for (const dir of this.optionalDirs) if (dirname(dir) === this.cwd) rootNames.add(basename(dir))\n this.addWatcher(this.cwd, false, (name) => (rootNames.has(name) ? name : undefined))\n for (const dir of new Set([this.commandsDir, ...this.optionalDirs])) {\n if (existsSync(dir)) this.addWatcher(dir, true, (name) => relative(this.cwd, resolve(dir, name)))\n }\n }\n\n private addWatcher(dir: string, recursive: boolean, accept: (name: string) => string | undefined): void {\n try {\n const watcher = watch(dir, { recursive, persistent: false }, (_event, filename) => {\n const name = filename === null ? undefined : accept(filename.toString())\n if (name !== undefined) this.schedule(name)\n })\n watcher.on(\"error\", (error) => {\n this.log(`file watching stopped for ${relative(this.cwd, dir) || \".\"} (${error.message})`)\n watcher.close()\n this.watchers.delete(dir)\n })\n this.watchers.set(dir, watcher)\n } catch (error) {\n // R3: Linux inotify 한도 (ENOSPC) 등. 서버는 계속, 재시작은 수동\n this.log(`cannot watch ${relative(this.cwd, dir) || \".\"} (${(error as Error).message}); restart mext dev after changes`)\n }\n }\n\n private schedule(name: string): void {\n if (this.closing) return\n this.changed.add(name)\n clearTimeout(this.debounce)\n this.debounce = setTimeout(() => {\n const names = [...this.changed]\n this.changed.clear()\n const shown = names.slice(0, 3).join(\", \") + (names.length > 3 ? `, +${names.length - 3} more` : \"\")\n this.log(`change detected (${shown}); reloading`)\n this.spawn()\n }, DEV_DEBOUNCE_MS)\n }\n\n /* -------------------------------------------------------------- 종료 */\n\n async close(): Promise<void> {\n this.closing = true\n clearTimeout(this.debounce)\n for (const w of this.watchers.values()) w.close()\n this.audit.close()\n this.watchers.clear()\n const children = [this.current, this.pending, ...this.retired].filter((c): c is ServerChild => c !== undefined)\n const exited = children.map(\n (c) =>\n new Promise<void>((done) => {\n if (c.proc.exitCode !== null || c.proc.signalCode !== null) return done()\n c.proc.once(\"exit\", () => done())\n this.stop(c)\n }),\n )\n if (this.server) {\n const server = this.server\n server.closeAllConnections()\n await new Promise<void>((done) => server.close(() => done()))\n }\n this.flush()\n await Promise.all(exited)\n }\n}\n\nfunction indent(text: string): string {\n return text\n .split(\"\\n\")\n .map((l) => ` ${l}`)\n .join(\"\\n\")\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown): void {\n if (res.headersSent || res.destroyed) return\n const text = JSON.stringify(body)\n res.writeHead(status, { \"Content-Type\": \"application/json\", \"Content-Length\": Buffer.byteLength(text) })\n res.end(text)\n}\n\nfunction rpcError(code: number, message: string, data?: unknown, id: string | number | null = null) {\n return { jsonrpc: \"2.0\", id, error: data === undefined ? { code, message } : { code, message, data } }\n}\n\nfunction requestId(body: Buffer): string | number | null {\n try {\n const { id } = JSON.parse(body.toString(\"utf8\")) as { id?: unknown }\n return typeof id === \"string\" || typeof id === \"number\" ? id : null\n } catch {\n return null\n }\n}\n\nexport function devHelp(): string {\n const lines = [\n \"Run the development MCP server (MCP 2026-07-28). Reloads on file changes.\",\n \"\",\n \"Usage:\",\n ` ${DEV_PROG} [--port <n>] [--host <host>]`,\n ` ${DEV_PROG} --stdio`,\n \"\",\n \"Modes:\",\n ...table([\n [\n DEV_PROG,\n `Streamable HTTP at POST http://${DEFAULT_HOST}:${DEFAULT_PORT}${MCP_PATH} (mext.config.ts: app · auth · tools · server · oauth)`,\n ],\n [\"\", `Watches commands/, ${DEV_WATCHED_ROOT_FILES.join(\", \")} and restarts the server process; the port stays open`],\n [`${DEV_PROG} --stdio`, \"stdio (line-delimited JSON-RPC). Local principal; other stdout output goes to stderr. No watching\"],\n ]).map((l) => ` ${l}`),\n \"\",\n \"Flags:\",\n ...table([\n [\"--port <n>\", `HTTP port (default server.port or ${DEFAULT_PORT}; 0 = any free port)`],\n [\"--host <host>\", `HTTP bind address (default server.host or ${DEFAULT_HOST})`],\n [\"--stdio\", \"Serve over stdin/stdout instead of HTTP\"],\n [\"-h, --help\", \"Show help\"],\n ]).map((l) => ` ${l}`),\n \"\",\n \"One HTTP dev server per project: .mext/dev/lock records { pid, url, startedAt } (add .mext/ to .gitignore).\",\n 'Register with an MCP client: \"mext mcp install\".',\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n"]}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAqB,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAkB,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,OAAO,IAAI,WAAW,EAA0D,MAAM,WAAW,CAAA;AAExH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAoB,MAAM,gBAAgB,CAAA;AACnF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAgB,MAAM,eAAe,CAAA;AAE3F,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE3D,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAA;AAElC,6CAA6C;AAC7C,MAAM,CAAC,MAAM,sBAAsB,GAAsB,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAA;AAE5F,gCAAgC;AAChC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;AAElC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAuB,EAAE,EAAS;IACjE,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IACjC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,MAAM,UAAU,QAAQ,uBAAuB,CAAC,CAAA;QAC1E,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC1B,OAAO,IAAI,CAAC,EAAE,CAAA;IAChB,CAAC;IACD,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,WAAW,CAAC,EAAE,CAAC,CAAA;IACxC,OAAO,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AAC9B,CAAC;AASD,0BAA0B;AAC1B,MAAM,UAAU,YAAY,CAAC,IAAuB;IAClD,MAAM,IAAI,GAAY,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAA;QACpB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;YAChB,SAAQ;QACV,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;YACjB,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,wBAAwB,GAAG,GAAG,CAAA;QAChE,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3B,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QACrD,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,kBAAkB,IAAI,EAAE,CAAA;QACvE,MAAM,KAAK,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;QACpD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,KAAK,IAAI,mBAAmB,CAAA;QAC5E,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;YAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,MAAM;gBAAE,OAAO,+CAA+C,CAAA;YAChH,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAClB,CAAC;;YAAM,IAAI,CAAC,IAAI,GAAG,KAAK,CAAA;IAC1B,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;QAAE,OAAO,2CAA2C,CAAA;IAC1H,OAAO,IAAI,CAAA;AACb,CAAC;AAED,4EAA4E;AAE5E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAS,EAAE,IAAI,GAAW,QAAQ;IAClE,MAAM,QAAQ,GAAG,EAAE,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAC5E,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,IAAI,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,CAAA;IACtD,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,MAAM,0BAA0B,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;QAChE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,WAAW,CAC1B,aAAa,CAAC,MAAM,YAAY,CAAC,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,eAAe,CAAC,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,EACjI,MAAM,aAAa,CAAC,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CACvD,CAAA;QACD,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC9D,MAAM,MAAM,GAAG,aAAa,CAAC;YAC3B,QAAQ;YACR,eAAe;YACf,SAAS;YACT,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1C,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,GAAG,oBAAoB,CAAC,MAAM,CAAC;YAC/B,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,CAAC,OAAO,IAAI,CAAC;SAC/D,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,KAAK,MAAM,CAAC,KAAK,EAAE,CAAA;QAC/C,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO;YAAE,OAAO,EAAE,CAAA;QACjC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7D,wEAAwE;QACxE,IAAI,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAC9C,MAAM,MAAM,CAAC,MAAM,CAAA;QACnB,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAChD,IAAI,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAC7C,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAA;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;QACzC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;IACD,sEAAsE;AACxE,CAAC;AAED,iDAAiD;AACjD,SAAS,YAAY,CAAC,MAAiB;IACrC,OAAO,IAAI,QAAQ,CAAC;QAClB,KAAK,CAAC,KAAsB,EAAE,SAAS,EAAE,QAAQ;YAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;YACxE,QAAQ,EAAE,CAAA;QACZ,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,mFAAmF;AAEnF;;;;;GAKG;AACH,KAAK,UAAU,SAAS,CAAC,IAAa,EAAE,EAAS;IAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IAC3B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAA;IAElF,uDAAuD;IACvD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,IAAI,IAAa,CAAA;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;QACjD,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,YAAY,CAAA;YACtE,EAAE,CAAC,MAAM,CAAC,KAAK,CACb,UAAU,QAAQ,uBAAuB,KAAK,SAAS,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM;gBAC1E,6CAA6C,CAChD,CAAA;YACD,OAAO,IAAI,CAAC,KAAK,CAAA;QACnB,CAAC;QACD,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAA;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,GAAS,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IAC9C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE1B,MAAM,UAAU,GAAG,IAAI,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAA;IAC7E,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,YAAY,CAAA;QACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,YAAY,CAAA;QACrD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC/C,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,CAAA;QACvB,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACxB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,GAAG,IAAI,CAAC,CAAA;QACzE,UAAU,CAAC,UAAU,EAAE,CAAA;QACvB,2BAA2B;QAC3B,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE;YAC/B,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO;gBAAE,OAAO,IAAI,EAAE,CAAA;YACrC,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,EAAE,CAAA;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC7C,OAAO,UAAU,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;YAAS,CAAC;QACT,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;QACxB,cAAc,CAAC,GAAG,CAAC,CAAA;QACnB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,CAAC;AACH,CAAC;AAYD,sDAAsD;AACtD,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,eAAe,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAErH,sCAAsC;AACtC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;AAEzG,MAAM,aAAa;IACA,GAAG,CAAQ;IACX,GAAG,CAAwB;IACpC,MAAM,CAAoB;IAC1B,OAAO,CAAyB;IAChC,OAAO,CAAyB;IACvB,OAAO,GAAG,IAAI,GAAG,EAAe,CAAA;IACjD,gCAAgC;IACxB,KAAK,GAAmB,EAAE,CAAA;IAClC,2CAA2C;IACnC,SAAS,CAAoB;IAC7B,WAAW,CAAQ;IAC3B,4EAA4E;IACpE,YAAY,CAAmB;IAC/B,KAAK,CAA4C;IACjD,kBAAkB,GAAG,KAAK,CAAA;IAC1B,GAAG,GAAG,CAAC,CAAA;IACP,OAAO,GAAG,KAAK,CAAA;IACf,QAAQ,GAAG,IAAI,GAAG,EAAqB,CAAA;IACvC,QAAQ,CAA4B;IACpC,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;IAC3B,WAAW,CAA8E;IACjG,uCAAuC;IACtB,KAAK,CAAa;IAEnC,YAAY,GAAW,EAAE,GAA2B,EAAE,KAAkB;QACtE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;QAC3C,IAAI,CAAC,YAAY,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAA;IAC1F,CAAC;IAED,kFAAkF;IAClF,KAAK;QACH,OAAO,IAAI,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;YACvB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,IAAY;QACrC,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;QAClE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACvC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YAC5B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;gBAC7B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAC3B,IAAI,EAAE,CAAA;YACR,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAiB,CAAA;QAC/C,IAAI,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;QAC9E,OAAO,UAAU,KAAK,IAAI,OAAO,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAA;IACrD,CAAC;IAED,0EAA0E;IAElE,KAAK;QACX,IAAI,IAAI,CAAC,OAAO;YAAE,OAAM;QACxB,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzC,MAAM,KAAK,GAAgB;YACzB,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG;YACf,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE;gBAC1B,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,wDAAwD;gBACxD,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACjE,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC;aAC/C,CAAC;YACF,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAA;QACD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACpB,IAAI,MAAM,GAAG,KAAK,CAAA;QAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAwB,EAAE,EAAE;YACpD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;gBAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;iBACvD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;gBAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;iBACjF,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;gBAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;iBAC5D,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAClC,MAAM,GAAG,IAAI,CAAA;gBACb,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;YAC3C,CAAC;QACH,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/B,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;YACpD,MAAM,GAAG,IAAI,CAAA;QACf,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAC1B,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtC,MAAM,GAAG,IAAI,CAAA;gBACb,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,0BAA0B,MAAM,IAAI,QAAQ,IAAI,EAAE,uBAAuB,CAAC,CAAA;YACrG,CAAC;iBAAM,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAClC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;gBACxB,IAAI,IAAI,CAAC,OAAO;oBAAE,OAAM;gBACxB,IAAI,CAAC,GAAG,CAAC,uCAAuC,MAAM,IAAI,QAAQ,IAAI,EAAE,eAAe,CAAC,CAAA;gBACxF,IAAI,CAAC,KAAK,EAAE,CAAA;YACd,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,QAAQ,CAAC,KAAkB,EAAE,OAAqD;QACxF,IAAI,KAAK,KAAK,IAAI,CAAC,OAAO;YAAE,OAAM;QAClC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YAChC,IAAI,CAAC,WAAW,GAAG,SAAS,CAAA;QAC9B,CAAC;aAAM,IACL,IAAI,CAAC,KAAK;YACV,CAAC,IAAI,CAAC,kBAAkB;YACxB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC7E,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EACjF,CAAC;YACD,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAA;YAC9B,IAAI,CAAC,GAAG,CAAC,qFAAqF,CAAC,CAAA;QACjG,CAAC;QACD,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;QAClF,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5G,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAA;YACtC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;YAChC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC;gBAAE,IAAI,CAAC,UAAU,EAAE,CAAA;QAC/C,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,KAAkB,EAAE,IAAY,EAAE,QAAgB;QAChE,IAAI,KAAK,KAAK,IAAI,CAAC,OAAO;YAAE,OAAM;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;QAC7B,KAAK,CAAC,IAAI,GAAG,IAAI,CAAA;QACjB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACpB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAA;QACvC,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,WAAW,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,CAAA;QACzG,IAAI,QAAQ;YAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,iCAAiC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,IAAI,CAAC,UAAU,EAAE,CAAA;aAChF,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;YAAE,IAAI,CAAC,UAAU,EAAE,CAAA;IACnI,CAAC;IAEO,YAAY,CAAC,KAAkB,EAAE,OAAe;QACtD,IAAI,KAAK,KAAK,IAAI,CAAC,OAAO;YAAE,OAAM;QAClC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;QACxB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;YAC3B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAA;QAC9B,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,wFAAwF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACrH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,GAAG,OAAO,CAAA;YACxB,IAAI,CAAC,GAAG,CAAC,iEAAiE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC9F,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,sFAAsF;IAC9E,MAAM,CAAC,KAAkB;QAC/B,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAA;QACrB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACvB,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;aACrC,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAA6B,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACzG,CAAC;IAEO,IAAI,CAAC,KAAkB;QAC7B,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE,OAAM;QAC1E,yCAAyC;QACzC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAA6B,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC5E,CAAC;;YAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACjC,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAChG,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,CAAA;IACnB,CAAC;IAED,0EAA0E;IAElE,QAAQ,CAAC,GAAoB,EAAE,GAAmB;QACxD,+DAA+D;QAC/D,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAM;QACvC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;YAC9C,OAAM;QACR,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAA;QAC1B,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;QACjE,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,IAAI,mCAAmC,CAAC,CAAA;IACvF,CAAC;IAEO,KAAK;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAA;QACzB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;QACf,KAAK,MAAM,GAAG,IAAI,MAAM;YAAE,GAAG,EAAE,CAAA;IACjC,CAAC;IAEO,KAAK,CAAC,KAAkB,EAAE,GAAoB,EAAE,GAAmB;QACzE,oBAAoB;QACpB,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS;YAAE,OAAM;QAC1C,KAAK,CAAC,QAAQ,EAAE,CAAA;QAChB,IAAI,QAAQ,GAAG,KAAK,CAAA;QACpB,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,IAAI,QAAQ;gBAAE,OAAM;YACpB,QAAQ,GAAG,IAAI,CAAA;YACf,KAAK,CAAC,QAAQ,EAAE,CAAA;YAChB,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9D,CAAC,CAAA;QACD,MAAM,OAAO,GAAsC,EAAE,CAAA;QACrD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;QAC1E,CAAC;QACD,MAAM,QAAQ,GAAG,WAAW,CAAC;YAC3B,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,IAAI,EAAE,GAAG,CAAC,GAAG;YACb,OAAO;YACP,KAAK,EAAE,KAAK;SACb,CAAC,CAAA;QACF,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE;YAC7B,MAAM,GAAG,GAAsC,EAAE,CAAA;YACjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;YACtE,CAAC;YACD,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,UAAU,IAAI,GAAG,EAAE,GAAG,CAAC,CAAA;YACxC,GAAG,CAAC,YAAY,EAAE,CAAA;YAClB,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACZ,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;YACnC,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;QACvC,CAAC,CAAC,CAAA;QACF,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC7B,IAAI,GAAG,CAAC,WAAW;gBAAE,GAAG,CAAC,OAAO,EAAE,CAAA;iBAC7B,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;gBACxB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,6CAA6C,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAA;YACvG,CAAC;YACD,IAAI,EAAE,CAAA;QACR,CAAC,CAAC,CAAA;QACF,0DAA0D;QAC1D,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,IAAI,CAAC,GAAG,CAAC,gBAAgB;gBAAE,QAAQ,CAAC,OAAO,EAAE,CAAA;YAC7C,IAAI,EAAE,CAAA;QACR,CAAC,CAAC,CAAA;QACF,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACpB,CAAC;IAED,+DAA+D;IACvD,eAAe,CAAC,GAAoB,EAAE,GAAmB,EAAE,OAAe;QAChF,MAAM,MAAM,GAAa,EAAE,CAAA;QAC3B,IAAI,IAAI,GAAG,CAAC,CAAA;QACZ,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,IAAI,KAAK,CAAC,MAAM,CAAA;YACpB,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI;gBAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;QACF,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,MAAM,IAAI,GACR,mGAAmG,GAAG,OAAO,CAAA;YAC/G,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QACvG,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,0EAA0E;IAE1E,0HAA0H;IAC1H,UAAU;QACR,IAAI,IAAI,CAAC,OAAO;YAAE,OAAM;QACxB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YAAE,CAAC,CAAC,KAAK,EAAE,CAAA;QACjD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QACrB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,CAAA;QACjD,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,GAAG;YAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;QACrF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY;YAAE,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GAAG;gBAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;QAChG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;QACpF,KAAK,MAAM,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;YACpE,IAAI,UAAU,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnG,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,GAAW,EAAE,SAAkB,EAAE,MAA4C;QAC9F,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;gBAChF,MAAM,IAAI,GAAG,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;gBACxE,IAAI,IAAI,KAAK,SAAS;oBAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAC7C,CAAC,CAAC,CAAA;YACF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC5B,IAAI,CAAC,GAAG,CAAC,6BAA6B,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,KAAK,KAAK,CAAC,OAAO,GAAG,CAAC,CAAA;gBAC1F,OAAO,CAAC,KAAK,EAAE,CAAA;gBACf,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC3B,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,mDAAmD;YACnD,IAAI,CAAC,GAAG,CAAC,gBAAgB,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,KAAM,KAAe,CAAC,OAAO,mCAAmC,CAAC,CAAA;QAC1H,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,IAAY;QAC3B,IAAI,IAAI,CAAC,OAAO;YAAE,OAAM;QACxB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACtB,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC3B,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;YAC/B,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YACpG,IAAI,CAAC,GAAG,CAAC,oBAAoB,KAAK,cAAc,CAAC,CAAA;YACjD,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC,EAAE,eAAe,CAAC,CAAA;IACrB,CAAC;IAED,uEAAuE;IAEvE,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC3B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YAAE,CAAC,CAAC,KAAK,EAAE,CAAA;QACjD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;QACrB,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;QAC/G,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CACzB,CAAC,CAAC,EAAE,EAAE,CACJ,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI;gBAAE,OAAO,IAAI,EAAE,CAAA;YACzE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;YACjC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACd,CAAC,CAAC,CACL,CAAA;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;YAC1B,MAAM,CAAC,mBAAmB,EAAE,CAAA;YAC5B,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QAC/D,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B,CAAC;CACF;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO,IAAI;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;SACpB,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAa;IAClE,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,SAAS;QAAE,OAAM;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IACjC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACxG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,OAAe,EAAE,IAAc,EAAE,EAAE,GAA2B,IAAI;IAChG,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAA;AACxG,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAqB,CAAA;QACpE,OAAO,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,MAAM,KAAK,GAAG;QACZ,2EAA2E;QAC3E,EAAE;QACF,QAAQ;QACR,KAAK,QAAQ,+BAA+B;QAC5C,KAAK,QAAQ,UAAU;QACvB,EAAE;QACF,QAAQ;QACR,GAAG,KAAK,CAAC;YACP;gBACE,QAAQ;gBACR,kCAAkC,YAAY,IAAI,YAAY,GAAG,QAAQ,wDAAwD;aAClI;YACD,CAAC,EAAE,EAAE,sBAAsB,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,uDAAuD,CAAC;YACpH,CAAC,GAAG,QAAQ,UAAU,EAAE,mGAAmG,CAAC;SAC7H,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,EAAE;QACF,QAAQ;QACR,GAAG,KAAK,CAAC;YACP,CAAC,YAAY,EAAE,qCAAqC,YAAY,sBAAsB,CAAC;YACvF,CAAC,eAAe,EAAE,6CAA6C,YAAY,GAAG,CAAC;YAC/E,CAAC,SAAS,EAAE,yCAAyC,CAAC;YACtD,CAAC,YAAY,EAAE,WAAW,CAAC;SAC5B,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,EAAE;QACF,6GAA6G;QAC7G,kDAAkD;KACnD,CAAA;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;AAChC,CAAC","sourcesContent":["import { fork, type ChildProcess } from \"node:child_process\"\nimport { existsSync, watch, type FSWatcher } from \"node:fs\"\nimport { createServer, request as httpRequest, type IncomingMessage, type Server, type ServerResponse } from \"node:http\"\nimport type { AddressInfo } from \"node:net\"\nimport { basename, dirname, extname, relative, resolve } from \"node:path\"\nimport { Writable } from \"node:stream\"\nimport { fileURLToPath } from \"node:url\"\nimport {\n CONFIG_FILE,\n loadConfig,\n mcpStdioDeclarations,\n resolveCommandsDir,\n resolveLocalPrincipal,\n resolvePromptsDir,\n resolveResourcesDir,\n} from \"../config.ts\"\nimport { DEFAULT_HOST, DEFAULT_PORT, MCP_PATH } from \"../mcp/constants.ts\"\nimport { loadProjectInstrumentation } from \"../instrumentation.ts\"\nimport { redirectStdout, serveMcpStdio } from \"../mcp/stdio.ts\"\nimport { loadPromptSet, withPrompts } from \"../prompt.ts\"\nimport { loadResourceSet, withResources } from \"../resource.ts\"\nimport { loadRegistry } from \"../scan.ts\"\nimport { createDevAuditHub, newAuditToken, type DevAuditHub } from \"./dev-audit.ts\"\nimport { acquireDevLock, releaseDevLock, updateDevLock, type DevLock } from \"./dev-lock.ts\"\nimport type { DevChildMessage, DevParentMessage } from \"./dev-server.ts\"\nimport { table } from \"./help.ts\"\nimport type { CliIo, CliWriter } from \"./io.ts\"\nimport { EXIT, exitCodeOf, formatError } from \"./output.ts\"\n\nexport const DEV_PROG = \"mext dev\"\n\n/** 감시 대상 프로젝트 루트 파일 (commandsDir/** 와 함께) */\nexport const DEV_WATCHED_ROOT_FILES: readonly string[] = [CONFIG_FILE, \"instrumentation.ts\"]\n\n/** 파일 변경 → 재시작 debounce (ms) */\nexport const DEV_DEBOUNCE_MS = 100\n\n/**\n * mext dev [--port <n>] [--host <h>] 개발 HTTP 서버. 감독 프로세스 + 서버 자식 (파일 변경 시 교체)\n * mext dev --stdio stdio 서버 (감시 없음, 같은 프로세스)\n */\nexport async function devCommand(argv: readonly string[], io: CliIo): Promise<number> {\n const parsed = parseDevArgs(argv)\n if (typeof parsed === \"string\") {\n io.stderr.write(`error: ${parsed}\\nRun \"${DEV_PROG} --help\" for usage.\\n`)\n return EXIT.usage\n }\n if (parsed.help) {\n io.stdout.write(devHelp())\n return EXIT.ok\n }\n if (parsed.stdio) return sourceStdio(io)\n return supervise(parsed, io)\n}\n\ninterface DevArgs {\n help: boolean\n stdio: boolean\n port?: number\n host?: string\n}\n\n/** 반환 문자열 = 사용법 오류 메시지 */\nexport function parseDevArgs(argv: readonly string[]): DevArgs | string {\n const args: DevArgs = { help: false, stdio: false }\n for (let i = 0; i < argv.length; i++) {\n const tok = argv[i]!\n if (tok === \"--help\" || tok === \"-h\") {\n args.help = true\n continue\n }\n if (tok === \"--stdio\") {\n args.stdio = true\n continue\n }\n if (!tok.startsWith(\"--\")) return `unexpected argument \"${tok}\"`\n const eq = tok.indexOf(\"=\")\n const name = eq < 0 ? tok.slice(2) : tok.slice(2, eq)\n if (name !== \"port\" && name !== \"host\") return `unknown flag --${name}`\n const value = eq < 0 ? argv[++i] : tok.slice(eq + 1)\n if (value === undefined || value === \"\") return `--${name} requires a value`\n if (name === \"port\") {\n const port = Number(value)\n if (!Number.isInteger(port) || port < 0 || port > 65_535) return `--port must be an integer between 0 and 65535`\n args.port = port\n } else args.host = value\n }\n if (args.stdio && (args.port !== undefined || args.host !== undefined)) return \"--port and --host do not apply to --stdio\"\n return args\n}\n\n/* ---------------------------------------------------------------- stdio */\n\n/**\n * stdio (mext dev --stdio · mext serve --stdio): stdout = MCP 메시지만. D4: 이 프로세스의 그 외 stdout 쓰기 (console.log · process.stdout.write) 는\n * 명령어 import 전부터 종료까지 stderr 로 돌린다. stdin EOF = 연결 종료 → 바로 반환 (bin 이 exit).\n * 감시 · 잠금 없음: MCP 클라이언트가 프로세스를 소유 · 재실행한다\n */\nexport async function sourceStdio(io: CliIo, prog: string = DEV_PROG): Promise<number> {\n const redirect = io.stdout === process.stdout ? redirectStdout() : undefined\n const wire = redirect?.wire ?? writerStream(io.stdout)\n try {\n const instrumentation = await loadProjectInstrumentation(io.cwd)\n const config = await loadConfig(io.cwd)\n const registry = withPrompts(\n withResources(await loadRegistry(resolveCommandsDir(io.cwd, config)), await loadResourceSet(resolveResourcesDir(io.cwd, config))),\n await loadPromptSet(resolvePromptsDir(io.cwd, config)),\n )\n const principal = await resolveLocalPrincipal(config, \"stdio\")\n const server = serveMcpStdio({\n registry,\n instrumentation,\n principal,\n ...(config.app ? { app: config.app } : {}),\n ...(config.tools ? { tools: config.tools } : {}),\n ...mcpStdioDeclarations(config),\n stdin: io.stdin,\n stdout: wire,\n onerror: (error) => io.stderr.write(`mcp: ${error.message}\\n`),\n })\n const onAbort = (): void => void server.close()\n if (io.signal?.aborted) onAbort()\n io.signal?.addEventListener(\"abort\", onAbort, { once: true })\n // SIGTERM (MCP 클라이언트 종료) = close → cleanup 후 exit 0. 실제 프로세스 stdio 일 때만\n if (redirect) process.once(\"SIGTERM\", onAbort)\n await server.closed\n io.signal?.removeEventListener(\"abort\", onAbort)\n if (redirect) process.off(\"SIGTERM\", onAbort)\n return io.signal?.aborted ? EXIT.interrupted : EXIT.ok\n } catch (error) {\n io.stderr.write(formatError(error, prog))\n return exitCodeOf(error)\n }\n // redirect 는 원복하지 않는다: 종료 중 남은 핸들러 출력도 stdout 에 섞이지 않게 (프로세스는 곧 exit)\n}\n\n/** 주입된 CliWriter (테스트) → transport 용 Writable */\nfunction writerStream(writer: CliWriter): Writable {\n return new Writable({\n write(chunk: Buffer | string, _encoding, callback) {\n writer.write(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"))\n callback()\n },\n })\n}\n\n/* ---------------------------------------------------------------- HTTP 감독 프로세스 */\n\n/**\n * 감독 프로세스 (이 프로세스) 는 사용자 코드를 import 하지 않는다. listen 소켓 · HTTP 연결을 쥐고\n * 요청마다 현재 서버 자식 (dev-server.ts, 127.0.0.1 임의 포트) 으로 중계한다.\n * 파일 변경 → 새 자식 fork → ready 후 전환, 이전 자식은 진행 중 요청이 끝나면 종료.\n * D2: 재시작 중 (새 자식 준비 전) 들어온 요청은 대기 후 새 자식이 처리. 새 자식 로드 실패 = 이전 자식이 처리\n */\nasync function supervise(args: DevArgs, io: CliIo): Promise<number> {\n const cwd = resolve(io.cwd)\n const log = (line: string): void => void io.stderr.write(`${DEV_PROG}: ${line}\\n`)\n\n // 감사 tap (spec §10): 실행마다 새 토큰. 잠금 파일에만 적는다 (출력하지 않는다)\n const auditToken = newAuditToken()\n let lock: DevLock\n try {\n const got = acquireDevLock(cwd, null, auditToken)\n if (\"running\" in got) {\n const where = got.running.url ? `at ${got.running.url}` : \"(starting)\"\n io.stderr.write(\n `error: ${DEV_PROG} is already running ${where} (PID ${got.running.pid}).\\n` +\n \"Stop it first, or connect to that server.\\n\",\n )\n return EXIT.error\n }\n lock = got.acquired\n } catch (error) {\n io.stderr.write(formatError(error, DEV_PROG))\n return EXIT.error\n }\n const onExit = (): void => releaseDevLock(cwd)\n process.on(\"exit\", onExit)\n\n const supervisor = new DevSupervisor(cwd, log, createDevAuditHub(auditToken))\n try {\n const first = await supervisor.start()\n const host = args.host ?? first?.host ?? DEFAULT_HOST\n const port = args.port ?? first?.port ?? DEFAULT_PORT\n const url = await supervisor.listen(host, port)\n lock = { ...lock, url }\n updateDevLock(cwd, lock)\n io.stderr.write(`MCP dev server (Streamable HTTP) listening on ${url}\\n`)\n supervisor.watchFiles()\n // SIGINT (io.signal) 까지 실행\n await new Promise<void>((done) => {\n if (io.signal?.aborted) return done()\n io.signal?.addEventListener(\"abort\", () => done(), { once: true })\n })\n return EXIT.ok\n } catch (error) {\n io.stderr.write(formatError(error, DEV_PROG))\n return exitCodeOf(error)\n } finally {\n await supervisor.close()\n releaseDevLock(cwd)\n process.off(\"exit\", onExit)\n }\n}\n\ninterface ServerChild {\n seq: number\n proc: ChildProcess\n /** ready 후 자식의 127.0.0.1 포트 */\n port?: number\n inflight: number\n retiring: boolean\n startedAt: number\n}\n\n/** 자식 엔트리. tsc 빌드 (.js) · 원본 (.ts) 모두 이 모듈과 같은 확장자 */\nconst CHILD_ENTRY = fileURLToPath(new URL(`./dev-server${extname(fileURLToPath(import.meta.url))}`, import.meta.url))\n\n/** 요청 · 응답에서 중계하지 않는 hop-by-hop 헤더 */\nconst HOP_HEADERS = new Set([\"connection\", \"keep-alive\", \"proxy-connection\", \"upgrade\", \"te\", \"trailer\"])\n\nclass DevSupervisor {\n private readonly cwd: string\n private readonly log: (line: string) => void\n private server: Server | undefined\n private current: ServerChild | undefined\n private pending: ServerChild | undefined\n private readonly retired = new Set<ServerChild>()\n /** 새 자식 준비 전까지 대기 중인 요청 (D2) */\n private queue: (() => void)[] = []\n /** 자식이 하나도 없을 때의 로드 오류 (요청에 구조화 오류로 응답) */\n private loadError: string | undefined\n private commandsDir: string\n /** routes/ · resources/ · prompts/ (선택, §10 · §12.3 · §12.4). 없으면 생성 감지만 */\n private optionalDirs: readonly string[]\n private bound: { host: string; port: number } | undefined\n private warnedServerChange = false\n private seq = 0\n private closing = false\n private watchers = new Map<string, FSWatcher>()\n private debounce: NodeJS.Timeout | undefined\n private changed = new Set<string>()\n private firstConfig: ((server: { host?: string; port?: number } | undefined) => void) | undefined\n /** 감사 tap: 자식이 넘긴 이벤트 보관 · endpoint */\n private readonly audit: DevAuditHub\n\n constructor(cwd: string, log: (line: string) => void, audit: DevAuditHub) {\n this.cwd = cwd\n this.log = log\n this.audit = audit\n this.commandsDir = resolve(cwd, \"commands\")\n this.optionalDirs = [\"routes\", \"resources\", \"prompts\"].map((name) => resolve(cwd, name))\n }\n\n /** 첫 자식 fork. 자식이 보고한 config.server (host · port) 반환. config 로드 실패 = undefined */\n start(): Promise<{ host?: string; port?: number } | undefined> {\n return new Promise((done) => {\n this.firstConfig = done\n this.spawn()\n })\n }\n\n async listen(host: string, port: number): Promise<string> {\n const server = createServer((req, res) => this.dispatch(req, res))\n this.server = server\n await new Promise<void>((done, reject) => {\n server.once(\"error\", reject)\n server.listen(port, host, () => {\n server.off(\"error\", reject)\n done()\n })\n })\n const address = server.address() as AddressInfo\n this.bound = { host, port }\n const shown = host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host\n return `http://${shown}:${address.port}${MCP_PATH}`\n }\n\n /* -------------------------------------------------------------- 자식 수명 */\n\n private spawn(): void {\n if (this.closing) return\n if (this.pending) this.stop(this.pending)\n const child: ServerChild = {\n seq: ++this.seq,\n proc: fork(CHILD_ENTRY, [], {\n cwd: this.cwd,\n // node --test 의 실행 옵션은 자식에 넘기지 않는다 (--conditions 등은 유지)\n execArgv: process.execArgv.filter((a) => !a.startsWith(\"--test\")),\n stdio: [\"ignore\", \"inherit\", \"inherit\", \"ipc\"],\n }),\n inflight: 0,\n retiring: false,\n startedAt: Date.now(),\n }\n this.pending = child\n let failed = false\n child.proc.on(\"message\", (message: DevChildMessage) => {\n if (message.type === \"config\") this.onConfig(child, message)\n else if (message.type === \"ready\") this.onReady(child, message.port, message.commands)\n else if (message.type === \"audit\") this.audit.push(message.event)\n else if (message.type === \"error\") {\n failed = true\n this.onLoadFailed(child, message.message)\n }\n })\n child.proc.on(\"error\", (error) => {\n if (!failed) this.onLoadFailed(child, error.message)\n failed = true\n })\n child.proc.on(\"exit\", (code, signal) => {\n this.retired.delete(child)\n if (this.pending === child && !failed) {\n failed = true\n this.onLoadFailed(child, `server process exited (${signal ?? `code ${code}`}) before it was ready`)\n } else if (this.current === child) {\n this.current = undefined\n if (this.closing) return\n this.log(`server process exited unexpectedly (${signal ?? `code ${code}`}); restarting`)\n this.spawn()\n }\n })\n }\n\n private onConfig(child: ServerChild, message: Extract<DevChildMessage, { type: \"config\" }>): void {\n if (child !== this.pending) return\n if (this.firstConfig) {\n this.firstConfig(message.server)\n this.firstConfig = undefined\n } else if (\n this.bound &&\n !this.warnedServerChange &&\n ((message.server.host !== undefined && message.server.host !== this.bound.host) ||\n (message.server.port !== undefined && message.server.port !== this.bound.port))\n ) {\n this.warnedServerChange = true\n this.log(\"server.host / server.port changes in mext.config.ts apply after restarting mext dev\")\n }\n const optionalDirs = [message.routesDir, message.resourcesDir, message.promptsDir]\n if (message.commandsDir !== this.commandsDir || optionalDirs.some((dir, i) => dir !== this.optionalDirs[i])) {\n this.commandsDir = message.commandsDir\n this.optionalDirs = optionalDirs\n if (this.watchers.size > 0) this.watchFiles()\n }\n }\n\n private onReady(child: ServerChild, port: number, commands: number): void {\n if (child !== this.pending) return\n const previous = this.current\n child.port = port\n this.pending = undefined\n this.current = child\n this.loadError = undefined\n const ms = Date.now() - child.startedAt\n this.log(`${previous ? \"reloaded\" : \"ready\"} (${commands} command${commands === 1 ? \"\" : \"s\"}, ${ms}ms)`)\n if (previous) this.retire(previous)\n this.flush()\n // commands/ 가 없던 상태에서 생겼으면 감시 시작\n if (this.watchers.size > 0 && !this.watchers.has(this.commandsDir)) this.watchFiles()\n else if (this.watchers.size > 0 && this.optionalDirs.some((dir) => !this.watchers.has(dir) && existsSync(dir))) this.watchFiles()\n }\n\n private onLoadFailed(child: ServerChild, message: string): void {\n if (child !== this.pending) return\n this.pending = undefined\n if (this.firstConfig) {\n this.firstConfig(undefined)\n this.firstConfig = undefined\n }\n if (this.current) {\n this.log(`reload failed; still serving the previous version. Fix the error and save to retry.\\n${indent(message)}`)\n } else {\n this.loadError = message\n this.log(`load failed; requests return an error until the next change.\\n${indent(message)}`)\n }\n this.flush()\n }\n\n /** 진행 중 요청이 끝나면 종료. subscriptions/listen 스트림은 끝나지 않으므로 자식이 완료 result 후 닫는다 (§12.5) */\n private retire(child: ServerChild): void {\n child.retiring = true\n this.retired.add(child)\n if (child.inflight === 0) this.stop(child)\n else if (child.proc.connected) child.proc.send({ type: \"retire\" } satisfies DevParentMessage, () => {})\n }\n\n private stop(child: ServerChild): void {\n if (child.proc.exitCode !== null || child.proc.signalCode !== null) return\n // 준비 전 (로드 중) 자식은 shutdown 메시지를 처리하지 않는다\n if (child.port !== undefined && child.proc.connected) {\n child.proc.send({ type: \"shutdown\" } satisfies DevParentMessage, () => {})\n } else child.proc.kill(\"SIGTERM\")\n setTimeout(() => {\n if (child.proc.exitCode === null && child.proc.signalCode === null) child.proc.kill(\"SIGKILL\")\n }, 3_000).unref()\n }\n\n /* -------------------------------------------------------------- 요청 중계 */\n\n private dispatch(req: IncomingMessage, res: ServerResponse): void {\n // 감사 tap endpoint = 감독 프로세스가 직접 응답 (자식으로 중계하지 않는다. 재시작 중에도 응답)\n if (this.audit.handle(req, res)) return\n if (this.pending) {\n this.queue.push(() => this.dispatch(req, res))\n return\n }\n const child = this.current\n if (child?.port !== undefined) return this.proxy(child, req, res)\n this.sendUnavailable(req, res, this.loadError ?? \"the server process is not running\")\n }\n\n private flush(): void {\n const queued = this.queue\n this.queue = []\n for (const run of queued) run()\n }\n\n private proxy(child: ServerChild, req: IncomingMessage, res: ServerResponse): void {\n // 대기 중 클라이언트가 끊은 요청\n if (res.destroyed || req.destroyed) return\n child.inflight++\n let finished = false\n const done = (): void => {\n if (finished) return\n finished = true\n child.inflight--\n if (child.retiring && child.inflight === 0) this.stop(child)\n }\n const headers: Record<string, string | string[]> = {}\n for (const [name, value] of Object.entries(req.headers)) {\n if (value !== undefined && !HOP_HEADERS.has(name)) headers[name] = value\n }\n const upstream = httpRequest({\n host: \"127.0.0.1\",\n port: child.port,\n method: req.method,\n path: req.url,\n headers,\n agent: false,\n })\n upstream.on(\"response\", (up) => {\n const out: Record<string, string | string[]> = {}\n for (const [name, value] of Object.entries(up.headers)) {\n if (value !== undefined && !HOP_HEADERS.has(name)) out[name] = value\n }\n res.writeHead(up.statusCode ?? 502, out)\n res.flushHeaders()\n up.pipe(res)\n up.on(\"error\", () => res.destroy())\n up.on(\"aborted\", () => res.destroy())\n })\n upstream.on(\"error\", (error) => {\n if (res.headersSent) res.destroy()\n else if (!res.destroyed) {\n sendJson(res, 502, rpcError(-32_603, `mext dev: server process did not respond (${error.message}).`))\n }\n done()\n })\n // 클라이언트 연결 종료 (SSE 취소 포함) = 자식으로의 요청도 닫아 ctx.signal abort\n res.on(\"close\", () => {\n if (!res.writableFinished) upstream.destroy()\n done()\n })\n req.pipe(upstream)\n }\n\n /** 자식 없음 (로드 실패) = 503 + JSON-RPC 오류. MCP 엔드포인트 외 경로도 같은 응답 */\n private sendUnavailable(req: IncomingMessage, res: ServerResponse, message: string): void {\n const chunks: Buffer[] = []\n let size = 0\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length\n if (size <= 1024 * 1024) chunks.push(chunk)\n })\n req.on(\"end\", () => {\n const text =\n \"mext dev: the project failed to load. Fix the error and save; the server reloads automatically.\\n\" + message\n sendJson(res, 503, rpcError(-32_603, text, { loadError: message }, requestId(Buffer.concat(chunks))))\n })\n }\n\n /* -------------------------------------------------------------- 파일 감시 */\n\n /** commandsDir · routes · resources · prompts (recursive) + 프로젝트 루트 (mext.config.ts · instrumentation.ts · 폴더 생성 · 삭제) */\n watchFiles(): void {\n if (this.closing) return\n for (const w of this.watchers.values()) w.close()\n this.watchers.clear()\n const rootNames = new Set(DEV_WATCHED_ROOT_FILES)\n if (dirname(this.commandsDir) === this.cwd) rootNames.add(basename(this.commandsDir))\n for (const dir of this.optionalDirs) if (dirname(dir) === this.cwd) rootNames.add(basename(dir))\n this.addWatcher(this.cwd, false, (name) => (rootNames.has(name) ? name : undefined))\n for (const dir of new Set([this.commandsDir, ...this.optionalDirs])) {\n if (existsSync(dir)) this.addWatcher(dir, true, (name) => relative(this.cwd, resolve(dir, name)))\n }\n }\n\n private addWatcher(dir: string, recursive: boolean, accept: (name: string) => string | undefined): void {\n try {\n const watcher = watch(dir, { recursive, persistent: false }, (_event, filename) => {\n const name = filename === null ? undefined : accept(filename.toString())\n if (name !== undefined) this.schedule(name)\n })\n watcher.on(\"error\", (error) => {\n this.log(`file watching stopped for ${relative(this.cwd, dir) || \".\"} (${error.message})`)\n watcher.close()\n this.watchers.delete(dir)\n })\n this.watchers.set(dir, watcher)\n } catch (error) {\n // R3: Linux inotify 한도 (ENOSPC) 등. 서버는 계속, 재시작은 수동\n this.log(`cannot watch ${relative(this.cwd, dir) || \".\"} (${(error as Error).message}); restart mext dev after changes`)\n }\n }\n\n private schedule(name: string): void {\n if (this.closing) return\n this.changed.add(name)\n clearTimeout(this.debounce)\n this.debounce = setTimeout(() => {\n const names = [...this.changed]\n this.changed.clear()\n const shown = names.slice(0, 3).join(\", \") + (names.length > 3 ? `, +${names.length - 3} more` : \"\")\n this.log(`change detected (${shown}); reloading`)\n this.spawn()\n }, DEV_DEBOUNCE_MS)\n }\n\n /* -------------------------------------------------------------- 종료 */\n\n async close(): Promise<void> {\n this.closing = true\n clearTimeout(this.debounce)\n for (const w of this.watchers.values()) w.close()\n this.audit.close()\n this.watchers.clear()\n const children = [this.current, this.pending, ...this.retired].filter((c): c is ServerChild => c !== undefined)\n const exited = children.map(\n (c) =>\n new Promise<void>((done) => {\n if (c.proc.exitCode !== null || c.proc.signalCode !== null) return done()\n c.proc.once(\"exit\", () => done())\n this.stop(c)\n }),\n )\n if (this.server) {\n const server = this.server\n server.closeAllConnections()\n await new Promise<void>((done) => server.close(() => done()))\n }\n this.flush()\n await Promise.all(exited)\n }\n}\n\nfunction indent(text: string): string {\n return text\n .split(\"\\n\")\n .map((l) => ` ${l}`)\n .join(\"\\n\")\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown): void {\n if (res.headersSent || res.destroyed) return\n const text = JSON.stringify(body)\n res.writeHead(status, { \"Content-Type\": \"application/json\", \"Content-Length\": Buffer.byteLength(text) })\n res.end(text)\n}\n\nfunction rpcError(code: number, message: string, data?: unknown, id: string | number | null = null) {\n return { jsonrpc: \"2.0\", id, error: data === undefined ? { code, message } : { code, message, data } }\n}\n\nfunction requestId(body: Buffer): string | number | null {\n try {\n const { id } = JSON.parse(body.toString(\"utf8\")) as { id?: unknown }\n return typeof id === \"string\" || typeof id === \"number\" ? id : null\n } catch {\n return null\n }\n}\n\nexport function devHelp(): string {\n const lines = [\n \"Run the development MCP server (MCP 2026-07-28). Reloads on file changes.\",\n \"\",\n \"Usage:\",\n ` ${DEV_PROG} [--port <n>] [--host <host>]`,\n ` ${DEV_PROG} --stdio`,\n \"\",\n \"Modes:\",\n ...table([\n [\n DEV_PROG,\n `Streamable HTTP at POST http://${DEFAULT_HOST}:${DEFAULT_PORT}${MCP_PATH} (mext.config.ts: app · auth · tools · server · oauth)`,\n ],\n [\"\", `Watches commands/, ${DEV_WATCHED_ROOT_FILES.join(\", \")} and restarts the server process; the port stays open`],\n [`${DEV_PROG} --stdio`, \"stdio (line-delimited JSON-RPC). Local principal; other stdout output goes to stderr. No watching\"],\n ]).map((l) => ` ${l}`),\n \"\",\n \"Flags:\",\n ...table([\n [\"--port <n>\", `HTTP port (default server.port or ${DEFAULT_PORT}; 0 = any free port)`],\n [\"--host <host>\", `HTTP bind address (default server.host or ${DEFAULT_HOST})`],\n [\"--stdio\", \"Serve over stdin/stdout instead of HTTP\"],\n [\"-h, --help\", \"Show help\"],\n ]).map((l) => ` ${l}`),\n \"\",\n \"One HTTP dev server per project: .mext/dev/lock records { pid, url, startedAt } (add .mext/ to .gitignore).\",\n 'Register with an MCP client: \"mext mcp install\".',\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n"]}
package/dist/cli/main.js CHANGED
@@ -9,6 +9,7 @@ import { devCommand } from "./dev.js";
9
9
  import { runLogout } from "./logout.js";
10
10
  import { mcpCommand } from "./mcp.js";
11
11
  import { runCommand } from "./run.js";
12
+ import { serveCommand } from "./serve.js";
12
13
  import { startCommand } from "./start.js";
13
14
  import { typesCommand } from "./types.js";
14
15
  /**
@@ -18,6 +19,7 @@ import { typesCommand } from "./types.js";
18
19
  export const SUBCOMMANDS = [
19
20
  { name: "run", summary: "Run a command locally, or remotely with --url (mext run help)", run: runCommand },
20
21
  { name: "dev", summary: "Development MCP server with file watching (mext dev, mext dev --stdio)", run: devCommand },
22
+ { name: "serve", summary: "Production MCP server from source, no build, no file watching (mext serve --help)", run: serveCommand },
21
23
  { name: "mcp", summary: "Print MCP client registration commands (mext mcp install)", run: mcpCommand },
22
24
  { name: "login", summary: "Log in to a remote server (mext login --url <url>)", run: runLogin },
23
25
  { name: "logout", summary: "Revoke and remove stored credentials (mext logout --url <url>)", run: runLogout },
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\"\nimport { closest } from \"../suggest.ts\"\nimport { table } from \"./help.ts\"\nimport { resolveIo, type CliIo } from \"./io.ts\"\nimport { EXIT } from \"./output.ts\"\nimport { runBuild } from \"./build.ts\"\nimport { runLogin } from \"./login.ts\"\nimport { devCommand } from \"./dev.ts\"\nimport { runLogout } from \"./logout.ts\"\nimport { mcpCommand } from \"./mcp.ts\"\nimport { runCommand } from \"./run.ts\"\nimport { startCommand } from \"./start.ts\"\nimport { typesCommand } from \"./types.ts\"\n\n/** mext 의 하위 명령 (run · dev · mcp install · login · logout · build · start) */\nexport interface CliSubcommand {\n name: string\n /** mext help 한 줄 설명 */\n summary: string\n /** 하위 명령 이름 뒤의 argv. 반환 = exit code */\n run(argv: readonly string[], io: CliIo): Promise<number>\n}\n\n/**\n * 하위 명령 표. 이후 단계가 항목을 추가한다 (mcp · mcp --stdio · mcp install · login · build · run --url).\n * 순서 = help 표시 순서.\n */\nexport const SUBCOMMANDS: CliSubcommand[] = [\n { name: \"run\", summary: \"Run a command locally, or remotely with --url (mext run help)\", run: runCommand },\n { name: \"dev\", summary: \"Development MCP server with file watching (mext dev, mext dev --stdio)\", run: devCommand },\n { name: \"mcp\", summary: \"Print MCP client registration commands (mext mcp install)\", run: mcpCommand },\n { name: \"login\", summary: \"Log in to a remote server (mext login --url <url>)\", run: runLogin },\n { name: \"logout\", summary: \"Revoke and remove stored credentials (mext logout --url <url>)\", run: runLogout },\n { name: \"build\", summary: \"Build .mext/ for production: bundle, manifest, server.js (mext build --help)\", run: (argv, io) => runBuild(argv, io) },\n { name: \"start\", summary: \"Production MCP server from .mext/ (mext start, mext start --stdio)\", run: startCommand },\n { name: \"types\", summary: \"Generate command types for the typed client (mext types --help)\", run: typesCommand },\n // inspect 는 실행할 때만 읽는다 (mext start · run 이 inspector 코드를 import 하지 않게)\n {\n name: \"inspect\",\n summary: \"Inspect a server: commands, calls as caller profiles, scenarios (mext inspect --help)\",\n run: async (argv, io) => (await import(\"./inspect.ts\")).inspectCommand(argv, io),\n },\n]\n\n/**\n * mext CLI 진입점. argv = 실행 파일 뒤 인자 (process.argv.slice(2)). 반환 = exit code.\n * io 는 테스트용 주입 (stdin · stdout · stderr · isTTY · env · cwd · signal), 생략 = process.\n */\nexport async function runCli(argv: readonly string[], io: Partial<CliIo> = {}): Promise<number> {\n const resolved = resolveIo(io)\n const subcommands = SUBCOMMANDS\n const [first, ...rest] = argv\n if (first === undefined) {\n resolved.stderr.write(rootHelp(subcommands))\n return EXIT.usage\n }\n if (first === \"help\" || first === \"--help\" || first === \"-h\") {\n resolved.stdout.write(rootHelp(subcommands))\n return EXIT.ok\n }\n if (first === \"--version\" || first === \"-v\") {\n resolved.stdout.write(`${packageVersion()}\\n`)\n return EXIT.ok\n }\n const sub = subcommands.find((s) => s.name === first)\n if (!sub) {\n const suggested = closest(first, subcommands.map((s): [string, string] => [s.name, s.name]))\n const hint = suggested.length > 0 ? ` Did you mean \"mext ${suggested[0]}\"?` : \"\"\n resolved.stderr.write(`error: unknown command \"${first}\".${hint}\\nRun \"mext help\" for available commands.\\n`)\n return EXIT.usage\n }\n return sub.run(rest, resolved)\n}\n\nfunction rootHelp(subcommands: readonly CliSubcommand[]): string {\n const lines = [\n \"mext — file-based commands as a CLI and an MCP server\",\n \"\",\n \"Usage:\",\n \" mext <command> [args]\",\n \"\",\n \"Commands:\",\n ...table(subcommands.map((s) => [s.name, s.summary])).map((l) => ` ${l}`),\n \"\",\n \"Flags:\",\n ...table([\n [\"-h, --help\", \"Show help\"],\n [\"-v, --version\", \"Print the version\"],\n ]).map((l) => ` ${l}`),\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n\nfunction packageVersion(): string {\n const pkg = JSON.parse(readFileSync(new URL(\"../../package.json\", import.meta.url), \"utf8\")) as { version?: string }\n return pkg.version ?? \"0.0.0\"\n}\n"]}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\"\nimport { closest } from \"../suggest.ts\"\nimport { table } from \"./help.ts\"\nimport { resolveIo, type CliIo } from \"./io.ts\"\nimport { EXIT } from \"./output.ts\"\nimport { runBuild } from \"./build.ts\"\nimport { runLogin } from \"./login.ts\"\nimport { devCommand } from \"./dev.ts\"\nimport { runLogout } from \"./logout.ts\"\nimport { mcpCommand } from \"./mcp.ts\"\nimport { runCommand } from \"./run.ts\"\nimport { serveCommand } from \"./serve.ts\"\nimport { startCommand } from \"./start.ts\"\nimport { typesCommand } from \"./types.ts\"\n\n/** mext 의 하위 명령 (run · dev · mcp install · login · logout · build · start) */\nexport interface CliSubcommand {\n name: string\n /** mext help 한 줄 설명 */\n summary: string\n /** 하위 명령 이름 뒤의 argv. 반환 = exit code */\n run(argv: readonly string[], io: CliIo): Promise<number>\n}\n\n/**\n * 하위 명령 표. 이후 단계가 항목을 추가한다 (mcp · mcp --stdio · mcp install · login · build · run --url).\n * 순서 = help 표시 순서.\n */\nexport const SUBCOMMANDS: CliSubcommand[] = [\n { name: \"run\", summary: \"Run a command locally, or remotely with --url (mext run help)\", run: runCommand },\n { name: \"dev\", summary: \"Development MCP server with file watching (mext dev, mext dev --stdio)\", run: devCommand },\n { name: \"serve\", summary: \"Production MCP server from source, no build, no file watching (mext serve --help)\", run: serveCommand },\n { name: \"mcp\", summary: \"Print MCP client registration commands (mext mcp install)\", run: mcpCommand },\n { name: \"login\", summary: \"Log in to a remote server (mext login --url <url>)\", run: runLogin },\n { name: \"logout\", summary: \"Revoke and remove stored credentials (mext logout --url <url>)\", run: runLogout },\n { name: \"build\", summary: \"Build .mext/ for production: bundle, manifest, server.js (mext build --help)\", run: (argv, io) => runBuild(argv, io) },\n { name: \"start\", summary: \"Production MCP server from .mext/ (mext start, mext start --stdio)\", run: startCommand },\n { name: \"types\", summary: \"Generate command types for the typed client (mext types --help)\", run: typesCommand },\n // inspect 는 실행할 때만 읽는다 (mext start · run 이 inspector 코드를 import 하지 않게)\n {\n name: \"inspect\",\n summary: \"Inspect a server: commands, calls as caller profiles, scenarios (mext inspect --help)\",\n run: async (argv, io) => (await import(\"./inspect.ts\")).inspectCommand(argv, io),\n },\n]\n\n/**\n * mext CLI 진입점. argv = 실행 파일 뒤 인자 (process.argv.slice(2)). 반환 = exit code.\n * io 는 테스트용 주입 (stdin · stdout · stderr · isTTY · env · cwd · signal), 생략 = process.\n */\nexport async function runCli(argv: readonly string[], io: Partial<CliIo> = {}): Promise<number> {\n const resolved = resolveIo(io)\n const subcommands = SUBCOMMANDS\n const [first, ...rest] = argv\n if (first === undefined) {\n resolved.stderr.write(rootHelp(subcommands))\n return EXIT.usage\n }\n if (first === \"help\" || first === \"--help\" || first === \"-h\") {\n resolved.stdout.write(rootHelp(subcommands))\n return EXIT.ok\n }\n if (first === \"--version\" || first === \"-v\") {\n resolved.stdout.write(`${packageVersion()}\\n`)\n return EXIT.ok\n }\n const sub = subcommands.find((s) => s.name === first)\n if (!sub) {\n const suggested = closest(first, subcommands.map((s): [string, string] => [s.name, s.name]))\n const hint = suggested.length > 0 ? ` Did you mean \"mext ${suggested[0]}\"?` : \"\"\n resolved.stderr.write(`error: unknown command \"${first}\".${hint}\\nRun \"mext help\" for available commands.\\n`)\n return EXIT.usage\n }\n return sub.run(rest, resolved)\n}\n\nfunction rootHelp(subcommands: readonly CliSubcommand[]): string {\n const lines = [\n \"mext — file-based commands as a CLI and an MCP server\",\n \"\",\n \"Usage:\",\n \" mext <command> [args]\",\n \"\",\n \"Commands:\",\n ...table(subcommands.map((s) => [s.name, s.summary])).map((l) => ` ${l}`),\n \"\",\n \"Flags:\",\n ...table([\n [\"-h, --help\", \"Show help\"],\n [\"-v, --version\", \"Print the version\"],\n ]).map((l) => ` ${l}`),\n ]\n return `${lines.join(\"\\n\")}\\n`\n}\n\nfunction packageVersion(): string {\n const pkg = JSON.parse(readFileSync(new URL(\"../../package.json\", import.meta.url), \"utf8\")) as { version?: string }\n return pkg.version ?? \"0.0.0\"\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import type { CliWriter } from "./io.ts";
2
+ /**
3
+ * CLI 의 결과 콘텐츠 (spec §4): MCP content 블록 중 image · audio = 파일 저장 + stderr 1줄, resource_link = stderr 1줄.
4
+ * 로컬 (mext run · 로컬 bin) · 원격 (고객 CLI · mext run --url) 공용. 서버 코드 · Zod 를 import 하지 않는다 (고객 CLI 번들)
5
+ */
6
+ export interface SaveContentOptions {
7
+ /** 정식 명령어 ID (파일 이름 접두) */
8
+ command: string;
9
+ /** 실행 파일 이름. 폴더 환경변수 = <BIN>_MEDIA_DIR (mext run = MEXT_MEDIA_DIR) */
10
+ bin: string;
11
+ env: Record<string, string | undefined>;
12
+ /** 상대 경로 <BIN>_MEDIA_DIR 의 기준 */
13
+ cwd: string;
14
+ stderr: CliWriter;
15
+ }
16
+ /** content 블록 (값 text 제외) 처리. 저장 파일 경로 목록 (순서 = 블록 순서) */
17
+ export declare function saveContent(blocks: readonly unknown[], options: SaveContentOptions): string[];
18
+ /** mimeType → 확장자. 표에 없으면 subtype (영숫자만), 그것도 없으면 bin */
19
+ export declare function extensionOf(mimeType: string): string;
@@ -0,0 +1,77 @@
1
+ import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join, resolve } from "node:path";
4
+ /** content 블록 (값 text 제외) 처리. 저장 파일 경로 목록 (순서 = 블록 순서) */
5
+ export function saveContent(blocks, options) {
6
+ const saved = [];
7
+ let dir;
8
+ for (const block of blocks) {
9
+ if (!isRecord(block))
10
+ continue;
11
+ if (block.type === "resource_link" && typeof block.uri === "string") {
12
+ const name = typeof block.name === "string" && block.name !== "" ? ` (${block.name})` : "";
13
+ options.stderr.write(`resource ${block.uri}${name}\n`);
14
+ continue;
15
+ }
16
+ if ((block.type !== "image" && block.type !== "audio") || typeof block.data !== "string" || typeof block.mimeType !== "string")
17
+ continue;
18
+ dir ??= mediaDir(options);
19
+ const bytes = Buffer.from(block.data, "base64");
20
+ const file = join(dir, `${safeName(options.command)}-${saved.length + 1}.${extensionOf(block.mimeType)}`);
21
+ writeFileSync(file, bytes);
22
+ saved.push(file);
23
+ options.stderr.write(`saved ${block.mimeType} (${formatSize(bytes.byteLength)}) → ${file}\n`);
24
+ }
25
+ return saved;
26
+ }
27
+ /** <BIN>_MEDIA_DIR (없으면 만든다) 또는 실행마다 새 임시 폴더 */
28
+ function mediaDir(options) {
29
+ const configured = options.env[`${options.bin.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_MEDIA_DIR`];
30
+ if (configured !== undefined && configured !== "") {
31
+ const dir = resolve(options.cwd, configured);
32
+ mkdirSync(dir, { recursive: true });
33
+ return dir;
34
+ }
35
+ return mkdtempSync(join(tmpdir(), `${safeName(options.bin)}-media-`));
36
+ }
37
+ const EXTENSIONS = {
38
+ "image/png": "png",
39
+ "image/jpeg": "jpg",
40
+ "image/gif": "gif",
41
+ "image/webp": "webp",
42
+ "image/svg+xml": "svg",
43
+ "image/avif": "avif",
44
+ "image/bmp": "bmp",
45
+ "audio/mpeg": "mp3",
46
+ "audio/wav": "wav",
47
+ "audio/x-wav": "wav",
48
+ "audio/wave": "wav",
49
+ "audio/ogg": "ogg",
50
+ "audio/webm": "webm",
51
+ "audio/flac": "flac",
52
+ "audio/aac": "aac",
53
+ "audio/mp4": "m4a",
54
+ };
55
+ /** mimeType → 확장자. 표에 없으면 subtype (영숫자만), 그것도 없으면 bin */
56
+ export function extensionOf(mimeType) {
57
+ const base = mimeType.split(";")[0].trim().toLowerCase();
58
+ const known = EXTENSIONS[base];
59
+ if (known !== undefined)
60
+ return known;
61
+ const subtype = (base.split("/")[1] ?? "").replace(/[^a-z0-9]/g, "");
62
+ return subtype === "" ? "bin" : subtype;
63
+ }
64
+ function safeName(name) {
65
+ return name.replace(/[^A-Za-z0-9._-]/g, "_");
66
+ }
67
+ function formatSize(bytes) {
68
+ if (bytes < 1024)
69
+ return `${bytes} B`;
70
+ if (bytes < 1024 * 1024)
71
+ return `${(bytes / 1024).toFixed(1)} KB`;
72
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
73
+ }
74
+ function isRecord(value) {
75
+ return typeof value === "object" && value !== null && !Array.isArray(value);
76
+ }
77
+ //# sourceMappingURL=media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/cli/media.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, mkdtempSync, writeFileSync } from \"node:fs\"\nimport { tmpdir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\nimport type { CliWriter } from \"./io.ts\"\n\n/**\n * CLI 의 결과 콘텐츠 (spec §4): MCP content 블록 중 image · audio = 파일 저장 + stderr 1줄, resource_link = stderr 1줄.\n * 로컬 (mext run · 로컬 bin) · 원격 (고객 CLI · mext run --url) 공용. 서버 코드 · Zod 를 import 하지 않는다 (고객 CLI 번들)\n */\n\nexport interface SaveContentOptions {\n /** 정식 명령어 ID (파일 이름 접두) */\n command: string\n /** 실행 파일 이름. 폴더 환경변수 = <BIN>_MEDIA_DIR (mext run = MEXT_MEDIA_DIR) */\n bin: string\n env: Record<string, string | undefined>\n /** 상대 경로 <BIN>_MEDIA_DIR 의 기준 */\n cwd: string\n stderr: CliWriter\n}\n\n/** content 블록 (값 text 제외) 처리. 저장 파일 경로 목록 (순서 = 블록 순서) */\nexport function saveContent(blocks: readonly unknown[], options: SaveContentOptions): string[] {\n const saved: string[] = []\n let dir: string | undefined\n for (const block of blocks) {\n if (!isRecord(block)) continue\n if (block.type === \"resource_link\" && typeof block.uri === \"string\") {\n const name = typeof block.name === \"string\" && block.name !== \"\" ? ` (${block.name})` : \"\"\n options.stderr.write(`resource ${block.uri}${name}\\n`)\n continue\n }\n if ((block.type !== \"image\" && block.type !== \"audio\") || typeof block.data !== \"string\" || typeof block.mimeType !== \"string\") continue\n dir ??= mediaDir(options)\n const bytes = Buffer.from(block.data, \"base64\")\n const file = join(dir, `${safeName(options.command)}-${saved.length + 1}.${extensionOf(block.mimeType)}`)\n writeFileSync(file, bytes)\n saved.push(file)\n options.stderr.write(`saved ${block.mimeType} (${formatSize(bytes.byteLength)}) → ${file}\\n`)\n }\n return saved\n}\n\n/** <BIN>_MEDIA_DIR (없으면 만든다) 또는 실행마다 새 임시 폴더 */\nfunction mediaDir(options: SaveContentOptions): string {\n const configured = options.env[`${options.bin.toUpperCase().replace(/[^A-Z0-9]/g, \"_\")}_MEDIA_DIR`]\n if (configured !== undefined && configured !== \"\") {\n const dir = resolve(options.cwd, configured)\n mkdirSync(dir, { recursive: true })\n return dir\n }\n return mkdtempSync(join(tmpdir(), `${safeName(options.bin)}-media-`))\n}\n\nconst EXTENSIONS: Record<string, string> = {\n \"image/png\": \"png\",\n \"image/jpeg\": \"jpg\",\n \"image/gif\": \"gif\",\n \"image/webp\": \"webp\",\n \"image/svg+xml\": \"svg\",\n \"image/avif\": \"avif\",\n \"image/bmp\": \"bmp\",\n \"audio/mpeg\": \"mp3\",\n \"audio/wav\": \"wav\",\n \"audio/x-wav\": \"wav\",\n \"audio/wave\": \"wav\",\n \"audio/ogg\": \"ogg\",\n \"audio/webm\": \"webm\",\n \"audio/flac\": \"flac\",\n \"audio/aac\": \"aac\",\n \"audio/mp4\": \"m4a\",\n}\n\n/** mimeType → 확장자. 표에 없으면 subtype (영숫자만), 그것도 없으면 bin */\nexport function extensionOf(mimeType: string): string {\n const base = mimeType.split(\";\")[0]!.trim().toLowerCase()\n const known = EXTENSIONS[base]\n if (known !== undefined) return known\n const subtype = (base.split(\"/\")[1] ?? \"\").replace(/[^a-z0-9]/g, \"\")\n return subtype === \"\" ? \"bin\" : subtype\n}\n\nfunction safeName(name: string): string {\n return name.replace(/[^A-Za-z0-9._-]/g, \"_\")\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / 1024 / 1024).toFixed(1)} MB`\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n"]}
package/dist/cli/run.js CHANGED
@@ -15,6 +15,7 @@ import { cliPath, renderHelp } from "./help.js";
15
15
  import { createLineReader, readAll } from "./io.js";
16
16
  import { CliInterrupted, emitError, EXIT, errorJson, exitCodeOf, formatError, formatJson, formatProgress, formatResult, } from "./output.js";
17
17
  import { remoteTarget, runRemoteCommand } from "./remote.js";
18
+ import { saveContent } from "./media.js";
18
19
  export const RUN_PROG = "mext run";
19
20
  /** mext run 의 소스: 도입 프로젝트 (cwd) 의 instrumentation.ts · mext.config.ts · cli.errors · commands/ */
20
21
  export function projectSource(cwd) {
@@ -145,6 +146,10 @@ export async function runLocalCommand(argv, io, source) {
145
146
  if (controller.signal.aborted)
146
147
  throw new CliInterrupted();
147
148
  io.stdout.write(json ? formatJson(result.value) : formatResult(result.value));
149
+ // 결과 콘텐츠 (spec §4) = 파일 저장 + stderr 줄. 폴더 = <BIN>_MEDIA_DIR (mext run = MEXT_MEDIA_DIR)
150
+ if (result.content) {
151
+ saveContent(result.content, { command: entry.id, bin: source.prog.split(" ")[0], env: io.env, cwd: io.cwd, stderr: io.stderr });
152
+ }
148
153
  return EXIT.ok;
149
154
  }
150
155
  catch (error) {