@schoolai/shipyard 3.7.0 → 3.8.0-rc.20260529.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 (104) hide show
  1. package/dist/{auth-SS7LV5XK.js → auth-EXHO3AG5.js} +4 -4
  2. package/dist/capability-detector-worker.js +142 -0
  3. package/dist/capability-detector-worker.js.map +1 -0
  4. package/dist/{chunk-DKMDBOFU.js → chunk-2CNIEBKO.js} +21 -11
  5. package/dist/chunk-2CNIEBKO.js.map +1 -0
  6. package/dist/chunk-4T2OQAVL.js +51 -0
  7. package/dist/chunk-4T2OQAVL.js.map +1 -0
  8. package/dist/chunk-5ER6ZHA2.js +46 -0
  9. package/dist/chunk-5ER6ZHA2.js.map +1 -0
  10. package/dist/chunk-7LSEE26O.js +24227 -0
  11. package/dist/chunk-7LSEE26O.js.map +1 -0
  12. package/dist/{chunk-7AHRFPAL.js → chunk-7YOU7MBN.js} +183 -17
  13. package/dist/chunk-7YOU7MBN.js.map +1 -0
  14. package/dist/chunk-CMGJGK6R.js +382 -0
  15. package/dist/chunk-CMGJGK6R.js.map +1 -0
  16. package/dist/{chunk-VPMN47TL.js → chunk-CNR7O5YH.js} +1 -2
  17. package/dist/{chunk-2J3WSIAF.js → chunk-EF2DAODF.js} +18 -3
  18. package/dist/chunk-EF2DAODF.js.map +1 -0
  19. package/dist/chunk-HQ43PHOH.js +1203 -0
  20. package/dist/chunk-HQ43PHOH.js.map +1 -0
  21. package/dist/chunk-KITSAHTX.js +134 -0
  22. package/dist/chunk-KITSAHTX.js.map +1 -0
  23. package/dist/chunk-LESHN5J5.js +6898 -0
  24. package/dist/chunk-LESHN5J5.js.map +1 -0
  25. package/dist/{chunk-LW2MS4T5.js → chunk-LMJFHKRD.js} +15 -12
  26. package/dist/chunk-LMJFHKRD.js.map +1 -0
  27. package/dist/{chunk-SNYEQHUK.js → chunk-NACJENDW.js} +14 -21
  28. package/dist/chunk-NACJENDW.js.map +1 -0
  29. package/dist/{chunk-IISLTKYY.js → chunk-TU63KZFW.js} +2 -2
  30. package/dist/chunk-TX6DK4PK.js +186 -0
  31. package/dist/chunk-TX6DK4PK.js.map +1 -0
  32. package/dist/chunk-UQVXWOPT.js +48 -0
  33. package/dist/chunk-UQVXWOPT.js.map +1 -0
  34. package/dist/{chunk-3MNPDCO5.js → chunk-WBB4XHLH.js} +139 -140
  35. package/dist/chunk-WBB4XHLH.js.map +1 -0
  36. package/dist/chunk-X3MULCV5.js +11 -0
  37. package/dist/chunk-X3MULCV5.js.map +1 -0
  38. package/dist/chunk-YZ3Z3ZYI.js +787 -0
  39. package/dist/chunk-YZ3Z3ZYI.js.map +1 -0
  40. package/dist/{chunk-2UN5AR7V.js → chunk-ZAOPND5G.js} +2 -2
  41. package/dist/chunk-ZFKJAYAN.js +542 -0
  42. package/dist/chunk-ZFKJAYAN.js.map +1 -0
  43. package/dist/cursor-hook-shim.js +316 -0
  44. package/dist/cursor-hook-shim.js.map +1 -0
  45. package/dist/cursor-runner.js +358 -0
  46. package/dist/cursor-runner.js.map +1 -0
  47. package/dist/electron-utility.js +111 -0
  48. package/dist/electron-utility.js.map +1 -0
  49. package/dist/git-pool-V73Q53NX.js +18 -0
  50. package/dist/{git-repo-VRT57DGC.js → git-repo-TN3VZXQV.js} +9 -6
  51. package/dist/index.js +12 -12
  52. package/dist/index.js.map +1 -1
  53. package/dist/{logger-GQCSLSZH.js → logger-QHPTO22N.js} +4 -4
  54. package/dist/login-Q7SZI7JJ.js +20 -0
  55. package/dist/{logout-VUNCW5B2.js → logout-O4AVMO5S.js} +6 -6
  56. package/dist/mcp-servers-F64M5T4I.js +24 -0
  57. package/dist/{roi-Y3MX5UW4.js → roi-EYDLPOCS.js} +5 -5
  58. package/dist/rss-worker.js +159 -0
  59. package/dist/rss-worker.js.map +1 -0
  60. package/dist/{serve-O53FNK64.js → serve-6A7RJWEF.js} +89862 -102999
  61. package/dist/{serve-O53FNK64.js.map → serve-6A7RJWEF.js.map} +1 -1
  62. package/dist/skills-ZHEPSBHW.js +11 -0
  63. package/dist/{start-IDFDHRD6.js → start-YGYYIK53.js} +229 -27
  64. package/dist/start-YGYYIK53.js.map +1 -0
  65. package/dist/vault-crypto-BKDOA65F.js +13 -0
  66. package/dist/vault-crypto-BKDOA65F.js.map +1 -0
  67. package/dist/worker.js +6 -3
  68. package/dist/worker.js.map +1 -1
  69. package/package.json +17 -10
  70. package/dist/chunk-2J3WSIAF.js.map +0 -1
  71. package/dist/chunk-3MNPDCO5.js.map +0 -1
  72. package/dist/chunk-66OBOZ3X.js +0 -79
  73. package/dist/chunk-66OBOZ3X.js.map +0 -1
  74. package/dist/chunk-7AHRFPAL.js.map +0 -1
  75. package/dist/chunk-DKMDBOFU.js.map +0 -1
  76. package/dist/chunk-L2WQMPWS.js +0 -666
  77. package/dist/chunk-L2WQMPWS.js.map +0 -1
  78. package/dist/chunk-LW2MS4T5.js.map +0 -1
  79. package/dist/chunk-PI77CUEP.js +0 -49
  80. package/dist/chunk-PI77CUEP.js.map +0 -1
  81. package/dist/chunk-RXI4637N.js +0 -395
  82. package/dist/chunk-RXI4637N.js.map +0 -1
  83. package/dist/chunk-SNYEQHUK.js.map +0 -1
  84. package/dist/chunk-VBPHGPBR.js +0 -126
  85. package/dist/chunk-VBPHGPBR.js.map +0 -1
  86. package/dist/index.d.ts +0 -2
  87. package/dist/login-L4BBPUYO.js +0 -20
  88. package/dist/mcp-servers-MXS5VAWI.js +0 -18
  89. package/dist/shell-V36EX2IJ.js +0 -27
  90. package/dist/skills-GPGRNV4R.js +0 -9
  91. package/dist/start-IDFDHRD6.js.map +0 -1
  92. package/dist/worker.d.ts +0 -49
  93. /package/dist/{auth-SS7LV5XK.js.map → auth-EXHO3AG5.js.map} +0 -0
  94. /package/dist/{chunk-VPMN47TL.js.map → chunk-CNR7O5YH.js.map} +0 -0
  95. /package/dist/{chunk-IISLTKYY.js.map → chunk-TU63KZFW.js.map} +0 -0
  96. /package/dist/{chunk-2UN5AR7V.js.map → chunk-ZAOPND5G.js.map} +0 -0
  97. /package/dist/{git-repo-VRT57DGC.js.map → git-pool-V73Q53NX.js.map} +0 -0
  98. /package/dist/{logger-GQCSLSZH.js.map → git-repo-TN3VZXQV.js.map} +0 -0
  99. /package/dist/{login-L4BBPUYO.js.map → logger-QHPTO22N.js.map} +0 -0
  100. /package/dist/{mcp-servers-MXS5VAWI.js.map → login-Q7SZI7JJ.js.map} +0 -0
  101. /package/dist/{logout-VUNCW5B2.js.map → logout-O4AVMO5S.js.map} +0 -0
  102. /package/dist/{shell-V36EX2IJ.js.map → mcp-servers-F64M5T4I.js.map} +0 -0
  103. /package/dist/{roi-Y3MX5UW4.js.map → roi-EYDLPOCS.js.map} +0 -0
  104. /package/dist/{skills-GPGRNV4R.js.map → skills-ZHEPSBHW.js.map} +0 -0
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cursor-hook-shim/index.ts
4
+ import { createHmac, randomUUID } from "crypto";
5
+ import { readFileSync } from "fs";
6
+ import net from "net";
7
+ var DEFAULT_TIMEOUT_MS = 55e3;
8
+ function applyArg(flag, value, result) {
9
+ switch (flag) {
10
+ case "--task-id":
11
+ if (value === void 0) return { error: `missing value for ${flag}` };
12
+ result.taskId = value;
13
+ return null;
14
+ case "--socket-path":
15
+ if (value === void 0) return { error: `missing value for ${flag}` };
16
+ result.socketPath = value;
17
+ return null;
18
+ case "--hmac-keyfile":
19
+ if (value === void 0) return { error: `missing value for ${flag}` };
20
+ result.hmacKeyfile = value;
21
+ return null;
22
+ case "--policy":
23
+ return applyPolicy(value, result);
24
+ case "--timeout-ms":
25
+ return applyTimeoutMs(value, result);
26
+ case "--auto-allow-list":
27
+ if (value === void 0) return { error: `missing value for ${flag}` };
28
+ result.autoAllowList = value.split(",").filter((s) => s.length > 0);
29
+ return null;
30
+ default:
31
+ return null;
32
+ }
33
+ }
34
+ function applyPolicy(value, result) {
35
+ if (value === void 0) return { error: "missing value for --policy" };
36
+ if (value !== "prompt" && value !== "allow" && value !== "deny") {
37
+ return { error: `invalid --policy: ${value}` };
38
+ }
39
+ result.policy = value;
40
+ return null;
41
+ }
42
+ function applyTimeoutMs(value, result) {
43
+ if (value === void 0) return { error: "missing value for --timeout-ms" };
44
+ const n = Number.parseInt(value, 10);
45
+ if (!Number.isFinite(n) || n <= 0) return { error: `invalid --timeout-ms: ${value}` };
46
+ result.timeoutMs = n;
47
+ return null;
48
+ }
49
+ var FLAG_TAKES_VALUE = /* @__PURE__ */ new Set([
50
+ "--task-id",
51
+ "--socket-path",
52
+ "--hmac-keyfile",
53
+ "--policy",
54
+ "--timeout-ms",
55
+ "--auto-allow-list"
56
+ ]);
57
+ function parseArgv(argv) {
58
+ const result = {
59
+ timeoutMs: DEFAULT_TIMEOUT_MS,
60
+ autoAllowList: []
61
+ };
62
+ for (let i = 0; i < argv.length; i++) {
63
+ const flag = argv[i];
64
+ if (flag === void 0) continue;
65
+ const value = argv[i + 1];
66
+ const err = applyArg(flag, value, result);
67
+ if (err !== null) return err;
68
+ if (FLAG_TAKES_VALUE.has(flag)) i++;
69
+ }
70
+ return finalizeArgv(result);
71
+ }
72
+ function finalizeArgv(result) {
73
+ const policy = result.policy;
74
+ if (policy === void 0) return { error: "missing --policy" };
75
+ if (policy === "prompt") {
76
+ if (result.taskId === void 0) return { error: "missing --task-id" };
77
+ if (result.socketPath === void 0) return { error: "missing --socket-path" };
78
+ if (result.hmacKeyfile === void 0) return { error: "missing --hmac-keyfile" };
79
+ }
80
+ return {
81
+ taskId: result.taskId ?? "",
82
+ socketPath: result.socketPath ?? "",
83
+ hmacKeyfile: result.hmacKeyfile ?? "",
84
+ policy,
85
+ timeoutMs: result.timeoutMs ?? DEFAULT_TIMEOUT_MS,
86
+ autoAllowList: result.autoAllowList ?? []
87
+ };
88
+ }
89
+ async function readAllStdin(maxWaitMs) {
90
+ return new Promise((resolve) => {
91
+ const chunks = [];
92
+ let settled = false;
93
+ const finalize = () => {
94
+ if (settled) return;
95
+ settled = true;
96
+ resolve(Buffer.concat(chunks).toString("utf8"));
97
+ };
98
+ const timer = setTimeout(finalize, maxWaitMs);
99
+ process.stdin.on("data", (chunk) => {
100
+ chunks.push(chunk);
101
+ });
102
+ process.stdin.on("end", () => {
103
+ clearTimeout(timer);
104
+ finalize();
105
+ });
106
+ process.stdin.on("error", () => {
107
+ clearTimeout(timer);
108
+ finalize();
109
+ });
110
+ });
111
+ }
112
+ function isHookInput(value) {
113
+ if (typeof value !== "object" || value === null) return false;
114
+ const hookEventName = Reflect.get(value, "hook_event_name");
115
+ if (hookEventName !== void 0 && typeof hookEventName !== "string") return false;
116
+ const toolName = Reflect.get(value, "tool_name");
117
+ if (toolName !== void 0 && typeof toolName !== "string") return false;
118
+ const requestId = Reflect.get(value, "request_id");
119
+ if (requestId !== void 0 && typeof requestId !== "string") return false;
120
+ return true;
121
+ }
122
+ async function readHookInput() {
123
+ const stdinBytes = await readAllStdin(150);
124
+ if (stdinBytes.length > 0) {
125
+ try {
126
+ const parsed = JSON.parse(stdinBytes);
127
+ if (isHookInput(parsed)) return parsed;
128
+ } catch {
129
+ }
130
+ }
131
+ const fromEnv = process.env.CURSOR_HOOK_INPUT;
132
+ if (fromEnv) {
133
+ try {
134
+ const parsed = JSON.parse(fromEnv);
135
+ if (isHookInput(parsed)) return parsed;
136
+ } catch {
137
+ }
138
+ }
139
+ return {};
140
+ }
141
+ function errnoCode(err) {
142
+ if (err !== null && typeof err === "object" && "code" in err) {
143
+ const code = Reflect.get(err, "code");
144
+ if (typeof code === "string") return code;
145
+ }
146
+ return "UNKNOWN";
147
+ }
148
+ function toHookOutput(value) {
149
+ if (typeof value !== "object" || value === null) return null;
150
+ const permission = Reflect.get(value, "permission");
151
+ if (permission !== "allow" && permission !== "deny" && permission !== "ask") {
152
+ return null;
153
+ }
154
+ const out = { permission };
155
+ const am = Reflect.get(value, "agent_message");
156
+ if (typeof am === "string") out.agent_message = am;
157
+ const um = Reflect.get(value, "user_message");
158
+ if (typeof um === "string") out.user_message = um;
159
+ const ui = Reflect.get(value, "updated_input");
160
+ if (typeof ui === "object" && ui !== null) {
161
+ const dest = {};
162
+ for (const k of Object.keys(ui)) {
163
+ dest[k] = Reflect.get(ui, k);
164
+ }
165
+ out.updated_input = dest;
166
+ }
167
+ return out;
168
+ }
169
+ function daemonRoundtrip(socketPath, framedRequest, timeoutMs) {
170
+ return new Promise((resolve) => {
171
+ let buf = "";
172
+ let settled = false;
173
+ const settle = (output) => {
174
+ if (settled) return;
175
+ settled = true;
176
+ resolve({ output });
177
+ };
178
+ const sock = net.connect(socketPath);
179
+ const timer = setTimeout(() => {
180
+ sock.destroy();
181
+ settle({
182
+ permission: "deny",
183
+ agent_message: "Permission request timed out before the user could respond.",
184
+ user_message: "Permission request timed out."
185
+ });
186
+ }, timeoutMs);
187
+ sock.on("connect", () => {
188
+ sock.write(framedRequest);
189
+ });
190
+ sock.on("error", (err) => {
191
+ clearTimeout(timer);
192
+ const code = errnoCode(err);
193
+ settle({
194
+ permission: "deny",
195
+ agent_message: `Could not reach Shipyard daemon (${code}). Refusing tool call.`,
196
+ user_message: `Shipyard daemon socket unreachable: ${code}.`
197
+ });
198
+ });
199
+ sock.on("data", (chunk) => {
200
+ buf += chunk.toString("utf8");
201
+ const newlineIdx = buf.indexOf("\n");
202
+ if (newlineIdx >= 0) {
203
+ clearTimeout(timer);
204
+ const line = buf.slice(0, newlineIdx).trim();
205
+ sock.destroy();
206
+ try {
207
+ const parsed = JSON.parse(line);
208
+ const reply = toHookOutput(parsed);
209
+ if (reply !== null) {
210
+ settle(reply);
211
+ return;
212
+ }
213
+ settle({
214
+ permission: "deny",
215
+ agent_message: "Malformed daemon response.",
216
+ user_message: "Internal error talking to Shipyard daemon."
217
+ });
218
+ } catch {
219
+ settle({
220
+ permission: "deny",
221
+ agent_message: "Malformed daemon response (not JSON).",
222
+ user_message: "Internal error talking to Shipyard daemon."
223
+ });
224
+ }
225
+ }
226
+ });
227
+ sock.on("end", () => {
228
+ if (settled) return;
229
+ clearTimeout(timer);
230
+ sock.destroy();
231
+ settle({
232
+ permission: "deny",
233
+ agent_message: "Shipyard daemon disconnected before responding.",
234
+ user_message: "Shipyard daemon disconnected."
235
+ });
236
+ });
237
+ });
238
+ }
239
+ function readKeyfile(path) {
240
+ try {
241
+ return readFileSync(path, "utf8").trim();
242
+ } catch {
243
+ return null;
244
+ }
245
+ }
246
+ function emit(output) {
247
+ process.stdout.write(`${JSON.stringify(output)}
248
+ `);
249
+ process.exit(0);
250
+ }
251
+ async function main() {
252
+ const parsedArgv = parseArgv(process.argv.slice(2));
253
+ if ("error" in parsedArgv) {
254
+ return emit({
255
+ permission: "deny",
256
+ agent_message: `Shipyard hook shim misconfigured: ${parsedArgv.error}`,
257
+ user_message: "Shipyard hook shim misconfigured \u2014 denying tool call."
258
+ });
259
+ }
260
+ if (parsedArgv.policy === "deny") {
261
+ return emit({
262
+ permission: "deny",
263
+ agent_message: "Plan mode active \u2014 file edits and shell commands are blocked.",
264
+ user_message: "Plan mode active."
265
+ });
266
+ }
267
+ if (parsedArgv.policy === "allow") {
268
+ return emit({
269
+ permission: "allow",
270
+ agent_message: "Bypass mode active \u2014 auto-approved."
271
+ });
272
+ }
273
+ const input = await readHookInput();
274
+ if (input.tool_name !== void 0 && parsedArgv.autoAllowList.includes(input.tool_name)) {
275
+ return emit({
276
+ permission: "allow",
277
+ agent_message: `Pre-approved (session) for ${input.tool_name}.`
278
+ });
279
+ }
280
+ const secret = readKeyfile(parsedArgv.hmacKeyfile);
281
+ if (secret === null) {
282
+ return emit({
283
+ permission: "deny",
284
+ agent_message: "Shipyard HMAC keyfile missing \u2014 refusing tool call.",
285
+ user_message: "Shipyard daemon configuration error."
286
+ });
287
+ }
288
+ const requestId = input.request_id ?? randomUUID();
289
+ const nonce = randomUUID();
290
+ const payload = JSON.stringify({
291
+ taskId: parsedArgv.taskId,
292
+ requestId,
293
+ nonce,
294
+ hookEvent: input.hook_event_name ?? "unknown",
295
+ toolName: input.tool_name ?? null,
296
+ toolInput: input.tool_input ?? null
297
+ });
298
+ const hmac = createHmac("sha256", secret).update(payload).digest("hex");
299
+ const framed = `${JSON.stringify({ payload, hmac })}
300
+ `;
301
+ const { output } = await daemonRoundtrip(parsedArgv.socketPath, framed, parsedArgv.timeoutMs);
302
+ return emit(output);
303
+ }
304
+ main().catch((err) => {
305
+ const detail = err instanceof Error ? err.message : String(err);
306
+ process.stdout.write(
307
+ `${JSON.stringify({
308
+ permission: "deny",
309
+ agent_message: `Shipyard hook shim error: ${detail}`,
310
+ user_message: "Shipyard hook shim error \u2014 denied."
311
+ })}
312
+ `
313
+ );
314
+ process.exit(0);
315
+ });
316
+ //# sourceMappingURL=cursor-hook-shim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cursor-hook-shim/index.ts"],"sourcesContent":["/**\n * Cursor Hook Shim — leaf binary the Cursor SDK invokes per tool call.\n *\n * Spawned by `cursor-agent` (the native binary inside `@cursor/sdk`) when\n * its `.cursor/hooks.json` matches a `preToolUse`/`beforeShellExecution`/\n * other configured event. The shim:\n *\n * 1. Parses argv for the policy bits (`--policy`, `--socket-path`, `--hmac-keyfile`, etc).\n * 2. Reads the SDK's hook input from stdin (preferred) or `CURSOR_HOOK_INPUT` env.\n * 3. Fast-paths for `--policy deny` / `--policy allow` / `--auto-allow-list`.\n * 4. Otherwise opens the daemon's per-task Unix socket, sends an HMAC-signed\n * request payload, blocks until the daemon writes a JSON reply.\n * 5. Prints the reply to stdout and exits 0.\n *\n * The Cursor SDK distinguishes \"exit 0 with JSON\" (gating decision) from\n * non-zero exits (hard-error). We ALWAYS exit 0 with a structured payload\n * so the user sees a meaningful deny message — never the generic SDK\n * \"hook exec failed\" surface.\n *\n * Trust posture: spawned by the Cursor SDK (in turn spawned by the\n * cursor-runner the daemon owns). Argv flows in at hook-config-write time\n * via `cursor-skill-writer.ts`. The HMAC keyfile lives in the same\n * task-scoped 0600 dir as the hooks.json. See `docs/cursor-implementation-specs/r2-permission-bridge.md` §6.3 for the threat model.\n *\n * The shim deliberately has zero daemon-internal imports — it is a leaf\n * binary, ~250 LOC. Bundled into `dist/cursor-hook-shim.js` by tsup as a\n * separate entry; chmod 755 in postbuild so the SDK can exec it directly.\n */\n\nimport { createHmac, randomUUID } from 'node:crypto';\nimport { readFileSync } from 'node:fs';\nimport net from 'node:net';\n\n/**\n * Hook output shape the Cursor SDK expects to read from the shim's stdout.\n * `permission: null` means \"fall through\" (the SDK runs the tool); we never\n * emit null in practice. `agent_message` is shown to the agent in the\n * tool-result envelope; `user_message` is shown to the user (e.g. in a\n * notification).\n */\ninterface HookOutput {\n permission: 'allow' | 'deny' | 'ask';\n agent_message?: string;\n user_message?: string;\n updated_input?: Record<string, unknown>;\n}\n\n/**\n * The SDK delivers hook input either via stdin (newline-terminated JSON) or\n * via `CURSOR_HOOK_INPUT` env. The shim prefers stdin and falls back to env.\n * The schema we care about is a subset of what the SDK actually sends.\n */\ninterface HookInput {\n hook_event_name?: string;\n tool_name?: string;\n tool_input?: unknown;\n request_id?: string;\n}\n\ninterface ParsedArgv {\n taskId: string;\n socketPath: string;\n hmacKeyfile: string;\n policy: 'prompt' | 'allow' | 'deny';\n timeoutMs: number;\n autoAllowList: string[];\n}\n\nconst DEFAULT_TIMEOUT_MS = 55_000;\n\n/**\n * Pure: parse a single flag/value pair onto the accumulator. Returns the\n * error result (truthy) when the value is invalid; returns null when\n * the flag was applied successfully or was an unknown flag. Extracting\n * each flag into its own branch keeps `parseArgv` under the cognitive\n * complexity budget.\n */\nfunction applyArg(\n flag: string,\n value: string | undefined,\n result: Partial<ParsedArgv>\n): { error: string } | null {\n switch (flag) {\n case '--task-id':\n if (value === undefined) return { error: `missing value for ${flag}` };\n result.taskId = value;\n return null;\n case '--socket-path':\n if (value === undefined) return { error: `missing value for ${flag}` };\n result.socketPath = value;\n return null;\n case '--hmac-keyfile':\n if (value === undefined) return { error: `missing value for ${flag}` };\n result.hmacKeyfile = value;\n return null;\n case '--policy':\n return applyPolicy(value, result);\n case '--timeout-ms':\n return applyTimeoutMs(value, result);\n case '--auto-allow-list':\n if (value === undefined) return { error: `missing value for ${flag}` };\n result.autoAllowList = value.split(',').filter((s) => s.length > 0);\n return null;\n default:\n /** Forward-compat: ignore unknown flags so a future hooks.json with new flags works on old shims. */\n return null;\n }\n}\n\nfunction applyPolicy(\n value: string | undefined,\n result: Partial<ParsedArgv>\n): { error: string } | null {\n if (value === undefined) return { error: 'missing value for --policy' };\n if (value !== 'prompt' && value !== 'allow' && value !== 'deny') {\n return { error: `invalid --policy: ${value}` };\n }\n result.policy = value;\n return null;\n}\n\nfunction applyTimeoutMs(\n value: string | undefined,\n result: Partial<ParsedArgv>\n): { error: string } | null {\n if (value === undefined) return { error: 'missing value for --timeout-ms' };\n const n = Number.parseInt(value, 10);\n if (!Number.isFinite(n) || n <= 0) return { error: `invalid --timeout-ms: ${value}` };\n result.timeoutMs = n;\n return null;\n}\n\n/** Flags that take a value advance the loop index by two. */\nconst FLAG_TAKES_VALUE = new Set([\n '--task-id',\n '--socket-path',\n '--hmac-keyfile',\n '--policy',\n '--timeout-ms',\n '--auto-allow-list',\n]);\n\nfunction parseArgv(argv: readonly string[]): ParsedArgv | { error: string } {\n const result: Partial<ParsedArgv> = {\n timeoutMs: DEFAULT_TIMEOUT_MS,\n autoAllowList: [],\n };\n for (let i = 0; i < argv.length; i++) {\n const flag = argv[i];\n if (flag === undefined) continue;\n const value = argv[i + 1];\n const err = applyArg(flag, value, result);\n if (err !== null) return err;\n if (FLAG_TAKES_VALUE.has(flag)) i++;\n }\n return finalizeArgv(result);\n}\n\nfunction finalizeArgv(result: Partial<ParsedArgv>): ParsedArgv | { error: string } {\n const policy = result.policy;\n if (policy === undefined) return { error: 'missing --policy' };\n /**\n * `policy === 'prompt'` requires socket bits; the immediate-decision\n * policies (allow/deny) need none — we only spawn them in plan mode /\n * bypass and never round-trip through the daemon.\n */\n if (policy === 'prompt') {\n if (result.taskId === undefined) return { error: 'missing --task-id' };\n if (result.socketPath === undefined) return { error: 'missing --socket-path' };\n if (result.hmacKeyfile === undefined) return { error: 'missing --hmac-keyfile' };\n }\n return {\n taskId: result.taskId ?? '',\n socketPath: result.socketPath ?? '',\n hmacKeyfile: result.hmacKeyfile ?? '',\n policy,\n timeoutMs: result.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n autoAllowList: result.autoAllowList ?? [],\n };\n}\n\nasync function readAllStdin(maxWaitMs: number): Promise<string> {\n return new Promise((resolve) => {\n const chunks: Buffer[] = [];\n let settled = false;\n const finalize = (): void => {\n if (settled) return;\n settled = true;\n resolve(Buffer.concat(chunks).toString('utf8'));\n };\n /**\n * Cap how long we wait. The Cursor SDK delivers input synchronously\n * on stdin pre-spawn, so the bytes are already in the pipe buffer; if\n * they're not, falling back to env after the cap is correct.\n */\n const timer = setTimeout(finalize, maxWaitMs);\n process.stdin.on('data', (chunk: Buffer) => {\n chunks.push(chunk);\n });\n process.stdin.on('end', () => {\n clearTimeout(timer);\n finalize();\n });\n process.stdin.on('error', () => {\n clearTimeout(timer);\n finalize();\n });\n });\n}\n\n/** Pure: type guard for the HookInput JSON-from-stdin shape. */\nfunction isHookInput(value: unknown): value is HookInput {\n if (typeof value !== 'object' || value === null) return false;\n const hookEventName: unknown = Reflect.get(value, 'hook_event_name');\n if (hookEventName !== undefined && typeof hookEventName !== 'string') return false;\n const toolName: unknown = Reflect.get(value, 'tool_name');\n if (toolName !== undefined && typeof toolName !== 'string') return false;\n const requestId: unknown = Reflect.get(value, 'request_id');\n if (requestId !== undefined && typeof requestId !== 'string') return false;\n return true;\n}\n\nasync function readHookInput(): Promise<HookInput> {\n const stdinBytes = await readAllStdin(150);\n if (stdinBytes.length > 0) {\n try {\n const parsed: unknown = JSON.parse(stdinBytes);\n if (isHookInput(parsed)) return parsed;\n } catch {\n /** Fall through to env. */\n }\n }\n const fromEnv = process.env.CURSOR_HOOK_INPUT;\n if (fromEnv) {\n try {\n const parsed: unknown = JSON.parse(fromEnv);\n if (isHookInput(parsed)) return parsed;\n } catch {\n /** Fall through to empty. */\n }\n }\n return {};\n}\n\ninterface DaemonRoundtripResult {\n output: HookOutput;\n}\n\n/** Pure: extract the `code` field from an Error without a type assertion. */\nfunction errnoCode(err: unknown): string {\n if (err !== null && typeof err === 'object' && 'code' in err) {\n const code: unknown = Reflect.get(err, 'code');\n if (typeof code === 'string') return code;\n }\n return 'UNKNOWN';\n}\n\n/**\n * Pure: validate a parsed JSON value matches the HookOutput shape. Returns\n * the typed object or null if invalid. Avoids the `as HookOutput` assertion.\n */\nfunction toHookOutput(value: unknown): HookOutput | null {\n if (typeof value !== 'object' || value === null) return null;\n const permission: unknown = Reflect.get(value, 'permission');\n if (permission !== 'allow' && permission !== 'deny' && permission !== 'ask') {\n return null;\n }\n const out: HookOutput = { permission };\n const am: unknown = Reflect.get(value, 'agent_message');\n if (typeof am === 'string') out.agent_message = am;\n const um: unknown = Reflect.get(value, 'user_message');\n if (typeof um === 'string') out.user_message = um;\n const ui: unknown = Reflect.get(value, 'updated_input');\n if (typeof ui === 'object' && ui !== null) {\n /**\n * `updated_input` is forwarded verbatim to the SDK; build a fresh\n * Record from its enumerable own keys via Reflect to avoid an `as`.\n */\n const dest: Record<string, unknown> = {};\n for (const k of Object.keys(ui)) {\n dest[k] = Reflect.get(ui, k);\n }\n out.updated_input = dest;\n }\n return out;\n}\n\nfunction daemonRoundtrip(\n socketPath: string,\n framedRequest: string,\n timeoutMs: number\n): Promise<DaemonRoundtripResult> {\n return new Promise((resolve) => {\n let buf = '';\n let settled = false;\n const settle = (output: HookOutput): void => {\n if (settled) return;\n settled = true;\n resolve({ output });\n };\n const sock = net.connect(socketPath);\n const timer = setTimeout(() => {\n sock.destroy();\n settle({\n permission: 'deny',\n agent_message: 'Permission request timed out before the user could respond.',\n user_message: 'Permission request timed out.',\n });\n }, timeoutMs);\n sock.on('connect', () => {\n sock.write(framedRequest);\n });\n sock.on('error', (err) => {\n clearTimeout(timer);\n const code = errnoCode(err);\n settle({\n permission: 'deny',\n agent_message: `Could not reach Shipyard daemon (${code}). Refusing tool call.`,\n user_message: `Shipyard daemon socket unreachable: ${code}.`,\n });\n });\n sock.on('data', (chunk: Buffer) => {\n buf += chunk.toString('utf8');\n const newlineIdx = buf.indexOf('\\n');\n if (newlineIdx >= 0) {\n clearTimeout(timer);\n const line = buf.slice(0, newlineIdx).trim();\n sock.destroy();\n try {\n const parsed: unknown = JSON.parse(line);\n const reply = toHookOutput(parsed);\n if (reply !== null) {\n settle(reply);\n return;\n }\n settle({\n permission: 'deny',\n agent_message: 'Malformed daemon response.',\n user_message: 'Internal error talking to Shipyard daemon.',\n });\n } catch {\n settle({\n permission: 'deny',\n agent_message: 'Malformed daemon response (not JSON).',\n user_message: 'Internal error talking to Shipyard daemon.',\n });\n }\n }\n });\n sock.on('end', () => {\n if (settled) return;\n clearTimeout(timer);\n sock.destroy();\n settle({\n permission: 'deny',\n agent_message: 'Shipyard daemon disconnected before responding.',\n user_message: 'Shipyard daemon disconnected.',\n });\n });\n });\n}\n\nfunction readKeyfile(path: string): string | null {\n try {\n return readFileSync(path, 'utf8').trim();\n } catch {\n return null;\n }\n}\n\nfunction emit(output: HookOutput): never {\n process.stdout.write(`${JSON.stringify(output)}\\n`);\n process.exit(0);\n}\n\nasync function main(): Promise<never> {\n const parsedArgv = parseArgv(process.argv.slice(2));\n if ('error' in parsedArgv) {\n return emit({\n permission: 'deny',\n agent_message: `Shipyard hook shim misconfigured: ${parsedArgv.error}`,\n user_message: 'Shipyard hook shim misconfigured — denying tool call.',\n });\n }\n\n if (parsedArgv.policy === 'deny') {\n return emit({\n permission: 'deny',\n agent_message: 'Plan mode active — file edits and shell commands are blocked.',\n user_message: 'Plan mode active.',\n });\n }\n if (parsedArgv.policy === 'allow') {\n return emit({\n permission: 'allow',\n agent_message: 'Bypass mode active — auto-approved.',\n });\n }\n\n const input = await readHookInput();\n\n if (input.tool_name !== undefined && parsedArgv.autoAllowList.includes(input.tool_name)) {\n return emit({\n permission: 'allow',\n agent_message: `Pre-approved (session) for ${input.tool_name}.`,\n });\n }\n\n const secret = readKeyfile(parsedArgv.hmacKeyfile);\n if (secret === null) {\n return emit({\n permission: 'deny',\n agent_message: 'Shipyard HMAC keyfile missing — refusing tool call.',\n user_message: 'Shipyard daemon configuration error.',\n });\n }\n\n /**\n * `request_id` correlates the SDK breadcrumb with the daemon-side\n * pending entry. If the SDK didn't send one (older variants), mint a\n * UUID so the daemon can still key its pending map; correlation back\n * to the SDK turn is best-effort.\n */\n const requestId = input.request_id ?? randomUUID();\n const nonce = randomUUID();\n\n const payload = JSON.stringify({\n taskId: parsedArgv.taskId,\n requestId,\n nonce,\n hookEvent: input.hook_event_name ?? 'unknown',\n toolName: input.tool_name ?? null,\n toolInput: input.tool_input ?? null,\n });\n const hmac = createHmac('sha256', secret).update(payload).digest('hex');\n\n const framed = `${JSON.stringify({ payload, hmac })}\\n`;\n const { output } = await daemonRoundtrip(parsedArgv.socketPath, framed, parsedArgv.timeoutMs);\n return emit(output);\n}\n\nmain().catch((err: unknown) => {\n /** Any uncaught path = deny. Safer default. */\n const detail = err instanceof Error ? err.message : String(err);\n process.stdout.write(\n `${JSON.stringify({\n permission: 'deny',\n agent_message: `Shipyard hook shim error: ${detail}`,\n user_message: 'Shipyard hook shim error — denied.',\n })}\\n`\n );\n process.exit(0);\n});\n"],"mappings":";;;AA6BA,SAAS,YAAY,kBAAkB;AACvC,SAAS,oBAAoB;AAC7B,OAAO,SAAS;AAqChB,IAAM,qBAAqB;AAS3B,SAAS,SACP,MACA,OACA,QAC0B;AAC1B,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,UAAI,UAAU,OAAW,QAAO,EAAE,OAAO,qBAAqB,IAAI,GAAG;AACrE,aAAO,SAAS;AAChB,aAAO;AAAA,IACT,KAAK;AACH,UAAI,UAAU,OAAW,QAAO,EAAE,OAAO,qBAAqB,IAAI,GAAG;AACrE,aAAO,aAAa;AACpB,aAAO;AAAA,IACT,KAAK;AACH,UAAI,UAAU,OAAW,QAAO,EAAE,OAAO,qBAAqB,IAAI,GAAG;AACrE,aAAO,cAAc;AACrB,aAAO;AAAA,IACT,KAAK;AACH,aAAO,YAAY,OAAO,MAAM;AAAA,IAClC,KAAK;AACH,aAAO,eAAe,OAAO,MAAM;AAAA,IACrC,KAAK;AACH,UAAI,UAAU,OAAW,QAAO,EAAE,OAAO,qBAAqB,IAAI,GAAG;AACrE,aAAO,gBAAgB,MAAM,MAAM,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAClE,aAAO;AAAA,IACT;AAEE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,YACP,OACA,QAC0B;AAC1B,MAAI,UAAU,OAAW,QAAO,EAAE,OAAO,6BAA6B;AACtE,MAAI,UAAU,YAAY,UAAU,WAAW,UAAU,QAAQ;AAC/D,WAAO,EAAE,OAAO,qBAAqB,KAAK,GAAG;AAAA,EAC/C;AACA,SAAO,SAAS;AAChB,SAAO;AACT;AAEA,SAAS,eACP,OACA,QAC0B;AAC1B,MAAI,UAAU,OAAW,QAAO,EAAE,OAAO,iCAAiC;AAC1E,QAAM,IAAI,OAAO,SAAS,OAAO,EAAE;AACnC,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,QAAO,EAAE,OAAO,yBAAyB,KAAK,GAAG;AACpF,SAAO,YAAY;AACnB,SAAO;AACT;AAGA,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,UAAU,MAAyD;AAC1E,QAAM,SAA8B;AAAA,IAClC,WAAW;AAAA,IACX,eAAe,CAAC;AAAA,EAClB;AACA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,OAAO,KAAK,CAAC;AACnB,QAAI,SAAS,OAAW;AACxB,UAAM,QAAQ,KAAK,IAAI,CAAC;AACxB,UAAM,MAAM,SAAS,MAAM,OAAO,MAAM;AACxC,QAAI,QAAQ,KAAM,QAAO;AACzB,QAAI,iBAAiB,IAAI,IAAI,EAAG;AAAA,EAClC;AACA,SAAO,aAAa,MAAM;AAC5B;AAEA,SAAS,aAAa,QAA6D;AACjF,QAAM,SAAS,OAAO;AACtB,MAAI,WAAW,OAAW,QAAO,EAAE,OAAO,mBAAmB;AAM7D,MAAI,WAAW,UAAU;AACvB,QAAI,OAAO,WAAW,OAAW,QAAO,EAAE,OAAO,oBAAoB;AACrE,QAAI,OAAO,eAAe,OAAW,QAAO,EAAE,OAAO,wBAAwB;AAC7E,QAAI,OAAO,gBAAgB,OAAW,QAAO,EAAE,OAAO,yBAAyB;AAAA,EACjF;AACA,SAAO;AAAA,IACL,QAAQ,OAAO,UAAU;AAAA,IACzB,YAAY,OAAO,cAAc;AAAA,IACjC,aAAa,OAAO,eAAe;AAAA,IACnC;AAAA,IACA,WAAW,OAAO,aAAa;AAAA,IAC/B,eAAe,OAAO,iBAAiB,CAAC;AAAA,EAC1C;AACF;AAEA,eAAe,aAAa,WAAoC;AAC9D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,SAAmB,CAAC;AAC1B,QAAI,UAAU;AACd,UAAM,WAAW,MAAY;AAC3B,UAAI,QAAS;AACb,gBAAU;AACV,cAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,CAAC;AAAA,IAChD;AAMA,UAAM,QAAQ,WAAW,UAAU,SAAS;AAC5C,YAAQ,MAAM,GAAG,QAAQ,CAAC,UAAkB;AAC1C,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,YAAQ,MAAM,GAAG,OAAO,MAAM;AAC5B,mBAAa,KAAK;AAClB,eAAS;AAAA,IACX,CAAC;AACD,YAAQ,MAAM,GAAG,SAAS,MAAM;AAC9B,mBAAa,KAAK;AAClB,eAAS;AAAA,IACX,CAAC;AAAA,EACH,CAAC;AACH;AAGA,SAAS,YAAY,OAAoC;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,gBAAyB,QAAQ,IAAI,OAAO,iBAAiB;AACnE,MAAI,kBAAkB,UAAa,OAAO,kBAAkB,SAAU,QAAO;AAC7E,QAAM,WAAoB,QAAQ,IAAI,OAAO,WAAW;AACxD,MAAI,aAAa,UAAa,OAAO,aAAa,SAAU,QAAO;AACnE,QAAM,YAAqB,QAAQ,IAAI,OAAO,YAAY;AAC1D,MAAI,cAAc,UAAa,OAAO,cAAc,SAAU,QAAO;AACrE,SAAO;AACT;AAEA,eAAe,gBAAoC;AACjD,QAAM,aAAa,MAAM,aAAa,GAAG;AACzC,MAAI,WAAW,SAAS,GAAG;AACzB,QAAI;AACF,YAAM,SAAkB,KAAK,MAAM,UAAU;AAC7C,UAAI,YAAY,MAAM,EAAG,QAAO;AAAA,IAClC,QAAQ;AAAA,IAER;AAAA,EACF;AACA,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,SAAS;AACX,QAAI;AACF,YAAM,SAAkB,KAAK,MAAM,OAAO;AAC1C,UAAI,YAAY,MAAM,EAAG,QAAO;AAAA,IAClC,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO,CAAC;AACV;AAOA,SAAS,UAAU,KAAsB;AACvC,MAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,UAAU,KAAK;AAC5D,UAAM,OAAgB,QAAQ,IAAI,KAAK,MAAM;AAC7C,QAAI,OAAO,SAAS,SAAU,QAAO;AAAA,EACvC;AACA,SAAO;AACT;AAMA,SAAS,aAAa,OAAmC;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,aAAsB,QAAQ,IAAI,OAAO,YAAY;AAC3D,MAAI,eAAe,WAAW,eAAe,UAAU,eAAe,OAAO;AAC3E,WAAO;AAAA,EACT;AACA,QAAM,MAAkB,EAAE,WAAW;AACrC,QAAM,KAAc,QAAQ,IAAI,OAAO,eAAe;AACtD,MAAI,OAAO,OAAO,SAAU,KAAI,gBAAgB;AAChD,QAAM,KAAc,QAAQ,IAAI,OAAO,cAAc;AACrD,MAAI,OAAO,OAAO,SAAU,KAAI,eAAe;AAC/C,QAAM,KAAc,QAAQ,IAAI,OAAO,eAAe;AACtD,MAAI,OAAO,OAAO,YAAY,OAAO,MAAM;AAKzC,UAAM,OAAgC,CAAC;AACvC,eAAW,KAAK,OAAO,KAAK,EAAE,GAAG;AAC/B,WAAK,CAAC,IAAI,QAAQ,IAAI,IAAI,CAAC;AAAA,IAC7B;AACA,QAAI,gBAAgB;AAAA,EACtB;AACA,SAAO;AACT;AAEA,SAAS,gBACP,YACA,eACA,WACgC;AAChC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,MAAM;AACV,QAAI,UAAU;AACd,UAAM,SAAS,CAAC,WAA6B;AAC3C,UAAI,QAAS;AACb,gBAAU;AACV,cAAQ,EAAE,OAAO,CAAC;AAAA,IACpB;AACA,UAAM,OAAO,IAAI,QAAQ,UAAU;AACnC,UAAM,QAAQ,WAAW,MAAM;AAC7B,WAAK,QAAQ;AACb,aAAO;AAAA,QACL,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,cAAc;AAAA,MAChB,CAAC;AAAA,IACH,GAAG,SAAS;AACZ,SAAK,GAAG,WAAW,MAAM;AACvB,WAAK,MAAM,aAAa;AAAA,IAC1B,CAAC;AACD,SAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,mBAAa,KAAK;AAClB,YAAM,OAAO,UAAU,GAAG;AAC1B,aAAO;AAAA,QACL,YAAY;AAAA,QACZ,eAAe,oCAAoC,IAAI;AAAA,QACvD,cAAc,uCAAuC,IAAI;AAAA,MAC3D,CAAC;AAAA,IACH,CAAC;AACD,SAAK,GAAG,QAAQ,CAAC,UAAkB;AACjC,aAAO,MAAM,SAAS,MAAM;AAC5B,YAAM,aAAa,IAAI,QAAQ,IAAI;AACnC,UAAI,cAAc,GAAG;AACnB,qBAAa,KAAK;AAClB,cAAM,OAAO,IAAI,MAAM,GAAG,UAAU,EAAE,KAAK;AAC3C,aAAK,QAAQ;AACb,YAAI;AACF,gBAAM,SAAkB,KAAK,MAAM,IAAI;AACvC,gBAAM,QAAQ,aAAa,MAAM;AACjC,cAAI,UAAU,MAAM;AAClB,mBAAO,KAAK;AACZ;AAAA,UACF;AACA,iBAAO;AAAA,YACL,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,cAAc;AAAA,UAChB,CAAC;AAAA,QACH,QAAQ;AACN,iBAAO;AAAA,YACL,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,cAAc;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AACD,SAAK,GAAG,OAAO,MAAM;AACnB,UAAI,QAAS;AACb,mBAAa,KAAK;AAClB,WAAK,QAAQ;AACb,aAAO;AAAA,QACL,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,cAAc;AAAA,MAChB,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,YAAY,MAA6B;AAChD,MAAI;AACF,WAAO,aAAa,MAAM,MAAM,EAAE,KAAK;AAAA,EACzC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,KAAK,QAA2B;AACvC,UAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,CAAC;AAAA,CAAI;AAClD,UAAQ,KAAK,CAAC;AAChB;AAEA,eAAe,OAAuB;AACpC,QAAM,aAAa,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAClD,MAAI,WAAW,YAAY;AACzB,WAAO,KAAK;AAAA,MACV,YAAY;AAAA,MACZ,eAAe,qCAAqC,WAAW,KAAK;AAAA,MACpE,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,MAAI,WAAW,WAAW,QAAQ;AAChC,WAAO,KAAK;AAAA,MACV,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AACA,MAAI,WAAW,WAAW,SAAS;AACjC,WAAO,KAAK;AAAA,MACV,YAAY;AAAA,MACZ,eAAe;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ,MAAM,cAAc;AAElC,MAAI,MAAM,cAAc,UAAa,WAAW,cAAc,SAAS,MAAM,SAAS,GAAG;AACvF,WAAO,KAAK;AAAA,MACV,YAAY;AAAA,MACZ,eAAe,8BAA8B,MAAM,SAAS;AAAA,IAC9D,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,YAAY,WAAW,WAAW;AACjD,MAAI,WAAW,MAAM;AACnB,WAAO,KAAK;AAAA,MACV,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAQA,QAAM,YAAY,MAAM,cAAc,WAAW;AACjD,QAAM,QAAQ,WAAW;AAEzB,QAAM,UAAU,KAAK,UAAU;AAAA,IAC7B,QAAQ,WAAW;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW,MAAM,mBAAmB;AAAA,IACpC,UAAU,MAAM,aAAa;AAAA,IAC7B,WAAW,MAAM,cAAc;AAAA,EACjC,CAAC;AACD,QAAM,OAAO,WAAW,UAAU,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAEtE,QAAM,SAAS,GAAG,KAAK,UAAU,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA;AACnD,QAAM,EAAE,OAAO,IAAI,MAAM,gBAAgB,WAAW,YAAY,QAAQ,WAAW,SAAS;AAC5F,SAAO,KAAK,MAAM;AACpB;AAEA,KAAK,EAAE,MAAM,CAAC,QAAiB;AAE7B,QAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,UAAQ,OAAO;AAAA,IACb,GAAG,KAAK,UAAU;AAAA,MAChB,YAAY;AAAA,MACZ,eAAe,6BAA6B,MAAM;AAAA,MAClD,cAAc;AAAA,IAChB,CAAC,CAAC;AAAA;AAAA,EACJ;AACA,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}