@obov/mext 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +30 -3
- 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/build.js +4 -2
- 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 +24 -1
- 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.js +16 -4
- 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 +8 -0
- package/dist/cli/main.js.map +1 -1
- 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 +28 -4
- package/dist/cli/run.js.map +1 -1
- 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 +10 -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 +37 -3
- package/dist/client/runner.js.map +1 -1
- package/dist/client/typed.d.ts +54 -0
- package/dist/client/typed.js +490 -0
- package/dist/client/typed.js.map +1 -0
- package/dist/client/types.d.ts +196 -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 +42 -10
- package/dist/config.js +32 -7
- package/dist/config.js.map +1 -1
- 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 +15 -6
- package/dist/index.js +7 -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 +32 -5
- package/dist/invoke.js +150 -16
- package/dist/invoke.js.map +1 -1
- package/dist/manifest.d.ts +13 -2
- package/dist/manifest.js +5 -1
- package/dist/manifest.js.map +1 -1
- package/dist/mcp/constants.d.ts +5 -0
- package/dist/mcp/constants.js +5 -0
- package/dist/mcp/constants.js.map +1 -1
- package/dist/mcp/dispatch.d.ts +1 -1
- package/dist/mcp/dispatch.js +14 -3
- 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/http.d.ts +16 -2
- package/dist/mcp/http.js +76 -7
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +1 -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 +6 -3
- 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 +2 -0
- package/dist/remote/client.js +3 -2
- package/dist/remote/client.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/start.js +6 -2
- 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/principal.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/** 행위자 종류. auth · localPrincipal 이 정한다 */
|
|
2
|
+
export type ActorKind = "human" | "agent" | "service" | "system";
|
|
3
|
+
/** 행위자. 서버 (auth · localPrincipal) 가 정한 값만. 클라이언트 신고 값으로 정하지 않는다 */
|
|
4
|
+
export interface Actor {
|
|
5
|
+
kind: ActorKind;
|
|
6
|
+
/** 행위자 식별자 (사용자 ID · 에이전트 ID). principal.id 와 다를 수 있다 (에이전트가 사용자 계정으로 실행) */
|
|
7
|
+
id?: string;
|
|
8
|
+
}
|
|
1
9
|
/** 요청 주체. 서버가 요청마다 생성 (HTTP · CLI 원격), 로컬 · stdio = kind local */
|
|
2
10
|
export interface Principal {
|
|
3
11
|
/** "local:obov" | "user_123" | "anonymous" */
|
|
@@ -7,6 +15,13 @@ export interface Principal {
|
|
|
7
15
|
scopes: string[];
|
|
8
16
|
/** 검증된 토큰 내용. 토큰 원문은 포함하지 않는다 */
|
|
9
17
|
claims?: Record<string, unknown>;
|
|
18
|
+
/** 행위자 (ctx.caller.actor). 없음 = 미확정. mext 는 추정하지 않는다 */
|
|
19
|
+
actor?: Actor;
|
|
20
|
+
/**
|
|
21
|
+
* 논리 표면 (ctx.caller.surface). kebab-case 이름. 없음 = 어댑터 기본 (cli · mcp · stdio).
|
|
22
|
+
* 같은 POST /mcp 요청을 호출자별로 나눌 때 auth 가 정한다 (예: 웹 앱 세션 = "web")
|
|
23
|
+
*/
|
|
24
|
+
surface?: string;
|
|
10
25
|
}
|
|
11
26
|
/** 인증 없는 주체. scopes 없음 → readOnly 명령어만 */
|
|
12
27
|
export declare const ANONYMOUS: Principal;
|
|
@@ -14,3 +29,10 @@ export declare const ANONYMOUS: Principal;
|
|
|
14
29
|
export declare function localPrincipal(user?: string): Principal;
|
|
15
30
|
/** "*" = 전체 */
|
|
16
31
|
export declare function hasScope(principal: Principal, scope: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* principal.actor · surface 형식 문제. 없으면 undefined.
|
|
34
|
+
* id · kind · scopes 는 검사하지 않는다 (auth 결과를 검사하지 않던 기존 동작 유지)
|
|
35
|
+
*/
|
|
36
|
+
export declare function callerFieldsProblem(value: unknown): string | undefined;
|
|
37
|
+
/** callerFieldsProblem 이 있으면 TypeError ("<source>: principal <문제>"). source = "auth" · "localPrincipal" */
|
|
38
|
+
export declare function assertCallerFields(value: unknown, source: string): asserts value is Principal;
|
package/dist/principal.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { userInfo } from "node:os";
|
|
2
|
+
import { isSegment } from "./ids.js";
|
|
3
|
+
const ACTOR_KINDS = ["human", "agent", "service", "system"];
|
|
2
4
|
/** 인증 없는 주체. scopes 없음 → readOnly 명령어만 */
|
|
3
5
|
export const ANONYMOUS = Object.freeze({
|
|
4
6
|
id: "anonymous",
|
|
@@ -13,6 +15,33 @@ export function localPrincipal(user = osUser()) {
|
|
|
13
15
|
export function hasScope(principal, scope) {
|
|
14
16
|
return principal.scopes.includes("*") || principal.scopes.includes(scope);
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* principal.actor · surface 형식 문제. 없으면 undefined.
|
|
20
|
+
* id · kind · scopes 는 검사하지 않는다 (auth 결과를 검사하지 않던 기존 동작 유지)
|
|
21
|
+
*/
|
|
22
|
+
export function callerFieldsProblem(value) {
|
|
23
|
+
const p = value;
|
|
24
|
+
if (typeof p !== "object" || p === null)
|
|
25
|
+
return "must be an object ({ id, kind, scopes })";
|
|
26
|
+
if (p.surface !== undefined && (typeof p.surface !== "string" || !isSegment(p.surface))) {
|
|
27
|
+
return 'surface must be a kebab-case name (e.g. "web")';
|
|
28
|
+
}
|
|
29
|
+
if (p.actor !== undefined) {
|
|
30
|
+
const a = p.actor;
|
|
31
|
+
if (typeof a !== "object" || a === null || !ACTOR_KINDS.includes(a.kind)) {
|
|
32
|
+
return 'actor.kind must be "human", "agent", "service" or "system"';
|
|
33
|
+
}
|
|
34
|
+
if (a.id !== undefined && typeof a.id !== "string")
|
|
35
|
+
return "actor.id must be a string";
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
/** callerFieldsProblem 이 있으면 TypeError ("<source>: principal <문제>"). source = "auth" · "localPrincipal" */
|
|
40
|
+
export function assertCallerFields(value, source) {
|
|
41
|
+
const problem = callerFieldsProblem(value);
|
|
42
|
+
if (problem !== undefined)
|
|
43
|
+
throw new TypeError(`${source}: principal ${problem}`);
|
|
44
|
+
}
|
|
16
45
|
function osUser() {
|
|
17
46
|
try {
|
|
18
47
|
return userInfo().username;
|
package/dist/principal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principal.js","sourceRoot":"","sources":["../src/principal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"principal.js","sourceRoot":"","sources":["../src/principal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAYpC,MAAM,WAAW,GAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;AAoB9E,0CAA0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAc,MAAM,CAAC,MAAM,CAAC;IAChD,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAwB;CACjD,CAAc,CAAA;AAEf,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,IAAI,GAAW,MAAM,EAAE;IACpD,OAAO,EAAE,EAAE,EAAE,SAAS,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;AAC9D,CAAC;AAED,eAAe;AACf,MAAM,UAAU,QAAQ,CAAC,SAAoB,EAAE,KAAa;IAC1D,OAAO,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC3E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,MAAM,CAAC,GAAG,KAAkC,CAAA;IAC5C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,0CAA0C,CAAA;IAC1F,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACxF,OAAO,gDAAgD,CAAA;IACzD,CAAC;IACD,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,KAA8B,CAAA;QAC1C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAc,CAAC,EAAE,CAAC;YACnF,OAAO,4DAA4D,CAAA;QACrE,CAAC;QACD,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO,2BAA2B,CAAA;IACxF,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,2GAA2G;AAC3G,MAAM,UAAU,kBAAkB,CAAC,KAAc,EAAE,MAAc;IAC/D,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IAC1C,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,SAAS,CAAC,GAAG,MAAM,eAAe,OAAO,EAAE,CAAC,CAAA;AACnF,CAAC;AAED,SAAS,MAAM;IACb,IAAI,CAAC;QACH,OAAO,QAAQ,EAAE,CAAC,QAAQ,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAA;IAC9D,CAAC;AACH,CAAC","sourcesContent":["import { userInfo } from \"node:os\"\nimport { isSegment } from \"./ids.ts\"\n\n/** 행위자 종류. auth · localPrincipal 이 정한다 */\nexport type ActorKind = \"human\" | \"agent\" | \"service\" | \"system\"\n\n/** 행위자. 서버 (auth · localPrincipal) 가 정한 값만. 클라이언트 신고 값으로 정하지 않는다 */\nexport interface Actor {\n kind: ActorKind\n /** 행위자 식별자 (사용자 ID · 에이전트 ID). principal.id 와 다를 수 있다 (에이전트가 사용자 계정으로 실행) */\n id?: string\n}\n\nconst ACTOR_KINDS: readonly string[] = [\"human\", \"agent\", \"service\", \"system\"]\n\n/** 요청 주체. 서버가 요청마다 생성 (HTTP · CLI 원격), 로컬 · stdio = kind local */\nexport interface Principal {\n /** \"local:obov\" | \"user_123\" | \"anonymous\" */\n id: string\n kind: \"local\" | \"token\" | \"anonymous\"\n /** \"*\" = 전체 */\n scopes: string[]\n /** 검증된 토큰 내용. 토큰 원문은 포함하지 않는다 */\n claims?: Record<string, unknown>\n /** 행위자 (ctx.caller.actor). 없음 = 미확정. mext 는 추정하지 않는다 */\n actor?: Actor\n /**\n * 논리 표면 (ctx.caller.surface). kebab-case 이름. 없음 = 어댑터 기본 (cli · mcp · stdio).\n * 같은 POST /mcp 요청을 호출자별로 나눌 때 auth 가 정한다 (예: 웹 앱 세션 = \"web\")\n */\n surface?: string\n}\n\n/** 인증 없는 주체. scopes 없음 → readOnly 명령어만 */\nexport const ANONYMOUS: Principal = Object.freeze({\n id: \"anonymous\",\n kind: \"anonymous\",\n scopes: Object.freeze([]) as unknown as string[],\n}) as Principal\n\n/** 로컬 · stdio 실행의 기본 주체: { id: \"local:<OS 사용자>\", kind: \"local\", scopes: [\"*\"] } */\nexport function localPrincipal(user: string = osUser()): Principal {\n return { id: `local:${user}`, kind: \"local\", scopes: [\"*\"] }\n}\n\n/** \"*\" = 전체 */\nexport function hasScope(principal: Principal, scope: string): boolean {\n return principal.scopes.includes(\"*\") || principal.scopes.includes(scope)\n}\n\n/**\n * principal.actor · surface 형식 문제. 없으면 undefined.\n * id · kind · scopes 는 검사하지 않는다 (auth 결과를 검사하지 않던 기존 동작 유지)\n */\nexport function callerFieldsProblem(value: unknown): string | undefined {\n const p = value as Partial<Principal> | null\n if (typeof p !== \"object\" || p === null) return \"must be an object ({ id, kind, scopes })\"\n if (p.surface !== undefined && (typeof p.surface !== \"string\" || !isSegment(p.surface))) {\n return 'surface must be a kebab-case name (e.g. \"web\")'\n }\n if (p.actor !== undefined) {\n const a = p.actor as Partial<Actor> | null\n if (typeof a !== \"object\" || a === null || !ACTOR_KINDS.includes(a.kind as string)) {\n return 'actor.kind must be \"human\", \"agent\", \"service\" or \"system\"'\n }\n if (a.id !== undefined && typeof a.id !== \"string\") return \"actor.id must be a string\"\n }\n return undefined\n}\n\n/** callerFieldsProblem 이 있으면 TypeError (\"<source>: principal <문제>\"). source = \"auth\" · \"localPrincipal\" */\nexport function assertCallerFields(value: unknown, source: string): asserts value is Principal {\n const problem = callerFieldsProblem(value)\n if (problem !== undefined) throw new TypeError(`${source}: principal ${problem}`)\n}\n\nfunction osUser(): string {\n try {\n return userInfo().username\n } catch {\n return process.env.USER ?? process.env.USERNAME ?? \"unknown\"\n }\n}\n"]}
|
package/dist/registry.d.ts
CHANGED
|
@@ -90,6 +90,11 @@ export declare function createLazyRegistry(input: {
|
|
|
90
90
|
commands: readonly LazyCommandInput[];
|
|
91
91
|
namespaces?: readonly RegistryNamespaceInput[];
|
|
92
92
|
}): Registry;
|
|
93
|
+
/**
|
|
94
|
+
* keep 을 통과한 명령어만 남긴 Registry (expose 의 표면별 보기). 별칭 · 네임스페이스를 다시 계산한다:
|
|
95
|
+
* 남은 명령어가 없는 네임스페이스는 없어지고, 남은 네임스페이스의 설명은 유지. 명령어 항목 · 자원 · 프롬프트는 원본과 같은 객체
|
|
96
|
+
*/
|
|
97
|
+
export declare function filterRegistry(registry: Registry, keep: (entry: RegisteredCommand) => boolean): Registry;
|
|
93
98
|
/** 실행 가능한 명령어. eager = entry.command, lazy = entry.load() (모듈 import) */
|
|
94
99
|
export declare function loadCommand(entry: RegisteredCommand): Promise<Command>;
|
|
95
100
|
/** 정식 ID 또는 별칭으로 명령어 찾기 */
|
package/dist/registry.js
CHANGED
|
@@ -134,6 +134,27 @@ export function createLazyRegistry(input) {
|
|
|
134
134
|
}
|
|
135
135
|
return { commands, aliases, namespaces: namespaceTable(namespaceIds, [...commands.keys()], input.namespaces) };
|
|
136
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* keep 을 통과한 명령어만 남긴 Registry (expose 의 표면별 보기). 별칭 · 네임스페이스를 다시 계산한다:
|
|
139
|
+
* 남은 명령어가 없는 네임스페이스는 없어지고, 남은 네임스페이스의 설명은 유지. 명령어 항목 · 자원 · 프롬프트는 원본과 같은 객체
|
|
140
|
+
*/
|
|
141
|
+
export function filterRegistry(registry, keep) {
|
|
142
|
+
const commands = new Map();
|
|
143
|
+
for (const [id, entry] of registry.commands)
|
|
144
|
+
if (keep(entry))
|
|
145
|
+
commands.set(id, entry);
|
|
146
|
+
const aliases = new Map();
|
|
147
|
+
for (const [alias, id] of registry.aliases)
|
|
148
|
+
if (commands.has(id))
|
|
149
|
+
aliases.set(alias, id);
|
|
150
|
+
const namespaceIds = new Set([""]);
|
|
151
|
+
for (const id of commands.keys()) {
|
|
152
|
+
for (let ns = parentNamespace(id); ns !== ""; ns = parentNamespace(ns))
|
|
153
|
+
namespaceIds.add(ns);
|
|
154
|
+
}
|
|
155
|
+
const descriptions = [...registry.namespaces.values()].flatMap((n) => (n.description === undefined ? [] : [{ id: n.id, description: n.description }]));
|
|
156
|
+
return { ...registry, commands, aliases, namespaces: namespaceTable(namespaceIds, [...commands.keys()], descriptions) };
|
|
157
|
+
}
|
|
137
158
|
/** 실행 가능한 명령어. eager = entry.command, lazy = entry.load() (모듈 import) */
|
|
138
159
|
export function loadCommand(entry) {
|
|
139
160
|
return entry.load ? entry.load() : Promise.resolve(entry.command);
|
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AACxB,OAAO,EAAE,SAAS,EAAgB,MAAM,cAAc,CAAA;AACtD,OAAO,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAoE7E,gEAAgE;AAChE,MAAM,UAAU,cAAc,CAAC,KAAoB;IACjD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IACnD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC,CAAA;IACvD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAoB;IAClD,MAAM,MAAM,GAAiB,EAAE,CAAA;IAC/B,MAAM,QAAQ,GAA2B,EAAE,CAAA;IAC3C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAgC,CAAA;IAEpD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;QAChD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,4BAA4B,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;YACzF,SAAQ;QACV,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/C,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,GAAG,qBAAqB,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;YACjG,SAAQ;QACV,CAAC;QACD,IAAI,sBAAsB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,QAAQ,CAAC,CAAC,CAAC,eAAe,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;YACpG,SAAQ;QACV,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC/B,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,sBAAsB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;YACvG,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;QACzB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;IAED,6BAA6B;IAC7B,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1C,KAAK,MAAM,EAAE,EAAE,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC9B,KAAK,IAAI,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC;YAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC9F,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAA;IACzC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAA;IAC7C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;QAChD,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACxC,MAAM,GAAG,GAAa,EAAE,CAAA;QACxB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC1C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,KAAK,+BAA+B,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;gBACzG,SAAQ;YACV,CAAC;YACD,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,KAAK,wCAAwC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;gBAClH,SAAQ;YACV,CAAC;YACD,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,KAAK,EAAE,CAAA;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACvD,IAAI,KAAK,KAAK,SAAS,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClD,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,SAAS,IAAI,eAAe,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,EAAE;oBAClF,GAAG,KAAK;iBACT,CAAC,CAAA;gBACF,SAAQ;YACV,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;YAC3B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAA;IACrD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;QAChD,IAAI,WAAuB,CAAA;QAC3B,IAAI,YAAoC,CAAA;QACxC,IAAI,CAAC;YACH,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;YACxD,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAChG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;YACvF,SAAQ;QACV,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE;YACrB,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE;YACtC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW;YACX,YAAY;SACb,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,cAAc,CAAC,YAAY,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;IACvF,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,CAAA;AAChE,CAAC;AAgBD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAGlC;IACC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAA;IACrD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAA;IACzC,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC/E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QACvB,IAAI,OAAqC,CAAA;QACzC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE;YACrB,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE;YAClC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,IAAI,EAAE,GAAG,EAAE,CACT,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBAC3C,OAAO,GAAG,SAAS,CAAA;gBACnB,MAAM,KAAK,CAAA;YACb,CAAC,CAAC,CAAC;SACN,CAAC,CAAA;QACF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;IACjE,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1C,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QACjC,KAAK,IAAI,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC;YAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC9F,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC,YAAY,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAA;AAChH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,WAAW,CAAC,KAAwB;IAClD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AACnE,CAAC;AAED,SAAS,cAAc,CACrB,YAAiC,EACjC,UAA6B,EAC7B,MAAqD;IAErD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAA;IAC1D,KAAK,MAAM,EAAE,IAAI,MAAM,IAAI,EAAE;QAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,CAAA;IACtE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyB,CAAA;IACnD,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACpD,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE;YACjB,EAAE;YACF,WAAW,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;YAC7D,UAAU,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;SACpG,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,2BAA2B;AAC3B,MAAM,UAAU,cAAc,CAAC,QAAkB,EAAE,EAAU;IAC3D,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;AAC3F,CAAC;AAED,SAAS,YAAY,CAAC,MAAiB,EAAE,EAAsB;IAC7D,OAAO,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,CAAe,CAAA;AACxG,CAAC;AAED,SAAS,UAAU,CAAC,CAAS,EAAE,CAAS;IACtC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACnC,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC/D,CAAC","sourcesContent":["import * as z from \"zod\"\nimport { isCommand, type Command } from \"./command.ts\"\nimport { MextBuildError, type BuildIssue } from \"./errors.ts\"\nimport { isSegment, parentNamespace, RESERVED_ROOT_SEGMENTS } from \"./ids.ts\"\nimport type { PromptSet } from \"./prompt.ts\"\nimport type { ResourceSet } from \"./resource.ts\"\n\nexport type JsonSchema = Record<string, unknown>\n\nexport interface RegistryCommandInput {\n /** 정식 ID. 점 구분 kebab-case 세그먼트 */\n id: string\n command: Command\n /** commands/ 기준 상대 경로 (posix). 스캔 결과에만 있음 */\n file?: string\n}\n\nexport interface RegistryNamespaceInput {\n /** \"\" = 루트 */\n id: string\n description?: string\n}\n\nexport interface RegistryInput {\n commands: readonly RegistryCommandInput[]\n namespaces?: readonly RegistryNamespaceInput[]\n}\n\nexport interface RegisteredCommand {\n id: string\n /**\n * 메타데이터 (description · 안전성 · scopes · examples · positional · aliases) 의 원본.\n * eager (createRegistry) = 실행 가능한 명령어 그대로. lazy (createLazyRegistry) = manifest 로 만든 메타데이터만\n * (input · execute 는 load() 결과에서)\n */\n command: Command\n /** lazy Registry: 명령어 모듈 import (1회 캐시) → 실행 가능한 명령어. 없음 = command 가 실행 가능. loadCommand 로 호출 */\n load?: () => Promise<Command>\n /** 별칭의 전체 ID (정렬) */\n aliases: readonly string[]\n file: string | undefined\n /** input 의 JSON Schema 2020-12 (io: input) */\n inputSchema: JsonSchema\n /** output 의 JSON Schema 2020-12 (io: output) */\n outputSchema: JsonSchema | undefined\n}\n\nexport interface NamespaceInfo {\n /** \"\" = 루트 */\n id: string\n /** _index.md 내용 */\n description: string | undefined\n /** 직속 명령어 정식 ID (정렬). index.ts 명령어 (네임스페이스와 같은 ID) 는 상위 네임스페이스에 속한다 */\n commands: readonly string[]\n /** 직속 하위 네임스페이스 ID (정렬) */\n namespaces: readonly string[]\n}\n\nexport interface Registry {\n /** 정식 ID → 명령어. ID 순 */\n readonly commands: ReadonlyMap<string, RegisteredCommand>\n /** 별칭 전체 ID → 정식 ID */\n readonly aliases: ReadonlyMap<string, string>\n /** 네임스페이스 ID → 정보. 루트 (\"\") 포함, ID 순 */\n readonly namespaces: ReadonlyMap<string, NamespaceInfo>\n /** MCP 자원 (resources/, §12.3). 없음 = 기능 없음 (capability 미선언). 명령어 Map 과 별개 */\n readonly resources?: ResourceSet\n /** MCP 프롬프트 (prompts/, §12.3). 없음 = 기능 없음 (capability 미선언). 이름 순 */\n readonly prompts?: PromptSet\n}\n\n/** 명령어 목록에서 Registry 생성. ID · 별칭 · 스키마 규칙 위반은 MextBuildError */\nexport function createRegistry(input: RegistryInput): Registry {\n const { registry, issues } = collectRegistry(input)\n if (issues.length > 0) throw new MextBuildError(issues)\n return registry\n}\n\n/**\n * createRegistry 의 수집형 (mext build 의 일괄 검증용). 던지지 않는다.\n * registry = 규칙을 통과한 명령어만, issues = 위반 전부\n */\nexport function collectRegistry(input: RegistryInput): { registry: Registry; issues: BuildIssue[] } {\n const issues: BuildIssue[] = []\n const accepted: RegistryCommandInput[] = []\n const seen = new Map<string, RegistryCommandInput>()\n\n for (const entry of input.commands) {\n const where = { id: entry.id, file: entry.file }\n if (!isCommand(entry.command)) {\n issues.push({ code: \"INVALID_COMMAND\", message: \"not a defineCommand result\", ...where })\n continue\n }\n const segments = entry.id.split(\".\")\n const bad = segments.find((s) => !isSegment(s))\n if (bad !== undefined) {\n issues.push({ code: \"INVALID_SEGMENT\", message: `segment \"${bad}\" is not kebab-case`, ...where })\n continue\n }\n if (RESERVED_ROOT_SEGMENTS.includes(segments[0]!)) {\n issues.push({ code: \"RESERVED_ID\", message: `root segment \"${segments[0]}\" is reserved`, ...where })\n continue\n }\n const prev = seen.get(entry.id)\n if (prev) {\n issues.push({ code: \"DUPLICATE_ID\", message: `duplicate ID (also ${prev.file ?? prev.id})`, ...where })\n continue\n }\n seen.set(entry.id, entry)\n accepted.push(entry)\n }\n\n // 네임스페이스 = 명령어 ID 의 모든 상위 경로\n const namespaceIds = new Set<string>([\"\"])\n for (const { id } of accepted) {\n for (let ns = parentNamespace(id); ns !== \"\"; ns = parentNamespace(ns)) namespaceIds.add(ns)\n }\n\n const aliases = new Map<string, string>()\n const aliasesOf = new Map<string, string[]>()\n for (const entry of accepted) {\n const where = { id: entry.id, file: entry.file }\n const parent = parentNamespace(entry.id)\n const own: string[] = []\n for (const alias of entry.command.aliases) {\n if (!isSegment(alias)) {\n issues.push({ code: \"INVALID_ALIAS\", message: `alias \"${alias}\" is not a kebab-case segment`, ...where })\n continue\n }\n if (parent === \"\") {\n issues.push({ code: \"INVALID_ALIAS\", message: `alias \"${alias}\": aliases are not allowed at the root`, ...where })\n continue\n }\n const full = `${parent}.${alias}`\n const owner = seen.has(full) ? full : aliases.get(full)\n if (owner !== undefined || namespaceIds.has(full)) {\n issues.push({\n code: \"DUPLICATE_ID\",\n message: `alias ${full} duplicates ${owner !== undefined ? owner : \"a namespace\"}`,\n ...where,\n })\n continue\n }\n aliases.set(full, entry.id)\n own.push(full)\n }\n aliasesOf.set(entry.id, own.sort())\n }\n\n const commands = new Map<string, RegisteredCommand>()\n for (const entry of [...accepted].sort((a, b) => compareIds(a.id, b.id))) {\n const where = { id: entry.id, file: entry.file }\n let inputSchema: JsonSchema\n let outputSchema: JsonSchema | undefined\n try {\n inputSchema = toJsonSchema(entry.command.input, \"input\")\n outputSchema = entry.command.output ? toJsonSchema(entry.command.output, \"output\") : undefined\n } catch (error) {\n issues.push({ code: \"SCHEMA_UNREPRESENTABLE\", message: errorMessage(error), ...where })\n continue\n }\n commands.set(entry.id, {\n id: entry.id,\n command: entry.command,\n aliases: aliasesOf.get(entry.id) ?? [],\n file: entry.file,\n inputSchema,\n outputSchema,\n })\n }\n\n const namespaces = namespaceTable(namespaceIds, [...commands.keys()], input.namespaces)\n return { registry: { commands, aliases, namespaces }, issues }\n}\n\n/** lazy Registry 의 명령어: manifest 메타데이터 + 모듈 로더 (규칙 검증은 mext build 가 이미 함) */\nexport interface LazyCommandInput {\n id: string\n /** 메타데이터만 있는 명령어 (input · execute 는 load 결과). RegisteredCommand.command */\n command: Command\n /** 별칭의 전체 ID */\n aliases: readonly string[]\n file?: string\n inputSchema: JsonSchema\n outputSchema?: JsonSchema\n /** 실행 시 1회 호출 (결과 캐시, 실패는 다음 호출에서 재시도) */\n load: () => Promise<Command>\n}\n\n/**\n * manifest (mext build 산출) 로 Registry 생성. 명령어 모듈을 import 하지 않는다 (mext start · handler.js).\n * help · tools/list · UNKNOWN_COMMAND · 권한 검사 = 메타데이터만, 입력 검증 · execute = loadCommand 후\n */\nexport function createLazyRegistry(input: {\n commands: readonly LazyCommandInput[]\n namespaces?: readonly RegistryNamespaceInput[]\n}): Registry {\n const commands = new Map<string, RegisteredCommand>()\n const aliases = new Map<string, string>()\n for (const entry of [...input.commands].sort((a, b) => compareIds(a.id, b.id))) {\n const load = entry.load\n let pending: Promise<Command> | undefined\n commands.set(entry.id, {\n id: entry.id,\n command: entry.command,\n aliases: [...entry.aliases].sort(),\n file: entry.file,\n inputSchema: entry.inputSchema,\n outputSchema: entry.outputSchema,\n load: () =>\n (pending ??= load().catch((error: unknown) => {\n pending = undefined\n throw error\n })),\n })\n for (const alias of entry.aliases) aliases.set(alias, entry.id)\n }\n const namespaceIds = new Set<string>([\"\"])\n for (const id of commands.keys()) {\n for (let ns = parentNamespace(id); ns !== \"\"; ns = parentNamespace(ns)) namespaceIds.add(ns)\n }\n return { commands, aliases, namespaces: namespaceTable(namespaceIds, [...commands.keys()], input.namespaces) }\n}\n\n/** 실행 가능한 명령어. eager = entry.command, lazy = entry.load() (모듈 import) */\nexport function loadCommand(entry: RegisteredCommand): Promise<Command> {\n return entry.load ? entry.load() : Promise.resolve(entry.command)\n}\n\nfunction namespaceTable(\n namespaceIds: ReadonlySet<string>,\n commandIds: readonly string[],\n inputs: readonly RegistryNamespaceInput[] | undefined,\n): Map<string, NamespaceInfo> {\n const descriptions = new Map<string, string | undefined>()\n for (const ns of inputs ?? []) descriptions.set(ns.id, ns.description)\n const namespaces = new Map<string, NamespaceInfo>()\n for (const id of [...namespaceIds].sort(compareIds)) {\n namespaces.set(id, {\n id,\n description: descriptions.get(id),\n commands: commandIds.filter((c) => parentNamespace(c) === id),\n namespaces: [...namespaceIds].filter((n) => n !== \"\" && parentNamespace(n) === id).sort(compareIds),\n })\n }\n return namespaces\n}\n\n/** 정식 ID 또는 별칭으로 명령어 찾기 */\nexport function resolveCommand(registry: Registry, id: string): RegisteredCommand | undefined {\n return registry.commands.get(id) ?? registry.commands.get(registry.aliases.get(id) ?? \"\")\n}\n\nfunction toJsonSchema(schema: z.ZodType, io: \"input\" | \"output\"): JsonSchema {\n return z.toJSONSchema(schema, { target: \"draft-2020-12\", io, unrepresentable: \"throw\" }) as JsonSchema\n}\n\nfunction compareIds(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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","sourcesContent":["import * as z from \"zod\"\nimport { isCommand, type Command } from \"./command.ts\"\nimport { MextBuildError, type BuildIssue } from \"./errors.ts\"\nimport { isSegment, parentNamespace, RESERVED_ROOT_SEGMENTS } from \"./ids.ts\"\nimport type { PromptSet } from \"./prompt.ts\"\nimport type { ResourceSet } from \"./resource.ts\"\n\nexport type JsonSchema = Record<string, unknown>\n\nexport interface RegistryCommandInput {\n /** 정식 ID. 점 구분 kebab-case 세그먼트 */\n id: string\n command: Command\n /** commands/ 기준 상대 경로 (posix). 스캔 결과에만 있음 */\n file?: string\n}\n\nexport interface RegistryNamespaceInput {\n /** \"\" = 루트 */\n id: string\n description?: string\n}\n\nexport interface RegistryInput {\n commands: readonly RegistryCommandInput[]\n namespaces?: readonly RegistryNamespaceInput[]\n}\n\nexport interface RegisteredCommand {\n id: string\n /**\n * 메타데이터 (description · 안전성 · scopes · examples · positional · aliases) 의 원본.\n * eager (createRegistry) = 실행 가능한 명령어 그대로. lazy (createLazyRegistry) = manifest 로 만든 메타데이터만\n * (input · execute 는 load() 결과에서)\n */\n command: Command\n /** lazy Registry: 명령어 모듈 import (1회 캐시) → 실행 가능한 명령어. 없음 = command 가 실행 가능. loadCommand 로 호출 */\n load?: () => Promise<Command>\n /** 별칭의 전체 ID (정렬) */\n aliases: readonly string[]\n file: string | undefined\n /** input 의 JSON Schema 2020-12 (io: input) */\n inputSchema: JsonSchema\n /** output 의 JSON Schema 2020-12 (io: output) */\n outputSchema: JsonSchema | undefined\n}\n\nexport interface NamespaceInfo {\n /** \"\" = 루트 */\n id: string\n /** _index.md 내용 */\n description: string | undefined\n /** 직속 명령어 정식 ID (정렬). index.ts 명령어 (네임스페이스와 같은 ID) 는 상위 네임스페이스에 속한다 */\n commands: readonly string[]\n /** 직속 하위 네임스페이스 ID (정렬) */\n namespaces: readonly string[]\n}\n\nexport interface Registry {\n /** 정식 ID → 명령어. ID 순 */\n readonly commands: ReadonlyMap<string, RegisteredCommand>\n /** 별칭 전체 ID → 정식 ID */\n readonly aliases: ReadonlyMap<string, string>\n /** 네임스페이스 ID → 정보. 루트 (\"\") 포함, ID 순 */\n readonly namespaces: ReadonlyMap<string, NamespaceInfo>\n /** MCP 자원 (resources/, §12.3). 없음 = 기능 없음 (capability 미선언). 명령어 Map 과 별개 */\n readonly resources?: ResourceSet\n /** MCP 프롬프트 (prompts/, §12.3). 없음 = 기능 없음 (capability 미선언). 이름 순 */\n readonly prompts?: PromptSet\n}\n\n/** 명령어 목록에서 Registry 생성. ID · 별칭 · 스키마 규칙 위반은 MextBuildError */\nexport function createRegistry(input: RegistryInput): Registry {\n const { registry, issues } = collectRegistry(input)\n if (issues.length > 0) throw new MextBuildError(issues)\n return registry\n}\n\n/**\n * createRegistry 의 수집형 (mext build 의 일괄 검증용). 던지지 않는다.\n * registry = 규칙을 통과한 명령어만, issues = 위반 전부\n */\nexport function collectRegistry(input: RegistryInput): { registry: Registry; issues: BuildIssue[] } {\n const issues: BuildIssue[] = []\n const accepted: RegistryCommandInput[] = []\n const seen = new Map<string, RegistryCommandInput>()\n\n for (const entry of input.commands) {\n const where = { id: entry.id, file: entry.file }\n if (!isCommand(entry.command)) {\n issues.push({ code: \"INVALID_COMMAND\", message: \"not a defineCommand result\", ...where })\n continue\n }\n const segments = entry.id.split(\".\")\n const bad = segments.find((s) => !isSegment(s))\n if (bad !== undefined) {\n issues.push({ code: \"INVALID_SEGMENT\", message: `segment \"${bad}\" is not kebab-case`, ...where })\n continue\n }\n if (RESERVED_ROOT_SEGMENTS.includes(segments[0]!)) {\n issues.push({ code: \"RESERVED_ID\", message: `root segment \"${segments[0]}\" is reserved`, ...where })\n continue\n }\n const prev = seen.get(entry.id)\n if (prev) {\n issues.push({ code: \"DUPLICATE_ID\", message: `duplicate ID (also ${prev.file ?? prev.id})`, ...where })\n continue\n }\n seen.set(entry.id, entry)\n accepted.push(entry)\n }\n\n // 네임스페이스 = 명령어 ID 의 모든 상위 경로\n const namespaceIds = new Set<string>([\"\"])\n for (const { id } of accepted) {\n for (let ns = parentNamespace(id); ns !== \"\"; ns = parentNamespace(ns)) namespaceIds.add(ns)\n }\n\n const aliases = new Map<string, string>()\n const aliasesOf = new Map<string, string[]>()\n for (const entry of accepted) {\n const where = { id: entry.id, file: entry.file }\n const parent = parentNamespace(entry.id)\n const own: string[] = []\n for (const alias of entry.command.aliases) {\n if (!isSegment(alias)) {\n issues.push({ code: \"INVALID_ALIAS\", message: `alias \"${alias}\" is not a kebab-case segment`, ...where })\n continue\n }\n if (parent === \"\") {\n issues.push({ code: \"INVALID_ALIAS\", message: `alias \"${alias}\": aliases are not allowed at the root`, ...where })\n continue\n }\n const full = `${parent}.${alias}`\n const owner = seen.has(full) ? full : aliases.get(full)\n if (owner !== undefined || namespaceIds.has(full)) {\n issues.push({\n code: \"DUPLICATE_ID\",\n message: `alias ${full} duplicates ${owner !== undefined ? owner : \"a namespace\"}`,\n ...where,\n })\n continue\n }\n aliases.set(full, entry.id)\n own.push(full)\n }\n aliasesOf.set(entry.id, own.sort())\n }\n\n const commands = new Map<string, RegisteredCommand>()\n for (const entry of [...accepted].sort((a, b) => compareIds(a.id, b.id))) {\n const where = { id: entry.id, file: entry.file }\n let inputSchema: JsonSchema\n let outputSchema: JsonSchema | undefined\n try {\n inputSchema = toJsonSchema(entry.command.input, \"input\")\n outputSchema = entry.command.output ? toJsonSchema(entry.command.output, \"output\") : undefined\n } catch (error) {\n issues.push({ code: \"SCHEMA_UNREPRESENTABLE\", message: errorMessage(error), ...where })\n continue\n }\n commands.set(entry.id, {\n id: entry.id,\n command: entry.command,\n aliases: aliasesOf.get(entry.id) ?? [],\n file: entry.file,\n inputSchema,\n outputSchema,\n })\n }\n\n const namespaces = namespaceTable(namespaceIds, [...commands.keys()], input.namespaces)\n return { registry: { commands, aliases, namespaces }, issues }\n}\n\n/** lazy Registry 의 명령어: manifest 메타데이터 + 모듈 로더 (규칙 검증은 mext build 가 이미 함) */\nexport interface LazyCommandInput {\n id: string\n /** 메타데이터만 있는 명령어 (input · execute 는 load 결과). RegisteredCommand.command */\n command: Command\n /** 별칭의 전체 ID */\n aliases: readonly string[]\n file?: string\n inputSchema: JsonSchema\n outputSchema?: JsonSchema\n /** 실행 시 1회 호출 (결과 캐시, 실패는 다음 호출에서 재시도) */\n load: () => Promise<Command>\n}\n\n/**\n * manifest (mext build 산출) 로 Registry 생성. 명령어 모듈을 import 하지 않는다 (mext start · handler.js).\n * help · tools/list · UNKNOWN_COMMAND · 권한 검사 = 메타데이터만, 입력 검증 · execute = loadCommand 후\n */\nexport function createLazyRegistry(input: {\n commands: readonly LazyCommandInput[]\n namespaces?: readonly RegistryNamespaceInput[]\n}): Registry {\n const commands = new Map<string, RegisteredCommand>()\n const aliases = new Map<string, string>()\n for (const entry of [...input.commands].sort((a, b) => compareIds(a.id, b.id))) {\n const load = entry.load\n let pending: Promise<Command> | undefined\n commands.set(entry.id, {\n id: entry.id,\n command: entry.command,\n aliases: [...entry.aliases].sort(),\n file: entry.file,\n inputSchema: entry.inputSchema,\n outputSchema: entry.outputSchema,\n load: () =>\n (pending ??= load().catch((error: unknown) => {\n pending = undefined\n throw error\n })),\n })\n for (const alias of entry.aliases) aliases.set(alias, entry.id)\n }\n const namespaceIds = new Set<string>([\"\"])\n for (const id of commands.keys()) {\n for (let ns = parentNamespace(id); ns !== \"\"; ns = parentNamespace(ns)) namespaceIds.add(ns)\n }\n return { commands, aliases, namespaces: namespaceTable(namespaceIds, [...commands.keys()], input.namespaces) }\n}\n\n/**\n * keep 을 통과한 명령어만 남긴 Registry (expose 의 표면별 보기). 별칭 · 네임스페이스를 다시 계산한다:\n * 남은 명령어가 없는 네임스페이스는 없어지고, 남은 네임스페이스의 설명은 유지. 명령어 항목 · 자원 · 프롬프트는 원본과 같은 객체\n */\nexport function filterRegistry(registry: Registry, keep: (entry: RegisteredCommand) => boolean): Registry {\n const commands = new Map<string, RegisteredCommand>()\n for (const [id, entry] of registry.commands) if (keep(entry)) commands.set(id, entry)\n const aliases = new Map<string, string>()\n for (const [alias, id] of registry.aliases) if (commands.has(id)) aliases.set(alias, id)\n const namespaceIds = new Set<string>([\"\"])\n for (const id of commands.keys()) {\n for (let ns = parentNamespace(id); ns !== \"\"; ns = parentNamespace(ns)) namespaceIds.add(ns)\n }\n const descriptions = [...registry.namespaces.values()].flatMap((n) => (n.description === undefined ? [] : [{ id: n.id, description: n.description }]))\n return { ...registry, commands, aliases, namespaces: namespaceTable(namespaceIds, [...commands.keys()], descriptions) }\n}\n\n/** 실행 가능한 명령어. eager = entry.command, lazy = entry.load() (모듈 import) */\nexport function loadCommand(entry: RegisteredCommand): Promise<Command> {\n return entry.load ? entry.load() : Promise.resolve(entry.command)\n}\n\nfunction namespaceTable(\n namespaceIds: ReadonlySet<string>,\n commandIds: readonly string[],\n inputs: readonly RegistryNamespaceInput[] | undefined,\n): Map<string, NamespaceInfo> {\n const descriptions = new Map<string, string | undefined>()\n for (const ns of inputs ?? []) descriptions.set(ns.id, ns.description)\n const namespaces = new Map<string, NamespaceInfo>()\n for (const id of [...namespaceIds].sort(compareIds)) {\n namespaces.set(id, {\n id,\n description: descriptions.get(id),\n commands: commandIds.filter((c) => parentNamespace(c) === id),\n namespaces: [...namespaceIds].filter((n) => n !== \"\" && parentNamespace(n) === id).sort(compareIds),\n })\n }\n return namespaces\n}\n\n/** 정식 ID 또는 별칭으로 명령어 찾기 */\nexport function resolveCommand(registry: Registry, id: string): RegisteredCommand | undefined {\n return registry.commands.get(id) ?? registry.commands.get(registry.aliases.get(id) ?? \"\")\n}\n\nfunction toJsonSchema(schema: z.ZodType, io: \"input\" | \"output\"): JsonSchema {\n return z.toJSONSchema(schema, { target: \"draft-2020-12\", io, unrepresentable: \"throw\" }) as JsonSchema\n}\n\nfunction compareIds(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n"]}
|
package/dist/remote/client.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export interface RequestOptions {
|
|
|
61
61
|
export interface CallToolOptions extends RequestOptions {
|
|
62
62
|
/** input_required 응답 처리 → 이번 라운드의 inputResponses. 없으면 RemoteInputRequiredError */
|
|
63
63
|
onInputRequired?: (request: InputRequired, round: number) => Promise<InputResponses>;
|
|
64
|
+
/** tools/call 요청 params._meta 에 실을 값 (예: 확인 표시 "dev.mext/approval"). 재시도 라운드에도 같은 값 */
|
|
65
|
+
meta?: Record<string, unknown>;
|
|
64
66
|
}
|
|
65
67
|
/** HTTP 401. challenge = WWW-Authenticate 파싱 결과, data = JSON-RPC error.data (mext 는 UNAUTHENTICATED toJSON) */
|
|
66
68
|
export declare class RemoteUnauthorizedError extends Error {
|
package/dist/remote/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VERSION } from "../version.js";
|
|
1
|
+
import { VERSION } from "../version-constant.js";
|
|
2
2
|
/**
|
|
3
3
|
* 원격 실행용 최소 MCP 클라이언트 (Streamable HTTP, 프로토콜 2026-07-28, stateless).
|
|
4
4
|
* 요청마다 POST 1회: _meta envelope (버전 · clientInfo · clientCapabilities) + MCP-Protocol-Version · Mcp-Method ·
|
|
@@ -154,8 +154,9 @@ export function createRemoteClient(options) {
|
|
|
154
154
|
const callTool = async (tool, args, opts = {}) => {
|
|
155
155
|
const headers = { "Mcp-Name": tool.name, ...paramHeaders(tool, args) };
|
|
156
156
|
let retry = {};
|
|
157
|
+
const meta = opts.meta ? { _meta: opts.meta } : {};
|
|
157
158
|
for (let round = 0;; round++) {
|
|
158
|
-
const result = await request("tools/call", { name: tool.name, arguments: args, ...retry }, opts, headers);
|
|
159
|
+
const result = await request("tools/call", { name: tool.name, arguments: args, ...retry, ...meta }, opts, headers);
|
|
159
160
|
if (result.resultType !== "input_required")
|
|
160
161
|
return result;
|
|
161
162
|
const required = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/remote/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAA;AAE5C,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,eAAe,EAAE,yCAAyC;IAC1D,UAAU,EAAE,oCAAoC;IAChD,kBAAkB,EAAE,4CAA4C;CACxD,CAAA;AAEV,sFAAsF;AACtF,MAAM,CAAC,MAAM,kBAAkB,GAAG,+BAA+B,CAAA;AAEjE,gGAAgG;AAChG,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,WAAW,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;IAClC,UAAU,EAAE,EAAE,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE;CAChC,CAAA;AAEV,gDAAgD;AAChD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAA;AA6CjC,+GAA+G;AAC/G,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,SAAS,CAAiB;IAC1B,IAAI,CAAS;IACtB,YAAY,OAAe,EAAE,SAA0B,EAAE,IAAa;QACpE,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAA;QACrC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED,+CAA+C;AAC/C,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,IAAI,CAAQ;IACZ,IAAI,CAAS;IACb,MAAM,CAAQ;IACvB,YAAY,OAAe,EAAE,IAAY,EAAE,IAAa,EAAE,MAAc;QACtE,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAA;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;CACF;AAED,+BAA+B;AAC/B,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF;AAED,yDAAyD;AACzD,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACxC,OAAO,CAAe;IAC/B,YAAY,OAAe,EAAE,OAAsB;QACjD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAA;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;CACF;AAgCD,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAA;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAA;IAC3E,IAAI,MAAM,GAAG,CAAC,CAAA;IAEd,MAAM,OAAO,GAAG,KAAK,EACnB,MAAc,EACd,MAAM,GAA4B,EAAE,EACpC,IAAI,GAAmB,EAAE,EACzB,YAAY,GAA2B,EAAE,EACP,EAAE;QACpC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAA;QACnB,MAAM,IAAI,GAA4B;YACpC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,gBAAgB;YAC7C,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,UAAU;YAClC,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,mBAAmB;SACpD,CAAA;QACD,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS;YAAE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QAC7E,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAA;QAC/E,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,qCAAqC;YAC7C,sBAAsB,EAAE,gBAAgB;YACxC,YAAY,EAAE,MAAM;YACpB,GAAG,YAAY;SAChB,CAAA;QACD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,EAAE,CAAA;QACrC,IAAI,KAAK;YAAE,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAA;QAEpD,IAAI,GAAa,CAAA;QACjB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC/B,MAAM,EAAE,MAAM;gBACd,OAAO;gBACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChD,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,KAAK,CAAA;YACrC,MAAM,IAAI,oBAAoB,CAAC,gBAAgB,OAAO,CAAC,GAAG,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;QACzG,CAAC;QAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;QAClD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;YACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;YAC7E,MAAM,IAAI,uBAAuB,CAC/B,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,EAC1E,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,EACzD,GAAG,CAAC,IAAI,CACT,CAAA;QACH,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACvC,OAAO,aAAa,CAAC,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QACpE,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,oBAAoB,CAAC,GAAG,OAAO,CAAC,GAAG,kBAAkB,GAAG,CAAC,MAAM,+BAA+B,CAAC,CAAA;QAC3G,CAAC;QACD,OAAO,aAAa,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/C,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,CAAC,OAAgB,EAAE,EAAU,EAAE,MAAc,EAA2B,EAAE;QAC9F,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,MAAM,IAAI,oBAAoB,CAAC,mCAAmC,MAAM,IAAI,CAAC,CAAA;QACrG,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAA;YACvB,MAAM,IAAI,cAAc,CACtB,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAC5D,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,EAC7C,CAAC,CAAC,IAAI,EACN,MAAM,CACP,CAAA;QACH,CAAC;QACD,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,oBAAoB,CAAC,mCAAmC,MAAM,IAAI,CAAC,CAAA;QAC/E,CAAC;QACD,OAAO,OAAO,CAAC,MAAM,CAAA;IACvB,CAAC,CAAA;IAED,MAAM,eAAe,GAAG,KAAK,EAAE,IAAI,GAAmB,EAAE,EAA4B,EAAE;QACpF,MAAM,KAAK,GAAiB,EAAE,CAAA;QAC9B,MAAM,GAAG,GAAoB,EAAE,KAAK,EAAE,CAAA;QACtC,IAAI,MAA0B,CAAA;QAC9B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,CAAA;YACxF,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;oBAAE,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;gBACpH,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ;oBAAE,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAA;YAC/E,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK;oBAAE,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;wBAAE,KAAK,CAAC,IAAI,CAAC,CAA0B,CAAC,CAAA;YACrH,CAAC;YACD,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,KAAK,EAAE;gBAAE,MAAK;YAC5E,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;QAC5B,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC,CAAA;IAED,MAAM,QAAQ,GAAG,KAAK,EACpB,IAAgB,EAChB,IAA6B,EAC7B,IAAI,GAAoB,EAAE,EACD,EAAE;QAC3B,MAAM,OAAO,GAA2B,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAA;QAC9F,IAAI,KAAK,GAA+D,EAAE,CAAA;QAC1E,KAAK,IAAI,KAAK,GAAG,CAAC,GAAI,KAAK,EAAE,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;YACzG,IAAI,MAAM,CAAC,UAAU,KAAK,gBAAgB;gBAAE,OAAO,MAAwB,CAAA;YAC3E,MAAM,QAAQ,GAAkB,EAAE,CAAA;YAClC,IAAI,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC;gBAAE,QAAQ,CAAC,aAAa,GAAG,MAAM,CAAC,aAA+C,CAAA;YACnH,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ;gBAAE,QAAQ,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAA;YACxF,IAAI,CAAC,IAAI,CAAC,eAAe;gBAAE,MAAM,IAAI,wBAAwB,CAAC,GAAG,IAAI,CAAC,IAAI,kBAAkB,EAAE,QAAQ,CAAC,CAAA;YACvG,IAAI,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBAC9B,MAAM,IAAI,wBAAwB,CAAC,GAAG,IAAI,CAAC,IAAI,+BAA+B,gBAAgB,UAAU,EAAE,QAAQ,CAAC,CAAA;YACrH,CAAC;YACD,gEAAgE;YAChE,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YAClG,KAAK,GAAG,EAAE,CAAA;YACV,IAAI,SAAS,KAAK,SAAS;gBAAE,KAAK,CAAC,cAAc,GAAG,SAAS,CAAA;YAC7D,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS;gBAAE,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAA;QACrF,CAAC;IACH,CAAC,CAAA;IAED,uDAAuD;IACvD,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,MAAc,EAAE,MAA+B,EAAE,IAAI,GAAmB,EAAE,EAAE,EAAE,CACjH,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;IAEtE,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC;QAChE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;QAC9D,eAAe;QACf,QAAQ;QACR,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC;QACrE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE;YACjD,MAAM,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,EAAE,IAAI,CAAC,CAAA;QACrE,CAAC;QACD,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;YACjC,MAAM,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,CAAA;QACrD,CAAC;KACF,CAAA;AACH,CAAC;AAED,4FAA4F;AAC5F,SAAS,YAAY,CAAC,IAAgB,EAAE,IAA6B;IACnE,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAA;IAC1C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAC/B,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,cAAc,CAAC,KAAK,QAAQ;YAAE,SAAQ;QAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QACvB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YACzF,GAAG,CAAC,aAAa,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS;AAET,6DAA6D;AAC7D,KAAK,UAAU,OAAO,CAAC,GAAa,EAAE,EAAU,EAAE,IAAoB;IACpE,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,MAAM,IAAI,oBAAoB,CAAC,qBAAqB,CAAC,CAAA;IACpE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC,SAAS,EAAE,CAAA;IACxE,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,IAAI,GAAa,EAAE,CAAA;IACvB,MAAM,QAAQ,GAAG,GAAY,EAAE;QAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAA;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,GAAG,EAAE,CAAA;QACT,IAAI,OAAgB,CAAA;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,SAAS,CAAA;QACxC,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YACnE,IAAI,CAAC;gBACH,IAAI,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YACvF,CAAC;YAAC,MAAM,CAAC;gBACP,mBAAmB;YACrB,CAAC;YACD,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC;YAAE,OAAO,OAAO,CAAA;QACpF,OAAO,SAAS,CAAA;IAClB,CAAC,CAAA;IACD,IAAI,CAAC;QACH,SAAS,CAAC;YACR,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;YAC3C,IAAI,IAAI;gBAAE,MAAK;YACf,MAAM,IAAI,KAAK,CAAA;YACf,IAAI,EAAU,CAAA;YACd,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;gBAChC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBACnE,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;oBAChB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAA;oBACxB,IAAI,KAAK,KAAK,SAAS;wBAAE,OAAO,KAAK,CAAA;oBACrC,SAAQ;gBACV,CAAC;gBACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,SAAQ;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;gBAC/B,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;gBACrD,IAAI,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;gBAClD,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBACjD,IAAI,KAAK,KAAK,MAAM;oBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACxC,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAA;QACxB,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAA;IACvC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACvC,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;QAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;IAClD,MAAM,IAAI,oBAAoB,CAAC,wCAAwC,CAAC,CAAA;AAC1E,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAa;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IAC7C,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,SAAS,CAAA;IACjC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAYD,uFAAuF;AACvF,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IACrC,MAAM,CAAC,GAAG,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACjD,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IAChC,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,MAAM,EAAE,GAAG,4DAA4D,CAAA;IACvE,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;QAC5D,MAAM,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAA;IACzF,CAAC;IACD,MAAM,GAAG,GAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;IAC7C,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;QAAE,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;IACxD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;QAAE,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;IACxD,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS;QAAE,GAAG,CAAC,gBAAgB,GAAG,MAAM,CAAC,iBAAiB,CAAA;IAC3F,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAI,KAA6B,CAAC,KAAK,CAAA;QAClD,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAA;IAChF,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC","sourcesContent":["import { VERSION } from \"../version.ts\"\n\n/**\n * 원격 실행용 최소 MCP 클라이언트 (Streamable HTTP, 프로토콜 2026-07-28, stateless).\n * 요청마다 POST 1회: _meta envelope (버전 · clientInfo · clientCapabilities) + MCP-Protocol-Version · Mcp-Method ·\n * Mcp-Name · Mcp-Param-* 헤더. 응답 = application/json 또는 text/event-stream (progress 알림 → onNotification).\n * MRTR (InputRequiredResult) 재시도 루프는 callTool 의 onInputRequired 가 담당.\n * tasks 확장 (§12.6) 선언: tools/call 이 CreateTaskResult (resultType \"task\") 를 그대로 돌려주고, 폴링 · 답 · 취소 =\n * getTask · updateTask · cancelTask (Mcp-Name = taskId). 폴링 루프는 client/task.ts\n */\n\nexport const PROTOCOL_VERSION = \"2026-07-28\"\n\nexport const META_KEYS = {\n protocolVersion: \"io.modelcontextprotocol/protocolVersion\",\n clientInfo: \"io.modelcontextprotocol/clientInfo\",\n clientCapabilities: \"io.modelcontextprotocol/clientCapabilities\",\n} as const\n\n/** tasks 확장 ID (mcp/tasks.ts TASKS_EXTENSION 과 같은 값. 이 모듈은 서버 SDK 를 import 하지 않는다) */\nexport const TASKS_EXTENSION_ID = \"io.modelcontextprotocol/tasks\"\n\n/** 클라이언트가 처리하는 입력 요청 = elicitation form · url (sampling · roots 없음) + tasks 확장 (폴링 · 답 · 취소) */\nexport const CLIENT_CAPABILITIES = {\n elicitation: { form: {}, url: {} },\n extensions: { [TASKS_EXTENSION_ID]: {} },\n} as const\n\n/** MRTR 재시도 상한 (같은 요청의 input_required 연속 횟수) */\nexport const MAX_INPUT_ROUNDS = 8\n\nexport interface RemoteTool {\n name: string\n description?: string\n inputSchema?: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n annotations?: Record<string, unknown>\n _meta?: Record<string, unknown>\n}\n\nexport interface CallToolResult {\n content?: unknown[]\n structuredContent?: unknown\n isError?: boolean\n [key: string]: unknown\n}\n\n/** InputRequiredResult (resultType: input_required) */\nexport interface InputRequired {\n inputRequests?: Record<string, InputRequestObject>\n requestState?: string\n}\n\nexport interface InputRequestObject {\n method: string\n params?: Record<string, unknown>\n}\n\n/** 입력 요청 key → 응답 (ElicitResult 등). 이번 라운드 요청에 대한 것만 */\nexport type InputResponses = Record<string, unknown>\n\nexport interface RequestOptions {\n signal?: AbortSignal\n /** 서버 → 클라이언트 알림 (notifications/progress 등) */\n onNotification?: (method: string, params: Record<string, unknown>) => void\n /** _meta.progressToken. 있으면 서버가 SSE 로 응답 */\n progressToken?: string | number\n}\n\nexport interface CallToolOptions extends RequestOptions {\n /** input_required 응답 처리 → 이번 라운드의 inputResponses. 없으면 RemoteInputRequiredError */\n onInputRequired?: (request: InputRequired, round: number) => Promise<InputResponses>\n}\n\n/** HTTP 401. challenge = WWW-Authenticate 파싱 결과, data = JSON-RPC error.data (mext 는 UNAUTHENTICATED toJSON) */\nexport class RemoteUnauthorizedError extends Error {\n readonly challenge: BearerChallenge\n readonly data: unknown\n constructor(message: string, challenge: BearerChallenge, data: unknown) {\n super(message)\n this.name = \"RemoteUnauthorizedError\"\n this.challenge = challenge\n this.data = data\n }\n}\n\n/** JSON-RPC 오류 응답 (HTTP 400 · 403 · 500 포함) */\nexport class RemoteRpcError extends Error {\n readonly code: number\n readonly data: unknown\n readonly status: number\n constructor(message: string, code: number, data: unknown, status: number) {\n super(message)\n this.name = \"RemoteRpcError\"\n this.code = code\n this.data = data\n this.status = status\n }\n}\n\n/** 연결 실패 · JSON-RPC 가 아닌 응답 */\nexport class RemoteTransportError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = \"RemoteTransportError\"\n }\n}\n\n/** onInputRequired 없이 input_required 를 받음 · 라운드 상한 초과 */\nexport class RemoteInputRequiredError extends Error {\n readonly request: InputRequired\n constructor(message: string, request: InputRequired) {\n super(message)\n this.name = \"RemoteInputRequiredError\"\n this.request = request\n }\n}\n\nexport interface RemoteClientOptions {\n /** MCP 엔드포인트 (http(s)://host/mcp) */\n url: string\n /** 요청마다 호출. 없으면 Authorization 헤더 없음 */\n token?: () => string | undefined | Promise<string | undefined>\n fetch?: typeof fetch\n clientInfo?: { name: string; version: string }\n}\n\n/** tools/list 전체 페이지 + 첫 페이지의 캐시 힌트 (2026-07-28 ttlMs · cacheScope) */\nexport interface ToolsListResult {\n tools: RemoteTool[]\n ttlMs?: number\n cacheScope?: string\n}\n\nexport interface RemoteClient {\n readonly url: string\n request(method: string, params?: Record<string, unknown>, options?: RequestOptions): Promise<Record<string, unknown>>\n listTools(options?: RequestOptions): Promise<RemoteTool[]>\n listToolsResult(options?: RequestOptions): Promise<ToolsListResult>\n callTool(tool: RemoteTool, args: Record<string, unknown>, options?: CallToolOptions): Promise<CallToolResult>\n /** tasks/get (Mcp-Name = taskId) */\n getTask(taskId: string, options?: RequestOptions): Promise<Record<string, unknown>>\n /** tasks/update { taskId, inputResponses } */\n updateTask(taskId: string, inputResponses: InputResponses, options?: RequestOptions): Promise<void>\n /** tasks/cancel { taskId } */\n cancelTask(taskId: string, options?: RequestOptions): Promise<void>\n}\n\nexport function createRemoteClient(options: RemoteClientOptions): RemoteClient {\n const doFetch = options.fetch ?? fetch\n const clientInfo = options.clientInfo ?? { name: \"mext\", version: VERSION }\n let nextId = 1\n\n const request = async (\n method: string,\n params: Record<string, unknown> = {},\n opts: RequestOptions = {},\n extraHeaders: Record<string, string> = {},\n ): Promise<Record<string, unknown>> => {\n const id = nextId++\n const meta: Record<string, unknown> = {\n ...(isRecord(params._meta) ? params._meta : {}),\n [META_KEYS.protocolVersion]: PROTOCOL_VERSION,\n [META_KEYS.clientInfo]: clientInfo,\n [META_KEYS.clientCapabilities]: CLIENT_CAPABILITIES,\n }\n if (opts.progressToken !== undefined) meta.progressToken = opts.progressToken\n const body = { jsonrpc: \"2.0\", id, method, params: { ...params, _meta: meta } }\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"MCP-Protocol-Version\": PROTOCOL_VERSION,\n \"Mcp-Method\": method,\n ...extraHeaders,\n }\n const token = await options.token?.()\n if (token) headers.Authorization = `Bearer ${token}`\n\n let res: Response\n try {\n res = await doFetch(options.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n ...(opts.signal ? { signal: opts.signal } : {}),\n })\n } catch (error) {\n if (opts.signal?.aborted) throw error\n throw new RemoteTransportError(`Cannot reach ${options.url}: ${errorMessage(error)}`, { cause: error })\n }\n\n const type = res.headers.get(\"content-type\") ?? \"\"\n if (res.status === 401) {\n const payload = await readJson(res)\n const err = isRecord(payload) && isRecord(payload.error) ? payload.error : {}\n throw new RemoteUnauthorizedError(\n typeof err.message === \"string\" ? err.message : \"Authentication required.\",\n parseBearerChallenge(res.headers.get(\"www-authenticate\")),\n err.data,\n )\n }\n if (type.includes(\"text/event-stream\")) {\n return handleMessage(await readSse(res, id, opts), id, res.status)\n }\n const payload = await readJson(res)\n if (payload === undefined) {\n throw new RemoteTransportError(`${options.url} returned HTTP ${res.status} without a JSON-RPC response.`)\n }\n return handleMessage(payload, id, res.status)\n }\n\n const handleMessage = (message: unknown, id: number, status: number): Record<string, unknown> => {\n if (!isRecord(message)) throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n if (isRecord(message.error)) {\n const e = message.error\n throw new RemoteRpcError(\n typeof e.message === \"string\" ? e.message : \"JSON-RPC error\",\n typeof e.code === \"number\" ? e.code : -32_603,\n e.data,\n status,\n )\n }\n if (message.id !== id || !isRecord(message.result)) {\n throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n }\n return message.result\n }\n\n const listToolsResult = async (opts: RequestOptions = {}): Promise<ToolsListResult> => {\n const tools: RemoteTool[] = []\n const out: ToolsListResult = { tools }\n let cursor: string | undefined\n for (let page = 0; page < 100; page++) {\n const result = await request(\"tools/list\", cursor === undefined ? {} : { cursor }, opts)\n if (page === 0) {\n if (typeof result.ttlMs === \"number\" && Number.isFinite(result.ttlMs) && result.ttlMs >= 0) out.ttlMs = result.ttlMs\n if (typeof result.cacheScope === \"string\") out.cacheScope = result.cacheScope\n }\n if (Array.isArray(result.tools)) {\n for (const t of result.tools) if (isRecord(t) && typeof t.name === \"string\") tools.push(t as unknown as RemoteTool)\n }\n if (typeof result.nextCursor !== \"string\" || result.nextCursor === \"\") break\n cursor = result.nextCursor\n }\n return out\n }\n\n const callTool = async (\n tool: RemoteTool,\n args: Record<string, unknown>,\n opts: CallToolOptions = {},\n ): Promise<CallToolResult> => {\n const headers: Record<string, string> = { \"Mcp-Name\": tool.name, ...paramHeaders(tool, args) }\n let retry: { inputResponses?: InputResponses; requestState?: string } = {}\n for (let round = 0; ; round++) {\n const result = await request(\"tools/call\", { name: tool.name, arguments: args, ...retry }, opts, headers)\n if (result.resultType !== \"input_required\") return result as CallToolResult\n const required: InputRequired = {}\n if (isRecord(result.inputRequests)) required.inputRequests = result.inputRequests as InputRequired[\"inputRequests\"]\n if (typeof result.requestState === \"string\") required.requestState = result.requestState\n if (!opts.onInputRequired) throw new RemoteInputRequiredError(`${tool.name} requires input.`, required)\n if (round >= MAX_INPUT_ROUNDS) {\n throw new RemoteInputRequiredError(`${tool.name} still required input after ${MAX_INPUT_ROUNDS} rounds.`, required)\n }\n // 요청이 있으면 응답을 만든 뒤 재시도. requestState 는 그대로 되돌려 보내고, 없으면 보내지 않는다\n const responses = required.inputRequests ? await opts.onInputRequired(required, round) : undefined\n retry = {}\n if (responses !== undefined) retry.inputResponses = responses\n if (required.requestState !== undefined) retry.requestState = required.requestState\n }\n }\n\n /** tasks/* = Mcp-Name 헤더 = taskId (SDK 검증, 없으면 400) */\n const taskRequest = (method: string, taskId: string, params: Record<string, unknown>, opts: RequestOptions = {}) =>\n request(method, { taskId, ...params }, opts, { \"Mcp-Name\": taskId })\n\n return {\n url: options.url,\n request: (method, params, opts) => request(method, params, opts),\n listTools: async (opts) => (await listToolsResult(opts)).tools,\n listToolsResult,\n callTool,\n getTask: (taskId, opts) => taskRequest(\"tasks/get\", taskId, {}, opts),\n updateTask: async (taskId, inputResponses, opts) => {\n await taskRequest(\"tasks/update\", taskId, { inputResponses }, opts)\n },\n cancelTask: async (taskId, opts) => {\n await taskRequest(\"tasks/cancel\", taskId, {}, opts)\n },\n }\n}\n\n/** inputSchema 의 x-mcp-header 속성 → Mcp-Param-<Name> 헤더 (SEP-2243). 문자열 · 숫자 · boolean 값만 */\nfunction paramHeaders(tool: RemoteTool, args: Record<string, unknown>): Record<string, string> {\n const props = tool.inputSchema?.properties\n if (!isRecord(props)) return {}\n const out: Record<string, string> = {}\n for (const [key, schema] of Object.entries(props)) {\n if (!isRecord(schema) || typeof schema[\"x-mcp-header\"] !== \"string\") continue\n const value = args[key]\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n out[`Mcp-Param-${schema[\"x-mcp-header\"]}`] = String(value)\n }\n }\n return out\n}\n\n/* SSE */\n\n/** 응답 스트림에서 id 의 응답 메시지가 올 때까지 읽는다. 알림은 콜백, 응답 후 스트림을 닫는다 */\nasync function readSse(res: Response, id: number, opts: RequestOptions): Promise<unknown> {\n if (!res.body) throw new RemoteTransportError(\"Empty event stream.\")\n const reader = res.body.pipeThrough(new TextDecoderStream()).getReader()\n let buffer = \"\"\n let data: string[] = []\n const dispatch = (): unknown => {\n if (data.length === 0) return undefined\n const text = data.join(\"\\n\")\n data = []\n let message: unknown\n try {\n message = JSON.parse(text)\n } catch {\n return undefined\n }\n if (!isRecord(message)) return undefined\n if (typeof message.method === \"string\" && message.id === undefined) {\n try {\n opts.onNotification?.(message.method, isRecord(message.params) ? message.params : {})\n } catch {\n // 표시 오류는 응답에 영향 없음\n }\n return undefined\n }\n if (message.id === id && (\"result\" in message || \"error\" in message)) return message\n return undefined\n }\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += value\n let nl: number\n while ((nl = buffer.search(/\\r\\n|\\r|\\n/)) >= 0) {\n const line = buffer.slice(0, nl)\n buffer = buffer.slice(nl + (buffer.startsWith(\"\\r\\n\", nl) ? 2 : 1))\n if (line === \"\") {\n const found = dispatch()\n if (found !== undefined) return found\n continue\n }\n if (line.startsWith(\":\")) continue\n const colon = line.indexOf(\":\")\n const field = colon < 0 ? line : line.slice(0, colon)\n let value = colon < 0 ? \"\" : line.slice(colon + 1)\n if (value.startsWith(\" \")) value = value.slice(1)\n if (field === \"data\") data.push(value)\n }\n }\n const found = dispatch()\n if (found !== undefined) return found\n } finally {\n await reader.cancel().catch(() => {})\n }\n if (opts.signal?.aborted) throw opts.signal.reason\n throw new RemoteTransportError(\"Event stream ended without a response.\")\n}\n\nasync function readJson(res: Response): Promise<unknown> {\n const text = await res.text().catch(() => \"\")\n if (text === \"\") return undefined\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n\n/* WWW-Authenticate */\n\nexport interface BearerChallenge {\n /** Bearer challenge 가 있었는지 */\n bearer: boolean\n error?: string\n scope?: string\n resourceMetadata?: string\n}\n\n/** WWW-Authenticate 의 Bearer challenge 파라미터 (RFC 6750 · RFC 9728 resource_metadata) */\nexport function parseBearerChallenge(header: string | null): BearerChallenge {\n if (!header) return { bearer: false }\n const m = /(?:^|,\\s*)Bearer\\b(.*)$/i.exec(header)\n if (!m) return { bearer: false }\n const params: Record<string, string> = {}\n const re = /([A-Za-z_][\\w-]*)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g\n for (let p = re.exec(m[1]!); p !== null; p = re.exec(m[1]!)) {\n params[p[1]!.toLowerCase()] = p[2] !== undefined ? p[2].replace(/\\\\(.)/g, \"$1\") : p[3]!\n }\n const out: BearerChallenge = { bearer: true }\n if (params.error !== undefined) out.error = params.error\n if (params.scope !== undefined) out.scope = params.scope\n if (params.resource_metadata !== undefined) out.resourceMetadata = params.resource_metadata\n return out\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n const cause = (error as { cause?: unknown }).cause\n return cause instanceof Error && cause.message ? cause.message : error.message\n }\n return String(error)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/remote/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../version-constant.ts\"\n\n/**\n * 원격 실행용 최소 MCP 클라이언트 (Streamable HTTP, 프로토콜 2026-07-28, stateless).\n * 요청마다 POST 1회: _meta envelope (버전 · clientInfo · clientCapabilities) + MCP-Protocol-Version · Mcp-Method ·\n * Mcp-Name · Mcp-Param-* 헤더. 응답 = application/json 또는 text/event-stream (progress 알림 → onNotification).\n * MRTR (InputRequiredResult) 재시도 루프는 callTool 의 onInputRequired 가 담당.\n * tasks 확장 (§12.6) 선언: tools/call 이 CreateTaskResult (resultType \"task\") 를 그대로 돌려주고, 폴링 · 답 · 취소 =\n * getTask · updateTask · cancelTask (Mcp-Name = taskId). 폴링 루프는 client/task.ts\n */\n\nexport const PROTOCOL_VERSION = \"2026-07-28\"\n\nexport const META_KEYS = {\n protocolVersion: \"io.modelcontextprotocol/protocolVersion\",\n clientInfo: \"io.modelcontextprotocol/clientInfo\",\n clientCapabilities: \"io.modelcontextprotocol/clientCapabilities\",\n} as const\n\n/** tasks 확장 ID (mcp/tasks.ts TASKS_EXTENSION 과 같은 값. 이 모듈은 서버 SDK 를 import 하지 않는다) */\nexport const TASKS_EXTENSION_ID = \"io.modelcontextprotocol/tasks\"\n\n/** 클라이언트가 처리하는 입력 요청 = elicitation form · url (sampling · roots 없음) + tasks 확장 (폴링 · 답 · 취소) */\nexport const CLIENT_CAPABILITIES = {\n elicitation: { form: {}, url: {} },\n extensions: { [TASKS_EXTENSION_ID]: {} },\n} as const\n\n/** MRTR 재시도 상한 (같은 요청의 input_required 연속 횟수) */\nexport const MAX_INPUT_ROUNDS = 8\n\nexport interface RemoteTool {\n name: string\n description?: string\n inputSchema?: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n annotations?: Record<string, unknown>\n _meta?: Record<string, unknown>\n}\n\nexport interface CallToolResult {\n content?: unknown[]\n structuredContent?: unknown\n isError?: boolean\n [key: string]: unknown\n}\n\n/** InputRequiredResult (resultType: input_required) */\nexport interface InputRequired {\n inputRequests?: Record<string, InputRequestObject>\n requestState?: string\n}\n\nexport interface InputRequestObject {\n method: string\n params?: Record<string, unknown>\n}\n\n/** 입력 요청 key → 응답 (ElicitResult 등). 이번 라운드 요청에 대한 것만 */\nexport type InputResponses = Record<string, unknown>\n\nexport interface RequestOptions {\n signal?: AbortSignal\n /** 서버 → 클라이언트 알림 (notifications/progress 등) */\n onNotification?: (method: string, params: Record<string, unknown>) => void\n /** _meta.progressToken. 있으면 서버가 SSE 로 응답 */\n progressToken?: string | number\n}\n\nexport interface CallToolOptions extends RequestOptions {\n /** input_required 응답 처리 → 이번 라운드의 inputResponses. 없으면 RemoteInputRequiredError */\n onInputRequired?: (request: InputRequired, round: number) => Promise<InputResponses>\n /** tools/call 요청 params._meta 에 실을 값 (예: 확인 표시 \"dev.mext/approval\"). 재시도 라운드에도 같은 값 */\n meta?: Record<string, unknown>\n}\n\n/** HTTP 401. challenge = WWW-Authenticate 파싱 결과, data = JSON-RPC error.data (mext 는 UNAUTHENTICATED toJSON) */\nexport class RemoteUnauthorizedError extends Error {\n readonly challenge: BearerChallenge\n readonly data: unknown\n constructor(message: string, challenge: BearerChallenge, data: unknown) {\n super(message)\n this.name = \"RemoteUnauthorizedError\"\n this.challenge = challenge\n this.data = data\n }\n}\n\n/** JSON-RPC 오류 응답 (HTTP 400 · 403 · 500 포함) */\nexport class RemoteRpcError extends Error {\n readonly code: number\n readonly data: unknown\n readonly status: number\n constructor(message: string, code: number, data: unknown, status: number) {\n super(message)\n this.name = \"RemoteRpcError\"\n this.code = code\n this.data = data\n this.status = status\n }\n}\n\n/** 연결 실패 · JSON-RPC 가 아닌 응답 */\nexport class RemoteTransportError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = \"RemoteTransportError\"\n }\n}\n\n/** onInputRequired 없이 input_required 를 받음 · 라운드 상한 초과 */\nexport class RemoteInputRequiredError extends Error {\n readonly request: InputRequired\n constructor(message: string, request: InputRequired) {\n super(message)\n this.name = \"RemoteInputRequiredError\"\n this.request = request\n }\n}\n\nexport interface RemoteClientOptions {\n /** MCP 엔드포인트 (http(s)://host/mcp) */\n url: string\n /** 요청마다 호출. 없으면 Authorization 헤더 없음 */\n token?: () => string | undefined | Promise<string | undefined>\n fetch?: typeof fetch\n clientInfo?: { name: string; version: string }\n}\n\n/** tools/list 전체 페이지 + 첫 페이지의 캐시 힌트 (2026-07-28 ttlMs · cacheScope) */\nexport interface ToolsListResult {\n tools: RemoteTool[]\n ttlMs?: number\n cacheScope?: string\n}\n\nexport interface RemoteClient {\n readonly url: string\n request(method: string, params?: Record<string, unknown>, options?: RequestOptions): Promise<Record<string, unknown>>\n listTools(options?: RequestOptions): Promise<RemoteTool[]>\n listToolsResult(options?: RequestOptions): Promise<ToolsListResult>\n callTool(tool: RemoteTool, args: Record<string, unknown>, options?: CallToolOptions): Promise<CallToolResult>\n /** tasks/get (Mcp-Name = taskId) */\n getTask(taskId: string, options?: RequestOptions): Promise<Record<string, unknown>>\n /** tasks/update { taskId, inputResponses } */\n updateTask(taskId: string, inputResponses: InputResponses, options?: RequestOptions): Promise<void>\n /** tasks/cancel { taskId } */\n cancelTask(taskId: string, options?: RequestOptions): Promise<void>\n}\n\nexport function createRemoteClient(options: RemoteClientOptions): RemoteClient {\n const doFetch = options.fetch ?? fetch\n const clientInfo = options.clientInfo ?? { name: \"mext\", version: VERSION }\n let nextId = 1\n\n const request = async (\n method: string,\n params: Record<string, unknown> = {},\n opts: RequestOptions = {},\n extraHeaders: Record<string, string> = {},\n ): Promise<Record<string, unknown>> => {\n const id = nextId++\n const meta: Record<string, unknown> = {\n ...(isRecord(params._meta) ? params._meta : {}),\n [META_KEYS.protocolVersion]: PROTOCOL_VERSION,\n [META_KEYS.clientInfo]: clientInfo,\n [META_KEYS.clientCapabilities]: CLIENT_CAPABILITIES,\n }\n if (opts.progressToken !== undefined) meta.progressToken = opts.progressToken\n const body = { jsonrpc: \"2.0\", id, method, params: { ...params, _meta: meta } }\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n \"MCP-Protocol-Version\": PROTOCOL_VERSION,\n \"Mcp-Method\": method,\n ...extraHeaders,\n }\n const token = await options.token?.()\n if (token) headers.Authorization = `Bearer ${token}`\n\n let res: Response\n try {\n res = await doFetch(options.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n ...(opts.signal ? { signal: opts.signal } : {}),\n })\n } catch (error) {\n if (opts.signal?.aborted) throw error\n throw new RemoteTransportError(`Cannot reach ${options.url}: ${errorMessage(error)}`, { cause: error })\n }\n\n const type = res.headers.get(\"content-type\") ?? \"\"\n if (res.status === 401) {\n const payload = await readJson(res)\n const err = isRecord(payload) && isRecord(payload.error) ? payload.error : {}\n throw new RemoteUnauthorizedError(\n typeof err.message === \"string\" ? err.message : \"Authentication required.\",\n parseBearerChallenge(res.headers.get(\"www-authenticate\")),\n err.data,\n )\n }\n if (type.includes(\"text/event-stream\")) {\n return handleMessage(await readSse(res, id, opts), id, res.status)\n }\n const payload = await readJson(res)\n if (payload === undefined) {\n throw new RemoteTransportError(`${options.url} returned HTTP ${res.status} without a JSON-RPC response.`)\n }\n return handleMessage(payload, id, res.status)\n }\n\n const handleMessage = (message: unknown, id: number, status: number): Record<string, unknown> => {\n if (!isRecord(message)) throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n if (isRecord(message.error)) {\n const e = message.error\n throw new RemoteRpcError(\n typeof e.message === \"string\" ? e.message : \"JSON-RPC error\",\n typeof e.code === \"number\" ? e.code : -32_603,\n e.data,\n status,\n )\n }\n if (message.id !== id || !isRecord(message.result)) {\n throw new RemoteTransportError(`Invalid JSON-RPC response (HTTP ${status}).`)\n }\n return message.result\n }\n\n const listToolsResult = async (opts: RequestOptions = {}): Promise<ToolsListResult> => {\n const tools: RemoteTool[] = []\n const out: ToolsListResult = { tools }\n let cursor: string | undefined\n for (let page = 0; page < 100; page++) {\n const result = await request(\"tools/list\", cursor === undefined ? {} : { cursor }, opts)\n if (page === 0) {\n if (typeof result.ttlMs === \"number\" && Number.isFinite(result.ttlMs) && result.ttlMs >= 0) out.ttlMs = result.ttlMs\n if (typeof result.cacheScope === \"string\") out.cacheScope = result.cacheScope\n }\n if (Array.isArray(result.tools)) {\n for (const t of result.tools) if (isRecord(t) && typeof t.name === \"string\") tools.push(t as unknown as RemoteTool)\n }\n if (typeof result.nextCursor !== \"string\" || result.nextCursor === \"\") break\n cursor = result.nextCursor\n }\n return out\n }\n\n const callTool = async (\n tool: RemoteTool,\n args: Record<string, unknown>,\n opts: CallToolOptions = {},\n ): Promise<CallToolResult> => {\n const headers: Record<string, string> = { \"Mcp-Name\": tool.name, ...paramHeaders(tool, args) }\n let retry: { inputResponses?: InputResponses; requestState?: string } = {}\n const meta = opts.meta ? { _meta: opts.meta } : {}\n for (let round = 0; ; round++) {\n const result = await request(\"tools/call\", { name: tool.name, arguments: args, ...retry, ...meta }, opts, headers)\n if (result.resultType !== \"input_required\") return result as CallToolResult\n const required: InputRequired = {}\n if (isRecord(result.inputRequests)) required.inputRequests = result.inputRequests as InputRequired[\"inputRequests\"]\n if (typeof result.requestState === \"string\") required.requestState = result.requestState\n if (!opts.onInputRequired) throw new RemoteInputRequiredError(`${tool.name} requires input.`, required)\n if (round >= MAX_INPUT_ROUNDS) {\n throw new RemoteInputRequiredError(`${tool.name} still required input after ${MAX_INPUT_ROUNDS} rounds.`, required)\n }\n // 요청이 있으면 응답을 만든 뒤 재시도. requestState 는 그대로 되돌려 보내고, 없으면 보내지 않는다\n const responses = required.inputRequests ? await opts.onInputRequired(required, round) : undefined\n retry = {}\n if (responses !== undefined) retry.inputResponses = responses\n if (required.requestState !== undefined) retry.requestState = required.requestState\n }\n }\n\n /** tasks/* = Mcp-Name 헤더 = taskId (SDK 검증, 없으면 400) */\n const taskRequest = (method: string, taskId: string, params: Record<string, unknown>, opts: RequestOptions = {}) =>\n request(method, { taskId, ...params }, opts, { \"Mcp-Name\": taskId })\n\n return {\n url: options.url,\n request: (method, params, opts) => request(method, params, opts),\n listTools: async (opts) => (await listToolsResult(opts)).tools,\n listToolsResult,\n callTool,\n getTask: (taskId, opts) => taskRequest(\"tasks/get\", taskId, {}, opts),\n updateTask: async (taskId, inputResponses, opts) => {\n await taskRequest(\"tasks/update\", taskId, { inputResponses }, opts)\n },\n cancelTask: async (taskId, opts) => {\n await taskRequest(\"tasks/cancel\", taskId, {}, opts)\n },\n }\n}\n\n/** inputSchema 의 x-mcp-header 속성 → Mcp-Param-<Name> 헤더 (SEP-2243). 문자열 · 숫자 · boolean 값만 */\nfunction paramHeaders(tool: RemoteTool, args: Record<string, unknown>): Record<string, string> {\n const props = tool.inputSchema?.properties\n if (!isRecord(props)) return {}\n const out: Record<string, string> = {}\n for (const [key, schema] of Object.entries(props)) {\n if (!isRecord(schema) || typeof schema[\"x-mcp-header\"] !== \"string\") continue\n const value = args[key]\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n out[`Mcp-Param-${schema[\"x-mcp-header\"]}`] = String(value)\n }\n }\n return out\n}\n\n/* SSE */\n\n/** 응답 스트림에서 id 의 응답 메시지가 올 때까지 읽는다. 알림은 콜백, 응답 후 스트림을 닫는다 */\nasync function readSse(res: Response, id: number, opts: RequestOptions): Promise<unknown> {\n if (!res.body) throw new RemoteTransportError(\"Empty event stream.\")\n const reader = res.body.pipeThrough(new TextDecoderStream()).getReader()\n let buffer = \"\"\n let data: string[] = []\n const dispatch = (): unknown => {\n if (data.length === 0) return undefined\n const text = data.join(\"\\n\")\n data = []\n let message: unknown\n try {\n message = JSON.parse(text)\n } catch {\n return undefined\n }\n if (!isRecord(message)) return undefined\n if (typeof message.method === \"string\" && message.id === undefined) {\n try {\n opts.onNotification?.(message.method, isRecord(message.params) ? message.params : {})\n } catch {\n // 표시 오류는 응답에 영향 없음\n }\n return undefined\n }\n if (message.id === id && (\"result\" in message || \"error\" in message)) return message\n return undefined\n }\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += value\n let nl: number\n while ((nl = buffer.search(/\\r\\n|\\r|\\n/)) >= 0) {\n const line = buffer.slice(0, nl)\n buffer = buffer.slice(nl + (buffer.startsWith(\"\\r\\n\", nl) ? 2 : 1))\n if (line === \"\") {\n const found = dispatch()\n if (found !== undefined) return found\n continue\n }\n if (line.startsWith(\":\")) continue\n const colon = line.indexOf(\":\")\n const field = colon < 0 ? line : line.slice(0, colon)\n let value = colon < 0 ? \"\" : line.slice(colon + 1)\n if (value.startsWith(\" \")) value = value.slice(1)\n if (field === \"data\") data.push(value)\n }\n }\n const found = dispatch()\n if (found !== undefined) return found\n } finally {\n await reader.cancel().catch(() => {})\n }\n if (opts.signal?.aborted) throw opts.signal.reason\n throw new RemoteTransportError(\"Event stream ended without a response.\")\n}\n\nasync function readJson(res: Response): Promise<unknown> {\n const text = await res.text().catch(() => \"\")\n if (text === \"\") return undefined\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n\n/* WWW-Authenticate */\n\nexport interface BearerChallenge {\n /** Bearer challenge 가 있었는지 */\n bearer: boolean\n error?: string\n scope?: string\n resourceMetadata?: string\n}\n\n/** WWW-Authenticate 의 Bearer challenge 파라미터 (RFC 6750 · RFC 9728 resource_metadata) */\nexport function parseBearerChallenge(header: string | null): BearerChallenge {\n if (!header) return { bearer: false }\n const m = /(?:^|,\\s*)Bearer\\b(.*)$/i.exec(header)\n if (!m) return { bearer: false }\n const params: Record<string, string> = {}\n const re = /([A-Za-z_][\\w-]*)\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|([^\\s,]+))/g\n for (let p = re.exec(m[1]!); p !== null; p = re.exec(m[1]!)) {\n params[p[1]!.toLowerCase()] = p[2] !== undefined ? p[2].replace(/\\\\(.)/g, \"$1\") : p[3]!\n }\n const out: BearerChallenge = { bearer: true }\n if (params.error !== undefined) out.error = params.error\n if (params.scope !== undefined) out.scope = params.scope\n if (params.resource_metadata !== undefined) out.resourceMetadata = params.resource_metadata\n return out\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n const cause = (error as { cause?: unknown }).cause\n return cause instanceof Error && cause.message ? cause.message : error.message\n }\n return String(error)\n}\n"]}
|
package/dist/remote/oauth.d.ts
CHANGED
|
@@ -162,7 +162,7 @@ export interface DeviceLoginOptions {
|
|
|
162
162
|
signal?: AbortSignal;
|
|
163
163
|
fetch?: Fetch;
|
|
164
164
|
/** polling 대기 (테스트 주입). 기본 setTimeout */
|
|
165
|
-
sleep
|
|
165
|
+
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
166
166
|
/** 사용자 코드 준비됨 (안내 출력 · 브라우저 열기) */
|
|
167
167
|
onDeviceCode(device: DeviceAuthorization): void;
|
|
168
168
|
}
|
package/dist/remote/oauth.js
CHANGED
|
@@ -91,7 +91,7 @@ export const DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
|
91
91
|
*/
|
|
92
92
|
export async function registerClient(as, options, doFetch = fetch) {
|
|
93
93
|
if (options.clientId !== undefined) {
|
|
94
|
-
if (
|
|
94
|
+
if (options.clientId.startsWith("https://") && as.client_id_metadata_document_supported !== true) {
|
|
95
95
|
throw new OAuthFlowError(`${as.issuer} does not support Client ID Metadata Documents (client_id ${options.clientId}).`);
|
|
96
96
|
}
|
|
97
97
|
return { client_id: options.clientId, token_endpoint_auth_method: "none" };
|