@obov/mext 0.5.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.
- package/dist/approval.d.ts +33 -0
- package/dist/approval.js +36 -0
- package/dist/approval.js.map +1 -0
- package/dist/audit.d.ts +123 -0
- package/dist/audit.js +221 -0
- package/dist/audit.js.map +1 -0
- package/dist/build-cli.d.ts +1 -0
- package/dist/build-cli.js.map +1 -1
- package/dist/build.d.ts +2 -0
- package/dist/build.js +46 -5
- package/dist/build.js.map +1 -1
- package/dist/caller.d.ts +53 -0
- package/dist/caller.js +51 -0
- package/dist/caller.js.map +1 -0
- package/dist/cli/args.js +1 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/build.js +26 -4
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev-audit.d.ts +25 -0
- package/dist/cli/dev-audit.js +84 -0
- package/dist/cli/dev-audit.js.map +1 -0
- package/dist/cli/dev-lock.d.ts +3 -1
- package/dist/cli/dev-lock.js +12 -5
- package/dist/cli/dev-lock.js.map +1 -1
- package/dist/cli/dev-server.d.ts +9 -0
- package/dist/cli/dev-server.js +27 -3
- package/dist/cli/dev-server.js.map +1 -1
- package/dist/cli/dev-tap.d.ts +20 -0
- package/dist/cli/dev-tap.js +70 -0
- package/dist/cli/dev-tap.js.map +1 -0
- package/dist/cli/dev.d.ts +6 -0
- package/dist/cli/dev.js +20 -8
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/help.js +2 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/inspect.d.ts +7 -0
- package/dist/cli/inspect.js +699 -0
- package/dist/cli/inspect.js.map +1 -0
- package/dist/cli/main.js +10 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/media.d.ts +19 -0
- package/dist/cli/media.js +77 -0
- package/dist/cli/media.js.map +1 -0
- package/dist/cli/output.d.ts +1 -1
- package/dist/cli/output.js +3 -2
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/run.js +33 -4
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/serve.d.ts +10 -0
- package/dist/cli/serve.js +114 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/types.d.ts +9 -0
- package/dist/cli/types.js +77 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/manifest.js +6 -2
- package/dist/client/manifest.js.map +1 -1
- package/dist/client/runner.js +40 -3
- package/dist/client/runner.js.map +1 -1
- package/dist/client/typed.d.ts +56 -0
- package/dist/client/typed.js +526 -0
- package/dist/client/typed.js.map +1 -0
- package/dist/client/types.d.ts +225 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/command.d.ts +61 -5
- package/dist/command.js +42 -1
- package/dist/command.js.map +1 -1
- package/dist/config.d.ts +59 -10
- package/dist/config.js +67 -7
- package/dist/config.js.map +1 -1
- package/dist/content.d.ts +65 -0
- package/dist/content.js +99 -0
- package/dist/content.js.map +1 -0
- package/dist/errors.d.ts +21 -3
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -1
- package/dist/expose.d.ts +9 -0
- package/dist/expose.js +52 -0
- package/dist/expose.js.map +1 -0
- package/dist/index.d.ts +18 -7
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/inspect/agent.d.ts +104 -0
- package/dist/inspect/agent.js +125 -0
- package/dist/inspect/agent.js.map +1 -0
- package/dist/inspect/audit.d.ts +46 -0
- package/dist/inspect/audit.js +133 -0
- package/dist/inspect/audit.js.map +1 -0
- package/dist/inspect/compare.d.ts +12 -0
- package/dist/inspect/compare.js +31 -0
- package/dist/inspect/compare.js.map +1 -0
- package/dist/inspect/index.d.ts +17 -0
- package/dist/inspect/index.js +12 -0
- package/dist/inspect/index.js.map +1 -0
- package/dist/inspect/inspector.d.ts +168 -0
- package/dist/inspect/inspector.js +392 -0
- package/dist/inspect/inspector.js.map +1 -0
- package/dist/inspect/profiles.d.ts +95 -0
- package/dist/inspect/profiles.js +235 -0
- package/dist/inspect/profiles.js.map +1 -0
- package/dist/inspect/scenario.d.ts +126 -0
- package/dist/inspect/scenario.js +555 -0
- package/dist/inspect/scenario.js.map +1 -0
- package/dist/inspect/ui-server.d.ts +31 -0
- package/dist/inspect/ui-server.js +378 -0
- package/dist/inspect/ui-server.js.map +1 -0
- package/dist/inspect/ui.html +917 -0
- package/dist/instrumentation.d.ts +13 -2
- package/dist/instrumentation.js +11 -1
- package/dist/instrumentation.js.map +1 -1
- package/dist/invoke.d.ts +36 -5
- package/dist/invoke.js +162 -21
- package/dist/invoke.js.map +1 -1
- package/dist/manifest.d.ts +19 -3
- package/dist/manifest.js +5 -1
- package/dist/manifest.js.map +1 -1
- package/dist/mcp/constants.d.ts +7 -0
- package/dist/mcp/constants.js +7 -0
- package/dist/mcp/constants.js.map +1 -1
- package/dist/mcp/dispatch.d.ts +10 -4
- package/dist/mcp/dispatch.js +24 -7
- package/dist/mcp/dispatch.js.map +1 -1
- package/dist/mcp/help.d.ts +2 -0
- package/dist/mcp/help.js +6 -1
- package/dist/mcp/help.js.map +1 -1
- package/dist/mcp/host.d.ts +14 -0
- package/dist/mcp/host.js +48 -0
- package/dist/mcp/host.js.map +1 -0
- package/dist/mcp/http.d.ts +38 -7
- package/dist/mcp/http.js +199 -23
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -1
- package/dist/mcp/index.js +2 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +12 -1
- package/dist/mcp/server.js +63 -17
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts +4 -0
- package/dist/mcp/stdio.js +3 -0
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/mcp/tasks.d.ts +3 -1
- package/dist/mcp/tasks.js +7 -4
- package/dist/mcp/tasks.js.map +1 -1
- package/dist/principal.d.ts +22 -0
- package/dist/principal.js +29 -0
- package/dist/principal.js.map +1 -1
- package/dist/registry.d.ts +5 -0
- package/dist/registry.js +21 -0
- package/dist/registry.js.map +1 -1
- package/dist/remote/client.d.ts +26 -1
- package/dist/remote/client.js +180 -55
- package/dist/remote/client.js.map +1 -1
- package/dist/remote/index.d.ts +1 -1
- package/dist/remote/index.js.map +1 -1
- package/dist/remote/oauth.d.ts +1 -1
- package/dist/remote/oauth.js +1 -1
- package/dist/remote/oauth.js.map +1 -1
- package/dist/route.d.ts +40 -2
- package/dist/route.js +128 -8
- package/dist/route.js.map +1 -1
- package/dist/start.js +9 -4
- package/dist/start.js.map +1 -1
- package/dist/suggest.js +1 -1
- package/dist/suggest.js.map +1 -1
- package/dist/typegen.d.ts +27 -0
- package/dist/typegen.js +62 -0
- package/dist/typegen.js.map +1 -0
- package/dist/version-constant.d.ts +5 -0
- package/dist/version-constant.js +6 -0
- package/dist/version-constant.js.map +1 -0
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/dist/version.js.map +1 -1
- package/package.json +12 -2
package/dist/cli/dev-server.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
import type { AuditEvent } from "../audit.ts";
|
|
1
2
|
/** 자식 → 부모 */
|
|
2
3
|
export type DevChildMessage = {
|
|
4
|
+
type: "error";
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
/** 감사 tap (spec §10): 호출 1건의 감사 이벤트 */
|
|
8
|
+
| {
|
|
9
|
+
type: "audit";
|
|
10
|
+
event: AuditEvent;
|
|
11
|
+
} | {
|
|
3
12
|
type: "config";
|
|
4
13
|
commandsDir: string;
|
|
5
14
|
routesDir: string;
|
package/dist/cli/dev-server.js
CHANGED
|
@@ -4,13 +4,16 @@
|
|
|
4
4
|
* 요청은 감독 프로세스 (부모) 가 받아 이 포트로 중계한다. 부모 IPC 가 끊기면 종료.
|
|
5
5
|
*/
|
|
6
6
|
import { createServer } from "node:http";
|
|
7
|
-
import {
|
|
7
|
+
import { relative } from "node:path";
|
|
8
|
+
import { httpServerOptions, loadConfig, mcpDeclarations, resolveCommandsDir, resolvePromptsDir, resolveResourcesDir, resolveRoutesDir } from "../config.js";
|
|
8
9
|
import { loadProjectInstrumentation } from "../instrumentation.js";
|
|
9
10
|
import { createMcpHttpHandler } from "../mcp/http.js";
|
|
10
11
|
import { loadPromptSet, withPrompts } from "../prompt.js";
|
|
11
12
|
import { loadResourceSet, withResources } from "../resource.js";
|
|
12
13
|
import { loadRoutes } from "../route.js";
|
|
13
14
|
import { loadRegistry } from "../scan.js";
|
|
15
|
+
import { resolveTypesPath, writeTypes } from "../typegen.js";
|
|
16
|
+
import { tapAudit } from "./dev-tap.js";
|
|
14
17
|
const send = (message) => new Promise((resolve) => {
|
|
15
18
|
if (!process.connected)
|
|
16
19
|
return resolve();
|
|
@@ -41,16 +44,24 @@ async function main() {
|
|
|
41
44
|
});
|
|
42
45
|
const registry = withPrompts(withResources(await loadRegistry(commandsDir), await loadResourceSet(resourcesDir)), await loadPromptSet(promptsDir));
|
|
43
46
|
const routes = await loadRoutes(routesDir);
|
|
47
|
+
generateTypes(cwd, config.types, commandsDir);
|
|
48
|
+
// 감사 tap: 모든 호출의 이벤트를 감독 프로세스로 (전달을 기다리지 않는다). 프로젝트 audit 설정의 동작은 그대로
|
|
49
|
+
const tapped = tapAudit(registry, config.audit, (event) => {
|
|
50
|
+
if (process.connected)
|
|
51
|
+
process.send({ type: "audit", event }, undefined, {}, () => { });
|
|
52
|
+
});
|
|
44
53
|
const listener = createMcpHttpHandler({
|
|
45
|
-
registry,
|
|
54
|
+
registry: tapped.registry,
|
|
46
55
|
instrumentation,
|
|
47
56
|
...(config.app ? { app: config.app } : {}),
|
|
48
57
|
...(config.auth ? { auth: config.auth } : {}),
|
|
49
58
|
...(config.tools ? { tools: config.tools } : {}),
|
|
50
59
|
...(config.oauth ? { oauth: config.oauth } : {}),
|
|
60
|
+
...(config.routes ? { routeDefaults: config.routes } : {}),
|
|
51
61
|
...(routes.length > 0 ? { routes } : {}),
|
|
52
62
|
...mcpDeclarations(config),
|
|
53
|
-
|
|
63
|
+
audit: tapped.audit,
|
|
64
|
+
server: httpServerOptions(config),
|
|
54
65
|
onerror: (error) => process.stderr.write(`mcp: ${error.message}\n`),
|
|
55
66
|
});
|
|
56
67
|
const server = createServer(listener);
|
|
@@ -77,6 +88,19 @@ main().catch(async (error) => {
|
|
|
77
88
|
await send({ type: "error", message: describeLoadError(error) });
|
|
78
89
|
process.exit(1);
|
|
79
90
|
});
|
|
91
|
+
/** 명령어 타입 생성 (config.types, specs/client.md §4). 실패 = stderr 1줄 (서버는 계속) */
|
|
92
|
+
function generateTypes(cwd, types, commandsDir) {
|
|
93
|
+
const out = resolveTypesPath(cwd, types);
|
|
94
|
+
if (out === undefined)
|
|
95
|
+
return;
|
|
96
|
+
try {
|
|
97
|
+
if (writeTypes(commandsDir, out).changed)
|
|
98
|
+
process.stderr.write(`mext dev: wrote ${relative(cwd, out) || out}\n`);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
process.stderr.write(`mext dev: cannot write command types (${error instanceof Error ? error.message : String(error)})\n`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
80
104
|
/** SyntaxError 는 stack 첫 줄들에 파일 위치가 있다 (ESM 파싱 오류). 그 외는 message (MextBuildError = issue 목록) */
|
|
81
105
|
function describeLoadError(error) {
|
|
82
106
|
if (error instanceof SyntaxError && error.stack) {
|
|
@@ -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 { 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\"\n\n/** 자식 → 부모 */\nexport type DevChildMessage =\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 const listener = createMcpHttpHandler({\n 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 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/** 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"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AuditConfig, AuditEvent } from "../audit.ts";
|
|
2
|
+
import type { Registry } from "../registry.ts";
|
|
3
|
+
/**
|
|
4
|
+
* mext dev 의 감사 tap, 서버 자식 쪽 (spec §10 감사 tap). cli/dev-server.ts 만 import 한다:
|
|
5
|
+
* mext start · handler.js · 로컬 bin · 고객 CLI · mext dev --stdio 에는 이 코드 경로가 없다.
|
|
6
|
+
*
|
|
7
|
+
* 프로젝트 audit 설정을 감싸 모든 호출의 이벤트를 emit 으로 넘긴다 (readOnly · 숨긴 명령어 호출 시도 포함).
|
|
8
|
+
* 프로젝트가 관찰하는 동작은 tap 이 없을 때와 같다: 프로젝트 sink 는 자기 설정 (includeReadOnly · includeHidden) 이
|
|
9
|
+
* 기록했을 이벤트만 같은 인자로 받고, onerror 는 그 이벤트에서 난 예외만 받는다
|
|
10
|
+
*/
|
|
11
|
+
export interface TappedAudit<R extends Registry> {
|
|
12
|
+
registry: R;
|
|
13
|
+
audit: AuditConfig;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* emit = 이벤트 사본 (JSON 값) 전달. 예외는 삼키고 반환값을 기다리지 않는다.
|
|
17
|
+
* registry = 프로젝트가 기록하지 않는 호출 (설정 없음 · readOnly 인데 includeReadOnly 아님) 의 명령어만
|
|
18
|
+
* audit 함수 (target · summary · input) 를 예외를 삼키는 래퍼로 바꾼 사본: 그 예외가 프로젝트 onerror 로 가지 않게
|
|
19
|
+
*/
|
|
20
|
+
export declare function tapAudit<R extends Registry>(registry: R, project: AuditConfig | undefined, emit: (event: AuditEvent) => void): TappedAudit<R>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* emit = 이벤트 사본 (JSON 값) 전달. 예외는 삼키고 반환값을 기다리지 않는다.
|
|
3
|
+
* registry = 프로젝트가 기록하지 않는 호출 (설정 없음 · readOnly 인데 includeReadOnly 아님) 의 명령어만
|
|
4
|
+
* audit 함수 (target · summary · input) 를 예외를 삼키는 래퍼로 바꾼 사본: 그 예외가 프로젝트 onerror 로 가지 않게
|
|
5
|
+
*/
|
|
6
|
+
export function tapAudit(registry, project, emit) {
|
|
7
|
+
/** 프로젝트 설정이 이 이벤트를 기록했을지 (audit.ts startAudit · auditHidden 과 같은 조건) */
|
|
8
|
+
const recorded = (event) => {
|
|
9
|
+
if (!project)
|
|
10
|
+
return false;
|
|
11
|
+
if (event.outcome === "hidden")
|
|
12
|
+
return project.includeHidden === true;
|
|
13
|
+
return !event.readOnly || project.includeReadOnly === true;
|
|
14
|
+
};
|
|
15
|
+
const audit = {
|
|
16
|
+
includeReadOnly: true,
|
|
17
|
+
includeHidden: true,
|
|
18
|
+
...(project?.input !== undefined ? { input: project.input } : {}),
|
|
19
|
+
...(project?.onerror ? { onerror: project.onerror } : {}),
|
|
20
|
+
sink(event) {
|
|
21
|
+
try {
|
|
22
|
+
// 프로젝트 sink 가 이벤트를 바꾸기 전의 값. 직렬화할 수 없는 입력 (순환 · bigint) = 입력 없이
|
|
23
|
+
emit(copy(event));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// tap 의 예외는 응답 · 프로젝트 sink 에 영향을 주지 않는다
|
|
27
|
+
}
|
|
28
|
+
// 프로젝트 sink 의 반환 (Promise) · 예외는 그대로: 응답 전 await · onerror 보고 (§11.1)
|
|
29
|
+
return recorded(event) ? project.sink(event) : undefined;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const quiet = (entry) => !project || (entry.command.readOnly && project.includeReadOnly !== true);
|
|
33
|
+
const commands = new Map();
|
|
34
|
+
for (const [id, entry] of registry.commands) {
|
|
35
|
+
commands.set(id, entry.command.audit && quiet(entry) ? { ...entry, command: quietAudit(entry.command) } : entry);
|
|
36
|
+
}
|
|
37
|
+
return { registry: { ...registry, commands }, audit };
|
|
38
|
+
}
|
|
39
|
+
function copy(event) {
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(JSON.stringify(event));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
const { input: _input, target: _target, ...rest } = event;
|
|
45
|
+
return JSON.parse(JSON.stringify(rest));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** audit 함수의 예외 = 그 필드 없음 (audit.ts guarded 가 보고 없이 계속했을 때와 같은 이벤트) */
|
|
49
|
+
function quietAudit(command) {
|
|
50
|
+
const a = command.audit;
|
|
51
|
+
const audit = {
|
|
52
|
+
...a,
|
|
53
|
+
...(typeof a.target === "function" ? { target: quiet(a.target) } : {}),
|
|
54
|
+
...(typeof a.summary === "function" ? { summary: quiet(a.summary) } : {}),
|
|
55
|
+
// 가림 함수 예외 = 입력 없이 (가리지 않은 값으로 대체하지 않는다)
|
|
56
|
+
...(typeof a.input === "function" ? { input: quiet(a.input) } : {}),
|
|
57
|
+
};
|
|
58
|
+
return { ...command, audit };
|
|
59
|
+
}
|
|
60
|
+
function quiet(fn) {
|
|
61
|
+
return (...args) => {
|
|
62
|
+
try {
|
|
63
|
+
return fn(...args);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=dev-tap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-tap.js","sourceRoot":"","sources":["../../src/cli/dev-tap.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AuditConfig, AuditEvent } from \"../audit.ts\"\nimport type { Command, CommandAudit } from \"../command.ts\"\nimport type { RegisteredCommand, Registry } from \"../registry.ts\"\n\n/**\n * mext dev 의 감사 tap, 서버 자식 쪽 (spec §10 감사 tap). cli/dev-server.ts 만 import 한다:\n * mext start · handler.js · 로컬 bin · 고객 CLI · mext dev --stdio 에는 이 코드 경로가 없다.\n *\n * 프로젝트 audit 설정을 감싸 모든 호출의 이벤트를 emit 으로 넘긴다 (readOnly · 숨긴 명령어 호출 시도 포함).\n * 프로젝트가 관찰하는 동작은 tap 이 없을 때와 같다: 프로젝트 sink 는 자기 설정 (includeReadOnly · includeHidden) 이\n * 기록했을 이벤트만 같은 인자로 받고, onerror 는 그 이벤트에서 난 예외만 받는다\n */\n\nexport interface TappedAudit<R extends Registry> {\n registry: R\n audit: AuditConfig\n}\n\n/**\n * emit = 이벤트 사본 (JSON 값) 전달. 예외는 삼키고 반환값을 기다리지 않는다.\n * registry = 프로젝트가 기록하지 않는 호출 (설정 없음 · readOnly 인데 includeReadOnly 아님) 의 명령어만\n * audit 함수 (target · summary · input) 를 예외를 삼키는 래퍼로 바꾼 사본: 그 예외가 프로젝트 onerror 로 가지 않게\n */\nexport function tapAudit<R extends Registry>(registry: R, project: AuditConfig | undefined, emit: (event: AuditEvent) => void): TappedAudit<R> {\n /** 프로젝트 설정이 이 이벤트를 기록했을지 (audit.ts startAudit · auditHidden 과 같은 조건) */\n const recorded = (event: AuditEvent): boolean => {\n if (!project) return false\n if (event.outcome === \"hidden\") return project.includeHidden === true\n return !event.readOnly || project.includeReadOnly === true\n }\n const audit: AuditConfig = {\n includeReadOnly: true,\n includeHidden: true,\n ...(project?.input !== undefined ? { input: project.input } : {}),\n ...(project?.onerror ? { onerror: project.onerror } : {}),\n sink(event) {\n try {\n // 프로젝트 sink 가 이벤트를 바꾸기 전의 값. 직렬화할 수 없는 입력 (순환 · bigint) = 입력 없이\n emit(copy(event))\n } catch {\n // tap 의 예외는 응답 · 프로젝트 sink 에 영향을 주지 않는다\n }\n // 프로젝트 sink 의 반환 (Promise) · 예외는 그대로: 응답 전 await · onerror 보고 (§11.1)\n return recorded(event) ? project!.sink(event) : undefined\n },\n }\n const quiet = (entry: RegisteredCommand): boolean => !project || (entry.command.readOnly && project.includeReadOnly !== true)\n const commands = new Map<string, RegisteredCommand>()\n for (const [id, entry] of registry.commands) {\n commands.set(id, entry.command.audit && quiet(entry) ? { ...entry, command: quietAudit(entry.command) } : entry)\n }\n return { registry: { ...registry, commands }, audit }\n}\n\nfunction copy(event: AuditEvent): AuditEvent {\n try {\n return JSON.parse(JSON.stringify(event)) as AuditEvent\n } catch {\n const { input: _input, target: _target, ...rest } = event\n return JSON.parse(JSON.stringify(rest)) as AuditEvent\n }\n}\n\n/** audit 함수의 예외 = 그 필드 없음 (audit.ts guarded 가 보고 없이 계속했을 때와 같은 이벤트) */\nfunction quietAudit(command: Command): Command {\n const a = command.audit!\n const audit: CommandAudit = {\n ...a,\n ...(typeof a.target === \"function\" ? { target: quiet(a.target) } : {}),\n ...(typeof a.summary === \"function\" ? { summary: quiet(a.summary) } : {}),\n // 가림 함수 예외 = 입력 없이 (가리지 않은 값으로 대체하지 않는다)\n ...(typeof a.input === \"function\" ? { input: quiet(a.input) } : {}),\n }\n return { ...command, audit }\n}\n\nfunction quiet<A extends unknown[], T>(fn: (...args: A) => T): (...args: A) => T | undefined {\n return (...args) => {\n try {\n return fn(...args)\n } catch {\n return undefined\n }\n }\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
|
@@ -11,6 +11,7 @@ import { redirectStdout, serveMcpStdio } from "../mcp/stdio.js";
|
|
|
11
11
|
import { loadPromptSet, withPrompts } from "../prompt.js";
|
|
12
12
|
import { loadResourceSet, withResources } from "../resource.js";
|
|
13
13
|
import { loadRegistry } from "../scan.js";
|
|
14
|
+
import { createDevAuditHub, newAuditToken } from "./dev-audit.js";
|
|
14
15
|
import { acquireDevLock, releaseDevLock, updateDevLock } from "./dev-lock.js";
|
|
15
16
|
import { table } from "./help.js";
|
|
16
17
|
import { EXIT, exitCodeOf, formatError } from "./output.js";
|
|
@@ -34,7 +35,7 @@ export async function devCommand(argv, io) {
|
|
|
34
35
|
return EXIT.ok;
|
|
35
36
|
}
|
|
36
37
|
if (parsed.stdio)
|
|
37
|
-
return
|
|
38
|
+
return sourceStdio(io);
|
|
38
39
|
return supervise(parsed, io);
|
|
39
40
|
}
|
|
40
41
|
/** 반환 문자열 = 사용법 오류 메시지 */
|
|
@@ -74,18 +75,18 @@ export function parseDevArgs(argv) {
|
|
|
74
75
|
}
|
|
75
76
|
/* ---------------------------------------------------------------- stdio */
|
|
76
77
|
/**
|
|
77
|
-
* 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) 는
|
|
78
79
|
* 명령어 import 전부터 종료까지 stderr 로 돌린다. stdin EOF = 연결 종료 → 바로 반환 (bin 이 exit).
|
|
79
80
|
* 감시 · 잠금 없음: MCP 클라이언트가 프로세스를 소유 · 재실행한다
|
|
80
81
|
*/
|
|
81
|
-
async function
|
|
82
|
+
export async function sourceStdio(io, prog = DEV_PROG) {
|
|
82
83
|
const redirect = io.stdout === process.stdout ? redirectStdout() : undefined;
|
|
83
84
|
const wire = redirect?.wire ?? writerStream(io.stdout);
|
|
84
85
|
try {
|
|
85
86
|
const instrumentation = await loadProjectInstrumentation(io.cwd);
|
|
86
87
|
const config = await loadConfig(io.cwd);
|
|
87
88
|
const registry = withPrompts(withResources(await loadRegistry(resolveCommandsDir(io.cwd, config)), await loadResourceSet(resolveResourcesDir(io.cwd, config))), await loadPromptSet(resolvePromptsDir(io.cwd, config)));
|
|
88
|
-
const principal = await resolveLocalPrincipal(config);
|
|
89
|
+
const principal = await resolveLocalPrincipal(config, "stdio");
|
|
89
90
|
const server = serveMcpStdio({
|
|
90
91
|
registry,
|
|
91
92
|
instrumentation,
|
|
@@ -111,7 +112,7 @@ async function stdio(io) {
|
|
|
111
112
|
return io.signal?.aborted ? EXIT.interrupted : EXIT.ok;
|
|
112
113
|
}
|
|
113
114
|
catch (error) {
|
|
114
|
-
io.stderr.write(formatError(error,
|
|
115
|
+
io.stderr.write(formatError(error, prog));
|
|
115
116
|
return exitCodeOf(error);
|
|
116
117
|
}
|
|
117
118
|
// redirect 는 원복하지 않는다: 종료 중 남은 핸들러 출력도 stdout 에 섞이지 않게 (프로세스는 곧 exit)
|
|
@@ -135,9 +136,11 @@ function writerStream(writer) {
|
|
|
135
136
|
async function supervise(args, io) {
|
|
136
137
|
const cwd = resolve(io.cwd);
|
|
137
138
|
const log = (line) => void io.stderr.write(`${DEV_PROG}: ${line}\n`);
|
|
139
|
+
// 감사 tap (spec §10): 실행마다 새 토큰. 잠금 파일에만 적는다 (출력하지 않는다)
|
|
140
|
+
const auditToken = newAuditToken();
|
|
138
141
|
let lock;
|
|
139
142
|
try {
|
|
140
|
-
const got = acquireDevLock(cwd);
|
|
143
|
+
const got = acquireDevLock(cwd, null, auditToken);
|
|
141
144
|
if ("running" in got) {
|
|
142
145
|
const where = got.running.url ? `at ${got.running.url}` : "(starting)";
|
|
143
146
|
io.stderr.write(`error: ${DEV_PROG} is already running ${where} (PID ${got.running.pid}).\n` +
|
|
@@ -152,7 +155,7 @@ async function supervise(args, io) {
|
|
|
152
155
|
}
|
|
153
156
|
const onExit = () => releaseDevLock(cwd);
|
|
154
157
|
process.on("exit", onExit);
|
|
155
|
-
const supervisor = new DevSupervisor(cwd, log);
|
|
158
|
+
const supervisor = new DevSupervisor(cwd, log, createDevAuditHub(auditToken));
|
|
156
159
|
try {
|
|
157
160
|
const first = await supervisor.start();
|
|
158
161
|
const host = args.host ?? first?.host ?? DEFAULT_HOST;
|
|
@@ -206,9 +209,12 @@ class DevSupervisor {
|
|
|
206
209
|
debounce;
|
|
207
210
|
changed = new Set();
|
|
208
211
|
firstConfig;
|
|
209
|
-
|
|
212
|
+
/** 감사 tap: 자식이 넘긴 이벤트 보관 · endpoint */
|
|
213
|
+
audit;
|
|
214
|
+
constructor(cwd, log, audit) {
|
|
210
215
|
this.cwd = cwd;
|
|
211
216
|
this.log = log;
|
|
217
|
+
this.audit = audit;
|
|
212
218
|
this.commandsDir = resolve(cwd, "commands");
|
|
213
219
|
this.optionalDirs = ["routes", "resources", "prompts"].map((name) => resolve(cwd, name));
|
|
214
220
|
}
|
|
@@ -259,6 +265,8 @@ class DevSupervisor {
|
|
|
259
265
|
this.onConfig(child, message);
|
|
260
266
|
else if (message.type === "ready")
|
|
261
267
|
this.onReady(child, message.port, message.commands);
|
|
268
|
+
else if (message.type === "audit")
|
|
269
|
+
this.audit.push(message.event);
|
|
262
270
|
else if (message.type === "error") {
|
|
263
271
|
failed = true;
|
|
264
272
|
this.onLoadFailed(child, message.message);
|
|
@@ -367,6 +375,9 @@ class DevSupervisor {
|
|
|
367
375
|
}
|
|
368
376
|
/* -------------------------------------------------------------- 요청 중계 */
|
|
369
377
|
dispatch(req, res) {
|
|
378
|
+
// 감사 tap endpoint = 감독 프로세스가 직접 응답 (자식으로 중계하지 않는다. 재시작 중에도 응답)
|
|
379
|
+
if (this.audit.handle(req, res))
|
|
380
|
+
return;
|
|
370
381
|
if (this.pending) {
|
|
371
382
|
this.queue.push(() => this.dispatch(req, res));
|
|
372
383
|
return;
|
|
@@ -509,6 +520,7 @@ class DevSupervisor {
|
|
|
509
520
|
clearTimeout(this.debounce);
|
|
510
521
|
for (const w of this.watchers.values())
|
|
511
522
|
w.close();
|
|
523
|
+
this.audit.close();
|
|
512
524
|
this.watchers.clear();
|
|
513
525
|
const children = [this.current, this.pending, ...this.retired].filter((c) => c !== undefined);
|
|
514
526
|
const exited = children.map((c) => new Promise((done) => {
|
package/dist/cli/dev.js.map
CHANGED
|
@@ -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 { 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)\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 let lock: DevLock\n try {\n const got = acquireDevLock(cwd)\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)\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\n constructor(cwd: string, log: (line: string) => void) {\n this.cwd = cwd\n this.log = log\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 === \"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 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.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/help.js
CHANGED
|
@@ -71,6 +71,8 @@ export function renderCommandHelp(entry, options) {
|
|
|
71
71
|
safety.push("destructive");
|
|
72
72
|
if (c.requiresConfirmation)
|
|
73
73
|
safety.push("requires confirmation (--yes to approve)");
|
|
74
|
+
else if (c.needsApproval !== undefined)
|
|
75
|
+
safety.push("may require confirmation (--yes to approve)");
|
|
74
76
|
if (c.scopes.length > 0)
|
|
75
77
|
safety.push(`scopes: ${c.scopes.join(", ")}`);
|
|
76
78
|
out.push(`Safety: ${safety.join(", ")}`);
|