toolhome 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -0
  3. package/README.zh.md +281 -0
  4. package/dist/server/app.d.ts +16 -0
  5. package/dist/server/app.d.ts.map +1 -0
  6. package/dist/server/app.js +166 -0
  7. package/dist/server/app.js.map +1 -0
  8. package/dist/server/cli/main.d.ts +3 -0
  9. package/dist/server/cli/main.d.ts.map +1 -0
  10. package/dist/server/cli/main.js +587 -0
  11. package/dist/server/cli/main.js.map +1 -0
  12. package/dist/server/cli-plane/allow-list.d.ts +18 -0
  13. package/dist/server/cli-plane/allow-list.d.ts.map +1 -0
  14. package/dist/server/cli-plane/allow-list.js +28 -0
  15. package/dist/server/cli-plane/allow-list.js.map +1 -0
  16. package/dist/server/cli-plane/cli-service.d.ts +41 -0
  17. package/dist/server/cli-plane/cli-service.d.ts.map +1 -0
  18. package/dist/server/cli-plane/cli-service.js +282 -0
  19. package/dist/server/cli-plane/cli-service.js.map +1 -0
  20. package/dist/server/cli-plane/frames.d.ts +26 -0
  21. package/dist/server/cli-plane/frames.d.ts.map +1 -0
  22. package/dist/server/cli-plane/frames.js +12 -0
  23. package/dist/server/cli-plane/frames.js.map +1 -0
  24. package/dist/server/cli-plane/models.d.ts +174 -0
  25. package/dist/server/cli-plane/models.d.ts.map +1 -0
  26. package/dist/server/cli-plane/models.js +169 -0
  27. package/dist/server/cli-plane/models.js.map +1 -0
  28. package/dist/server/cli-plane/routes.d.ts +32 -0
  29. package/dist/server/cli-plane/routes.d.ts.map +1 -0
  30. package/dist/server/cli-plane/routes.js +94 -0
  31. package/dist/server/cli-plane/routes.js.map +1 -0
  32. package/dist/server/cli-plane/runner.d.ts +41 -0
  33. package/dist/server/cli-plane/runner.d.ts.map +1 -0
  34. package/dist/server/cli-plane/runner.js +163 -0
  35. package/dist/server/cli-plane/runner.js.map +1 -0
  36. package/dist/server/cli-plane/status.d.ts +12 -0
  37. package/dist/server/cli-plane/status.d.ts.map +1 -0
  38. package/dist/server/cli-plane/status.js +24 -0
  39. package/dist/server/cli-plane/status.js.map +1 -0
  40. package/dist/server/config/harness-import.d.ts +44 -0
  41. package/dist/server/config/harness-import.d.ts.map +1 -0
  42. package/dist/server/config/harness-import.js +166 -0
  43. package/dist/server/config/harness-import.js.map +1 -0
  44. package/dist/server/config.d.ts +20 -0
  45. package/dist/server/config.d.ts.map +1 -0
  46. package/dist/server/config.js +80 -0
  47. package/dist/server/config.js.map +1 -0
  48. package/dist/server/control/client.d.ts +24 -0
  49. package/dist/server/control/client.d.ts.map +1 -0
  50. package/dist/server/control/client.js +115 -0
  51. package/dist/server/control/client.js.map +1 -0
  52. package/dist/server/control/control-api.d.ts +39 -0
  53. package/dist/server/control/control-api.d.ts.map +1 -0
  54. package/dist/server/control/control-api.js +291 -0
  55. package/dist/server/control/control-api.js.map +1 -0
  56. package/dist/server/control/control-service.d.ts +713 -0
  57. package/dist/server/control/control-service.d.ts.map +1 -0
  58. package/dist/server/control/control-service.js +693 -0
  59. package/dist/server/control/control-service.js.map +1 -0
  60. package/dist/server/control/openapi.d.ts +2 -0
  61. package/dist/server/control/openapi.d.ts.map +1 -0
  62. package/dist/server/control/openapi.js +370 -0
  63. package/dist/server/control/openapi.js.map +1 -0
  64. package/dist/server/data-plane/data-plane.d.ts +20 -0
  65. package/dist/server/data-plane/data-plane.d.ts.map +1 -0
  66. package/dist/server/data-plane/data-plane.js +335 -0
  67. package/dist/server/data-plane/data-plane.js.map +1 -0
  68. package/dist/server/data-plane/gateway-server.d.ts +13 -0
  69. package/dist/server/data-plane/gateway-server.d.ts.map +1 -0
  70. package/dist/server/data-plane/gateway-server.js +796 -0
  71. package/dist/server/data-plane/gateway-server.js.map +1 -0
  72. package/dist/server/data-plane/legacy-session.d.ts +18 -0
  73. package/dist/server/data-plane/legacy-session.d.ts.map +1 -0
  74. package/dist/server/data-plane/legacy-session.js +137 -0
  75. package/dist/server/data-plane/legacy-session.js.map +1 -0
  76. package/dist/server/data-plane/projection.d.ts +18 -0
  77. package/dist/server/data-plane/projection.d.ts.map +1 -0
  78. package/dist/server/data-plane/projection.js +44 -0
  79. package/dist/server/data-plane/projection.js.map +1 -0
  80. package/dist/server/data-plane/registry.d.ts +31 -0
  81. package/dist/server/data-plane/registry.d.ts.map +1 -0
  82. package/dist/server/data-plane/registry.js +129 -0
  83. package/dist/server/data-plane/registry.js.map +1 -0
  84. package/dist/server/data-plane/task-extension.d.ts +7 -0
  85. package/dist/server/data-plane/task-extension.d.ts.map +1 -0
  86. package/dist/server/data-plane/task-extension.js +33 -0
  87. package/dist/server/data-plane/task-extension.js.map +1 -0
  88. package/dist/server/data-plane/virtualization.d.ts +35 -0
  89. package/dist/server/data-plane/virtualization.d.ts.map +1 -0
  90. package/dist/server/data-plane/virtualization.js +228 -0
  91. package/dist/server/data-plane/virtualization.js.map +1 -0
  92. package/dist/server/domain/errors.d.ts +9 -0
  93. package/dist/server/domain/errors.d.ts.map +1 -0
  94. package/dist/server/domain/errors.js +19 -0
  95. package/dist/server/domain/errors.js.map +1 -0
  96. package/dist/server/domain/models.d.ts +720 -0
  97. package/dist/server/domain/models.d.ts.map +1 -0
  98. package/dist/server/domain/models.js +327 -0
  99. package/dist/server/domain/models.js.map +1 -0
  100. package/dist/server/main.d.ts +2 -0
  101. package/dist/server/main.d.ts.map +1 -0
  102. package/dist/server/main.js +37 -0
  103. package/dist/server/main.js.map +1 -0
  104. package/dist/server/manage/management-mcp.d.ts +27 -0
  105. package/dist/server/manage/management-mcp.d.ts.map +1 -0
  106. package/dist/server/manage/management-mcp.js +431 -0
  107. package/dist/server/manage/management-mcp.js.map +1 -0
  108. package/dist/server/market/catalog.d.ts +111 -0
  109. package/dist/server/market/catalog.d.ts.map +1 -0
  110. package/dist/server/market/catalog.js +784 -0
  111. package/dist/server/market/catalog.js.map +1 -0
  112. package/dist/server/market/installers.d.ts +64 -0
  113. package/dist/server/market/installers.d.ts.map +1 -0
  114. package/dist/server/market/installers.js +181 -0
  115. package/dist/server/market/installers.js.map +1 -0
  116. package/dist/server/market/market-service.d.ts +146 -0
  117. package/dist/server/market/market-service.d.ts.map +1 -0
  118. package/dist/server/market/market-service.js +930 -0
  119. package/dist/server/market/market-service.js.map +1 -0
  120. package/dist/server/observability/call-recorder.d.ts +22 -0
  121. package/dist/server/observability/call-recorder.d.ts.map +1 -0
  122. package/dist/server/observability/call-recorder.js +99 -0
  123. package/dist/server/observability/call-recorder.js.map +1 -0
  124. package/dist/server/observability/logger.d.ts +16 -0
  125. package/dist/server/observability/logger.d.ts.map +1 -0
  126. package/dist/server/observability/logger.js +25 -0
  127. package/dist/server/observability/logger.js.map +1 -0
  128. package/dist/server/security/api-keys.d.ts +15 -0
  129. package/dist/server/security/api-keys.d.ts.map +1 -0
  130. package/dist/server/security/api-keys.js +35 -0
  131. package/dist/server/security/api-keys.js.map +1 -0
  132. package/dist/server/security/auth-service.d.ts +26 -0
  133. package/dist/server/security/auth-service.d.ts.map +1 -0
  134. package/dist/server/security/auth-service.js +76 -0
  135. package/dist/server/security/auth-service.js.map +1 -0
  136. package/dist/server/security/control-session.d.ts +9 -0
  137. package/dist/server/security/control-session.d.ts.map +1 -0
  138. package/dist/server/security/control-session.js +51 -0
  139. package/dist/server/security/control-session.js.map +1 -0
  140. package/dist/server/security/credential-materializer.d.ts +20 -0
  141. package/dist/server/security/credential-materializer.d.ts.map +1 -0
  142. package/dist/server/security/credential-materializer.js +82 -0
  143. package/dist/server/security/credential-materializer.js.map +1 -0
  144. package/dist/server/security/cursor-codec.d.ts +13 -0
  145. package/dist/server/security/cursor-codec.d.ts.map +1 -0
  146. package/dist/server/security/cursor-codec.js +43 -0
  147. package/dist/server/security/cursor-codec.js.map +1 -0
  148. package/dist/server/security/oauth-routes.d.ts +21 -0
  149. package/dist/server/security/oauth-routes.d.ts.map +1 -0
  150. package/dist/server/security/oauth-routes.js +100 -0
  151. package/dist/server/security/oauth-routes.js.map +1 -0
  152. package/dist/server/security/oauth-server.d.ts +16 -0
  153. package/dist/server/security/oauth-server.d.ts.map +1 -0
  154. package/dist/server/security/oauth-server.js +544 -0
  155. package/dist/server/security/oauth-server.js.map +1 -0
  156. package/dist/server/security/secret-box.d.ts +7 -0
  157. package/dist/server/security/secret-box.d.ts.map +1 -0
  158. package/dist/server/security/secret-box.js +27 -0
  159. package/dist/server/security/secret-box.js.map +1 -0
  160. package/dist/server/security/secure-action.d.ts +21 -0
  161. package/dist/server/security/secure-action.d.ts.map +1 -0
  162. package/dist/server/security/secure-action.js +69 -0
  163. package/dist/server/security/secure-action.js.map +1 -0
  164. package/dist/server/storage/sqlite-store.d.ts +70 -0
  165. package/dist/server/storage/sqlite-store.d.ts.map +1 -0
  166. package/dist/server/storage/sqlite-store.js +1522 -0
  167. package/dist/server/storage/sqlite-store.js.map +1 -0
  168. package/dist/server/storage/store.d.ts +82 -0
  169. package/dist/server/storage/store.d.ts.map +1 -0
  170. package/dist/server/storage/store.js +2 -0
  171. package/dist/server/storage/store.js.map +1 -0
  172. package/dist/server/upstream/adapter.d.ts +52 -0
  173. package/dist/server/upstream/adapter.d.ts.map +1 -0
  174. package/dist/server/upstream/adapter.js +807 -0
  175. package/dist/server/upstream/adapter.js.map +1 -0
  176. package/dist/server/upstream/credential-resolver.d.ts +14 -0
  177. package/dist/server/upstream/credential-resolver.d.ts.map +1 -0
  178. package/dist/server/upstream/credential-resolver.js +56 -0
  179. package/dist/server/upstream/credential-resolver.js.map +1 -0
  180. package/dist/server/upstream/extension-transport.d.ts +17 -0
  181. package/dist/server/upstream/extension-transport.d.ts.map +1 -0
  182. package/dist/server/upstream/extension-transport.js +207 -0
  183. package/dist/server/upstream/extension-transport.js.map +1 -0
  184. package/dist/server/upstream/manager.d.ts +23 -0
  185. package/dist/server/upstream/manager.d.ts.map +1 -0
  186. package/dist/server/upstream/manager.js +324 -0
  187. package/dist/server/upstream/manager.js.map +1 -0
  188. package/dist/server/upstream/oauth-provider.d.ts +38 -0
  189. package/dist/server/upstream/oauth-provider.d.ts.map +1 -0
  190. package/dist/server/upstream/oauth-provider.js +225 -0
  191. package/dist/server/upstream/oauth-provider.js.map +1 -0
  192. package/dist/server/upstream/oauth-refresh.d.ts +65 -0
  193. package/dist/server/upstream/oauth-refresh.d.ts.map +1 -0
  194. package/dist/server/upstream/oauth-refresh.js +240 -0
  195. package/dist/server/upstream/oauth-refresh.js.map +1 -0
  196. package/dist/server/upstream/oauth-routes.d.ts +17 -0
  197. package/dist/server/upstream/oauth-routes.d.ts.map +1 -0
  198. package/dist/server/upstream/oauth-routes.js +87 -0
  199. package/dist/server/upstream/oauth-routes.js.map +1 -0
  200. package/dist/server/upstream/oauth-service.d.ts +143 -0
  201. package/dist/server/upstream/oauth-service.d.ts.map +1 -0
  202. package/dist/server/upstream/oauth-service.js +217 -0
  203. package/dist/server/upstream/oauth-service.js.map +1 -0
  204. package/dist/server/upstream/stable-json.d.ts +3 -0
  205. package/dist/server/upstream/stable-json.d.ts.map +1 -0
  206. package/dist/server/upstream/stable-json.js +17 -0
  207. package/dist/server/upstream/stable-json.js.map +1 -0
  208. package/package.json +69 -0
  209. package/skills/toolhome/SKILL.md +238 -0
  210. package/skills/toolhome/references/cli-reference.md +242 -0
  211. package/skills/toolhome/references/deployment.md +113 -0
  212. package/skills/toolhome/references/market-guide.md +128 -0
  213. package/skills/toolhome/references/oauth-guide.md +96 -0
  214. package/skills/toolhome/references/troubleshooting.md +133 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Evaluate a CLI allow-list against an argv array before spawn.
3
+ *
4
+ * Rules are token patterns matched as a prefix of argv; `*` matches a single
5
+ * argv token. A deny rule match always rejects. When the allow list is
6
+ * non-empty, at least one allow rule must match. An empty allow list means the
7
+ * entry is explicitly trusted (same trust decision the Market makes for
8
+ * home-stdio entries).
9
+ */
10
+ export function evaluateAllowList(argv, rules) {
11
+ for (const rule of rules.deny) {
12
+ if (ruleMatches(rule, argv)) {
13
+ return { verdict: 'deny', reason: `argv matches deny rule: ${rule.join(' ')}` };
14
+ }
15
+ }
16
+ if (rules.allow.length > 0) {
17
+ if (!rules.allow.some((rule) => ruleMatches(rule, argv))) {
18
+ return { verdict: 'deny', reason: 'argv does not match any allow rule' };
19
+ }
20
+ }
21
+ return { verdict: 'allow' };
22
+ }
23
+ function ruleMatches(rule, argv) {
24
+ if (argv.length < rule.length)
25
+ return false;
26
+ return rule.every((token, index) => token === '*' || token === argv[index]);
27
+ }
28
+ //# sourceMappingURL=allow-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allow-list.js","sourceRoot":"","sources":["../../../src/cli-plane/allow-list.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAc,EAAE,KAAmB;IACnE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,2BAA2B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QAClF,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,WAAW,CAAC,IAAkB,EAAE,IAAc;IACrD,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { CallRecorder } from '../observability/call-recorder.js';
2
+ import type { Store } from '../storage/store.js';
3
+ import type { CliExecFrame } from './frames.js';
4
+ import { type CliExecInput, type CliRecord } from './models.js';
5
+ import { type ExecOutcome } from './runner.js';
6
+ /**
7
+ * Non-interactive enforcement variables injected into every CLI execution
8
+ * (docs/cli-hosting-research.md §2.5): CLIs otherwise page, prompt, and
9
+ * colorize unpredictably in a headless context.
10
+ */
11
+ export declare const cliEnforcementEnv: Record<string, string>;
12
+ export interface CliStatus {
13
+ installed: boolean | null;
14
+ version: string | null;
15
+ loggedIn: boolean;
16
+ lastCheckedAt: string;
17
+ }
18
+ export declare class CliService {
19
+ #private;
20
+ constructor(store: Store, recorder?: CallRecorder);
21
+ list(): CliRecord[];
22
+ get(id: string): CliRecord;
23
+ getBySlug(slug: string): CliRecord;
24
+ create(value: unknown): CliRecord;
25
+ update(id: string, value: unknown): CliRecord;
26
+ delete(id: string): void;
27
+ /**
28
+ * Validate an exec request before any process is spawned: record lookup,
29
+ * enabled check, argv shape (array only — never a shell string), and the
30
+ * allow-list verdict. Throws a structured AppError for 404/400/403 cases.
31
+ */
32
+ prepareExec(slug: string, body: unknown): {
33
+ record: CliRecord;
34
+ input: CliExecInput;
35
+ };
36
+ /** Run a prepared exec, streaming NDJSON frames, and audit it as an event. */
37
+ runExec(record: CliRecord, input: CliExecInput, emit: (frame: CliExecFrame) => void, signal?: AbortSignal): Promise<ExecOutcome>;
38
+ /** Run the CLI's declared probe in the same isolated context and parse it. */
39
+ status(slug: string): Promise<CliStatus>;
40
+ }
41
+ //# sourceMappingURL=cli-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-service.d.ts","sourceRoot":"","sources":["../../../src/cli-plane/cli-service.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAKL,KAAK,YAAY,EAEjB,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AA2BxD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKpD,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,UAAU;;IAIrB,YAAY,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,YAAY,EAGhD;IAED,IAAI,IAAI,SAAS,EAAE,CAElB;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAIzB;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAIjC;IAED,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAahC;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,CA4B5C;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAUvB;IAED;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,YAAY,CAAA;KAAE,CAcnF;IAED,8EAA8E;IACxE,OAAO,CACX,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,WAAW,CAAC,CAuCtB;IAkCD,8EAA8E;IACxE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAqC7C;CAqDF"}
@@ -0,0 +1,282 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { AppError } from '../domain/errors.js';
4
+ import { materializeCliCredential, validateCliCredentialBindings, } from '../security/credential-materializer.js';
5
+ import { evaluateAllowList } from './allow-list.js';
6
+ import { assertCliRuntimeConfig, cliExecInputSchema, createCliInputSchema, updateCliInputSchema, } from './models.js';
7
+ import { execCli } from './runner.js';
8
+ import { parseProbeOutput } from './status.js';
9
+ const secretArgNamePattern = /(?:token|secret|password|passwd|api[-_]?key|credential)/i;
10
+ function redactArgv(argv) {
11
+ const redacted = [];
12
+ for (let index = 0; index < argv.length; index += 1) {
13
+ const argument = argv[index];
14
+ const equalIndex = argument.indexOf('=');
15
+ if (equalIndex > 0 && secretArgNamePattern.test(argument.slice(0, equalIndex))) {
16
+ redacted.push(`${argument.slice(0, equalIndex + 1)}[REDACTED]`);
17
+ continue;
18
+ }
19
+ if (argument.startsWith('-') && secretArgNamePattern.test(argument.replace(/^-+/, ''))) {
20
+ redacted.push(argument);
21
+ if (index + 1 < argv.length) {
22
+ redacted.push('[REDACTED]');
23
+ index += 1;
24
+ }
25
+ continue;
26
+ }
27
+ redacted.push(argument);
28
+ }
29
+ return redacted;
30
+ }
31
+ /**
32
+ * Non-interactive enforcement variables injected into every CLI execution
33
+ * (docs/cli-hosting-research.md §2.5): CLIs otherwise page, prompt, and
34
+ * colorize unpredictably in a headless context.
35
+ */
36
+ export const cliEnforcementEnv = {
37
+ CI: 'true',
38
+ NO_COLOR: '1',
39
+ PAGER: 'cat',
40
+ TERM: 'dumb',
41
+ };
42
+ export class CliService {
43
+ #store;
44
+ #recorder;
45
+ constructor(store, recorder) {
46
+ this.#store = store;
47
+ this.#recorder = recorder ?? null;
48
+ }
49
+ list() {
50
+ return this.#store.listClis();
51
+ }
52
+ get(id) {
53
+ const record = this.#store.getCli(id);
54
+ if (!record)
55
+ throw new AppError('cli_not_found', 'CLI not found', 404);
56
+ return record;
57
+ }
58
+ getBySlug(slug) {
59
+ const record = this.#store.getCliBySlug(slug);
60
+ if (!record)
61
+ throw new AppError('cli_not_found', `CLI "${slug}" not found`, 404);
62
+ return record;
63
+ }
64
+ create(value) {
65
+ const input = createCliInputSchema.parse(value);
66
+ assertCliRuntimeConfig(input);
67
+ this.#assertCredential(input.credentialId, input.credentialBindings);
68
+ const record = this.#store.createCli(input);
69
+ this.#store.appendEvent({
70
+ level: 'info',
71
+ type: 'cli.created',
72
+ serverId: null,
73
+ message: `Created CLI ${record.slug}`,
74
+ detail: { slug: record.slug, executionMode: record.executionMode },
75
+ });
76
+ return record;
77
+ }
78
+ update(id, value) {
79
+ const current = this.get(id);
80
+ const input = updateCliInputSchema.parse(value);
81
+ const nextCredentialId = input.credentialId === undefined ? current.credentialId : input.credentialId;
82
+ const nextExecutionMode = input.executionMode ?? current.executionMode;
83
+ const nextAuthStrategy = input.authStrategy ?? current.authStrategy;
84
+ const nextContainerVolumes = input.containerVolumes ?? current.containerVolumes;
85
+ assertCliRuntimeConfig({
86
+ executionMode: nextExecutionMode,
87
+ authStrategy: nextAuthStrategy,
88
+ containerVolumes: nextContainerVolumes,
89
+ });
90
+ this.#assertCredential(nextCredentialId, input.credentialBindings === undefined
91
+ ? current.credentialBindings
92
+ : input.credentialBindings);
93
+ const record = this.#store.updateCli(id, input);
94
+ this.#store.appendEvent({
95
+ level: 'info',
96
+ type: 'cli.updated',
97
+ serverId: null,
98
+ message: `Updated CLI ${record.slug}`,
99
+ detail: { slug: record.slug },
100
+ });
101
+ return record;
102
+ }
103
+ delete(id) {
104
+ const current = this.get(id);
105
+ this.#store.deleteCli(id);
106
+ this.#store.appendEvent({
107
+ level: 'info',
108
+ type: 'cli.deleted',
109
+ serverId: null,
110
+ message: `Deleted CLI ${current.slug}`,
111
+ detail: { slug: current.slug },
112
+ });
113
+ }
114
+ /**
115
+ * Validate an exec request before any process is spawned: record lookup,
116
+ * enabled check, argv shape (array only — never a shell string), and the
117
+ * allow-list verdict. Throws a structured AppError for 404/400/403 cases.
118
+ */
119
+ prepareExec(slug, body) {
120
+ const record = this.getBySlug(slug);
121
+ if (!record.enabled) {
122
+ throw new AppError('cli_disabled', `CLI "${slug}" is disabled`, 403);
123
+ }
124
+ const input = cliExecInputSchema.parse(body);
125
+ const verdict = evaluateAllowList(input.argv, record.allowList);
126
+ if (verdict.verdict === 'deny') {
127
+ throw new AppError('cli_denied', `argv denied by allow-list: ${verdict.reason}`, 403);
128
+ }
129
+ // Resolve credentials before the NDJSON response starts so authorization and
130
+ // binding errors remain structured HTTP errors instead of stream frames.
131
+ this.#buildEnv(record);
132
+ return { record, input };
133
+ }
134
+ /** Run a prepared exec, streaming NDJSON frames, and audit it as an event. */
135
+ async runExec(record, input, emit, signal) {
136
+ const env = this.#buildEnv(record);
137
+ const outcome = await execCli({
138
+ command: record.command,
139
+ argv: input.argv,
140
+ env,
141
+ stdin: input.stdin ?? null,
142
+ timeoutMs: Math.min(record.timeoutMs, input.timeoutMs ?? record.timeoutMs),
143
+ maxOutputBytes: Math.min(record.maxOutputBytes, input.maxOutputBytes ?? record.maxOutputBytes),
144
+ executionMode: record.executionMode,
145
+ containerEnvKeys: record.executionMode === 'docker' ? this.#containerEnvKeys(record) : undefined,
146
+ containerVolumes: record.executionMode === 'docker' ? record.containerVolumes : undefined,
147
+ authStrategy: record.authStrategy,
148
+ entrypoint: record.entrypoint,
149
+ }, emit, signal);
150
+ this.#store.appendEvent({
151
+ level: 'info',
152
+ type: 'cli.exec',
153
+ serverId: null,
154
+ message: `${record.slug} ${redactArgv(input.argv).join(' ')}`,
155
+ detail: {
156
+ slug: record.slug,
157
+ argv: redactArgv(input.argv),
158
+ exitCode: outcome.code,
159
+ durationMs: outcome.durationMs,
160
+ result: outcome.result,
161
+ truncated: outcome.truncated,
162
+ },
163
+ });
164
+ this.#recordCall(record, input.argv, outcome);
165
+ return outcome;
166
+ }
167
+ /** Mirror the exec into the calls panel (fire-and-forget, same as MCP calls). */
168
+ #recordCall(record, argv, outcome) {
169
+ if (this.#recorder === null)
170
+ return;
171
+ const completedAt = new Date();
172
+ const status = outcome.result === 'ok'
173
+ ? 'success'
174
+ : outcome.result === 'timeout'
175
+ ? 'timeout'
176
+ : outcome.code === null
177
+ ? 'rejected'
178
+ : 'tool_error';
179
+ const draft = {
180
+ endpointType: 'cli',
181
+ principalKind: 'cli',
182
+ principalId: record.id,
183
+ serverId: null,
184
+ exposedToolName: record.slug,
185
+ upstreamToolName: redactArgv(argv).join(' '),
186
+ status,
187
+ errorType: status === 'success' ? null : outcome.result,
188
+ startedAt: new Date(completedAt.getTime() - outcome.durationMs).toISOString(),
189
+ completedAt: completedAt.toISOString(),
190
+ durationMs: Math.max(0, outcome.durationMs),
191
+ };
192
+ this.#recorder.record(draft);
193
+ }
194
+ /** Run the CLI's declared probe in the same isolated context and parse it. */
195
+ async status(slug) {
196
+ const record = this.getBySlug(slug);
197
+ const lastCheckedAt = new Date().toISOString();
198
+ if (record.probe === null) {
199
+ return { installed: null, version: null, loggedIn: false, lastCheckedAt };
200
+ }
201
+ let stdout = '';
202
+ const env = this.#buildEnv(record);
203
+ const outcome = await execCli({
204
+ command: record.executionMode === 'docker'
205
+ ? record.command
206
+ : this.#resolveHostProbe(record, record.probe),
207
+ argv: record.probe.args,
208
+ env,
209
+ stdin: null,
210
+ timeoutMs: Math.min(record.timeoutMs, 30_000),
211
+ maxOutputBytes: 64 * 1024,
212
+ executionMode: record.executionMode,
213
+ containerEnvKeys: record.executionMode === 'docker' ? this.#containerEnvKeys(record) : undefined,
214
+ containerVolumes: record.executionMode === 'docker' ? record.containerVolumes : undefined,
215
+ authStrategy: record.authStrategy,
216
+ entrypoint: record.executionMode === 'docker' ? record.probe.command : record.entrypoint,
217
+ }, (frame) => {
218
+ if (frame.type === 'stdout')
219
+ stdout += frame.data;
220
+ });
221
+ const parsed = parseProbeOutput(stdout);
222
+ return {
223
+ installed: outcome.code === 0,
224
+ version: parsed.version,
225
+ loggedIn: parsed.loggedIn,
226
+ lastCheckedAt,
227
+ };
228
+ }
229
+ /**
230
+ * Bare probe command names resolve next to the installed host binary; the
231
+ * market bin directory is not on the gateway process PATH.
232
+ */
233
+ #resolveHostProbe(record, probe) {
234
+ if (probe.command.includes('/') || !record.command.includes('/'))
235
+ return probe.command;
236
+ const candidate = join(dirname(record.command), probe.command);
237
+ return existsSync(candidate) ? candidate : probe.command;
238
+ }
239
+ #containerEnvKeys(record) {
240
+ const keys = new Set();
241
+ if (!record.interactive) {
242
+ for (const key of Object.keys(cliEnforcementEnv))
243
+ keys.add(key);
244
+ }
245
+ if (record.credentialId !== null) {
246
+ const payload = this.#store.getCredentialPayload(record.credentialId);
247
+ if (payload) {
248
+ for (const key of Object.keys(materializeCliCredential(payload, record.credentialBindings))) {
249
+ keys.add(key);
250
+ }
251
+ }
252
+ }
253
+ return [...keys];
254
+ }
255
+ #buildEnv(record) {
256
+ const env = {};
257
+ for (const [name, value] of Object.entries(process.env)) {
258
+ if (value !== undefined)
259
+ env[name] = value;
260
+ }
261
+ if (!record.interactive) {
262
+ // interactive records opt out of the non-interactive enforcement vars
263
+ Object.assign(env, cliEnforcementEnv);
264
+ }
265
+ if (record.credentialId !== null) {
266
+ const payload = this.#store.getCredentialPayload(record.credentialId);
267
+ if (payload === null)
268
+ throw new AppError('credential_not_found', 'Credential not found', 400);
269
+ Object.assign(env, materializeCliCredential(payload, record.credentialBindings));
270
+ }
271
+ return env;
272
+ }
273
+ #assertCredential(credentialId, bindings) {
274
+ if (credentialId === null)
275
+ return;
276
+ const payload = this.#store.getCredentialPayload(credentialId);
277
+ if (!payload)
278
+ throw new AppError('credential_not_found', 'Credential not found', 400);
279
+ validateCliCredentialBindings(payload, bindings);
280
+ }
281
+ }
282
+ //# sourceMappingURL=cli-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-service.js","sourceRoot":"","sources":["../../../src/cli-plane/cli-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EACL,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,wCAAwC,CAAC;AAGhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,GAIrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAoB,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,oBAAoB,GAAG,0DAA0D,CAAC;AAExF,SAAS,UAAU,CAAC,IAAc;IAChC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,UAAU,GAAG,CAAC,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;YAC/E,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;YAChE,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;YACvF,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC5B,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;YACD,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,EAAE,EAAE,MAAM;IACV,QAAQ,EAAE,GAAG;IACb,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,MAAM;CACb,CAAC;AASF,MAAM,OAAO,UAAU;IACZ,MAAM,CAAQ;IACd,SAAS,CAAsB;IAExC,YAAY,KAAY,EAAE,QAAuB;QAC/C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,QAAQ,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC;QACvE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,QAAQ,IAAI,aAAa,EAAE,GAAG,CAAC,CAAC;QACjF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,KAAc;QACnB,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;YACtB,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,eAAe,MAAM,CAAC,IAAI,EAAE;YACrC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE;SACnE,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,EAAU,EAAE,KAAc;QAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,gBAAgB,GACpB,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;QAC/E,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;QACvE,MAAM,gBAAgB,GAAG,KAAK,CAAC,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;QACpE,MAAM,oBAAoB,GAAG,KAAK,CAAC,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC;QAChF,sBAAsB,CAAC;YACrB,aAAa,EAAE,iBAAiB;YAChC,YAAY,EAAE,gBAAgB;YAC9B,gBAAgB,EAAE,oBAAoB;SACvC,CAAC,CAAC;QACH,IAAI,CAAC,iBAAiB,CACpB,gBAAgB,EAChB,KAAK,CAAC,kBAAkB,KAAK,SAAS;YACpC,CAAC,CAAC,OAAO,CAAC,kBAAkB;YAC5B,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAC7B,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;YACtB,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,eAAe,MAAM,CAAC,IAAI,EAAE;YACrC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;SAC9B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,EAAU;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;YACtB,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,eAAe,OAAO,CAAC,IAAI,EAAE;YACtC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;SAC/B,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,IAAY,EAAE,IAAa;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,QAAQ,CAAC,cAAc,EAAE,QAAQ,IAAI,eAAe,EAAE,GAAG,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAChE,IAAI,OAAO,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;YAC/B,MAAM,IAAI,QAAQ,CAAC,YAAY,EAAE,8BAA8B,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;QACxF,CAAC;QACD,6EAA6E;QAC7E,yEAAyE;QACzE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,OAAO,CACX,MAAiB,EACjB,KAAmB,EACnB,IAAmC,EACnC,MAAoB;QAEpB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,OAAO,CAC3B;YACE,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG;YACH,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI;YAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;YAC1E,cAAc,EAAE,IAAI,CAAC,GAAG,CACtB,MAAM,CAAC,cAAc,EACrB,KAAK,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAC9C;YACD,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,gBAAgB,EACd,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;YAChF,gBAAgB,EAAE,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;YACzF,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,EACD,IAAI,EACJ,MAAM,CACP,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;YACtB,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC7D,MAAM,EAAE;gBACN,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC5B,QAAQ,EAAE,OAAO,CAAC,IAAI;gBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B;SACF,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,iFAAiF;IACjF,WAAW,CACT,MAAiB,EACjB,IAAc,EACd,OAAoE;QAEpE,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;YAAE,OAAO;QACpC,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;QAC/B,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,KAAK,IAAI;YACrB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS;gBAC5B,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI;oBACrB,CAAC,CAAC,UAAU;oBACZ,CAAC,CAAC,YAAY,CAAC;QACvB,MAAM,KAAK,GAAkB;YAC3B,YAAY,EAAE,KAAK;YACnB,aAAa,EAAE,KAAK;YACpB,WAAW,EAAE,MAAM,CAAC,EAAE;YACtB,QAAQ,EAAE,IAAI;YACd,eAAe,EAAE,MAAM,CAAC,IAAI;YAC5B,gBAAgB,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,MAAM;YACN,SAAS,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM;YACvD,SAAS,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE;YAC7E,WAAW,EAAE,WAAW,CAAC,WAAW,EAAE;YACtC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;SAC5C,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1B,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAC5E,CAAC;QACD,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,OAAO,CAC3B;YACE,OAAO,EACL,MAAM,CAAC,aAAa,KAAK,QAAQ;gBAC/B,CAAC,CAAC,MAAM,CAAC,OAAO;gBAChB,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC;YAClD,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;YACvB,GAAG;YACH,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;YAC7C,cAAc,EAAE,EAAE,GAAG,IAAI;YACzB,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,gBAAgB,EACd,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;YAChF,gBAAgB,EAAE,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;YACzF,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,UAAU,EAAE,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU;SACzF,EACD,CAAC,KAAK,EAAE,EAAE;YACR,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC;QACpD,CAAC,CACF,CAAC;QACF,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACxC,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC;YAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,aAAa;SACd,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,iBAAiB,CAAC,MAAiB,EAAE,KAAe;QAClD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC;QACvF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/D,OAAO,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;IAC3D,CAAC;IAED,iBAAiB,CAAC,MAAiB;QACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,MAAM,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACtE,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAC3B,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAC7D,EAAE,CAAC;oBACF,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,SAAS,CAAC,MAAiB;QACzB,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACxD,IAAI,KAAK,KAAK,SAAS;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,sEAAsE;YACtE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,MAAM,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACtE,IAAI,OAAO,KAAK,IAAI;gBAAE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,GAAG,CAAC,CAAC;YAC9F,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,iBAAiB,CAAC,YAA2B,EAAE,QAAgC;QAC7E,IAAI,YAAY,KAAK,IAAI;YAAE,OAAO;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;QAC/D,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,GAAG,CAAC,CAAC;QACtF,6BAA6B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * NDJSON frames for the CLI exec stream (docs/cli-hosting-research.md §2.2).
3
+ *
4
+ * The stream is newline-delimited JSON: one `stdout`/`stderr` frame per chunk,
5
+ * terminated by a single `exit` frame carrying the real exit code, duration,
6
+ * and an explicit `timeout`/`error` result when the process did not exit
7
+ * normally.
8
+ */
9
+ export type CliExecFrame = {
10
+ type: 'stdout';
11
+ data: string;
12
+ } | {
13
+ type: 'stderr';
14
+ data: string;
15
+ } | {
16
+ type: 'exit';
17
+ code: number | null;
18
+ durationMs: number;
19
+ result: 'ok' | 'error' | 'timeout';
20
+ truncated?: boolean;
21
+ };
22
+ export declare const cliNdjsonContentType = "application/x-ndjson";
23
+ export declare function encodeFrame(frame: CliExecFrame): string;
24
+ /** Parse a full NDJSON body into frames; throws on malformed input. */
25
+ export declare function parseFrames(body: string): CliExecFrame[];
26
+ //# sourceMappingURL=frames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../../../src/cli-plane/frames.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,IAAI,GAAG,OAAO,GAAG,SAAS,CAAC;IACnC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEN,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAEvD;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAKxD"}
@@ -0,0 +1,12 @@
1
+ export const cliNdjsonContentType = 'application/x-ndjson';
2
+ export function encodeFrame(frame) {
3
+ return `${JSON.stringify(frame)}\n`;
4
+ }
5
+ /** Parse a full NDJSON body into frames; throws on malformed input. */
6
+ export function parseFrames(body) {
7
+ return body
8
+ .split('\n')
9
+ .filter((line) => line.trim() !== '')
10
+ .map((line) => JSON.parse(line));
11
+ }
12
+ //# sourceMappingURL=frames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.js","sourceRoot":"","sources":["../../../src/cli-plane/frames.ts"],"names":[],"mappings":"AAmBA,MAAM,CAAC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE3D,MAAM,UAAU,WAAW,CAAC,KAAmB;IAC7C,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;AACtC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI;SACR,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;SACpC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,174 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * CLI plane record schemas (Form A of docs/cli-hosting-research.md).
4
+ *
5
+ * A CLI is a first-class entity: a command or container image plus a declarative
6
+ * allow-list, optional probe for status checks, and an optional Env Credential
7
+ * whose variables are injected into every execution.
8
+ */
9
+ /** One argv rule: token patterns, where `*` matches a single argv token. */
10
+ export declare const cliAllowRuleSchema: z.ZodArray<z.ZodString>;
11
+ export declare const cliAllowListSchema: z.ZodObject<{
12
+ allow: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
13
+ deny: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
14
+ }, z.core.$strip>;
15
+ export declare const cliProbeSchema: z.ZodObject<{
16
+ command: z.ZodString;
17
+ args: z.ZodDefault<z.ZodArray<z.ZodString>>;
18
+ }, z.core.$strip>;
19
+ export declare const cliCredentialBindingsSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
20
+ export declare const cliAuthStrategySchema: z.ZodDefault<z.ZodEnum<{
21
+ "azure-service-principal": "azure-service-principal";
22
+ none: "none";
23
+ "tailscale-auth-key": "tailscale-auth-key";
24
+ }>>;
25
+ export declare const cliRuntimeConfigSchema: z.ZodObject<{
26
+ executionMode: z.ZodEnum<{
27
+ docker: "docker";
28
+ host: "host";
29
+ }>;
30
+ authStrategy: z.ZodDefault<z.ZodEnum<{
31
+ "azure-service-principal": "azure-service-principal";
32
+ none: "none";
33
+ "tailscale-auth-key": "tailscale-auth-key";
34
+ }>>;
35
+ containerVolumes: z.ZodArray<z.ZodObject<{
36
+ source: z.ZodString;
37
+ target: z.ZodString;
38
+ readOnly: z.ZodDefault<z.ZodBoolean>;
39
+ }, z.core.$strip>>;
40
+ }, z.core.$strip>;
41
+ export declare const createCliInputSchema: z.ZodObject<{
42
+ slug: z.ZodString;
43
+ name: z.ZodString;
44
+ command: z.ZodString;
45
+ executionMode: z.ZodDefault<z.ZodEnum<{
46
+ docker: "docker";
47
+ host: "host";
48
+ }>>;
49
+ entrypoint: z.ZodDefault<z.ZodNullable<z.ZodString>>;
50
+ authStrategy: z.ZodDefault<z.ZodEnum<{
51
+ "azure-service-principal": "azure-service-principal";
52
+ none: "none";
53
+ "tailscale-auth-key": "tailscale-auth-key";
54
+ }>>;
55
+ containerVolumes: z.ZodDefault<z.ZodArray<z.ZodObject<{
56
+ source: z.ZodString;
57
+ target: z.ZodString;
58
+ readOnly: z.ZodDefault<z.ZodBoolean>;
59
+ }, z.core.$strip>>>;
60
+ platform: z.ZodDefault<z.ZodNullable<z.ZodString>>;
61
+ allowList: z.ZodDefault<z.ZodObject<{
62
+ allow: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
63
+ deny: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
64
+ }, z.core.$strip>>;
65
+ interactive: z.ZodDefault<z.ZodBoolean>;
66
+ credentialId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
67
+ credentialBindings: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
68
+ probe: z.ZodDefault<z.ZodNullable<z.ZodObject<{
69
+ command: z.ZodString;
70
+ args: z.ZodDefault<z.ZodArray<z.ZodString>>;
71
+ }, z.core.$strip>>>;
72
+ enabled: z.ZodDefault<z.ZodBoolean>;
73
+ timeoutMs: z.ZodDefault<z.ZodNumber>;
74
+ maxOutputBytes: z.ZodDefault<z.ZodNumber>;
75
+ }, z.core.$strip>;
76
+ export declare const updateCliInputSchema: z.ZodObject<{
77
+ name: z.ZodOptional<z.ZodString>;
78
+ command: z.ZodOptional<z.ZodString>;
79
+ executionMode: z.ZodOptional<z.ZodEnum<{
80
+ docker: "docker";
81
+ host: "host";
82
+ }>>;
83
+ entrypoint: z.ZodOptional<z.ZodNullable<z.ZodString>>;
84
+ authStrategy: z.ZodOptional<z.ZodEnum<{
85
+ "azure-service-principal": "azure-service-principal";
86
+ none: "none";
87
+ "tailscale-auth-key": "tailscale-auth-key";
88
+ }>>;
89
+ containerVolumes: z.ZodOptional<z.ZodArray<z.ZodObject<{
90
+ source: z.ZodString;
91
+ target: z.ZodString;
92
+ readOnly: z.ZodDefault<z.ZodBoolean>;
93
+ }, z.core.$strip>>>;
94
+ platform: z.ZodOptional<z.ZodNullable<z.ZodString>>;
95
+ allowList: z.ZodOptional<z.ZodObject<{
96
+ allow: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
97
+ deny: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
98
+ }, z.core.$strip>>;
99
+ interactive: z.ZodOptional<z.ZodBoolean>;
100
+ credentialId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
101
+ credentialBindings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
102
+ probe: z.ZodOptional<z.ZodNullable<z.ZodObject<{
103
+ command: z.ZodString;
104
+ args: z.ZodDefault<z.ZodArray<z.ZodString>>;
105
+ }, z.core.$strip>>>;
106
+ enabled: z.ZodOptional<z.ZodBoolean>;
107
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
108
+ maxOutputBytes: z.ZodOptional<z.ZodNumber>;
109
+ }, z.core.$strip>;
110
+ export declare function assertCliRuntimeConfig(value: {
111
+ executionMode: 'host' | 'docker';
112
+ authStrategy: 'none' | 'azure-service-principal' | 'tailscale-auth-key';
113
+ containerVolumes: {
114
+ source: string;
115
+ target: string;
116
+ readOnly: boolean;
117
+ }[];
118
+ }): void;
119
+ export declare const cliRecordSchema: z.ZodObject<{
120
+ id: z.ZodUUID;
121
+ slug: z.ZodString;
122
+ name: z.ZodString;
123
+ command: z.ZodString;
124
+ executionMode: z.ZodEnum<{
125
+ docker: "docker";
126
+ host: "host";
127
+ }>;
128
+ entrypoint: z.ZodNullable<z.ZodString>;
129
+ authStrategy: z.ZodDefault<z.ZodEnum<{
130
+ "azure-service-principal": "azure-service-principal";
131
+ none: "none";
132
+ "tailscale-auth-key": "tailscale-auth-key";
133
+ }>>;
134
+ containerVolumes: z.ZodArray<z.ZodObject<{
135
+ source: z.ZodString;
136
+ target: z.ZodString;
137
+ readOnly: z.ZodDefault<z.ZodBoolean>;
138
+ }, z.core.$strip>>;
139
+ platform: z.ZodNullable<z.ZodString>;
140
+ allowList: z.ZodObject<{
141
+ allow: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
142
+ deny: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodString>>>;
143
+ }, z.core.$strip>;
144
+ interactive: z.ZodBoolean;
145
+ credentialId: z.ZodNullable<z.ZodString>;
146
+ credentialBindings: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
147
+ probe: z.ZodNullable<z.ZodObject<{
148
+ command: z.ZodString;
149
+ args: z.ZodDefault<z.ZodArray<z.ZodString>>;
150
+ }, z.core.$strip>>;
151
+ enabled: z.ZodBoolean;
152
+ timeoutMs: z.ZodNumber;
153
+ maxOutputBytes: z.ZodNumber;
154
+ createdAt: z.ZodISODateTime;
155
+ updatedAt: z.ZodISODateTime;
156
+ }, z.core.$strip>;
157
+ /** Per-exec request body. `argv` is an array only — never a shell string. */
158
+ export declare const cliExecInputSchema: z.ZodObject<{
159
+ argv: z.ZodArray<z.ZodString>;
160
+ stdin: z.ZodOptional<z.ZodNullable<z.ZodString>>;
161
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
162
+ maxOutputBytes: z.ZodOptional<z.ZodNumber>;
163
+ }, z.core.$strip>;
164
+ export type CliAllowRule = z.infer<typeof cliAllowRuleSchema>;
165
+ export type CliAllowList = z.infer<typeof cliAllowListSchema>;
166
+ export type CliCredentialBindings = z.infer<typeof cliCredentialBindingsSchema>;
167
+ export type CliAuthStrategy = z.infer<typeof cliAuthStrategySchema>;
168
+ export type CliContainerVolume = z.infer<typeof cliRecordSchema>['containerVolumes'][number];
169
+ export type CliProbe = z.infer<typeof cliProbeSchema>;
170
+ export type CliRecord = z.infer<typeof cliRecordSchema>;
171
+ export type CreateCliInput = z.infer<typeof createCliInputSchema>;
172
+ export type UpdateCliInput = z.infer<typeof updateCliInputSchema>;
173
+ export type CliExecInput = z.infer<typeof cliExecInputSchema>;
174
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../../src/cli-plane/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;GAMG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,yBAAoC,CAAC;AAEpE,eAAO,MAAM,kBAAkB;;;iBAG7B,CAAC;AAEH,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AAGH,eAAO,MAAM,2BAA2B,qDAA+C,CAAC;AAOxF,eAAO,MAAM,qBAAqB;;;;GAA6C,CAAC;AAqBhF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;iBAgC/B,CAAC;AAEL,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmC7B,CAAC;AAEL,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqB/B,CAAC;AAEH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,aAAa,EAAE,MAAM,GAAG,QAAQ,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,yBAAyB,GAAG,oBAAoB,CAAC;IACxE,gBAAgB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC3E,GAAG,IAAI,CAEP;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoB1B,CAAC;AAEH,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB;;;;;iBAU7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAChF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAC7F,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}