@obov/mext 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build.js +16 -2
- package/dist/build.js.map +1 -1
- package/dist/cli/args.js +1 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/build.js +22 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev-server.js +3 -2
- package/dist/cli/dev-server.js.map +1 -1
- package/dist/cli/dev.d.ts +6 -0
- package/dist/cli/dev.js +4 -4
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/main.js +2 -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/run.js +5 -0
- 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/client/index.d.ts +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/runner.js +3 -0
- package/dist/client/runner.js.map +1 -1
- package/dist/client/typed.d.ts +3 -1
- package/dist/client/typed.js +39 -3
- package/dist/client/typed.js.map +1 -1
- package/dist/client/types.d.ts +31 -2
- package/dist/client/types.js.map +1 -1
- package/dist/config.d.ts +17 -0
- package/dist/config.js +36 -1
- 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/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/invoke.d.ts +4 -0
- package/dist/invoke.js +12 -5
- package/dist/invoke.js.map +1 -1
- package/dist/manifest.d.ts +6 -1
- package/dist/manifest.js.map +1 -1
- package/dist/mcp/constants.d.ts +2 -0
- package/dist/mcp/constants.js +2 -0
- package/dist/mcp/constants.js.map +1 -1
- package/dist/mcp/dispatch.d.ts +9 -3
- package/dist/mcp/dispatch.js +10 -4
- package/dist/mcp/dispatch.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 +22 -5
- package/dist/mcp/http.js +125 -18
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/tasks.js +1 -1
- package/dist/mcp/tasks.js.map +1 -1
- package/dist/remote/client.d.ts +24 -1
- package/dist/remote/client.js +177 -53
- 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/route.d.ts +40 -2
- package/dist/route.js +128 -8
- package/dist/route.js.map +1 -1
- package/dist/start.js +3 -2
- package/dist/start.js.map +1 -1
- package/dist/version-constant.d.ts +1 -1
- package/dist/version-constant.js +1 -1
- package/dist/version-constant.js.map +1 -1
- package/package.json +1 -1
package/dist/invoke.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoke.js","sourceRoot":"","sources":["../src/invoke.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AACxB,OAAO,EAAE,cAAc,EAAuB,MAAM,eAAe,CAAA;AACnE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAqC,MAAM,YAAY,CAAA;AACvF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAuB,MAAM,aAAa,CAAA;AAEtE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAsB,MAAM,aAAa,CAAA;AACzH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAwC,MAAM,sBAAsB,CAAA;AAC/G,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,cAAc,EAA0D,MAAM,eAAe,CAAA;AA+EnH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,QAAkB,EAClB,EAAU,EACV,QAAiB,EACjB,OAAsB;IAEtB,2EAA2E;IAC3E,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,CAAA;IAClG,IAAI,KAAwB,CAAA;IAC5B,IAAI,CAAC;QACH,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8EAA8E;QAC9E,IAAI,OAAO,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/D,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;YAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YACnD,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,OAAO,CAAC,UAAU;oBAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;;oBAC3C,MAAM,IAAI,CAAA;YACjB,CAAC;QACH,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;IACD,6CAA6C;IAC7C,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC3B,IAAI,OAAqD,CAAA;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1G,0CAA0C;IAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IACxC,MAAM,IAAI,GAAG,KAAK,IAA2B,EAAE;QAC7C,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;QACnE,wEAAwE;QACxE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,CAAA;QACxC,IAAI,KAA4B,CAAA;QAChC,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,uBAAuB;YACvB,KAAK,EAAE,IAAI,EAAE,CAAA;YACb,MAAM,KAAK,CAAA;QACb,CAAC;QACD,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAChC,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QACzC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;QAC3B,+DAA+D;QAC/D,MAAM,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;QAChD,MAAM,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;QACzD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAA;QAC9C,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;YACxB,OAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;YAC5E,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;YAC7H,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC5B,8CAA8C;YAC9C,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;gBACzF,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,CAAA;gBACrC,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;gBAChC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAA;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;gBAClE,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;gBACtD,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;gBAChC,MAAM,KAAK,CAAA;YACb,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;YACrF,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAA;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;YAC9D,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC,CAAA;IACD,MAAM,GAAG,GAAG,cAAc,CACxB,KAAK,CAAC,EAAE,EACR,OAAO,EACP,GAAG,EAAE,CAAC,MAAM,EACZ,CAAC,KAAK;QACJ,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACd,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAClB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAA;gBAC3B,IAAI,OAAO,CAAC,YAAY,EAAE,EAAE;oBAAE,KAAK,CAAC,IAAI,EAAE,CAAA;gBAC1C,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAA;gBAClD,OAAO,MAAM,CAAA;YACf,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,OAAO,CAAC,YAAY,EAAE,EAAE;oBAAE,KAAK,CAAC,IAAI,EAAE,CAAA;gBAC1C,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC,CAAA;gBACvD,MAAM,KAAK,CAAA;YACb,CAAC;QACH,CAAC,CACN,CAAA;IACD,oEAAoE;IACpE,OAAO,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AACzD,CAAC;AAED,gGAAgG;AAChG,OAAO,EAAE,WAAW,EAAE,CAAA;AAEtB;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAwB,EAAE,SAAoB,EAAE,OAAO,GAA2B,EAAE;IAC5G,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAA;IACvB,MAAM,IAAI,GAAG,CAAC,MAA2C,EAAE,OAAe,EAAS,EAAE,CACnF,UAAU,CACR,IAAI,SAAS,CAAC,mBAAmB,EAAE,OAAO,EAAE;QAC1C,OAAO,EAAE,KAAK,CAAC,EAAE;QACjB,MAAM;QACN,eAAe,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;QAC9B,WAAW,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;KACnC,CAAC,CACH,CAAA;IACH,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,QAAQ;QAAE,IAAI,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,EAAE,wCAAwC,CAAC,CAAA;IAC3G,IAAI,SAAS,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAClD,IAAI,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,EAAE,4DAA4D,CAAC,CAAA;IAC5F,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,EAAE,qBAAqB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9F,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,KAAK,CAClB,KAAwB,EACxB,OAAgB,EAChB,KAA4B,EAC5B,GAAmB,EACnB,OAAsB;IAEtB,IAAI,CAAC,OAAO,CAAC,SAAS;QAAE,OAAM;IAC9B,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,KAAe,EAAkC,EAAE;QAClF,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,mBAAmB,EAAE,OAAO,EAAE;YACxD,OAAO,EAAE,KAAK,CAAC,EAAE;YACjB,MAAM,EAAE,WAAW;YACnB,eAAe,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAC1C,WAAW,EAAE,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;SAC3C,CAAC,CAAA;QACF,uCAAuC;QACvC,IAAI,KAAK,KAAK,SAAS;YAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAA;QAC5C,OAAO,KAAK,CAAA;IACd,CAAC,CAAA;IACD,IAAI,OAAgB,CAAA;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,YAAY,EAAE,EAAE;YAAE,MAAM,KAAK,CAAA;QACrF,MAAM,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAC9D,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;IAC7G,CAAC;IACD,IAAI,OAAO,KAAK,IAAI;QAAE,MAAM,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,OAAO,CACpB,KAAwB,EACxB,OAAgB,EAChB,KAA4B,EAC5B,GAAmB,EACnB,OAAsB,EACtB,KAA6B;IAE7B,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,aAAa;YAAE,OAAM;QAClC,IAAI,CAAC,CAAC,MAAM,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;YACjE,KAAK,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;YACpC,OAAM;QACR,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAA;IAC3C,KAAK,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;IAC7D,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,KAAK,OAAO,CAAC,EAAE,CAAC;QACpE,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,gBAAgB,EAAE,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,EAAE,CAAC,CAAA;IAClF,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI;YAAE,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,aAAa,CAAC,CAAA;IACjF,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;QAChG,IAAI,CAAC,SAAS;YAAE,MAAM,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;QACxD,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;IAC7B,CAAC;IACD,KAAK,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AAC9D,CAAC;AAED,yGAAyG;AACzG,KAAK,UAAU,cAAc,CAC3B,KAAwB,EACxB,OAAgB,EAChB,KAA4B,EAC5B,GAAmB,EACnB,OAAsB;IAEtB,IAAI,CAAC;QACH,OAAQ,CAAC,MAAM,OAAO,CAAC,aAAc,CAAC,KAAK,EAAE,GAAG,CAAC,CAAa,KAAK,KAAK,CAAA;IAC1E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,YAAY,EAAE,EAAE;YAAE,MAAM,KAAK,CAAA;QAC/D,MAAM,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAC9D,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,GAAG,EAAE,oCAAoC,CAAA;AAEtF,qGAAqG;AACrG,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAwB,EAAE,QAAiB;IAC1E,MAAM,GAAG,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;IAClD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACzE,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,IAAI,CAAA;IACtC,MAAM,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;AAC3G,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,WAAW,CAAC,EAAU,EAAE,OAAgB,EAAE,KAAc;IACrE,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACjC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IACzD,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,IAAI,CAAA;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;SAC7F,IAAI,CAAC,IAAI,CAAC,CAAA;IACb,MAAM,IAAI,qBAAqB,CAAC,GAAG,EAAE,4DAA4D,OAAO,EAAE,CAAC,CAAA;AAC7G,CAAC;AAED,wFAAwF;AACxF,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAA;IACrC,CAAC;CACF;AAED,+CAA+C;AAC/C,MAAM,UAAU,aAAa,CAAC,KAAwB,EAAE,OAAsB;IAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAA;IAC3B,MAAM,GAAG,GAAG,KAAK,EAAE,OAAmB,EAAoB,EAAE;QAC1D,sEAAsE;QACtE,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK;YAAE,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACrD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,SAAS,CAAC,mBAAmB,EAAE,GAAG,KAAK,CAAC,EAAE,oDAAoD,EAAE;gBACxG,OAAO,EAAE,KAAK,CAAC,EAAE;gBACjB,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxD,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,CAAA;QACnG,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,IAAI,CAAA;QACjH,CAAC;QACD,MAAM,eAAe,GAAG,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,EAAE,OAAO,EAAE,CAAe,CAAA;QAC9G,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;YAC7B,OAAO,EAAE,KAAK,CAAC,EAAE;YACjB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,eAAe;SAChB,CAAC,CAAA;QACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;QAC5D,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,IAAI,CAAA;QACtC,MAAM,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,CAAC,CAAA;IACrF,CAAC,CAAA;IACD,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC;QACjF,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,MAAM;QACtD,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QACxC,GAAG,EAAE,GAAU;QACf,GAAG,EAAE,OAAO,CAAC,GAAG,IAAK,EAAc;QACnC,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,iBAAiB;KAC9D,CAAA;AACH,CAAC;AAED,gEAAgE;AAChE,KAAK,UAAU,iBAAiB,CAAC,GAAW;IAC1C,iBAAiB,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,mDAAmD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AAC1I,CAAC;AAED,iDAAiD;AACjD,SAAS,YAAY,CAAC,GAAY;IAChC,MAAM,MAAM,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACtF,IAAI,MAAM,EAAE,QAAQ,KAAK,OAAO,IAAI,MAAM,EAAE,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClE,MAAM,IAAI,SAAS,CAAC,gDAAgD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC5F,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,mBAAmB,CAAC,KAAwB,EAAE,KAAc;IAC1E,IAAI,IAAY,CAAA;IAChB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,IAAI,CAAA;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,IAAI,CAAA;IACb,CAAC;IACD,OAAO,OAAO,KAAK,CAAC,EAAE,SAAS,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AAC3G,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,GAAY,EACZ,SAAsC,EACtC,cAA0B,EAC1B,QAAmB;IAEnB,MAAM,MAAM,GAAoB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAClC,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,CAAC,CAAC,OAAO;KACnB,CAAC,CAAC,CAAA;IACH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;IACjC,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACxH,CAAC;IACD,MAAM,cAAc,GAAG,CAAC,GAAG,OAAO,CAAC,CAAA;IACnC,MAAM,OAAO,GACX,cAAc,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,qBAAqB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAClD,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpF,OAAO,IAAI,SAAS,CAAC,kBAAkB,EAAE,yBAAyB,OAAO,KAAK,OAAO,EAAE,EAAE;QACvF,OAAO;QACP,cAAc;QACd,MAAM;QACN,eAAe,EAAE,cAAc;QAC/B,QAAQ;KACT,CAAC,CAAA;AACJ,CAAC;AAED,sCAAsC;AACtC,SAAS,QAAQ,CAAC,GAAY,EAAE,IAA4B;IAC1D,IAAI,GAAG,GAAY,GAAG,CAAA;IACtB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QACxD,GAAG,GAAI,GAAoC,CAAC,GAAG,CAAC,CAAA;QAChD,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,IAAI,CAAA;IACpC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,UAAU,CAAC,KAAgB;IAClC,MAAM,KAAK,CAAA;AACb,CAAC","sourcesContent":["import * as z from \"zod\"\nimport { approvalModeOf, type ApprovalConfig } from \"./approval.ts\"\nimport { auditHidden, startAudit, type AuditConfig, type AuditTrail } from \"./audit.ts\"\nimport { callerOf, surfaceOf, type ReportedClient } from \"./caller.ts\"\nimport type { Ask, AskRequest, Command, CommandContext, InputSchema, MextApp, ProgressUpdate } from \"./command.ts\"\nimport { approvalRequired, inputDeclined, isCommandError, isMextError, MextError, type ArgumentIssue } from \"./errors.ts\"\nimport { exposedRegistry } from \"./expose.ts\"\nimport { observeCommand, reportCommandError, type Instrumentation, type Transport } from \"./instrumentation.ts\"\nimport { findCommand } from \"./lookup.ts\"\nimport { hasScope, type Principal } from \"./principal.ts\"\nimport { loadCommand, resolveCommand, type JsonSchema, type RegisteredCommand, type Registry } from \"./registry.ts\"\n\n/** 어댑터가 주입하는 ctx.ask 구현. command = 정식 ID */\nexport type AskHandler = (request: AskHandlerRequest) => Promise<unknown>\n\nexport type AskHandlerRequest =\n | { command: string; kind: \"confirm\"; message: string }\n | { command: string; kind: \"input\"; message: string; schema: InputSchema; requestedSchema: JsonSchema }\n | { command: string; kind: \"url\"; message: string; url: string }\n\nexport interface InvokeOptions {\n principal: Principal\n /** 기본 = abort 되지 않는 signal */\n signal?: AbortSignal\n /** 기본 = 무시 */\n progress?: (update: ProgressUpdate) => void\n /** 기본 = ctx.ask 호출 시 INPUT_UNAVAILABLE */\n ask?: AskHandler\n app?: MextApp\n /** readOnly 명령어만 허용 (split 의 query 도구). 그 외 = PERMISSION_DENIED */\n readOnly?: boolean\n /**\n * 응답을 기다리게 하지 않을 작업 (숨긴 명령어 호출 시도의 감사 전달, §11.1) 을 넘겨받는다. MCP 어댑터 = waitUntil 또는 그대로 둠.\n * 없음 = invoke 가 끝까지 기다린다 (로컬 실행: 프로세스가 곧 끝난다)\n */\n background?: (work: Promise<void>) => void\n /** loadInstrumentation 결과. onCommandError · mext.command span. 기본 = 없음 */\n instrumentation?: Instrumentation\n /** 실행 어댑터 (onCommandError · span 속성 · ctx.caller.transport · 기본 표면). 기본 \"local\" */\n transport?: Transport\n /** 클라이언트가 신고한 clientInfo (ctx.caller.client). 자가 신고 값. 기본 = 없음 */\n client?: ReportedClient\n /** W3C trace context carrier (MCP params._meta 의 traceparent · tracestate). span 의 부모 */\n traceContext?: Record<string, unknown>\n /** ctx.resourceUpdated (§12.5). 기본 = no-op */\n resourceUpdated?: (uri: string) => Promise<void>\n /**\n * tasks 확장 (§12.6). 입력 검증 · 권한 · 승인 (§4) 통과 후 execute 직전에 호출.\n * 반환 = 분리 실행: invoke 는 handle 로 바로 resolve, execute 는 반환된 signal · ask · progress 로 계속 실행 후 settle.\n * undefined = 동기 실행 (지금과 같음). span · onCommandError 는 분리 실행 전체를 덮는다\n */\n detach?: (entry: RegisteredCommand) => Promise<DetachedExecution | undefined>\n /** 감사 (config.audit, §11.1). 없음 = 이벤트 없음 */\n audit?: AuditConfig\n /** 승인의 표면별 확인 방식 (config.approval, §4 승인). 없음 = 모든 표면 ask */\n approval?: ApprovalConfig\n /**\n * 요청에 확인 표시가 실려 있음 (MCP params._meta[\"dev.mext/approval\"] = { confirmed: true }). 클라이언트가 실은 값이다:\n * client 방식 표면 + 서버가 정한 행위자 human 일 때만 인정한다. 기본 false\n */\n confirmed?: boolean\n /**\n * 이 호출이 입력 대기로 끝났는지 (MRTR 라운드: 답 없는 ctx.ask 가 있어 결과를 버리고 InputRequiredResult 를 돌려준다).\n * true = 감사 이벤트 없음 (답을 받아 끝난 라운드가 1건)\n */\n pendingInput?: () => boolean\n}\n\n/** detach 의 반환. execute 의 ctx 를 요청과 분리한다 (R2: 응답 종료 ≠ 취소) */\nexport interface DetachedExecution {\n /** invoke 결과의 detached (MCP = CreateTaskResult) */\n handle: unknown\n /** 감사 이벤트의 taskId (§11.1) */\n taskId?: string\n signal: AbortSignal\n ask: AskHandler\n progress: (update: ProgressUpdate) => void\n /** execute 종료. 값 = output 검증 후, 예외 = onCommandError 보고 후. 거부하지 않는다 */\n settle(outcome: { value: unknown } | { error: unknown }): Promise<void>\n}\n\nexport interface InvokeResult {\n /** 정식 ID (별칭으로 호출해도) */\n command: string\n value: unknown\n /** detach 로 분리 실행됨: DetachedExecution.handle (value 는 undefined) */\n detached?: unknown\n}\n\n/**\n * 어댑터 공통 실행기: ID 해석 (별칭 포함. 주체의 표면에서 숨긴 명령어 = 없는 ID, §4 expose) → 권한 → (lazy 면 모듈 import) → Zod safeParse 1회 → 가드 (authorize, §4) → 승인 (needsApproval · requiresConfirmation, §4) → execute.\n * 실패는 MextError (UNKNOWN_COMMAND · PERMISSION_DENIED · INVALID_ARGUMENT · APPROVAL_REQUIRED · INPUT_UNAVAILABLE · INPUT_DECLINED).\n * 핸들러 예외는 그대로 전파 (instrumentation 있으면 onCommandError 보고 후).\n * instrumentation.otel 있으면 findCommand 뒤 전체를 `mext.command <id>` span 으로 감싼다.\n * options.audit 있으면 호출 1건 = 감사 이벤트 1건 (§11.1. UNKNOWN_COMMAND · 입력 검증 실패 · 입력 대기 라운드 제외).\n */\nexport async function invoke(\n registry: Registry,\n id: string,\n rawInput: unknown,\n options: InvokeOptions,\n): Promise<InvokeResult> {\n // expose (§4): 주체의 표면에서 보이는 명령어만. 숨긴 명령어 = UNKNOWN_COMMAND (없는 ID 와 같은 본문)\n const view = exposedRegistry(registry, surfaceOf(options.principal, options.transport ?? \"local\"))\n let entry: RegisteredCommand\n try {\n entry = findCommand(view, id)\n } catch (error) {\n // 숨긴 명령어의 호출 시도 기록 (audit.includeHidden, §11.1). 응답 = 이 오류 그대로. 꺼져 있으면 찾지 않는다\n if (options.audit?.includeHidden === true && view !== registry) {\n const hidden = resolveCommand(registry, id)\n const work = hidden && auditHidden(hidden, options)\n if (work) {\n if (options.background) options.background(work)\n else await work\n }\n }\n throw error\n }\n // span 의 취소 판정 signal. 분리 실행 후 = task signal\n let signal = options.signal\n let handoff: ((result: InvokeResult) => void) | undefined\n const handedOff = options.detach ? new Promise<InvokeResult>((resolve) => (handoff = resolve)) : undefined\n // 감사 (§11.1). sink 없음 · 대상 아님 = undefined\n const trail = startAudit(entry, options)\n const body = async (): Promise<InvokeResult> => {\n authorize(entry, options.principal, { readOnly: options.readOnly })\n // lazy Registry (mext start) = 여기서 명령어 모듈 import. 권한 · ID 오류는 import 없이\n const command = await loadCommand(entry)\n let input: z.output<InputSchema>\n try {\n input = await parseInput(entry, rawInput)\n } catch (error) {\n // 입력 검증 실패 = 감사 이벤트 없음\n trail?.skip()\n throw error\n }\n trail?.validated(command, input)\n const ctx = createContext(entry, options)\n ctx.signal.throwIfAborted()\n // 가드 = 로드한 명령어의 authorize (lazy Registry 의 메타데이터 명령어에는 함수가 없다)\n await guard(entry, command, input, ctx, options)\n await approve(entry, command, input, ctx, options, trail)\n const detached = await options.detach?.(entry)\n if (detached) {\n signal = detached.signal\n handoff!({ command: entry.id, value: undefined, detached: detached.handle })\n const taskCtx = createContext(entry, { ...options, signal: detached.signal, ask: detached.ask, progress: detached.progress })\n trail?.task(detached.taskId)\n // 감사 = 분리 실행의 실제 종료 시점, task 결과 기록 (settle) 전\n try {\n const value = await parseOutput(entry.id, command, await command.execute(input, taskCtx))\n await trail?.finish({ value }, false)\n await detached.settle({ value })\n return { command: entry.id, value }\n } catch (error) {\n await reportCommandError(error, entry.id, options, taskCtx.signal)\n await trail?.finish({ error }, taskCtx.signal.aborted)\n await detached.settle({ error })\n throw error\n }\n }\n try {\n const value = await parseOutput(entry.id, command, await command.execute(input, ctx))\n return { command: entry.id, value }\n } catch (error) {\n await reportCommandError(error, entry.id, options, ctx.signal)\n throw error\n }\n }\n const run = observeCommand(\n entry.id,\n options,\n () => signal,\n !trail\n ? body\n : async (trace) => {\n trail.trace(trace)\n try {\n const result = await body()\n if (options.pendingInput?.()) trail.skip()\n await trail.finish({ value: result.value }, false)\n return result\n } catch (error) {\n if (options.pendingInput?.()) trail.skip()\n await trail.finish({ error }, signal?.aborted === true)\n throw error\n }\n },\n )\n // 분리 실행 = handoff 로 먼저 resolve. 이후 run 의 거부는 race 가 받는다 (미처리 거부 없음)\n return handedOff ? Promise.race([handedOff, run]) : run\n}\n\n/** ID · 별칭 → 명령어. 없으면 UNKNOWN_COMMAND (suggested · usage). 구현 = lookup.ts (help · 고객 CLI 공용) */\nexport { findCommand }\n\n/**\n * 안전성 메타데이터를 주체에 대해 강제.\n * readOnly 전용 호출 = readOnly 명령어만 · anonymous = readOnly 명령어만 · command.scopes 전부 보유 (\"*\" = 전체).\n */\nexport function authorize(entry: RegisteredCommand, principal: Principal, options: { readOnly?: boolean } = {}): void {\n const c = entry.command\n const deny = (reason: \"anonymous\" | \"read_only\" | \"scope\", message: string): never =>\n throwError(\n new MextError(\"PERMISSION_DENIED\", message, {\n command: entry.id,\n reason,\n required_scopes: [...c.scopes],\n held_scopes: [...principal.scopes],\n }),\n )\n if (options.readOnly && !c.readOnly) deny(\"read_only\", `${entry.id} is not read-only and cannot run here.`)\n if (principal.kind === \"anonymous\" && !c.readOnly) {\n deny(\"anonymous\", `${entry.id} is not read-only and requires an authenticated principal.`)\n }\n const missing = c.scopes.filter((s) => !hasScope(principal, s))\n if (missing.length > 0) deny(\"scope\", `${entry.id} requires scopes: ${missing.join(\", \")}.`)\n}\n\n/**\n * 실행 가드 (defineCommand authorize, §4). true 만 통과. 그 외 반환값 (undefined 포함) · 예외 = PERMISSION_DENIED (reason \"authorize\").\n * CommandError = 그 message 로 거부. 그 외 예외 = 거부 + onCommandError 보고 (message 는 응답에 싣지 않는다).\n * 취소 · mext 오류 (ctx.ask 의 INPUT_UNAVAILABLE 등) · 입력 대기 중의 예외는 바꾸지 않는다\n */\nasync function guard(\n entry: RegisteredCommand,\n command: Command,\n input: z.output<InputSchema>,\n ctx: CommandContext,\n options: InvokeOptions,\n): Promise<void> {\n if (!command.authorize) return\n const denied = (message: string, cause?: unknown): MextError<\"PERMISSION_DENIED\"> => {\n const error = new MextError(\"PERMISSION_DENIED\", message, {\n command: entry.id,\n reason: \"authorize\",\n required_scopes: [...entry.command.scopes],\n held_scopes: [...options.principal.scopes],\n })\n // 원인은 서버 쪽 디버깅용 (응답 본문 = toJSON 에는 없다)\n if (cause !== undefined) error.cause = cause\n return error\n }\n let verdict: unknown\n try {\n verdict = await command.authorize(input, ctx)\n } catch (error) {\n if (ctx.signal.aborted || isMextError(error) || options.pendingInput?.()) throw error\n await reportCommandError(error, entry.id, options, ctx.signal)\n throw denied(isCommandError(error) && error.message !== \"\" ? error.message : GUARD_DENIED(entry.id), error)\n }\n if (verdict !== true) throw denied(GUARD_DENIED(entry.id))\n}\n\n/**\n * 승인 (defineCommand needsApproval · requiresConfirmation, §4 승인). 승인이 필요한 호출을 표면의 확인 방식 한 곳에서 확인한다.\n * 행위자 agent = 승인 불가 (APPROVAL_REQUIRED human_required). 묻지 않는다\n * client 방식 표면 = 요청의 확인 표시 + 행위자 human 일 때만 통과. 묻지 않는다\n * ask 방식 표면 (기본) = ctx.ask confirm (CLI = 프롬프트 · --yes, MCP = MRTR). ask 미주입 = INPUT_UNAVAILABLE. 확인 표시는 보지 않는다\n * 승인 대상이 아닌 명령어 = 아무것도 하지 않는다\n */\nasync function approve(\n entry: RegisteredCommand,\n command: Command,\n input: z.output<InputSchema>,\n ctx: CommandContext,\n options: InvokeOptions,\n trail: AuditTrail | undefined,\n): Promise<void> {\n if (!command.requiresConfirmation) {\n if (!command.needsApproval) return\n if (!(await approvalNeeded(entry, command, input, ctx, options))) {\n trail?.approval({ required: false })\n return\n }\n }\n const method = approvalModeOf(options.approval, ctx.caller.surface)\n const actor = options.principal.actor?.kind\n trail?.approval({ required: true, method, confirmed: false })\n if (actor === \"agent\" || (method === \"client\" && actor !== \"human\")) {\n throw approvalRequired(entry.id, \"human_required\", { agent: actor === \"agent\" })\n }\n if (method === \"client\") {\n if (options.confirmed !== true) throw approvalRequired(entry.id, \"unconfirmed\")\n } else {\n const confirmed = await ctx.ask({ kind: \"confirm\", message: confirmationMessage(entry, input) })\n if (!confirmed) throw inputDeclined(entry.id, \"confirm\")\n ctx.signal.throwIfAborted()\n }\n trail?.approval({ required: true, method, confirmed: true })\n}\n\n/** needsApproval 조건식. false 만 승인 불필요. 그 외 반환값 · 예외 = 필요 (예외는 onCommandError 보고). 취소 · 입력 대기 중의 예외는 전파 */\nasync function approvalNeeded(\n entry: RegisteredCommand,\n command: Command,\n input: z.output<InputSchema>,\n ctx: CommandContext,\n options: InvokeOptions,\n): Promise<boolean> {\n try {\n return ((await command.needsApproval!(input, ctx)) as unknown) !== false\n } catch (error) {\n if (ctx.signal.aborted || options.pendingInput?.()) throw error\n await reportCommandError(error, entry.id, options, ctx.signal)\n return true\n }\n}\n\nconst GUARD_DENIED = (id: string): string => `${id} is not permitted for this caller.`\n\n/** Zod safeParse 1회. 실패 = INVALID_ARGUMENT (missing_fields · issues · expected_schema · examples) */\nexport async function parseInput(entry: RegisteredCommand, rawInput: unknown): Promise<z.output<InputSchema>> {\n const raw = rawInput === undefined ? {} : rawInput\n const result = await (await loadCommand(entry)).input.safeParseAsync(raw)\n if (result.success) return result.data\n throw invalidArgument(entry.id, raw, result.error.issues, entry.inputSchema, [...entry.command.examples])\n}\n\n/**\n * output 이 있으면 반환값 safeParse (모든 어댑터 · 노출 방식, §12.2). 결과 = 파싱된 값 (outputSchema 와 같은 모양).\n * 실패 = OutputValidationError (핸들러 예외와 같이 EXECUTION_ERROR · onCommandError 보고). 던진 오류는 검증하지 않는다\n */\nasync function parseOutput(id: string, command: Command, value: unknown): Promise<unknown> {\n if (!command.output) return value\n const result = await command.output.safeParseAsync(value)\n if (result.success) return result.data\n const summary = result.error.issues\n .map((i) => (i.path.length > 0 ? `${i.path.map(String).join(\".\")}: ${i.message}` : i.message))\n .join(\"; \")\n throw new OutputValidationError(`${id} returned a value that does not match its output schema: ${summary}`)\n}\n\n/** output 검증 실패. MextError 가 아님 = 응답 EXECUTION_ERROR (message 만) · onCommandError 보고 */\nexport class OutputValidationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"OutputValidationError\"\n }\n}\n\n/** ctx 생성. ask · progress · signal 은 어댑터 주입 */\nexport function createContext(entry: RegisteredCommand, options: InvokeOptions): CommandContext {\n const handler = options.ask\n const ask = async (request: AskRequest): Promise<unknown> => {\n // url 형식 오류 = 핸들러 버그 (TypeError → EXECUTION_ERROR). 실행 환경과 무관하게 먼저 검사\n if (request.kind === \"url\") assertAskUrl(request.url)\n if (!handler) {\n throw new MextError(\"INPUT_UNAVAILABLE\", `${entry.id} requested input, but this environment cannot ask.`, {\n command: entry.id,\n ...(request.kind === \"url\" ? { url: request.url } : {}),\n })\n }\n if (request.kind === \"confirm\") {\n return (await handler({ command: entry.id, kind: \"confirm\", message: request.message })) === true\n }\n if (request.kind === \"url\") {\n return (await handler({ command: entry.id, kind: \"url\", message: request.message, url: request.url })) === true\n }\n const requestedSchema = z.toJSONSchema(request.schema, { target: \"draft-2020-12\", io: \"input\" }) as JsonSchema\n const response = await handler({\n command: entry.id,\n kind: \"input\",\n message: request.message,\n schema: request.schema,\n requestedSchema,\n })\n const parsed = await request.schema.safeParseAsync(response)\n if (parsed.success) return parsed.data\n throw invalidArgument(entry.id, response, parsed.error.issues, requestedSchema, [])\n }\n return {\n principal: options.principal,\n caller: callerOf(options.principal, options.transport ?? \"local\", options.client),\n signal: options.signal ?? new AbortController().signal,\n progress: options.progress ?? (() => {}),\n ask: ask as Ask,\n app: options.app ?? ({} as MextApp),\n resourceUpdated: options.resourceUpdated ?? noResourceUpdates,\n }\n}\n\n/** state 없는 실행 (로컬 CLI · stateless 서버). uri 형식 오류만 TypeError */\nasync function noResourceUpdates(uri: string): Promise<void> {\n assertResourceUri(uri)\n}\n\n/** ctx.resourceUpdated uri: 비어 있지 않은 문자열. 아니면 TypeError (핸들러 버그) */\nexport function assertResourceUri(uri: unknown): asserts uri is string {\n if (typeof uri !== \"string\" || uri === \"\") throw new TypeError(`resourceUpdated uri must be a non-empty string: ${JSON.stringify(uri)}`)\n}\n\n/** ctx.ask url: http(s) 절대 URL. 아니면 TypeError */\nfunction assertAskUrl(url: unknown): asserts url is string {\n const parsed = typeof url === \"string\" && URL.canParse(url) ? new URL(url) : undefined\n if (parsed?.protocol !== \"http:\" && parsed?.protocol !== \"https:\") {\n throw new TypeError(`ctx.ask url must be an absolute http(s) URL: ${JSON.stringify(url)}`)\n }\n}\n\n/** 승인 확인 문구 (ask 방식). 검증된 입력을 포함 (무엇을 승인하는지) */\nexport function confirmationMessage(entry: RegisteredCommand, input: unknown): string {\n let args: string\n try {\n args = JSON.stringify(input) ?? \"{}\"\n } catch {\n args = \"{}\"\n }\n return `Run ${entry.id} with ${args}?${entry.command.destructive ? \" This command is destructive.\" : \"\"}`\n}\n\n/** INVALID_ARGUMENT (missing_fields · issues · expected_schema · examples). 프롬프트 인자 (§12.3) 도 사용 */\nexport function invalidArgument(\n command: string,\n raw: unknown,\n zodIssues: readonly z.core.$ZodIssue[],\n expectedSchema: JsonSchema,\n examples: unknown[],\n): MextError<\"INVALID_ARGUMENT\"> {\n const issues: ArgumentIssue[] = zodIssues.map((i) => ({\n path: i.path.map(String).join(\".\"),\n code: i.code,\n message: i.message,\n }))\n const missing = new Set<string>()\n for (const i of zodIssues) {\n if (i.code === \"invalid_type\" && i.path.length > 0 && isAbsent(raw, i.path)) missing.add(i.path.map(String).join(\".\"))\n }\n const missing_fields = [...missing]\n const summary =\n missing_fields.length > 0\n ? `missing required: ${missing_fields.join(\", \")}`\n : issues.map((i) => (i.path ? `${i.path}: ${i.message}` : i.message)).join(\"; \")\n return new MextError(\"INVALID_ARGUMENT\", `Invalid arguments for ${command}: ${summary}`, {\n command,\n missing_fields,\n issues,\n expected_schema: expectedSchema,\n examples,\n })\n}\n\n/** 원본 입력에 경로가 없는지 (값 undefined 포함) */\nfunction isAbsent(raw: unknown, path: readonly PropertyKey[]): boolean {\n let cur: unknown = raw\n for (const key of path) {\n if (cur === null || typeof cur !== \"object\") return true\n cur = (cur as Record<PropertyKey, unknown>)[key]\n if (cur === undefined) return true\n }\n return false\n}\n\nfunction throwError(error: MextError): never {\n throw error\n}\n"]}
|
|
1
|
+
{"version":3,"file":"invoke.js","sourceRoot":"","sources":["../src/invoke.ts"],"names":[],"mappings":"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","sourcesContent":["import * as z from \"zod\"\nimport { approvalModeOf, type ApprovalConfig } from \"./approval.ts\"\nimport { splitResult, type ContentBlock } from \"./content.ts\"\nimport { auditHidden, startAudit, type AuditConfig, type AuditTrail } from \"./audit.ts\"\nimport { callerOf, surfaceOf, type ReportedClient } from \"./caller.ts\"\nimport type { Ask, AskRequest, Command, CommandContext, InputSchema, MextApp, ProgressUpdate } from \"./command.ts\"\nimport { approvalRequired, inputDeclined, isCommandError, isMextError, MextError, type ArgumentIssue } from \"./errors.ts\"\nimport { exposedRegistry } from \"./expose.ts\"\nimport { observeCommand, reportCommandError, type Instrumentation, type Transport } from \"./instrumentation.ts\"\nimport { findCommand } from \"./lookup.ts\"\nimport { hasScope, type Principal } from \"./principal.ts\"\nimport { loadCommand, resolveCommand, type JsonSchema, type RegisteredCommand, type Registry } from \"./registry.ts\"\n\n/** 어댑터가 주입하는 ctx.ask 구현. command = 정식 ID */\nexport type AskHandler = (request: AskHandlerRequest) => Promise<unknown>\n\nexport type AskHandlerRequest =\n | { command: string; kind: \"confirm\"; message: string }\n | { command: string; kind: \"input\"; message: string; schema: InputSchema; requestedSchema: JsonSchema }\n | { command: string; kind: \"url\"; message: string; url: string }\n\nexport interface InvokeOptions {\n principal: Principal\n /** 기본 = abort 되지 않는 signal */\n signal?: AbortSignal\n /** 기본 = 무시 */\n progress?: (update: ProgressUpdate) => void\n /** 기본 = ctx.ask 호출 시 INPUT_UNAVAILABLE */\n ask?: AskHandler\n app?: MextApp\n /** readOnly 명령어만 허용 (split 의 query 도구). 그 외 = PERMISSION_DENIED */\n readOnly?: boolean\n /**\n * 응답을 기다리게 하지 않을 작업 (숨긴 명령어 호출 시도의 감사 전달, §11.1) 을 넘겨받는다. MCP 어댑터 = waitUntil 또는 그대로 둠.\n * 없음 = invoke 가 끝까지 기다린다 (로컬 실행: 프로세스가 곧 끝난다)\n */\n background?: (work: Promise<void>) => void\n /** loadInstrumentation 결과. onCommandError · mext.command span. 기본 = 없음 */\n instrumentation?: Instrumentation\n /** 실행 어댑터 (onCommandError · span 속성 · ctx.caller.transport · 기본 표면). 기본 \"local\" */\n transport?: Transport\n /** 클라이언트가 신고한 clientInfo (ctx.caller.client). 자가 신고 값. 기본 = 없음 */\n client?: ReportedClient\n /** W3C trace context carrier (MCP params._meta 의 traceparent · tracestate). span 의 부모 */\n traceContext?: Record<string, unknown>\n /** ctx.resourceUpdated (§12.5). 기본 = no-op */\n resourceUpdated?: (uri: string) => Promise<void>\n /**\n * tasks 확장 (§12.6). 입력 검증 · 권한 · 승인 (§4) 통과 후 execute 직전에 호출.\n * 반환 = 분리 실행: invoke 는 handle 로 바로 resolve, execute 는 반환된 signal · ask · progress 로 계속 실행 후 settle.\n * undefined = 동기 실행 (지금과 같음). span · onCommandError 는 분리 실행 전체를 덮는다\n */\n detach?: (entry: RegisteredCommand) => Promise<DetachedExecution | undefined>\n /** 감사 (config.audit, §11.1). 없음 = 이벤트 없음 */\n audit?: AuditConfig\n /** 승인의 표면별 확인 방식 (config.approval, §4 승인). 없음 = 모든 표면 ask */\n approval?: ApprovalConfig\n /**\n * 요청에 확인 표시가 실려 있음 (MCP params._meta[\"dev.mext/approval\"] = { confirmed: true }). 클라이언트가 실은 값이다:\n * client 방식 표면 + 서버가 정한 행위자 human 일 때만 인정한다. 기본 false\n */\n confirmed?: boolean\n /**\n * 이 호출이 입력 대기로 끝났는지 (MRTR 라운드: 답 없는 ctx.ask 가 있어 결과를 버리고 InputRequiredResult 를 돌려준다).\n * true = 감사 이벤트 없음 (답을 받아 끝난 라운드가 1건)\n */\n pendingInput?: () => boolean\n}\n\n/** detach 의 반환. execute 의 ctx 를 요청과 분리한다 (R2: 응답 종료 ≠ 취소) */\nexport interface DetachedExecution {\n /** invoke 결과의 detached (MCP = CreateTaskResult) */\n handle: unknown\n /** 감사 이벤트의 taskId (§11.1) */\n taskId?: string\n signal: AbortSignal\n ask: AskHandler\n progress: (update: ProgressUpdate) => void\n /** execute 종료. 값 = output 검증 후, 예외 = onCommandError 보고 후. 거부하지 않는다 */\n settle(outcome: { value: unknown; content?: ContentBlock[] } | { error: unknown }): Promise<void>\n}\n\nexport interface InvokeResult {\n /** 정식 ID (별칭으로 호출해도) */\n command: string\n value: unknown\n /** 결과 콘텐츠 (image · audio · resource_link, spec §4). 없으면 생략 */\n content?: ContentBlock[]\n /** detach 로 분리 실행됨: DetachedExecution.handle (value 는 undefined) */\n detached?: unknown\n}\n\n/**\n * 어댑터 공통 실행기: ID 해석 (별칭 포함. 주체의 표면에서 숨긴 명령어 = 없는 ID, §4 expose) → 권한 → (lazy 면 모듈 import) → Zod safeParse 1회 → 가드 (authorize, §4) → 승인 (needsApproval · requiresConfirmation, §4) → execute.\n * 실패는 MextError (UNKNOWN_COMMAND · PERMISSION_DENIED · INVALID_ARGUMENT · APPROVAL_REQUIRED · INPUT_UNAVAILABLE · INPUT_DECLINED).\n * 핸들러 예외는 그대로 전파 (instrumentation 있으면 onCommandError 보고 후).\n * instrumentation.otel 있으면 findCommand 뒤 전체를 `mext.command <id>` span 으로 감싼다.\n * options.audit 있으면 호출 1건 = 감사 이벤트 1건 (§11.1. UNKNOWN_COMMAND · 입력 검증 실패 · 입력 대기 라운드 제외).\n */\nexport async function invoke(\n registry: Registry,\n id: string,\n rawInput: unknown,\n options: InvokeOptions,\n): Promise<InvokeResult> {\n // expose (§4): 주체의 표면에서 보이는 명령어만. 숨긴 명령어 = UNKNOWN_COMMAND (없는 ID 와 같은 본문)\n const view = exposedRegistry(registry, surfaceOf(options.principal, options.transport ?? \"local\"))\n let entry: RegisteredCommand\n try {\n entry = findCommand(view, id)\n } catch (error) {\n // 숨긴 명령어의 호출 시도 기록 (audit.includeHidden, §11.1). 응답 = 이 오류 그대로. 꺼져 있으면 찾지 않는다\n if (options.audit?.includeHidden === true && view !== registry) {\n const hidden = resolveCommand(registry, id)\n const work = hidden && auditHidden(hidden, options)\n if (work) {\n if (options.background) options.background(work)\n else await work\n }\n }\n throw error\n }\n // span 의 취소 판정 signal. 분리 실행 후 = task signal\n let signal = options.signal\n let handoff: ((result: InvokeResult) => void) | undefined\n const handedOff = options.detach ? new Promise<InvokeResult>((resolve) => (handoff = resolve)) : undefined\n // 감사 (§11.1). sink 없음 · 대상 아님 = undefined\n const trail = startAudit(entry, options)\n const body = async (): Promise<InvokeResult> => {\n authorize(entry, options.principal, { readOnly: options.readOnly })\n // lazy Registry (mext start) = 여기서 명령어 모듈 import. 권한 · ID 오류는 import 없이\n const command = await loadCommand(entry)\n let input: z.output<InputSchema>\n try {\n input = await parseInput(entry, rawInput)\n } catch (error) {\n // 입력 검증 실패 = 감사 이벤트 없음\n trail?.skip()\n throw error\n }\n trail?.validated(command, input)\n const ctx = createContext(entry, options)\n ctx.signal.throwIfAborted()\n // 가드 = 로드한 명령어의 authorize (lazy Registry 의 메타데이터 명령어에는 함수가 없다)\n await guard(entry, command, input, ctx, options)\n await approve(entry, command, input, ctx, options, trail)\n const detached = await options.detach?.(entry)\n if (detached) {\n signal = detached.signal\n handoff!({ command: entry.id, value: undefined, detached: detached.handle })\n const taskCtx = createContext(entry, { ...options, signal: detached.signal, ask: detached.ask, progress: detached.progress })\n trail?.task(detached.taskId)\n // 감사 = 분리 실행의 실제 종료 시점, task 결과 기록 (settle) 전\n try {\n const { value, content } = await settleOutput(entry.id, command, await command.execute(input, taskCtx))\n await trail?.finish({ value }, false)\n await detached.settle(content ? { value, content } : { value })\n return { command: entry.id, value, ...(content ? { content } : {}) }\n } catch (error) {\n await reportCommandError(error, entry.id, options, taskCtx.signal)\n await trail?.finish({ error }, taskCtx.signal.aborted)\n await detached.settle({ error })\n throw error\n }\n }\n try {\n const { value, content } = await settleOutput(entry.id, command, await command.execute(input, ctx))\n return { command: entry.id, value, ...(content ? { content } : {}) }\n } catch (error) {\n await reportCommandError(error, entry.id, options, ctx.signal)\n throw error\n }\n }\n const run = observeCommand(\n entry.id,\n options,\n () => signal,\n !trail\n ? body\n : async (trace) => {\n trail.trace(trace)\n try {\n const result = await body()\n if (options.pendingInput?.()) trail.skip()\n await trail.finish({ value: result.value }, false)\n return result\n } catch (error) {\n if (options.pendingInput?.()) trail.skip()\n await trail.finish({ error }, signal?.aborted === true)\n throw error\n }\n },\n )\n // 분리 실행 = handoff 로 먼저 resolve. 이후 run 의 거부는 race 가 받는다 (미처리 거부 없음)\n return handedOff ? Promise.race([handedOff, run]) : run\n}\n\n/** ID · 별칭 → 명령어. 없으면 UNKNOWN_COMMAND (suggested · usage). 구현 = lookup.ts (help · 고객 CLI 공용) */\nexport { findCommand }\n\n/**\n * 안전성 메타데이터를 주체에 대해 강제.\n * readOnly 전용 호출 = readOnly 명령어만 · anonymous = readOnly 명령어만 · command.scopes 전부 보유 (\"*\" = 전체).\n */\nexport function authorize(entry: RegisteredCommand, principal: Principal, options: { readOnly?: boolean } = {}): void {\n const c = entry.command\n const deny = (reason: \"anonymous\" | \"read_only\" | \"scope\", message: string): never =>\n throwError(\n new MextError(\"PERMISSION_DENIED\", message, {\n command: entry.id,\n reason,\n required_scopes: [...c.scopes],\n held_scopes: [...principal.scopes],\n }),\n )\n if (options.readOnly && !c.readOnly) deny(\"read_only\", `${entry.id} is not read-only and cannot run here.`)\n if (principal.kind === \"anonymous\" && !c.readOnly) {\n deny(\"anonymous\", `${entry.id} is not read-only and requires an authenticated principal.`)\n }\n const missing = c.scopes.filter((s) => !hasScope(principal, s))\n if (missing.length > 0) deny(\"scope\", `${entry.id} requires scopes: ${missing.join(\", \")}.`)\n}\n\n/**\n * 실행 가드 (defineCommand authorize, §4). true 만 통과. 그 외 반환값 (undefined 포함) · 예외 = PERMISSION_DENIED (reason \"authorize\").\n * CommandError = 그 message 로 거부. 그 외 예외 = 거부 + onCommandError 보고 (message 는 응답에 싣지 않는다).\n * 취소 · mext 오류 (ctx.ask 의 INPUT_UNAVAILABLE 등) · 입력 대기 중의 예외는 바꾸지 않는다\n */\nasync function guard(\n entry: RegisteredCommand,\n command: Command,\n input: z.output<InputSchema>,\n ctx: CommandContext,\n options: InvokeOptions,\n): Promise<void> {\n if (!command.authorize) return\n const denied = (message: string, cause?: unknown): MextError<\"PERMISSION_DENIED\"> => {\n const error = new MextError(\"PERMISSION_DENIED\", message, {\n command: entry.id,\n reason: \"authorize\",\n required_scopes: [...entry.command.scopes],\n held_scopes: [...options.principal.scopes],\n })\n // 원인은 서버 쪽 디버깅용 (응답 본문 = toJSON 에는 없다)\n if (cause !== undefined) error.cause = cause\n return error\n }\n let verdict: unknown\n try {\n verdict = await command.authorize(input, ctx)\n } catch (error) {\n if (ctx.signal.aborted || isMextError(error) || options.pendingInput?.()) throw error\n await reportCommandError(error, entry.id, options, ctx.signal)\n throw denied(isCommandError(error) && error.message !== \"\" ? error.message : GUARD_DENIED(entry.id), error)\n }\n if (verdict !== true) throw denied(GUARD_DENIED(entry.id))\n}\n\n/**\n * 승인 (defineCommand needsApproval · requiresConfirmation, §4 승인). 승인이 필요한 호출을 표면의 확인 방식 한 곳에서 확인한다.\n * 행위자 agent = 승인 불가 (APPROVAL_REQUIRED human_required). 묻지 않는다\n * client 방식 표면 = 요청의 확인 표시 + 행위자 human 일 때만 통과. 묻지 않는다\n * ask 방식 표면 (기본) = ctx.ask confirm (CLI = 프롬프트 · --yes, MCP = MRTR). ask 미주입 = INPUT_UNAVAILABLE. 확인 표시는 보지 않는다\n * 승인 대상이 아닌 명령어 = 아무것도 하지 않는다\n */\nasync function approve(\n entry: RegisteredCommand,\n command: Command,\n input: z.output<InputSchema>,\n ctx: CommandContext,\n options: InvokeOptions,\n trail: AuditTrail | undefined,\n): Promise<void> {\n if (!command.requiresConfirmation) {\n if (!command.needsApproval) return\n if (!(await approvalNeeded(entry, command, input, ctx, options))) {\n trail?.approval({ required: false })\n return\n }\n }\n const method = approvalModeOf(options.approval, ctx.caller.surface)\n const actor = options.principal.actor?.kind\n trail?.approval({ required: true, method, confirmed: false })\n if (actor === \"agent\" || (method === \"client\" && actor !== \"human\")) {\n throw approvalRequired(entry.id, \"human_required\", { agent: actor === \"agent\" })\n }\n if (method === \"client\") {\n if (options.confirmed !== true) throw approvalRequired(entry.id, \"unconfirmed\")\n } else {\n const confirmed = await ctx.ask({ kind: \"confirm\", message: confirmationMessage(entry, input) })\n if (!confirmed) throw inputDeclined(entry.id, \"confirm\")\n ctx.signal.throwIfAborted()\n }\n trail?.approval({ required: true, method, confirmed: true })\n}\n\n/** needsApproval 조건식. false 만 승인 불필요. 그 외 반환값 · 예외 = 필요 (예외는 onCommandError 보고). 취소 · 입력 대기 중의 예외는 전파 */\nasync function approvalNeeded(\n entry: RegisteredCommand,\n command: Command,\n input: z.output<InputSchema>,\n ctx: CommandContext,\n options: InvokeOptions,\n): Promise<boolean> {\n try {\n return ((await command.needsApproval!(input, ctx)) as unknown) !== false\n } catch (error) {\n if (ctx.signal.aborted || options.pendingInput?.()) throw error\n await reportCommandError(error, entry.id, options, ctx.signal)\n return true\n }\n}\n\nconst GUARD_DENIED = (id: string): string => `${id} is not permitted for this caller.`\n\n/** Zod safeParse 1회. 실패 = INVALID_ARGUMENT (missing_fields · issues · expected_schema · examples) */\nexport async function parseInput(entry: RegisteredCommand, rawInput: unknown): Promise<z.output<InputSchema>> {\n const raw = rawInput === undefined ? {} : rawInput\n const result = await (await loadCommand(entry)).input.safeParseAsync(raw)\n if (result.success) return result.data\n throw invalidArgument(entry.id, raw, result.error.issues, entry.inputSchema, [...entry.command.examples])\n}\n\n/**\n * output 이 있으면 반환값 safeParse (모든 어댑터 · 노출 방식, §12.2). 결과 = 파싱된 값 (outputSchema 와 같은 모양).\n * 실패 = OutputValidationError (핸들러 예외와 같이 EXECUTION_ERROR · onCommandError 보고). 던진 오류는 검증하지 않는다\n */\n/** execute 반환값 → 값 · 콘텐츠 (spec §4 결과 콘텐츠). output 검증 = 값만 */\nasync function settleOutput(id: string, command: Command, raw: unknown): Promise<{ value: unknown; content?: ContentBlock[] }> {\n const { value, content } = splitResult(raw)\n const parsed = await parseOutput(id, command, value)\n return content ? { value: parsed, content } : { value: parsed }\n}\n\nasync function parseOutput(id: string, command: Command, value: unknown): Promise<unknown> {\n if (!command.output) return value\n const result = await command.output.safeParseAsync(value)\n if (result.success) return result.data\n const summary = result.error.issues\n .map((i) => (i.path.length > 0 ? `${i.path.map(String).join(\".\")}: ${i.message}` : i.message))\n .join(\"; \")\n throw new OutputValidationError(`${id} returned a value that does not match its output schema: ${summary}`)\n}\n\n/** output 검증 실패. MextError 가 아님 = 응답 EXECUTION_ERROR (message 만) · onCommandError 보고 */\nexport class OutputValidationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"OutputValidationError\"\n }\n}\n\n/** ctx 생성. ask · progress · signal 은 어댑터 주입 */\nexport function createContext(entry: RegisteredCommand, options: InvokeOptions): CommandContext {\n const handler = options.ask\n const ask = async (request: AskRequest): Promise<unknown> => {\n // url 형식 오류 = 핸들러 버그 (TypeError → EXECUTION_ERROR). 실행 환경과 무관하게 먼저 검사\n if (request.kind === \"url\") assertAskUrl(request.url)\n if (!handler) {\n throw new MextError(\"INPUT_UNAVAILABLE\", `${entry.id} requested input, but this environment cannot ask.`, {\n command: entry.id,\n ...(request.kind === \"url\" ? { url: request.url } : {}),\n })\n }\n if (request.kind === \"confirm\") {\n return (await handler({ command: entry.id, kind: \"confirm\", message: request.message })) === true\n }\n if (request.kind === \"url\") {\n return (await handler({ command: entry.id, kind: \"url\", message: request.message, url: request.url })) === true\n }\n const requestedSchema = z.toJSONSchema(request.schema, { target: \"draft-2020-12\", io: \"input\" }) as JsonSchema\n const response = await handler({\n command: entry.id,\n kind: \"input\",\n message: request.message,\n schema: request.schema,\n requestedSchema,\n })\n const parsed = await request.schema.safeParseAsync(response)\n if (parsed.success) return parsed.data\n throw invalidArgument(entry.id, response, parsed.error.issues, requestedSchema, [])\n }\n return {\n principal: options.principal,\n caller: callerOf(options.principal, options.transport ?? \"local\", options.client),\n signal: options.signal ?? new AbortController().signal,\n progress: options.progress ?? (() => {}),\n ask: ask as Ask,\n app: options.app ?? ({} as MextApp),\n resourceUpdated: options.resourceUpdated ?? noResourceUpdates,\n }\n}\n\n/** state 없는 실행 (로컬 CLI · stateless 서버). uri 형식 오류만 TypeError */\nasync function noResourceUpdates(uri: string): Promise<void> {\n assertResourceUri(uri)\n}\n\n/** ctx.resourceUpdated uri: 비어 있지 않은 문자열. 아니면 TypeError (핸들러 버그) */\nexport function assertResourceUri(uri: unknown): asserts uri is string {\n if (typeof uri !== \"string\" || uri === \"\") throw new TypeError(`resourceUpdated uri must be a non-empty string: ${JSON.stringify(uri)}`)\n}\n\n/** ctx.ask url: http(s) 절대 URL. 아니면 TypeError */\nfunction assertAskUrl(url: unknown): asserts url is string {\n const parsed = typeof url === \"string\" && URL.canParse(url) ? new URL(url) : undefined\n if (parsed?.protocol !== \"http:\" && parsed?.protocol !== \"https:\") {\n throw new TypeError(`ctx.ask url must be an absolute http(s) URL: ${JSON.stringify(url)}`)\n }\n}\n\n/** 승인 확인 문구 (ask 방식). 검증된 입력을 포함 (무엇을 승인하는지) */\nexport function confirmationMessage(entry: RegisteredCommand, input: unknown): string {\n let args: string\n try {\n args = JSON.stringify(input) ?? \"{}\"\n } catch {\n args = \"{}\"\n }\n return `Run ${entry.id} with ${args}?${entry.command.destructive ? \" This command is destructive.\" : \"\"}`\n}\n\n/** INVALID_ARGUMENT (missing_fields · issues · expected_schema · examples). 프롬프트 인자 (§12.3) 도 사용 */\nexport function invalidArgument(\n command: string,\n raw: unknown,\n zodIssues: readonly z.core.$ZodIssue[],\n expectedSchema: JsonSchema,\n examples: unknown[],\n): MextError<\"INVALID_ARGUMENT\"> {\n const issues: ArgumentIssue[] = zodIssues.map((i) => ({\n path: i.path.map(String).join(\".\"),\n code: i.code,\n message: i.message,\n }))\n const missing = new Set<string>()\n for (const i of zodIssues) {\n if (i.code === \"invalid_type\" && i.path.length > 0 && isAbsent(raw, i.path)) missing.add(i.path.map(String).join(\".\"))\n }\n const missing_fields = [...missing]\n const summary =\n missing_fields.length > 0\n ? `missing required: ${missing_fields.join(\", \")}`\n : issues.map((i) => (i.path ? `${i.path}: ${i.message}` : i.message)).join(\"; \")\n return new MextError(\"INVALID_ARGUMENT\", `Invalid arguments for ${command}: ${summary}`, {\n command,\n missing_fields,\n issues,\n expected_schema: expectedSchema,\n examples,\n })\n}\n\n/** 원본 입력에 경로가 없는지 (값 undefined 포함) */\nfunction isAbsent(raw: unknown, path: readonly PropertyKey[]): boolean {\n let cur: unknown = raw\n for (const key of path) {\n if (cur === null || typeof cur !== \"object\") return true\n cur = (cur as Record<PropertyKey, unknown>)[key]\n if (cur === undefined) return true\n }\n return false\n}\n\nfunction throwError(error: MextError): never {\n throw error\n}\n"]}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ToolExposure } from "./mcp/dispatch.ts";
|
|
|
2
2
|
import type { JsonSchema, RegisteredCommand, Registry } from "./registry.ts";
|
|
3
3
|
import type { ManifestPrompt } from "./prompt.ts";
|
|
4
4
|
import type { ManifestResource } from "./resource.ts";
|
|
5
|
-
import type { RouteMethod } from "./route.ts";
|
|
5
|
+
import type { RouteAuth, RouteMethod } from "./route.ts";
|
|
6
6
|
export declare const MANIFEST_SCHEMA_VERSION = 1;
|
|
7
7
|
export interface ManifestCommand {
|
|
8
8
|
id: string;
|
|
@@ -106,6 +106,11 @@ export interface BuildManifestRoute {
|
|
|
106
106
|
methods: RouteMethod[];
|
|
107
107
|
/** .mext/ 기준 상대 경로. routes/items/[id].ts → "routes/items/[id].js" */
|
|
108
108
|
module: string;
|
|
109
|
+
/** 적용 값 (export > 설정 routes > 없음 = false). 참고용: 실행은 모듈 export + 설정으로 판정. 0.7.0 전 빌드 = 없음 */
|
|
110
|
+
auth?: RouteAuth;
|
|
111
|
+
origin?: boolean;
|
|
112
|
+
/** 바이트 (true = server.maxBodyBytes 값) · false = 상한 없음 */
|
|
113
|
+
maxBodyBytes?: number | false;
|
|
109
114
|
}
|
|
110
115
|
/**
|
|
111
116
|
* 명령어 계약의 지문: ID · 별칭 · positional · 입력 스키마 · 안전성 메타데이터 (readOnly · destructive ·
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\"\nimport type { ToolExposure } from \"./mcp/dispatch.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"./registry.ts\"\nimport type { ManifestPrompt } from \"./prompt.ts\"\nimport type { ManifestResource } from \"./resource.ts\"\nimport type { RouteMethod } from \"./route.ts\"\nimport { loadRegistry } from \"./scan.ts\"\n\nexport const MANIFEST_SCHEMA_VERSION = 1\n\nexport interface ManifestCommand {\n id: string\n description: string\n /** 별칭 전체 ID */\n aliases: string[]\n /** commands/ 기준 상대 경로 (posix) */\n file?: string\n readOnly: boolean\n destructive: boolean\n /** 항상 승인 필요 (requiresConfirmation: true · needsApproval: true, §4 승인) */\n requiresConfirmation: boolean\n /** 승인이 조건식 (needsApproval 함수) 일 때만: 호출에 따라 승인이 필요할 수 있다. 없음 = 조건식 아님 */\n needsApproval?: \"conditional\"\n scopes: string[]\n positional: string[]\n examples: unknown[]\n /** JSON Schema 2020-12 */\n inputSchema: JsonSchema\n outputSchema?: JsonSchema\n /** task 명령어 (§12.6). 없음 = 동기 명령어 */\n task?: { ttlMs: number }\n}\n\nexport interface ManifestNamespace {\n id: string\n /** _index.md 내용 */\n description?: string\n}\n\nexport interface Manifest {\n schemaVersion: typeof MANIFEST_SCHEMA_VERSION\n /** commands/_index.md 내용 */\n description?: string\n /** 루트 제외, ID 순 */\n namespaces: ManifestNamespace[]\n /** ID 순 */\n commands: ManifestCommand[]\n}\n\n/** 명령어 하나의 메타데이터 (manifest · help 공통) */\nexport function describeCommand(entry: RegisteredCommand): ManifestCommand {\n const c = entry.command\n const out: ManifestCommand = {\n id: entry.id,\n description: c.description,\n aliases: [...entry.aliases],\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n scopes: [...c.scopes],\n positional: [...c.positional],\n examples: [...c.examples],\n inputSchema: entry.inputSchema,\n }\n if (c.needsApproval !== undefined) out.needsApproval = \"conditional\"\n if (entry.file !== undefined) out.file = entry.file\n if (entry.outputSchema !== undefined) out.outputSchema = entry.outputSchema\n if (c.task !== undefined) out.task = { ttlMs: c.task.ttlMs }\n return out\n}\n\nexport function buildManifest(registry: Registry): Manifest {\n const manifest: Manifest = {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n namespaces: [],\n commands: [...registry.commands.values()].map(describeCommand),\n }\n for (const ns of registry.namespaces.values()) {\n if (ns.id === \"\") {\n if (ns.description !== undefined) manifest.description = ns.description\n continue\n }\n manifest.namespaces.push(ns.description === undefined ? { id: ns.id } : { id: ns.id, description: ns.description })\n }\n return manifest\n}\n\n/** 빌드 시 manifest 생성: commands/ 스캔 → Manifest (JSON 직렬화 가능) */\nexport async function generateManifest(dir: string): Promise<Manifest> {\n return buildManifest(await loadRegistry(dir))\n}\n\n/** mext build 의 .mext/manifest.json 명령어: Manifest 명령어 + 번들 모듈 경로 */\nexport interface BuildManifestCommand extends ManifestCommand {\n /** .mext/ 기준 상대 경로 (posix). commands/users/get.ts → \"commands/users/get.js\". default export = defineCommand 결과 */\n module: string\n /**\n * 표면별 노출 (defineCommand expose, §4). 없음 = 모든 표면. 서버 (mext start · handler.js · 로컬 bin) 가 실행 시 판정.\n * help · tools/list · 고객 CLI 내장 manifest 에는 싣지 않는다\n */\n expose?: Record<string, boolean>\n}\n\n/** mext build 의 .mext/manifest.json 자원: 자원 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestResource extends ManifestResource {\n /** .mext/ 기준 상대 경로 (posix). resources/users/profile.ts → \"resources/users/profile.js\". default export = defineResource 결과 */\n module: string\n}\n\n/** mext build 의 .mext/manifest.json 프롬프트: 프롬프트 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestPrompt extends ManifestPrompt {\n /** .mext/ 기준 상대 경로 (posix). prompts/github/review.ts → \"prompts/github/review.js\". default export = definePrompt 결과 */\n module: string\n}\n\n/**\n * .mext/manifest.json (mext build 산출, mext start · handler.js 가 읽는다).\n * namespaces · description = Manifest 와 같음\n */\nexport interface BuildManifest extends Omit<Manifest, \"commands\"> {\n /** 빌드한 @obov/mext 버전. 실행 시 설치된 버전과 다르면 시작 오류 */\n mextVersion: string\n /** 빌드 식별자 (D3: mextVersion · manifestHash · 번들 코드의 sha256 앞 16자, 같은 입력 = 같은 값) */\n buildId: string\n /**\n * manifestHash(commands, { resources: 자원 uri, prompts: 이름 · argsSchema }). 전체 명령어 기준.\n * expose 로 숨긴 명령어가 있는 호출자에게는 서버가 그 보기의 값을 계산해 보낸다 (§4)\n */\n manifestHash: string\n /** MCP 도구 노출 방식 (mext.config.ts tools, 기본 execute). 고객 CLI 번들 형태의 호출 방식 (§12.2) */\n tools: ToolExposure\n /** mext.config.ts 번들 (.mext/ 기준). 설정 파일이 없으면 생략 */\n config?: string\n /** instrumentation.ts 번들 (.mext/ 기준). 없으면 생략 */\n instrumentation?: string\n /** ID 순 */\n commands: BuildManifestCommand[]\n /** MCP 자원 (§12.3). uri 순. 자원이 없으면 생략 */\n resources?: BuildManifestResource[]\n /** MCP 프롬프트 (§12.3). 이름 순. 프롬프트가 없으면 생략 */\n prompts?: BuildManifestPrompt[]\n /** routes/ (§12.4). 경로 순. route 가 없으면 생략. manifestHash 에 포함하지 않는다 (명령어 계약 아님) */\n routes?: BuildManifestRoute[]\n}\n\n/** .mext/manifest.json 의 route */\nexport interface BuildManifestRoute {\n /** URL 경로 패턴 (\"/items/[id]\") */\n path: string\n /** routes/ 기준 상대 경로 (posix) */\n file: string\n /** export 한 메서드. 그 외 = 405 (모듈 import 없음) */\n methods: RouteMethod[]\n /** .mext/ 기준 상대 경로. routes/items/[id].ts → \"routes/items/[id].js\" */\n module: string\n}\n\n/**\n * 명령어 계약의 지문: ID · 별칭 · positional · 입력 스키마 · 안전성 메타데이터 (readOnly · destructive ·\n * requiresConfirmation · needsApproval (조건식일 때만) · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.\n * 설명 · examples · outputSchema · task · 파일 경로는 제외 (클라이언트의 help 캐시 · 플래그 파싱에 영향 없음).\n * extra.resources = 자원 uri (고정 URI · 템플릿 원문, §12.3), extra.prompts = 프롬프트 이름 · args JSON Schema (§12.3).\n * 둘 다 없거나 비면 명령어만의 값과 같다.\n * 빌드 manifest · 서버 (_meta[\"dev.mext/manifestHash\"]) · 클라이언트가 같은 함수로 계산한다\n */\nexport function manifestHash(\n commands: readonly ManifestCommand[],\n extra: { resources?: readonly string[]; prompts?: readonly { name: string; argsSchema?: JsonSchema | undefined }[] } = {},\n): string {\n const normalized = [...commands]\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))\n .map((c) => ({\n id: c.id,\n aliases: [...c.aliases].sort(),\n positional: c.positional,\n inputSchema: c.inputSchema,\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n // 조건식일 때만 (없으면 속성 생략 = 기존 값과 같다)\n needsApproval: c.needsApproval,\n scopes: [...c.scopes].sort(),\n }))\n const resources = [...(extra.resources ?? [])].sort()\n const prompts = [...(extra.prompts ?? [])]\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))\n .map((p) => ({ name: p.name, argsSchema: p.argsSchema }))\n const value =\n resources.length > 0 || prompts.length > 0\n ? { commands: normalized, ...(resources.length > 0 ? { resources } : {}), ...(prompts.length > 0 ? { prompts } : {}) }\n : normalized\n return createHash(\"sha256\").update(canonicalJson(value)).digest(\"hex\")\n}\n\n/** 키 정렬 JSON (배열 순서 유지, undefined 속성 생략) */\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\"\n if (Array.isArray(value)) return `[${value.map((v) => (v === undefined ? \"null\" : canonicalJson(v))).join(\",\")}]`\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(\",\")}}`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAMxC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAA;AAyCxC,yCAAyC;AACzC,MAAM,UAAU,eAAe,CAAC,KAAwB;IACtD,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAA;IACvB,MAAM,GAAG,GAAoB;QAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;QAC3B,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,oBAAoB,EAAE,CAAC,CAAC,oBAAoB;QAC5C,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;QACrB,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;QAC7B,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACzB,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CAAA;IACD,IAAI,CAAC,CAAC,aAAa,KAAK,SAAS;QAAE,GAAG,CAAC,aAAa,GAAG,aAAa,CAAA;IACpE,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;IACnD,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS;QAAE,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAA;IAC3E,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;QAAE,GAAG,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;IAC5D,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAkB;IAC9C,MAAM,QAAQ,GAAa;QACzB,aAAa,EAAE,uBAAuB;QACtC,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC;KAC/D,CAAA;IACD,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YACjB,IAAI,EAAE,CAAC,WAAW,KAAK,SAAS;gBAAE,QAAQ,CAAC,WAAW,GAAG,EAAE,CAAC,WAAW,CAAA;YACvE,SAAQ;QACV,CAAC;QACD,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;IACrH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAW;IAChD,OAAO,aAAa,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC,CAAA;AAC/C,CAAC;AAwED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAoC,EACpC,KAAK,GAAkH,EAAE;IAEzH,MAAM,UAAU,GAAG,CAAC,GAAG,QAAQ,CAAC;SAC7B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACxD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE;QAC9B,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,oBAAoB,EAAE,CAAC,CAAC,oBAAoB;QAC5C,iCAAiC;QACjC,aAAa,EAAE,CAAC,CAAC,aAAa;QAC9B,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;KAC7B,CAAC,CAAC,CAAA;IACL,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACrD,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;SACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA;IAC3D,MAAM,KAAK,GACT,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QACxC,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;QACtH,CAAC,CAAC,UAAU,CAAA;IAChB,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACxE,CAAC;AAED,4CAA4C;AAC5C,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAA;IACvF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IACjH,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;SAC7D,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;SAClC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACnD,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;AAC7F,CAAC","sourcesContent":["import { createHash } from \"node:crypto\"\nimport type { ToolExposure } from \"./mcp/dispatch.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"./registry.ts\"\nimport type { ManifestPrompt } from \"./prompt.ts\"\nimport type { ManifestResource } from \"./resource.ts\"\nimport type { RouteAuth, RouteMethod } from \"./route.ts\"\nimport { loadRegistry } from \"./scan.ts\"\n\nexport const MANIFEST_SCHEMA_VERSION = 1\n\nexport interface ManifestCommand {\n id: string\n description: string\n /** 별칭 전체 ID */\n aliases: string[]\n /** commands/ 기준 상대 경로 (posix) */\n file?: string\n readOnly: boolean\n destructive: boolean\n /** 항상 승인 필요 (requiresConfirmation: true · needsApproval: true, §4 승인) */\n requiresConfirmation: boolean\n /** 승인이 조건식 (needsApproval 함수) 일 때만: 호출에 따라 승인이 필요할 수 있다. 없음 = 조건식 아님 */\n needsApproval?: \"conditional\"\n scopes: string[]\n positional: string[]\n examples: unknown[]\n /** JSON Schema 2020-12 */\n inputSchema: JsonSchema\n outputSchema?: JsonSchema\n /** task 명령어 (§12.6). 없음 = 동기 명령어 */\n task?: { ttlMs: number }\n}\n\nexport interface ManifestNamespace {\n id: string\n /** _index.md 내용 */\n description?: string\n}\n\nexport interface Manifest {\n schemaVersion: typeof MANIFEST_SCHEMA_VERSION\n /** commands/_index.md 내용 */\n description?: string\n /** 루트 제외, ID 순 */\n namespaces: ManifestNamespace[]\n /** ID 순 */\n commands: ManifestCommand[]\n}\n\n/** 명령어 하나의 메타데이터 (manifest · help 공통) */\nexport function describeCommand(entry: RegisteredCommand): ManifestCommand {\n const c = entry.command\n const out: ManifestCommand = {\n id: entry.id,\n description: c.description,\n aliases: [...entry.aliases],\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n scopes: [...c.scopes],\n positional: [...c.positional],\n examples: [...c.examples],\n inputSchema: entry.inputSchema,\n }\n if (c.needsApproval !== undefined) out.needsApproval = \"conditional\"\n if (entry.file !== undefined) out.file = entry.file\n if (entry.outputSchema !== undefined) out.outputSchema = entry.outputSchema\n if (c.task !== undefined) out.task = { ttlMs: c.task.ttlMs }\n return out\n}\n\nexport function buildManifest(registry: Registry): Manifest {\n const manifest: Manifest = {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n namespaces: [],\n commands: [...registry.commands.values()].map(describeCommand),\n }\n for (const ns of registry.namespaces.values()) {\n if (ns.id === \"\") {\n if (ns.description !== undefined) manifest.description = ns.description\n continue\n }\n manifest.namespaces.push(ns.description === undefined ? { id: ns.id } : { id: ns.id, description: ns.description })\n }\n return manifest\n}\n\n/** 빌드 시 manifest 생성: commands/ 스캔 → Manifest (JSON 직렬화 가능) */\nexport async function generateManifest(dir: string): Promise<Manifest> {\n return buildManifest(await loadRegistry(dir))\n}\n\n/** mext build 의 .mext/manifest.json 명령어: Manifest 명령어 + 번들 모듈 경로 */\nexport interface BuildManifestCommand extends ManifestCommand {\n /** .mext/ 기준 상대 경로 (posix). commands/users/get.ts → \"commands/users/get.js\". default export = defineCommand 결과 */\n module: string\n /**\n * 표면별 노출 (defineCommand expose, §4). 없음 = 모든 표면. 서버 (mext start · handler.js · 로컬 bin) 가 실행 시 판정.\n * help · tools/list · 고객 CLI 내장 manifest 에는 싣지 않는다\n */\n expose?: Record<string, boolean>\n}\n\n/** mext build 의 .mext/manifest.json 자원: 자원 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestResource extends ManifestResource {\n /** .mext/ 기준 상대 경로 (posix). resources/users/profile.ts → \"resources/users/profile.js\". default export = defineResource 결과 */\n module: string\n}\n\n/** mext build 의 .mext/manifest.json 프롬프트: 프롬프트 메타데이터 + 번들 모듈 경로 */\nexport interface BuildManifestPrompt extends ManifestPrompt {\n /** .mext/ 기준 상대 경로 (posix). prompts/github/review.ts → \"prompts/github/review.js\". default export = definePrompt 결과 */\n module: string\n}\n\n/**\n * .mext/manifest.json (mext build 산출, mext start · handler.js 가 읽는다).\n * namespaces · description = Manifest 와 같음\n */\nexport interface BuildManifest extends Omit<Manifest, \"commands\"> {\n /** 빌드한 @obov/mext 버전. 실행 시 설치된 버전과 다르면 시작 오류 */\n mextVersion: string\n /** 빌드 식별자 (D3: mextVersion · manifestHash · 번들 코드의 sha256 앞 16자, 같은 입력 = 같은 값) */\n buildId: string\n /**\n * manifestHash(commands, { resources: 자원 uri, prompts: 이름 · argsSchema }). 전체 명령어 기준.\n * expose 로 숨긴 명령어가 있는 호출자에게는 서버가 그 보기의 값을 계산해 보낸다 (§4)\n */\n manifestHash: string\n /** MCP 도구 노출 방식 (mext.config.ts tools, 기본 execute). 고객 CLI 번들 형태의 호출 방식 (§12.2) */\n tools: ToolExposure\n /** mext.config.ts 번들 (.mext/ 기준). 설정 파일이 없으면 생략 */\n config?: string\n /** instrumentation.ts 번들 (.mext/ 기준). 없으면 생략 */\n instrumentation?: string\n /** ID 순 */\n commands: BuildManifestCommand[]\n /** MCP 자원 (§12.3). uri 순. 자원이 없으면 생략 */\n resources?: BuildManifestResource[]\n /** MCP 프롬프트 (§12.3). 이름 순. 프롬프트가 없으면 생략 */\n prompts?: BuildManifestPrompt[]\n /** routes/ (§12.4). 경로 순. route 가 없으면 생략. manifestHash 에 포함하지 않는다 (명령어 계약 아님) */\n routes?: BuildManifestRoute[]\n}\n\n/** .mext/manifest.json 의 route */\nexport interface BuildManifestRoute {\n /** URL 경로 패턴 (\"/items/[id]\") */\n path: string\n /** routes/ 기준 상대 경로 (posix) */\n file: string\n /** export 한 메서드. 그 외 = 405 (모듈 import 없음) */\n methods: RouteMethod[]\n /** .mext/ 기준 상대 경로. routes/items/[id].ts → \"routes/items/[id].js\" */\n module: string\n /** 적용 값 (export > 설정 routes > 없음 = false). 참고용: 실행은 모듈 export + 설정으로 판정. 0.7.0 전 빌드 = 없음 */\n auth?: RouteAuth\n origin?: boolean\n /** 바이트 (true = server.maxBodyBytes 값) · false = 상한 없음 */\n maxBodyBytes?: number | false\n}\n\n/**\n * 명령어 계약의 지문: ID · 별칭 · positional · 입력 스키마 · 안전성 메타데이터 (readOnly · destructive ·\n * requiresConfirmation · needsApproval (조건식일 때만) · scopes) 의 정규화 JSON (키 정렬, ID 순) sha256 hex.\n * 설명 · examples · outputSchema · task · 파일 경로는 제외 (클라이언트의 help 캐시 · 플래그 파싱에 영향 없음).\n * extra.resources = 자원 uri (고정 URI · 템플릿 원문, §12.3), extra.prompts = 프롬프트 이름 · args JSON Schema (§12.3).\n * 둘 다 없거나 비면 명령어만의 값과 같다.\n * 빌드 manifest · 서버 (_meta[\"dev.mext/manifestHash\"]) · 클라이언트가 같은 함수로 계산한다\n */\nexport function manifestHash(\n commands: readonly ManifestCommand[],\n extra: { resources?: readonly string[]; prompts?: readonly { name: string; argsSchema?: JsonSchema | undefined }[] } = {},\n): string {\n const normalized = [...commands]\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))\n .map((c) => ({\n id: c.id,\n aliases: [...c.aliases].sort(),\n positional: c.positional,\n inputSchema: c.inputSchema,\n readOnly: c.readOnly,\n destructive: c.destructive,\n requiresConfirmation: c.requiresConfirmation,\n // 조건식일 때만 (없으면 속성 생략 = 기존 값과 같다)\n needsApproval: c.needsApproval,\n scopes: [...c.scopes].sort(),\n }))\n const resources = [...(extra.resources ?? [])].sort()\n const prompts = [...(extra.prompts ?? [])]\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))\n .map((p) => ({ name: p.name, argsSchema: p.argsSchema }))\n const value =\n resources.length > 0 || prompts.length > 0\n ? { commands: normalized, ...(resources.length > 0 ? { resources } : {}), ...(prompts.length > 0 ? { prompts } : {}) }\n : normalized\n return createHash(\"sha256\").update(canonicalJson(value)).digest(\"hex\")\n}\n\n/** 키 정렬 JSON (배열 순서 유지, undefined 속성 생략) */\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\"\n if (Array.isArray(value)) return `[${value.map((v) => (v === undefined ? \"null\" : canonicalJson(v))).join(\",\")}]`\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(\",\")}}`\n}\n"]}
|
package/dist/mcp/constants.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export declare const MCP_PATH = "/mcp";
|
|
3
3
|
export declare const DEFAULT_HOST = "127.0.0.1";
|
|
4
4
|
export declare const DEFAULT_PORT = 3100;
|
|
5
|
+
/** 요청 본문 상한 기본값 (SDK 기본과 같음, 4 MiB). server.maxBodyBytes 로 바꾼다 */
|
|
6
|
+
export declare const MAX_BODY_BYTES: number;
|
|
5
7
|
/**
|
|
6
8
|
* server/discover · tools/call 결과 _meta 의 현재 manifestHash 키 (스키마 drift 감지, §5).
|
|
7
9
|
* 고객 CLI 번들도 import (의존 없는 모듈)
|
package/dist/mcp/constants.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export const MCP_PATH = "/mcp";
|
|
3
3
|
export const DEFAULT_HOST = "127.0.0.1";
|
|
4
4
|
export const DEFAULT_PORT = 3100;
|
|
5
|
+
/** 요청 본문 상한 기본값 (SDK 기본과 같음, 4 MiB). server.maxBodyBytes 로 바꾼다 */
|
|
6
|
+
export const MAX_BODY_BYTES = 4 * 1024 * 1024;
|
|
5
7
|
/**
|
|
6
8
|
* server/discover · tools/call 결과 _meta 의 현재 manifestHash 키 (스키마 drift 감지, §5).
|
|
7
9
|
* 고객 CLI 번들도 import (의존 없는 모듈)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/mcp/constants.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAA;AAC9B,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAA;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/mcp/constants.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAA;AAC9B,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAA;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAA;AAChC,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;AAE7C;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAE7D,wGAAwG;AACxG,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAA;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAA;AAEpD,kGAAkG;AAClG,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAA","sourcesContent":["/** MCP 엔드포인트 경로 (POST 만) */\nexport const MCP_PATH = \"/mcp\"\nexport const DEFAULT_HOST = \"127.0.0.1\"\nexport const DEFAULT_PORT = 3100\n/** 요청 본문 상한 기본값 (SDK 기본과 같음, 4 MiB). server.maxBodyBytes 로 바꾼다 */\nexport const MAX_BODY_BYTES = 4 * 1024 * 1024\n\n/**\n * server/discover · tools/call 결과 _meta 의 현재 manifestHash 키 (스키마 drift 감지, §5).\n * 고객 CLI 번들도 import (의존 없는 모듈)\n */\nexport const MANIFEST_HASH_META_KEY = \"dev.mext/manifestHash\"\n\n/** server/discover 결과 _meta 의 도구 노출 방식 (execute · split · command). 원격 CLI 범용 형태가 호출 방식을 고른다 (§12.2) */\nexport const TOOLS_META_KEY = \"dev.mext/tools\"\n\n/**\n * tools/call 요청 params._meta 의 확인 표시 키 (§4 승인). 값 = { confirmed: true }.\n * client 방식 표면 (mext.config.ts approval.surfaces) + 서버가 정한 행위자 human 일 때만 인정한다\n */\nexport const APPROVAL_META_KEY = \"dev.mext/approval\"\n\n/** command 노출 도구의 tools/list _meta: 명령어 메타데이터 (aliases · 안전성 · scopes · positional · examples) */\nexport const COMMAND_META_KEY = \"dev.mext/command\"\n"]}
|
package/dist/mcp/dispatch.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ContentBlock } from "../content.ts";
|
|
1
2
|
import { type InvokeOptions } from "../invoke.ts";
|
|
2
3
|
import type { JsonSchema, Registry } from "../registry.ts";
|
|
3
4
|
import { type InputRequiredResult, type InputRound, type RequestStateSigner } from "./mrtr.ts";
|
|
@@ -43,7 +44,8 @@ export interface TextContent {
|
|
|
43
44
|
}
|
|
44
45
|
/** MCP CallToolResult 와 같은 형태 (SDK 타입 비의존) */
|
|
45
46
|
export interface ToolCallResult {
|
|
46
|
-
|
|
47
|
+
/** 값 text + 결과 콘텐츠 블록 (image · audio · resource_link, spec §4) */
|
|
48
|
+
content: (TextContent | ContentBlock)[];
|
|
47
49
|
/** 성공 = 핸들러 반환값 (undefined 는 null), 오류 = { error: MextError.toJSON() } */
|
|
48
50
|
structuredContent: unknown;
|
|
49
51
|
isError?: true;
|
|
@@ -72,8 +74,12 @@ export type DispatchResult = ToolCallResult | InputRequiredResult | CreateTaskRe
|
|
|
72
74
|
* options.input 이 있으면 ctx.ask 가 InputRequiredResult 를 돌려준다 (mrtr.ts).
|
|
73
75
|
*/
|
|
74
76
|
export declare function callDispatcher(registry: Registry, tool: DispatcherTool, rawArguments: unknown, options: DispatchOptions): Promise<DispatchResult>;
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
+
/**
|
|
78
|
+
* 핸들러 반환값 → 성공 결과 (undefined = null). task 완료 결과도 같은 변환.
|
|
79
|
+
* 결과 콘텐츠 (spec §4) = 값 text 뒤에 블록. 콘텐츠만 (값 undefined) = 블록만 · structuredContent 없음
|
|
80
|
+
* (null 을 실으면 SDK 가 text "null" 블록을 덧붙인다. 받는 쪽 CLI · 타입 client = null)
|
|
81
|
+
*/
|
|
82
|
+
export declare function valueResult(value: unknown, content?: readonly ContentBlock[]): ToolCallResult;
|
|
77
83
|
/** 오류 → isError 결과. MextError · CommandError = toJSON, 그 외 = EXECUTION_ERROR (message 만) */
|
|
78
84
|
export declare function errorResult(error: unknown): ToolCallResult;
|
|
79
85
|
/** dispatcher 도구 inputSchema. command 를 Mcp-Param-Command 헤더로 복사 (SEP-2243) */
|
package/dist/mcp/dispatch.js
CHANGED
|
@@ -106,16 +106,22 @@ export async function callDispatcher(registry, tool, rawArguments, options) {
|
|
|
106
106
|
return result;
|
|
107
107
|
if (result.detached !== undefined)
|
|
108
108
|
return result.detached;
|
|
109
|
-
return valueResult(result.value);
|
|
109
|
+
return valueResult(result.value, result.content);
|
|
110
110
|
}
|
|
111
111
|
catch (error) {
|
|
112
112
|
return errorResult(error);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
/**
|
|
116
|
-
|
|
115
|
+
/**
|
|
116
|
+
* 핸들러 반환값 → 성공 결과 (undefined = null). task 완료 결과도 같은 변환.
|
|
117
|
+
* 결과 콘텐츠 (spec §4) = 값 text 뒤에 블록. 콘텐츠만 (값 undefined) = 블록만 · structuredContent 없음
|
|
118
|
+
* (null 을 실으면 SDK 가 text "null" 블록을 덧붙인다. 받는 쪽 CLI · 타입 client = null)
|
|
119
|
+
*/
|
|
120
|
+
export function valueResult(value, content) {
|
|
121
|
+
if (content && value === undefined)
|
|
122
|
+
return { content: [...content], structuredContent: undefined };
|
|
117
123
|
const structured = value === undefined ? null : value;
|
|
118
|
-
return { content: [{ type: "text", text: stringify(structured) }], structuredContent: structured };
|
|
124
|
+
return { content: [{ type: "text", text: stringify(structured) }, ...(content ?? [])], structuredContent: structured };
|
|
119
125
|
}
|
|
120
126
|
/**
|
|
121
127
|
* MRTR 한 라운드: requestState 검증 → ask 세션으로 invoke. 답 없는 ask 가 있으면 (핸들러가 오류를 삼켜도)
|
package/dist/mcp/dispatch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/mcp/dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["import { surfaceOf } from \"../caller.ts\"\nimport { exposedRegistry } from \"../expose.ts\"\nimport { isDeclaredError, MextError } from \"../errors.ts\"\nimport { invoke, type InvokeOptions, type InvokeResult } from \"../invoke.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"../registry.ts\"\nimport { describeCommand } from \"../manifest.ts\"\nimport { COMMAND_META_KEY } from \"./constants.ts\"\nimport { formatHelp, help, HELP_COMMAND } from \"./help.ts\"\nimport {\n createAskSession,\n hasPending,\n inputRequiredResult,\n type InputRequiredResult,\n type InputRound,\n type RequestStateBinding,\n type RequestStateSigner,\n} from \"./mrtr.ts\"\nimport type { CreateTaskResult } from \"./tasks.ts\"\n\n/**\n * MCP 어댑터의 transport 무관 부분: dispatcher 도구 정의 · tools/call 실행 · help · 오류 → 결과 변환.\n * SDK · HTTP 에 의존하지 않는다 (HTTP · stdio 가 공유).\n */\n\n/**\n * execute = 도구 1개 (기본), split = query (readOnly · help) + mutate (그 외),\n * command = 명령어 1개 = 도구 1개 (도구 이름 = 명령어 ID, outputSchema, help 없음, §12.2)\n */\nexport type ToolExposure = \"execute\" | \"split\" | \"command\"\n\nexport type DispatcherToolName = \"execute\" | \"query\" | \"mutate\"\n\n/** MCP ToolAnnotations 중 mext 가 쓰는 항목 */\nexport interface DispatcherAnnotations {\n title?: string\n readOnlyHint: boolean\n destructiveHint?: boolean\n idempotentHint?: boolean\n openWorldHint?: boolean\n}\n\n/** tools/list 도구 하나. dispatcher (execute · query · mutate) 또는 명령어별 도구 (command 노출) */\nexport interface DispatcherTool {\n /** dispatcher = DispatcherToolName, command 노출 = 명령어 ID */\n name: string\n description: string\n /** JSON Schema 2020-12. dispatcher = command 에 x-mcp-header: \"Command\", command 노출 = 명령어 input */\n inputSchema: JsonSchema\n annotations: DispatcherAnnotations\n /** readOnly 명령어만 실행 (split 의 query). 그 외 = PERMISSION_DENIED */\n readOnly: boolean\n /** command 노출: 이 도구가 실행하는 명령어 ID (인자 = 명령어 input 그대로). 없음 = dispatcher ({ command, args }) */\n command?: string\n /** command 노출: output 의 JSON Schema 2020-12 (output 이 있을 때) */\n outputSchema?: JsonSchema\n /** command 노출: tools/list 도구 _meta (COMMAND_META_KEY = CLI 원격의 help · 플래그 파싱용 메타데이터) */\n _meta?: Record<string, unknown>\n}\n\nexport interface TextContent {\n type: \"text\"\n text: string\n}\n\n/** MCP CallToolResult 와 같은 형태 (SDK 타입 비의존) */\nexport interface ToolCallResult {\n content: TextContent[]\n /** 성공 = 핸들러 반환값 (undefined 는 null), 오류 = { error: MextError.toJSON() } */\n structuredContent: unknown\n isError?: true\n}\n\n/** 핸들러 예외 (MextError 외) 의 결과 code. CLI --json 과 같음 */\nexport const EXECUTION_ERROR = \"EXECUTION_ERROR\"\n\n/** 도구 설명에 나열할 명령어 수 상한. 넘으면 help 안내만 */\nconst DESCRIPTION_COMMAND_LIMIT = 50\n\n/** 노출 방식별 도구 (정렬 순서 고정: execute · query, mutate · 명령어 ID 순) */\nexport function dispatcherTools(registry: Registry, exposure: ToolExposure = \"execute\"): DispatcherTool[] {\n const all = [...registry.commands.values()]\n if (exposure === \"command\") return all.map(commandTool)\n if (exposure === \"split\") {\n const reads = all.filter((e) => e.command.readOnly)\n const writes = all.filter((e) => !e.command.readOnly)\n return [\n {\n name: \"query\",\n description: describeTool(\n \"query\",\n \"Run a read-only command.\",\n reads,\n 'Commands that are not read-only are rejected here; call them with the \"mutate\" tool.',\n ),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Query\", readOnlyHint: true, destructiveHint: false, idempotentHint: true },\n readOnly: true,\n },\n {\n name: \"mutate\",\n description: describeTool(\"mutate\", \"Run a command that changes state.\", writes),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Mutate\", readOnlyHint: false, destructiveHint: true },\n readOnly: false,\n },\n ]\n }\n const readOnly = all.every((e) => e.command.readOnly)\n return [\n {\n name: \"execute\",\n description: describeTool(\"execute\", \"Run a command.\", all),\n inputSchema: dispatcherInputSchema(),\n // 단일 dispatcher 는 최악값 (researches/others.md 9)\n annotations: readOnly\n ? { title: \"Execute\", readOnlyHint: true, destructiveHint: false }\n : { title: \"Execute\", readOnlyHint: false, destructiveHint: all.some((e) => e.command.destructive) },\n readOnly: false,\n },\n ]\n}\n\n/**\n * command 노출의 명령어별 도구 (§12.2). 이름 = 정식 ID (별칭은 도구 아님), annotations = execute 와 같은 계산을 명령어 하나에.\n * _meta[COMMAND_META_KEY] = tools/list 만으로 CLI 원격의 help · 별칭 · positional 을 만들 메타데이터\n */\nfunction commandTool(entry: RegisteredCommand): DispatcherTool {\n const { id, description: _d, inputSchema: _i, outputSchema: _o, file: _f, ...meta } = describeCommand(entry)\n const c = entry.command\n const tool: DispatcherTool = {\n name: id,\n description: c.description,\n inputSchema: entry.inputSchema,\n annotations: c.readOnly\n ? { title: id, readOnlyHint: true, destructiveHint: false }\n : { title: id, readOnlyHint: false, destructiveHint: c.destructive },\n readOnly: false,\n command: id,\n _meta: { [COMMAND_META_KEY]: meta },\n }\n if (entry.outputSchema !== undefined) tool.outputSchema = entry.outputSchema\n return tool\n}\n\nexport function findDispatcherTool(tools: readonly DispatcherTool[], name: string): DispatcherTool | undefined {\n return tools.find((t) => t.name === name)\n}\n\nexport interface DispatchOptions extends Omit<InvokeOptions, \"readOnly\"> {\n /** help 의 tool 표시용. dispatcherTools 결과 */\n tools?: readonly DispatcherTool[]\n /**\n * MRTR (MCP 2026-07-28). 지정하면 ctx.ask = InputRequiredResult 반환 · 재시도의 inputResponses 로 resolve\n * (ask 옵션 무시). requiresConfirmation 확인도 이 경로\n */\n input?: InputRound & { signer: RequestStateSigner }\n}\n\n/** tools/call 결과: 완료 (CallToolResult 형태) · 입력 요청 (InputRequiredResult) · task 생성 (options.detach, §12.6) */\nexport type DispatchResult = ToolCallResult | InputRequiredResult | CreateTaskResult\n\n/**\n * dispatcher 도구 호출: { command, args } → help 또는 invoke. registry = 전체 (expose 판정은 여기와 invoke 가 주체의 표면으로 한다).\n * MextError · 핸들러 예외는 isError 결과로 (throw 하지 않음). 인증 (UNAUTHENTICATED → 401) 은 transport 몫.\n * options.input 이 있으면 ctx.ask 가 InputRequiredResult 를 돌려준다 (mrtr.ts).\n */\nexport async function callDispatcher(\n registry: Registry,\n tool: DispatcherTool,\n rawArguments: unknown,\n options: DispatchOptions,\n): Promise<DispatchResult> {\n try {\n // command 노출: 인자 = 명령어 input 그대로 (검증 = invoke 의 Zod safeParse)\n const { command, args } =\n tool.command !== undefined ? { command: tool.command, args: rawArguments } : parseDispatcherArguments(tool, rawArguments)\n if (command === HELP_COMMAND) {\n const target = (args as { target?: unknown } | undefined)?.target\n if (target !== undefined && typeof target !== \"string\") {\n throw dispatcherArgumentError(tool, \"help\", \"args.target must be a string\", [], {\n path: \"args.target\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const toolFor = splitToolFor(options.tools)\n // help = 주체의 표면에서 보이는 명령어만 (§4 expose). 실행은 invoke 가 같은 판정을 한다\n const view = exposedRegistry(registry, surfaceOf(options.principal, options.transport ?? \"local\"))\n const value = help(view, target, toolFor ? { toolFor } : {})\n return { content: [{ type: \"text\", text: formatHelp(value, tool.name) }], structuredContent: value }\n }\n const { input, tools: _tools, ...invokeOptions } = options\n const result = input\n ? await invokeRound(registry, tool, command, args, invokeOptions, input)\n : await invoke(registry, command, args, { ...invokeOptions, readOnly: tool.readOnly })\n if (\"resultType\" in result) return result\n if (result.detached !== undefined) return result.detached as CreateTaskResult\n return valueResult(result.value)\n } catch (error) {\n return errorResult(error)\n }\n}\n\n/** 핸들러 반환값 → 성공 결과 (undefined = null). task 완료 결과도 같은 변환 */\nexport function valueResult(value: unknown): ToolCallResult {\n const structured = value === undefined ? null : value\n return { content: [{ type: \"text\", text: stringify(structured) }], structuredContent: structured }\n}\n\n/**\n * MRTR 한 라운드: requestState 검증 → ask 세션으로 invoke. 답 없는 ask 가 있으면 (핸들러가 오류를 삼켜도)\n * 결과를 버리고 InputRequiredResult. elicitation 미선언 클라이언트 = ask 미주입 (INPUT_UNAVAILABLE).\n * 선언한 mode 만 요청 (form · url). 미선언 mode 의 ask = INPUT_UNAVAILABLE\n */\nasync function invokeRound(\n registry: Registry,\n tool: DispatcherTool,\n command: string,\n args: unknown,\n options: Omit<InvokeOptions, \"readOnly\">,\n input: NonNullable<DispatchOptions[\"input\"]>,\n): Promise<InvokeResult | InputRequiredResult> {\n const { ask: _ask, ...rest } = options\n const modes = { form: input.elicitation, url: input.urlElicitation === true }\n if (!modes.form && !modes.url) return invoke(registry, command, args, { ...rest, readOnly: tool.readOnly })\n const binding: RequestStateBinding = {\n principal: `${options.principal.kind}:${options.principal.id}`,\n tool: tool.name,\n command,\n args: args ?? {},\n }\n let answers: Record<string, unknown> = { ...input.inputResponses }\n if (input.requestState !== undefined) {\n const prior = input.signer.verify(input.requestState, binding)\n if (!prior) throw invalidRequestState(tool, command)\n answers = { ...answers, ...prior }\n }\n const session = createAskSession(answers, modes)\n const signal = options.signal ? AbortSignal.any([options.signal, session.signal]) : session.signal\n try {\n const result = await invoke(registry, command, args, {\n ...rest,\n signal,\n ask: session.ask,\n readOnly: tool.readOnly,\n // 입력 대기로 끝난 라운드 = 감사 이벤트 없음 (§11.1)\n pendingInput: () => hasPending(session),\n })\n return hasPending(session) ? inputRequiredResult(session, input.signer, binding) : result\n } catch (error) {\n if (hasPending(session)) return inputRequiredResult(session, input.signer, binding)\n throw error\n }\n}\n\n/** 서명 · 만료 · 바인딩 검증 실패한 requestState. 처음부터 다시 호출하도록 안내 */\nfunction invalidRequestState(tool: DispatcherTool, command: string): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\n \"INVALID_ARGUMENT\",\n `Invalid arguments for ${command}: requestState is invalid or expired. Call ${tool.name} again without requestState and inputResponses.`,\n {\n command,\n missing_fields: [],\n issues: [\n {\n path: \"requestState\",\n code: \"invalid_request_state\",\n message: \"requestState failed verification (tampered, expired, or for a different call or server key)\",\n },\n ],\n expected_schema: tool.inputSchema,\n examples: [],\n },\n )\n}\n\n/** 오류 → isError 결과. MextError · CommandError = toJSON, 그 외 = EXECUTION_ERROR (message 만) */\nexport function errorResult(error: unknown): ToolCallResult {\n const body: Record<string, unknown> & { code: string; message: string } = isDeclaredError(error)\n ? error.toJSON()\n : { code: EXECUTION_ERROR, message: error instanceof Error ? error.message : String(error) }\n return {\n content: [{ type: \"text\", text: `${body.code}: ${body.message}\\n${stringify(body)}` }],\n structuredContent: { error: body },\n isError: true,\n }\n}\n\n/** dispatcher 도구 inputSchema. command 를 Mcp-Param-Command 헤더로 복사 (SEP-2243) */\nexport function dispatcherInputSchema(): JsonSchema {\n return {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: 'Command ID (e.g. \"users.get\"), or \"help\" to list namespaces and commands.',\n \"x-mcp-header\": \"Command\",\n },\n args: {\n type: \"object\",\n description: 'Command input. For \"help\": { \"target\": \"<namespace or command ID>\" }.',\n additionalProperties: true,\n },\n },\n required: [\"command\"],\n additionalProperties: false,\n }\n}\n\nfunction parseDispatcherArguments(tool: DispatcherTool, raw: unknown): { command: string; args: unknown } {\n const input = raw === undefined ? {} : raw\n if (input === null || typeof input !== \"object\" || Array.isArray(input)) {\n throw dispatcherArgumentError(tool, tool.name, \"arguments must be an object\", [], {\n path: \"\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n const { command, args, ...rest } = input as Record<string, unknown>\n if (command === undefined) {\n throw dispatcherArgumentError(tool, tool.name, \"missing required: command\", [\"command\"], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string, received undefined\",\n })\n }\n if (typeof command !== \"string\") {\n throw dispatcherArgumentError(tool, tool.name, \"command must be a string\", [], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const unknownKeys = Object.keys(rest)\n if (unknownKeys.length > 0) {\n throw dispatcherArgumentError(tool, tool.name, `unrecognized keys: ${unknownKeys.join(\", \")}`, [], {\n path: \"\",\n code: \"unrecognized_keys\",\n message: `Unrecognized keys: ${unknownKeys.join(\", \")}. Put command input under \"args\".`,\n })\n }\n if (args !== undefined && (args === null || typeof args !== \"object\" || Array.isArray(args))) {\n throw dispatcherArgumentError(tool, command, \"args must be an object\", [], {\n path: \"args\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n return { command, args }\n}\n\nfunction dispatcherArgumentError(\n tool: DispatcherTool,\n command: string,\n summary: string,\n missing: string[],\n issue: { path: string; code: string; message: string },\n): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\"INVALID_ARGUMENT\", `Invalid arguments for ${command}: ${summary}`, {\n command,\n missing_fields: missing,\n issues: [issue],\n expected_schema: tool.inputSchema,\n examples: [{ command: HELP_COMMAND }],\n })\n}\n\nfunction splitToolFor(tools: readonly DispatcherTool[] | undefined): ((e: RegisteredCommand) => string) | undefined {\n if (!tools || tools.length < 2) return undefined\n const query = tools.find((t) => t.readOnly)?.name\n const mutate = tools.find((t) => !t.readOnly)?.name\n if (query === undefined || mutate === undefined) return undefined\n return (e) => (e.command.readOnly ? query : mutate)\n}\n\nfunction describeTool(name: string, lead: string, commands: readonly RegisteredCommand[], note?: string): string {\n const lines = [\n lead,\n `Arguments: { \"command\": \"<command ID>\", \"args\": { ...input } }. ` +\n `Call ${name}({ \"command\": \"help\" }) to list namespaces and commands, ` +\n `${name}({ \"command\": \"help\", \"args\": { \"target\": \"<namespace or command ID>\" } }) for input schemas and examples.`,\n ]\n if (note) lines.push(note)\n if (commands.length > 0 && commands.length <= DESCRIPTION_COMMAND_LIMIT) {\n lines.push(\"\", \"Commands:\")\n for (const e of commands) lines.push(`- ${e.id}: ${firstLine(e.command.description)}`)\n }\n return lines.join(\"\\n\")\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\", 1)[0]!.trim()\n}\n\nfunction stringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2) ?? \"null\"\n } catch {\n return String(value)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/mcp/dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["import { surfaceOf } from \"../caller.ts\"\nimport type { ContentBlock } from \"../content.ts\"\nimport { exposedRegistry } from \"../expose.ts\"\nimport { isDeclaredError, MextError } from \"../errors.ts\"\nimport { invoke, type InvokeOptions, type InvokeResult } from \"../invoke.ts\"\nimport type { JsonSchema, RegisteredCommand, Registry } from \"../registry.ts\"\nimport { describeCommand } from \"../manifest.ts\"\nimport { COMMAND_META_KEY } from \"./constants.ts\"\nimport { formatHelp, help, HELP_COMMAND } from \"./help.ts\"\nimport {\n createAskSession,\n hasPending,\n inputRequiredResult,\n type InputRequiredResult,\n type InputRound,\n type RequestStateBinding,\n type RequestStateSigner,\n} from \"./mrtr.ts\"\nimport type { CreateTaskResult } from \"./tasks.ts\"\n\n/**\n * MCP 어댑터의 transport 무관 부분: dispatcher 도구 정의 · tools/call 실행 · help · 오류 → 결과 변환.\n * SDK · HTTP 에 의존하지 않는다 (HTTP · stdio 가 공유).\n */\n\n/**\n * execute = 도구 1개 (기본), split = query (readOnly · help) + mutate (그 외),\n * command = 명령어 1개 = 도구 1개 (도구 이름 = 명령어 ID, outputSchema, help 없음, §12.2)\n */\nexport type ToolExposure = \"execute\" | \"split\" | \"command\"\n\nexport type DispatcherToolName = \"execute\" | \"query\" | \"mutate\"\n\n/** MCP ToolAnnotations 중 mext 가 쓰는 항목 */\nexport interface DispatcherAnnotations {\n title?: string\n readOnlyHint: boolean\n destructiveHint?: boolean\n idempotentHint?: boolean\n openWorldHint?: boolean\n}\n\n/** tools/list 도구 하나. dispatcher (execute · query · mutate) 또는 명령어별 도구 (command 노출) */\nexport interface DispatcherTool {\n /** dispatcher = DispatcherToolName, command 노출 = 명령어 ID */\n name: string\n description: string\n /** JSON Schema 2020-12. dispatcher = command 에 x-mcp-header: \"Command\", command 노출 = 명령어 input */\n inputSchema: JsonSchema\n annotations: DispatcherAnnotations\n /** readOnly 명령어만 실행 (split 의 query). 그 외 = PERMISSION_DENIED */\n readOnly: boolean\n /** command 노출: 이 도구가 실행하는 명령어 ID (인자 = 명령어 input 그대로). 없음 = dispatcher ({ command, args }) */\n command?: string\n /** command 노출: output 의 JSON Schema 2020-12 (output 이 있을 때) */\n outputSchema?: JsonSchema\n /** command 노출: tools/list 도구 _meta (COMMAND_META_KEY = CLI 원격의 help · 플래그 파싱용 메타데이터) */\n _meta?: Record<string, unknown>\n}\n\nexport interface TextContent {\n type: \"text\"\n text: string\n}\n\n/** MCP CallToolResult 와 같은 형태 (SDK 타입 비의존) */\nexport interface ToolCallResult {\n /** 값 text + 결과 콘텐츠 블록 (image · audio · resource_link, spec §4) */\n content: (TextContent | ContentBlock)[]\n /** 성공 = 핸들러 반환값 (undefined 는 null), 오류 = { error: MextError.toJSON() } */\n structuredContent: unknown\n isError?: true\n}\n\n/** 핸들러 예외 (MextError 외) 의 결과 code. CLI --json 과 같음 */\nexport const EXECUTION_ERROR = \"EXECUTION_ERROR\"\n\n/** 도구 설명에 나열할 명령어 수 상한. 넘으면 help 안내만 */\nconst DESCRIPTION_COMMAND_LIMIT = 50\n\n/** 노출 방식별 도구 (정렬 순서 고정: execute · query, mutate · 명령어 ID 순) */\nexport function dispatcherTools(registry: Registry, exposure: ToolExposure = \"execute\"): DispatcherTool[] {\n const all = [...registry.commands.values()]\n if (exposure === \"command\") return all.map(commandTool)\n if (exposure === \"split\") {\n const reads = all.filter((e) => e.command.readOnly)\n const writes = all.filter((e) => !e.command.readOnly)\n return [\n {\n name: \"query\",\n description: describeTool(\n \"query\",\n \"Run a read-only command.\",\n reads,\n 'Commands that are not read-only are rejected here; call them with the \"mutate\" tool.',\n ),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Query\", readOnlyHint: true, destructiveHint: false, idempotentHint: true },\n readOnly: true,\n },\n {\n name: \"mutate\",\n description: describeTool(\"mutate\", \"Run a command that changes state.\", writes),\n inputSchema: dispatcherInputSchema(),\n annotations: { title: \"Mutate\", readOnlyHint: false, destructiveHint: true },\n readOnly: false,\n },\n ]\n }\n const readOnly = all.every((e) => e.command.readOnly)\n return [\n {\n name: \"execute\",\n description: describeTool(\"execute\", \"Run a command.\", all),\n inputSchema: dispatcherInputSchema(),\n // 단일 dispatcher 는 최악값 (researches/others.md 9)\n annotations: readOnly\n ? { title: \"Execute\", readOnlyHint: true, destructiveHint: false }\n : { title: \"Execute\", readOnlyHint: false, destructiveHint: all.some((e) => e.command.destructive) },\n readOnly: false,\n },\n ]\n}\n\n/**\n * command 노출의 명령어별 도구 (§12.2). 이름 = 정식 ID (별칭은 도구 아님), annotations = execute 와 같은 계산을 명령어 하나에.\n * _meta[COMMAND_META_KEY] = tools/list 만으로 CLI 원격의 help · 별칭 · positional 을 만들 메타데이터\n */\nfunction commandTool(entry: RegisteredCommand): DispatcherTool {\n const { id, description: _d, inputSchema: _i, outputSchema: _o, file: _f, ...meta } = describeCommand(entry)\n const c = entry.command\n const tool: DispatcherTool = {\n name: id,\n description: c.description,\n inputSchema: entry.inputSchema,\n annotations: c.readOnly\n ? { title: id, readOnlyHint: true, destructiveHint: false }\n : { title: id, readOnlyHint: false, destructiveHint: c.destructive },\n readOnly: false,\n command: id,\n _meta: { [COMMAND_META_KEY]: meta },\n }\n if (entry.outputSchema !== undefined) tool.outputSchema = entry.outputSchema\n return tool\n}\n\nexport function findDispatcherTool(tools: readonly DispatcherTool[], name: string): DispatcherTool | undefined {\n return tools.find((t) => t.name === name)\n}\n\nexport interface DispatchOptions extends Omit<InvokeOptions, \"readOnly\"> {\n /** help 의 tool 표시용. dispatcherTools 결과 */\n tools?: readonly DispatcherTool[]\n /**\n * MRTR (MCP 2026-07-28). 지정하면 ctx.ask = InputRequiredResult 반환 · 재시도의 inputResponses 로 resolve\n * (ask 옵션 무시). requiresConfirmation 확인도 이 경로\n */\n input?: InputRound & { signer: RequestStateSigner }\n}\n\n/** tools/call 결과: 완료 (CallToolResult 형태) · 입력 요청 (InputRequiredResult) · task 생성 (options.detach, §12.6) */\nexport type DispatchResult = ToolCallResult | InputRequiredResult | CreateTaskResult\n\n/**\n * dispatcher 도구 호출: { command, args } → help 또는 invoke. registry = 전체 (expose 판정은 여기와 invoke 가 주체의 표면으로 한다).\n * MextError · 핸들러 예외는 isError 결과로 (throw 하지 않음). 인증 (UNAUTHENTICATED → 401) 은 transport 몫.\n * options.input 이 있으면 ctx.ask 가 InputRequiredResult 를 돌려준다 (mrtr.ts).\n */\nexport async function callDispatcher(\n registry: Registry,\n tool: DispatcherTool,\n rawArguments: unknown,\n options: DispatchOptions,\n): Promise<DispatchResult> {\n try {\n // command 노출: 인자 = 명령어 input 그대로 (검증 = invoke 의 Zod safeParse)\n const { command, args } =\n tool.command !== undefined ? { command: tool.command, args: rawArguments } : parseDispatcherArguments(tool, rawArguments)\n if (command === HELP_COMMAND) {\n const target = (args as { target?: unknown } | undefined)?.target\n if (target !== undefined && typeof target !== \"string\") {\n throw dispatcherArgumentError(tool, \"help\", \"args.target must be a string\", [], {\n path: \"args.target\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const toolFor = splitToolFor(options.tools)\n // help = 주체의 표면에서 보이는 명령어만 (§4 expose). 실행은 invoke 가 같은 판정을 한다\n const view = exposedRegistry(registry, surfaceOf(options.principal, options.transport ?? \"local\"))\n const value = help(view, target, toolFor ? { toolFor } : {})\n return { content: [{ type: \"text\", text: formatHelp(value, tool.name) }], structuredContent: value }\n }\n const { input, tools: _tools, ...invokeOptions } = options\n const result = input\n ? await invokeRound(registry, tool, command, args, invokeOptions, input)\n : await invoke(registry, command, args, { ...invokeOptions, readOnly: tool.readOnly })\n if (\"resultType\" in result) return result\n if (result.detached !== undefined) return result.detached as CreateTaskResult\n return valueResult(result.value, result.content)\n } catch (error) {\n return errorResult(error)\n }\n}\n\n/**\n * 핸들러 반환값 → 성공 결과 (undefined = null). task 완료 결과도 같은 변환.\n * 결과 콘텐츠 (spec §4) = 값 text 뒤에 블록. 콘텐츠만 (값 undefined) = 블록만 · structuredContent 없음\n * (null 을 실으면 SDK 가 text \"null\" 블록을 덧붙인다. 받는 쪽 CLI · 타입 client = null)\n */\nexport function valueResult(value: unknown, content?: readonly ContentBlock[]): ToolCallResult {\n if (content && value === undefined) return { content: [...content], structuredContent: undefined }\n const structured = value === undefined ? null : value\n return { content: [{ type: \"text\", text: stringify(structured) }, ...(content ?? [])], structuredContent: structured }\n}\n\n/**\n * MRTR 한 라운드: requestState 검증 → ask 세션으로 invoke. 답 없는 ask 가 있으면 (핸들러가 오류를 삼켜도)\n * 결과를 버리고 InputRequiredResult. elicitation 미선언 클라이언트 = ask 미주입 (INPUT_UNAVAILABLE).\n * 선언한 mode 만 요청 (form · url). 미선언 mode 의 ask = INPUT_UNAVAILABLE\n */\nasync function invokeRound(\n registry: Registry,\n tool: DispatcherTool,\n command: string,\n args: unknown,\n options: Omit<InvokeOptions, \"readOnly\">,\n input: NonNullable<DispatchOptions[\"input\"]>,\n): Promise<InvokeResult | InputRequiredResult> {\n const { ask: _ask, ...rest } = options\n const modes = { form: input.elicitation, url: input.urlElicitation === true }\n if (!modes.form && !modes.url) return invoke(registry, command, args, { ...rest, readOnly: tool.readOnly })\n const binding: RequestStateBinding = {\n principal: `${options.principal.kind}:${options.principal.id}`,\n tool: tool.name,\n command,\n args: args ?? {},\n }\n let answers: Record<string, unknown> = { ...input.inputResponses }\n if (input.requestState !== undefined) {\n const prior = input.signer.verify(input.requestState, binding)\n if (!prior) throw invalidRequestState(tool, command)\n answers = { ...answers, ...prior }\n }\n const session = createAskSession(answers, modes)\n const signal = options.signal ? AbortSignal.any([options.signal, session.signal]) : session.signal\n try {\n const result = await invoke(registry, command, args, {\n ...rest,\n signal,\n ask: session.ask,\n readOnly: tool.readOnly,\n // 입력 대기로 끝난 라운드 = 감사 이벤트 없음 (§11.1)\n pendingInput: () => hasPending(session),\n })\n return hasPending(session) ? inputRequiredResult(session, input.signer, binding) : result\n } catch (error) {\n if (hasPending(session)) return inputRequiredResult(session, input.signer, binding)\n throw error\n }\n}\n\n/** 서명 · 만료 · 바인딩 검증 실패한 requestState. 처음부터 다시 호출하도록 안내 */\nfunction invalidRequestState(tool: DispatcherTool, command: string): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\n \"INVALID_ARGUMENT\",\n `Invalid arguments for ${command}: requestState is invalid or expired. Call ${tool.name} again without requestState and inputResponses.`,\n {\n command,\n missing_fields: [],\n issues: [\n {\n path: \"requestState\",\n code: \"invalid_request_state\",\n message: \"requestState failed verification (tampered, expired, or for a different call or server key)\",\n },\n ],\n expected_schema: tool.inputSchema,\n examples: [],\n },\n )\n}\n\n/** 오류 → isError 결과. MextError · CommandError = toJSON, 그 외 = EXECUTION_ERROR (message 만) */\nexport function errorResult(error: unknown): ToolCallResult {\n const body: Record<string, unknown> & { code: string; message: string } = isDeclaredError(error)\n ? error.toJSON()\n : { code: EXECUTION_ERROR, message: error instanceof Error ? error.message : String(error) }\n return {\n content: [{ type: \"text\", text: `${body.code}: ${body.message}\\n${stringify(body)}` }],\n structuredContent: { error: body },\n isError: true,\n }\n}\n\n/** dispatcher 도구 inputSchema. command 를 Mcp-Param-Command 헤더로 복사 (SEP-2243) */\nexport function dispatcherInputSchema(): JsonSchema {\n return {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: 'Command ID (e.g. \"users.get\"), or \"help\" to list namespaces and commands.',\n \"x-mcp-header\": \"Command\",\n },\n args: {\n type: \"object\",\n description: 'Command input. For \"help\": { \"target\": \"<namespace or command ID>\" }.',\n additionalProperties: true,\n },\n },\n required: [\"command\"],\n additionalProperties: false,\n }\n}\n\nfunction parseDispatcherArguments(tool: DispatcherTool, raw: unknown): { command: string; args: unknown } {\n const input = raw === undefined ? {} : raw\n if (input === null || typeof input !== \"object\" || Array.isArray(input)) {\n throw dispatcherArgumentError(tool, tool.name, \"arguments must be an object\", [], {\n path: \"\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n const { command, args, ...rest } = input as Record<string, unknown>\n if (command === undefined) {\n throw dispatcherArgumentError(tool, tool.name, \"missing required: command\", [\"command\"], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string, received undefined\",\n })\n }\n if (typeof command !== \"string\") {\n throw dispatcherArgumentError(tool, tool.name, \"command must be a string\", [], {\n path: \"command\",\n code: \"invalid_type\",\n message: \"expected string\",\n })\n }\n const unknownKeys = Object.keys(rest)\n if (unknownKeys.length > 0) {\n throw dispatcherArgumentError(tool, tool.name, `unrecognized keys: ${unknownKeys.join(\", \")}`, [], {\n path: \"\",\n code: \"unrecognized_keys\",\n message: `Unrecognized keys: ${unknownKeys.join(\", \")}. Put command input under \"args\".`,\n })\n }\n if (args !== undefined && (args === null || typeof args !== \"object\" || Array.isArray(args))) {\n throw dispatcherArgumentError(tool, command, \"args must be an object\", [], {\n path: \"args\",\n code: \"invalid_type\",\n message: \"expected object\",\n })\n }\n return { command, args }\n}\n\nfunction dispatcherArgumentError(\n tool: DispatcherTool,\n command: string,\n summary: string,\n missing: string[],\n issue: { path: string; code: string; message: string },\n): MextError<\"INVALID_ARGUMENT\"> {\n return new MextError(\"INVALID_ARGUMENT\", `Invalid arguments for ${command}: ${summary}`, {\n command,\n missing_fields: missing,\n issues: [issue],\n expected_schema: tool.inputSchema,\n examples: [{ command: HELP_COMMAND }],\n })\n}\n\nfunction splitToolFor(tools: readonly DispatcherTool[] | undefined): ((e: RegisteredCommand) => string) | undefined {\n if (!tools || tools.length < 2) return undefined\n const query = tools.find((t) => t.readOnly)?.name\n const mutate = tools.find((t) => !t.readOnly)?.name\n if (query === undefined || mutate === undefined) return undefined\n return (e) => (e.command.readOnly ? query : mutate)\n}\n\nfunction describeTool(name: string, lead: string, commands: readonly RegisteredCommand[], note?: string): string {\n const lines = [\n lead,\n `Arguments: { \"command\": \"<command ID>\", \"args\": { ...input } }. ` +\n `Call ${name}({ \"command\": \"help\" }) to list namespaces and commands, ` +\n `${name}({ \"command\": \"help\", \"args\": { \"target\": \"<namespace or command ID>\" } }) for input schemas and examples.`,\n ]\n if (note) lines.push(note)\n if (commands.length > 0 && commands.length <= DESCRIPTION_COMMAND_LIMIT) {\n lines.push(\"\", \"Commands:\")\n for (const e of commands) lines.push(`- ${e.id}: ${firstLine(e.command.description)}`)\n }\n return lines.join(\"\\n\")\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\", 1)[0]!.trim()\n}\n\nfunction stringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2) ?? \"null\"\n } catch {\n return String(value)\n }\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loopback 판정 · Host 허용 목록 (§6 보안). mcp/http.ts (Origin · Host 검사) · config.ts (allowedHosts 형식 검사) 가 공유.
|
|
3
|
+
* Node 내장 모듈 · SDK import 없음
|
|
4
|
+
*/
|
|
5
|
+
export declare const LOOPBACK_HOSTNAMES: ReadonlySet<string>;
|
|
6
|
+
/** allowedOrigins · allowedHosts 의 loopback 항목 */
|
|
7
|
+
export declare const LOOPBACK_ENTRY = "loopback";
|
|
8
|
+
/** allowedHosts 항목 형식 문제. 없으면 undefined (config 검사) */
|
|
9
|
+
export declare function allowedHostProblem(entry: unknown): string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Host 허용 여부 (server.allowedHosts). "*" = 전체, "loopback" = loopback 호스트 (포트 무관),
|
|
12
|
+
* 포트 없는 항목 = 그 호스트의 모든 포트, 포트 있는 항목 = 그 포트만. 대소문자 · 끝 "." 무시. 형식 오류 = false
|
|
13
|
+
*/
|
|
14
|
+
export declare function hostAllowed(host: string, allowed: readonly string[]): boolean;
|
package/dist/mcp/host.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loopback 판정 · Host 허용 목록 (§6 보안). mcp/http.ts (Origin · Host 검사) · config.ts (allowedHosts 형식 검사) 가 공유.
|
|
3
|
+
* Node 내장 모듈 · SDK import 없음
|
|
4
|
+
*/
|
|
5
|
+
export const LOOPBACK_HOSTNAMES = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
6
|
+
/** allowedOrigins · allowedHosts 의 loopback 항목 */
|
|
7
|
+
export const LOOPBACK_ENTRY = "loopback";
|
|
8
|
+
/** Host 값 → 소문자 hostname (끝 "." 제거) · port (없으면 ""). 형식 오류 = undefined */
|
|
9
|
+
function parseHost(value) {
|
|
10
|
+
if (value === "" || /[\s/?#@\\]/.test(value))
|
|
11
|
+
return undefined;
|
|
12
|
+
let url;
|
|
13
|
+
try {
|
|
14
|
+
url = new URL(`http://${value}`);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
// URL 이 기본 포트 (80) 를 지우므로 원문의 포트를 쓴다
|
|
20
|
+
const port = /:(\d+)$/.exec(value)?.[1] ?? "";
|
|
21
|
+
return { hostname: url.hostname.replace(/\.$/, ""), port };
|
|
22
|
+
}
|
|
23
|
+
/** allowedHosts 항목 형식 문제. 없으면 undefined (config 검사) */
|
|
24
|
+
export function allowedHostProblem(entry) {
|
|
25
|
+
if (entry === "*" || entry === LOOPBACK_ENTRY)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (typeof entry !== "string" || parseHost(entry) === undefined)
|
|
28
|
+
return `invalid host ${JSON.stringify(entry)}`;
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Host 허용 여부 (server.allowedHosts). "*" = 전체, "loopback" = loopback 호스트 (포트 무관),
|
|
33
|
+
* 포트 없는 항목 = 그 호스트의 모든 포트, 포트 있는 항목 = 그 포트만. 대소문자 · 끝 "." 무시. 형식 오류 = false
|
|
34
|
+
*/
|
|
35
|
+
export function hostAllowed(host, allowed) {
|
|
36
|
+
if (allowed.includes("*"))
|
|
37
|
+
return true;
|
|
38
|
+
const actual = parseHost(host);
|
|
39
|
+
if (actual === undefined)
|
|
40
|
+
return false;
|
|
41
|
+
if (LOOPBACK_HOSTNAMES.has(actual.hostname) && allowed.includes(LOOPBACK_ENTRY))
|
|
42
|
+
return true;
|
|
43
|
+
return allowed.some((entry) => {
|
|
44
|
+
const expected = entry === LOOPBACK_ENTRY ? undefined : parseHost(entry);
|
|
45
|
+
return expected !== undefined && expected.hostname === actual.hostname && (expected.port === "" || expected.port === actual.port);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/mcp/host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;AAEnG,kDAAkD;AAClD,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAA;AAExC,0EAA0E;AAC1E,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,KAAK,KAAK,EAAE,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IAC9D,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,KAAK,EAAE,CAAC,CAAA;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,qCAAqC;IACrC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7C,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAA;AAC5D,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,cAAc;QAAE,OAAO,SAAS,CAAA;IAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,SAAS;QAAE,OAAO,gBAAgB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAA;IAC/G,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,OAA0B;IAClE,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC9B,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IACtC,IAAI,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,IAAI,CAAA;IAC5F,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QAC5B,MAAM,QAAQ,GAAG,KAAK,KAAK,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;QACxE,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAA;IACnI,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["/**\n * loopback 판정 · Host 허용 목록 (§6 보안). mcp/http.ts (Origin · Host 검사) · config.ts (allowedHosts 형식 검사) 가 공유.\n * Node 내장 모듈 · SDK import 없음\n */\n\nexport const LOOPBACK_HOSTNAMES: ReadonlySet<string> = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\"])\n\n/** allowedOrigins · allowedHosts 의 loopback 항목 */\nexport const LOOPBACK_ENTRY = \"loopback\"\n\n/** Host 값 → 소문자 hostname (끝 \".\" 제거) · port (없으면 \"\"). 형식 오류 = undefined */\nfunction parseHost(value: string): { hostname: string; port: string } | undefined {\n if (value === \"\" || /[\\s/?#@\\\\]/.test(value)) return undefined\n let url: URL\n try {\n url = new URL(`http://${value}`)\n } catch {\n return undefined\n }\n // URL 이 기본 포트 (80) 를 지우므로 원문의 포트를 쓴다\n const port = /:(\\d+)$/.exec(value)?.[1] ?? \"\"\n return { hostname: url.hostname.replace(/\\.$/, \"\"), port }\n}\n\n/** allowedHosts 항목 형식 문제. 없으면 undefined (config 검사) */\nexport function allowedHostProblem(entry: unknown): string | undefined {\n if (entry === \"*\" || entry === LOOPBACK_ENTRY) return undefined\n if (typeof entry !== \"string\" || parseHost(entry) === undefined) return `invalid host ${JSON.stringify(entry)}`\n return undefined\n}\n\n/**\n * Host 허용 여부 (server.allowedHosts). \"*\" = 전체, \"loopback\" = loopback 호스트 (포트 무관),\n * 포트 없는 항목 = 그 호스트의 모든 포트, 포트 있는 항목 = 그 포트만. 대소문자 · 끝 \".\" 무시. 형식 오류 = false\n */\nexport function hostAllowed(host: string, allowed: readonly string[]): boolean {\n if (allowed.includes(\"*\")) return true\n const actual = parseHost(host)\n if (actual === undefined) return false\n if (LOOPBACK_HOSTNAMES.has(actual.hostname) && allowed.includes(LOOPBACK_ENTRY)) return true\n return allowed.some((entry) => {\n const expected = entry === LOOPBACK_ENTRY ? undefined : parseHost(entry)\n return expected !== undefined && expected.hostname === actual.hostname && (expected.port === \"\" || expected.port === actual.port)\n })\n}\n"]}
|