@_davideast/stitch-mcp 0.5.5 → 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.
Files changed (168) hide show
  1. package/dist/chunk-0xbbvsve.js +370 -0
  2. package/dist/chunk-0xbbvsve.js.map +16 -0
  3. package/dist/chunk-11ab03kg.js +137 -0
  4. package/dist/chunk-11ab03kg.js.map +10 -0
  5. package/dist/chunk-17cs61t4.js +270 -0
  6. package/dist/chunk-17cs61t4.js.map +10 -0
  7. package/dist/chunk-1mz7188j.js +20 -0
  8. package/dist/chunk-1mz7188j.js.map +9 -0
  9. package/dist/chunk-1txb8kjb.js +17 -0
  10. package/dist/chunk-1txb8kjb.js.map +9 -0
  11. package/dist/chunk-1v5q6d3n.js +17 -0
  12. package/dist/chunk-1v5q6d3n.js.map +9 -0
  13. package/dist/chunk-1wcg0pjg.js +94 -0
  14. package/dist/chunk-1wcg0pjg.js.map +10 -0
  15. package/dist/chunk-2zp03jky.js +19 -0
  16. package/dist/chunk-2zp03jky.js.map +9 -0
  17. package/dist/chunk-441ntz7a.js +137 -0
  18. package/dist/chunk-441ntz7a.js.map +10 -0
  19. package/dist/chunk-543135qd.js +43679 -0
  20. package/dist/chunk-543135qd.js.map +234 -0
  21. package/dist/chunk-564wpgj7.js +246 -0
  22. package/dist/chunk-564wpgj7.js.map +14 -0
  23. package/dist/chunk-5jbenaez.js +19185 -0
  24. package/dist/chunk-5jbenaez.js.map +115 -0
  25. package/dist/chunk-633ma50k.js +371 -0
  26. package/dist/chunk-633ma50k.js.map +16 -0
  27. package/dist/chunk-7ryqstaa.js +7065 -0
  28. package/dist/chunk-7ryqstaa.js.map +115 -0
  29. package/dist/chunk-7z5z40ar.js +165 -0
  30. package/dist/chunk-7z5z40ar.js.map +10 -0
  31. package/dist/chunk-86gwwcyr.js +46325 -0
  32. package/dist/chunk-86gwwcyr.js.map +261 -0
  33. package/dist/chunk-8gegrmmt.js +256 -0
  34. package/dist/chunk-8gegrmmt.js.map +11 -0
  35. package/dist/chunk-8hgrrc49.js +17 -0
  36. package/dist/chunk-8hgrrc49.js.map +9 -0
  37. package/dist/chunk-8w97w2wa.js +50 -0
  38. package/dist/chunk-8w97w2wa.js.map +9 -0
  39. package/dist/chunk-8yfetpqq.js +19132 -0
  40. package/dist/chunk-8yfetpqq.js.map +115 -0
  41. package/dist/chunk-94knm2sw.js +1495 -0
  42. package/dist/chunk-94knm2sw.js.map +23 -0
  43. package/dist/chunk-9ckyz47q.js +518 -0
  44. package/dist/chunk-9ckyz47q.js.map +12 -0
  45. package/dist/chunk-appd0sxm.js +5217 -0
  46. package/dist/chunk-appd0sxm.js.map +67 -0
  47. package/dist/chunk-b9atzag0.js +67 -0
  48. package/dist/chunk-b9atzag0.js.map +10 -0
  49. package/dist/chunk-c08qy4ty.js +67 -0
  50. package/dist/chunk-c08qy4ty.js.map +10 -0
  51. package/dist/chunk-c5dtqvff.js +11 -0
  52. package/dist/chunk-c5dtqvff.js.map +9 -0
  53. package/dist/chunk-d1ea3tmp.js +17 -0
  54. package/dist/chunk-d1ea3tmp.js.map +9 -0
  55. package/dist/chunk-ecn1ca83.js +34253 -0
  56. package/dist/chunk-ecn1ca83.js.map +261 -0
  57. package/dist/chunk-ef1c6gq5.js +947 -0
  58. package/dist/chunk-ef1c6gq5.js.map +28 -0
  59. package/dist/chunk-ef355a3f.js +20 -0
  60. package/dist/chunk-ef355a3f.js.map +9 -0
  61. package/dist/chunk-f0dt9hv8.js +680 -0
  62. package/dist/chunk-f0dt9hv8.js.map +17 -0
  63. package/dist/chunk-f2aj8ff8.js +11 -0
  64. package/dist/chunk-f2aj8ff8.js.map +9 -0
  65. package/dist/chunk-f3wp07zw.js +24 -0
  66. package/dist/chunk-f3wp07zw.js.map +9 -0
  67. package/dist/chunk-f5wqd3z3.js +10 -0
  68. package/dist/chunk-f5wqd3z3.js.map +9 -0
  69. package/dist/chunk-g8hwy0wx.js +504 -0
  70. package/dist/chunk-g8hwy0wx.js.map +21 -0
  71. package/dist/chunk-gcx3c3yc.js +680 -0
  72. package/dist/chunk-gcx3c3yc.js.map +17 -0
  73. package/dist/chunk-gq6vxp70.js +202 -0
  74. package/dist/chunk-gq6vxp70.js.map +13 -0
  75. package/dist/chunk-gw64p5pg.js +164 -0
  76. package/dist/chunk-gw64p5pg.js.map +10 -0
  77. package/dist/chunk-hgv5frj1.js +256 -0
  78. package/dist/chunk-hgv5frj1.js.map +11 -0
  79. package/dist/chunk-hst78da7.js +87 -0
  80. package/dist/chunk-hst78da7.js.map +13 -0
  81. package/dist/chunk-hsxpgjyd.js +256 -0
  82. package/dist/chunk-hsxpgjyd.js.map +11 -0
  83. package/dist/chunk-j1v44zzm.js +109 -0
  84. package/dist/chunk-j1v44zzm.js.map +10 -0
  85. package/dist/chunk-jfd5md63.js +736 -0
  86. package/dist/chunk-jfd5md63.js.map +16 -0
  87. package/dist/chunk-jn5pcnz9.js +270 -0
  88. package/dist/chunk-jn5pcnz9.js.map +10 -0
  89. package/dist/chunk-jvhzgyhy.js +62 -0
  90. package/dist/chunk-jvhzgyhy.js.map +10 -0
  91. package/dist/chunk-k86st2r8.js +7 -0
  92. package/dist/chunk-k86st2r8.js.map +9 -0
  93. package/dist/chunk-kztccppz.js +606 -0
  94. package/dist/chunk-kztccppz.js.map +15 -0
  95. package/dist/chunk-m2vk15q9.js +503 -0
  96. package/dist/chunk-m2vk15q9.js.map +21 -0
  97. package/dist/chunk-mk40f3ka.js +31529 -0
  98. package/dist/chunk-mk40f3ka.js.map +245 -0
  99. package/dist/chunk-mp1sf8x6.js +264 -0
  100. package/dist/chunk-mp1sf8x6.js.map +12 -0
  101. package/dist/chunk-mzyqavzd.js +736 -0
  102. package/dist/chunk-mzyqavzd.js.map +16 -0
  103. package/dist/chunk-n9fs543g.js +94 -0
  104. package/dist/chunk-n9fs543g.js.map +10 -0
  105. package/dist/chunk-nbbwjw90.js +165 -0
  106. package/dist/chunk-nbbwjw90.js.map +10 -0
  107. package/dist/chunk-nh14pn95.js +137 -0
  108. package/dist/chunk-nh14pn95.js.map +10 -0
  109. package/dist/chunk-qnd877d5.js +947 -0
  110. package/dist/chunk-qnd877d5.js.map +28 -0
  111. package/dist/chunk-rng2ypf7.js +538 -0
  112. package/dist/chunk-rng2ypf7.js.map +15 -0
  113. package/dist/chunk-sjq10wbw.js +39 -0
  114. package/dist/chunk-sjq10wbw.js.map +9 -0
  115. package/dist/chunk-snv6a65k.js +759 -0
  116. package/dist/chunk-snv6a65k.js.map +19 -0
  117. package/dist/chunk-sqhdg0mf.js +2138 -0
  118. package/dist/chunk-sqhdg0mf.js.map +44 -0
  119. package/dist/chunk-tebher8z.js +514 -0
  120. package/dist/chunk-tebher8z.js.map +12 -0
  121. package/dist/chunk-v0wtyr4k.js +66 -0
  122. package/dist/chunk-v0wtyr4k.js.map +10 -0
  123. package/dist/chunk-v20274k8.js +246 -0
  124. package/dist/chunk-v20274k8.js.map +14 -0
  125. package/dist/chunk-vcp9fp2w.js +839 -0
  126. package/dist/chunk-vcp9fp2w.js.map +11 -0
  127. package/dist/chunk-vz737k5f.js +269 -0
  128. package/dist/chunk-vz737k5f.js.map +10 -0
  129. package/dist/chunk-x6bsgeqa.js +736 -0
  130. package/dist/chunk-x6bsgeqa.js.map +16 -0
  131. package/dist/chunk-xg9kcbp1.js +371 -0
  132. package/dist/chunk-xg9kcbp1.js.map +16 -0
  133. package/dist/chunk-xhad5b8x.js +110 -0
  134. package/dist/chunk-xhad5b8x.js.map +10 -0
  135. package/dist/chunk-xkwa1mn5.js +203 -0
  136. package/dist/chunk-xkwa1mn5.js.map +13 -0
  137. package/dist/chunk-xtcg74kf.js +50 -0
  138. package/dist/chunk-xtcg74kf.js.map +9 -0
  139. package/dist/chunk-xzjkaqe9.js +759 -0
  140. package/dist/chunk-xzjkaqe9.js.map +19 -0
  141. package/dist/chunk-y65xgj69.js +1495 -0
  142. package/dist/chunk-y65xgj69.js.map +23 -0
  143. package/dist/commands/doctor/command.js +1 -1
  144. package/dist/commands/init/command.js +1 -1
  145. package/dist/commands/logout/command.js +1 -1
  146. package/dist/commands/proxy/LoggingCallToolHandler.d.ts +11 -0
  147. package/dist/commands/proxy/command.js +1 -1
  148. package/dist/commands/screens/command.js +4 -4
  149. package/dist/commands/serve/command.js +5 -5
  150. package/dist/commands/site/command.js +1 -1
  151. package/dist/commands/snapshot/command.js +1 -1
  152. package/dist/commands/tool/command.js +1 -1
  153. package/dist/commands/tool/steps/LogExecuteToolStep.d.ts +19 -0
  154. package/dist/commands/upload/command.d.ts +2 -0
  155. package/dist/commands/upload/command.js +77 -0
  156. package/dist/commands/upload/command.js.map +11 -0
  157. package/dist/commands/upload/handler.d.ts +20 -0
  158. package/dist/commands/upload/spec.d.ts +38 -0
  159. package/dist/commands/view/command.js +1 -1
  160. package/dist/index.js +9 -9
  161. package/dist/index.js.map +1 -1
  162. package/dist/lib/log/append.d.ts +12 -0
  163. package/dist/lib/log/blob-store/handler.d.ts +10 -0
  164. package/dist/lib/log/blob-store/spec.d.ts +251 -0
  165. package/dist/lib/log/capture/handler.d.ts +10 -0
  166. package/dist/lib/log/capture/spec.d.ts +1504 -0
  167. package/dist/lib/log/factory.d.ts +4 -0
  168. package/package.json +2 -2
@@ -0,0 +1,606 @@
1
+ import {
2
+ exports_external
3
+ } from "./chunk-c6ge431q.js";
4
+
5
+ // src/lib/log/factory.ts
6
+ import { join as join2 } from "node:path";
7
+
8
+ // src/lib/log/append.ts
9
+ import { appendFile, mkdir } from "node:fs/promises";
10
+ import { dirname } from "node:path";
11
+ var EnvelopeSchema = exports_external.object({
12
+ id: exports_external.string().min(1),
13
+ time: exports_external.string().min(1),
14
+ trace_id: exports_external.string().min(1),
15
+ schema_version: exports_external.literal(1),
16
+ type: exports_external.string().min(1),
17
+ payload: exports_external.unknown()
18
+ });
19
+ async function appendEvent(eventsPath, event) {
20
+ const parsed = EnvelopeSchema.safeParse(event);
21
+ if (!parsed.success) {
22
+ return {
23
+ success: false,
24
+ error: {
25
+ code: "EVENT_VALIDATION_FAILED",
26
+ message: parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; "),
27
+ recoverable: false
28
+ }
29
+ };
30
+ }
31
+ try {
32
+ await mkdir(dirname(eventsPath), { recursive: true });
33
+ await appendFile(eventsPath, JSON.stringify(parsed.data) + `
34
+ `, "utf8");
35
+ return { success: true };
36
+ } catch (e) {
37
+ return {
38
+ success: false,
39
+ error: {
40
+ code: "EVENT_WRITE_FAILED",
41
+ message: e instanceof Error ? e.message : String(e),
42
+ recoverable: false
43
+ }
44
+ };
45
+ }
46
+ }
47
+
48
+ // src/lib/log/blob-store/handler.ts
49
+ import { createHash } from "node:crypto";
50
+ import { mkdir as mkdir2, readdir, readFile, stat, writeFile } from "node:fs/promises";
51
+ import { dirname as dirname2, join } from "node:path";
52
+ var EXT_BY_MIME = {
53
+ "application/json": "json",
54
+ "text/html": "html",
55
+ "image/png": "png",
56
+ "image/webp": "webp",
57
+ "image/jpeg": "jpg"
58
+ };
59
+ function extForMime(mime) {
60
+ return EXT_BY_MIME[mime] ?? "bin";
61
+ }
62
+
63
+ class BlobStoreHandler {
64
+ root;
65
+ constructor(root) {
66
+ this.root = root;
67
+ }
68
+ async put(buffer, mime) {
69
+ try {
70
+ const sha256 = createHash("sha256").update(buffer).digest("hex");
71
+ const existing = await this.findBySha(sha256);
72
+ if (existing) {
73
+ const s = await stat(existing);
74
+ return { success: true, data: { sha256, size: s.size, mime } };
75
+ }
76
+ const path = join(this.root, sha256.slice(0, 2), `${sha256}.${extForMime(mime)}`);
77
+ await mkdir2(dirname2(path), { recursive: true });
78
+ await writeFile(path, buffer);
79
+ return { success: true, data: { sha256, size: buffer.length, mime } };
80
+ } catch (e) {
81
+ return {
82
+ success: false,
83
+ error: {
84
+ code: "BLOB_WRITE_FAILED",
85
+ message: e instanceof Error ? e.message : String(e),
86
+ recoverable: false
87
+ }
88
+ };
89
+ }
90
+ }
91
+ async findBySha(sha256) {
92
+ const dir = join(this.root, sha256.slice(0, 2));
93
+ let entries;
94
+ try {
95
+ entries = await readdir(dir);
96
+ } catch {
97
+ return null;
98
+ }
99
+ const match = entries.find((e) => e.startsWith(`${sha256}.`));
100
+ return match ? join(dir, match) : null;
101
+ }
102
+ async fetch(url, mimeHint) {
103
+ let response;
104
+ try {
105
+ response = await globalThis.fetch(url, {
106
+ redirect: "follow",
107
+ headers: { "User-Agent": "stitch-mcp-log/0.1 (Mozilla/5.0)" }
108
+ });
109
+ } catch (e) {
110
+ return {
111
+ success: false,
112
+ error: {
113
+ code: "BLOB_FETCH_NETWORK",
114
+ message: e instanceof Error ? e.message : String(e),
115
+ recoverable: true
116
+ }
117
+ };
118
+ }
119
+ if (!response.ok) {
120
+ return {
121
+ success: false,
122
+ error: {
123
+ code: "BLOB_FETCH_HTTP_ERROR",
124
+ message: `HTTP ${response.status} for ${url}`,
125
+ recoverable: false
126
+ }
127
+ };
128
+ }
129
+ const mime = (response.headers.get("content-type") ?? mimeHint ?? "application/octet-stream").split(";")[0].trim();
130
+ const buffer = Buffer.from(await response.arrayBuffer());
131
+ return this.put(buffer, mime);
132
+ }
133
+ async has(sha256) {
134
+ const path = await this.findBySha(sha256);
135
+ return { success: true, data: path != null };
136
+ }
137
+ async get(sha256) {
138
+ const path = await this.findBySha(sha256);
139
+ if (!path)
140
+ return { success: true, data: null };
141
+ const buf = await readFile(path);
142
+ return { success: true, data: buf };
143
+ }
144
+ }
145
+
146
+ // src/lib/log/capture/handler.ts
147
+ import { randomUUID } from "node:crypto";
148
+
149
+ // src/lib/log/blob-store/spec.ts
150
+ var Sha256Schema = exports_external.string().regex(/^[0-9a-f]{64}$/, "must be 64-char lowercase hex");
151
+ var MimeSchema = exports_external.string().min(1);
152
+ var BlobRefSchema = exports_external.object({
153
+ sha256: Sha256Schema,
154
+ size: exports_external.number().int().nonnegative(),
155
+ mime: MimeSchema
156
+ });
157
+ var BlobStoreErrorCodeSchema = exports_external.enum([
158
+ "BLOB_FETCH_NETWORK",
159
+ "BLOB_FETCH_HTTP_ERROR",
160
+ "BLOB_WRITE_FAILED",
161
+ "BLOB_READ_FAILED",
162
+ "BLOB_INVALID_INPUT"
163
+ ]);
164
+ var BlobStoreErrorSchema = exports_external.object({
165
+ code: BlobStoreErrorCodeSchema,
166
+ message: exports_external.string(),
167
+ suggestion: exports_external.string().optional(),
168
+ recoverable: exports_external.boolean()
169
+ });
170
+ var FailureSchema = exports_external.object({
171
+ success: exports_external.literal(false),
172
+ error: BlobStoreErrorSchema
173
+ });
174
+ var PutSuccessSchema = exports_external.object({
175
+ success: exports_external.literal(true),
176
+ data: BlobRefSchema
177
+ });
178
+ var PutResultSchema = exports_external.union([PutSuccessSchema, FailureSchema]);
179
+ var HasSuccessSchema = exports_external.object({
180
+ success: exports_external.literal(true),
181
+ data: exports_external.boolean()
182
+ });
183
+ var HasResultSchema = exports_external.union([HasSuccessSchema, FailureSchema]);
184
+ var GetSuccessSchema = exports_external.object({
185
+ success: exports_external.literal(true),
186
+ data: exports_external.instanceof(Buffer).nullable()
187
+ });
188
+ var GetResultSchema = exports_external.union([GetSuccessSchema, FailureSchema]);
189
+
190
+ // src/lib/log/capture/spec.ts
191
+ var GENERATIVE_TOOLS = new Set([
192
+ "generate_screen_from_text",
193
+ "edit_screens",
194
+ "generate_variants"
195
+ ]);
196
+ var READ_TOOLS = new Set([
197
+ "get_screen",
198
+ "list_screens",
199
+ "list_projects",
200
+ "get_project",
201
+ "create_project"
202
+ ]);
203
+ function kindOf(tool) {
204
+ if (GENERATIVE_TOOLS.has(tool))
205
+ return "generative";
206
+ if (READ_TOOLS.has(tool))
207
+ return "read";
208
+ return "unknown";
209
+ }
210
+ var ProducedScreenSchema = exports_external.object({
211
+ project_id: exports_external.string(),
212
+ screen_id: exports_external.string(),
213
+ name: exports_external.string(),
214
+ parent_screen_id: exports_external.string().nullable(),
215
+ sibling_screen_ids: exports_external.array(exports_external.string()),
216
+ effective_prompt: exports_external.string(),
217
+ html_blob: BlobRefSchema.nullable(),
218
+ screenshot_blob: BlobRefSchema.nullable(),
219
+ theme_blob: BlobRefSchema.nullable(),
220
+ design_system_blob: BlobRefSchema.nullable()
221
+ });
222
+ var RequestedPayloadSchema = exports_external.object({
223
+ tool: exports_external.string(),
224
+ project_id: exports_external.string().optional(),
225
+ selected_screen_ids: exports_external.array(exports_external.string()).optional(),
226
+ user_prompt: exports_external.string().optional(),
227
+ variant_options: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
228
+ device_type: exports_external.string().optional(),
229
+ model_id: exports_external.string().optional(),
230
+ args_blob: BlobRefSchema
231
+ });
232
+ var CompletedGenerativePayloadSchema = exports_external.object({
233
+ tool: exports_external.string(),
234
+ duration_ms: exports_external.number().int().nonnegative(),
235
+ kind: exports_external.literal("generative"),
236
+ stitch_session_id: exports_external.string().optional(),
237
+ structured_content_blob: BlobRefSchema,
238
+ produced_screens: exports_external.array(ProducedScreenSchema)
239
+ });
240
+ var CompletedReadPayloadSchema = exports_external.object({
241
+ tool: exports_external.string(),
242
+ duration_ms: exports_external.number().int().nonnegative(),
243
+ kind: exports_external.literal("read"),
244
+ project_id: exports_external.string().optional(),
245
+ screen_ids: exports_external.array(exports_external.string()).optional(),
246
+ returned_project_ids: exports_external.array(exports_external.string()).optional(),
247
+ returned_screen_ids: exports_external.array(exports_external.string()).optional(),
248
+ result_blob: BlobRefSchema
249
+ });
250
+ var CompletedUnknownPayloadSchema = exports_external.object({
251
+ tool: exports_external.string(),
252
+ duration_ms: exports_external.number().int().nonnegative(),
253
+ kind: exports_external.literal("unknown"),
254
+ project_id: exports_external.string().optional(),
255
+ result_blob: BlobRefSchema
256
+ });
257
+ var CompletedPayloadSchema = exports_external.discriminatedUnion("kind", [
258
+ CompletedGenerativePayloadSchema,
259
+ CompletedReadPayloadSchema,
260
+ CompletedUnknownPayloadSchema
261
+ ]);
262
+ var FailedPayloadSchema = exports_external.object({
263
+ tool: exports_external.string(),
264
+ duration_ms: exports_external.number().int().nonnegative(),
265
+ is_error: exports_external.union([exports_external.literal(true), exports_external.literal("empty")]),
266
+ error_text: exports_external.string().optional(),
267
+ raw_blob: BlobRefSchema.optional()
268
+ });
269
+ var baseEnvelope = {
270
+ id: exports_external.string().min(1),
271
+ time: exports_external.string().min(1),
272
+ trace_id: exports_external.string().min(1),
273
+ schema_version: exports_external.literal(1)
274
+ };
275
+ var EventSchema = exports_external.discriminatedUnion("type", [
276
+ exports_external.object({ ...baseEnvelope, type: exports_external.literal("call.requested"), payload: RequestedPayloadSchema }),
277
+ exports_external.object({ ...baseEnvelope, type: exports_external.literal("call.completed"), payload: CompletedPayloadSchema }),
278
+ exports_external.object({ ...baseEnvelope, type: exports_external.literal("call.failed"), payload: FailedPayloadSchema })
279
+ ]);
280
+ var CaptureInputSchema = exports_external.object({
281
+ tool: exports_external.string().min(1),
282
+ args: exports_external.record(exports_external.string(), exports_external.unknown()),
283
+ result: exports_external.unknown(),
284
+ duration_ms: exports_external.number().int().nonnegative(),
285
+ started_at: exports_external.string().min(1),
286
+ finished_at: exports_external.string().min(1)
287
+ });
288
+ var CaptureErrorCodeSchema = exports_external.enum([
289
+ "CAPTURE_UNKNOWN_TOOL",
290
+ "CAPTURE_APPEND_FAILED",
291
+ "CAPTURE_BLOB_FATAL",
292
+ "CAPTURE_INVALID_INPUT"
293
+ ]);
294
+ var CaptureFailure = exports_external.object({
295
+ success: exports_external.literal(false),
296
+ error: exports_external.object({
297
+ code: CaptureErrorCodeSchema,
298
+ message: exports_external.string(),
299
+ recoverable: exports_external.boolean()
300
+ })
301
+ });
302
+ var CaptureSuccess = exports_external.object({
303
+ success: exports_external.literal(true),
304
+ data: exports_external.object({
305
+ trace_id: exports_external.string(),
306
+ produced_screen_ids: exports_external.array(exports_external.string()),
307
+ warnings: exports_external.array(exports_external.string())
308
+ })
309
+ });
310
+ var CaptureResultSchema = exports_external.union([CaptureSuccess, CaptureFailure]);
311
+
312
+ // src/lib/log/capture/handler.ts
313
+ class CaptureHandler {
314
+ blobs;
315
+ append;
316
+ now;
317
+ newId;
318
+ constructor(deps) {
319
+ this.blobs = deps.blobs;
320
+ this.append = deps.append;
321
+ this.now = deps.now ?? (() => new Date);
322
+ this.newId = deps.newId ?? (() => randomUUID());
323
+ }
324
+ async capture(input) {
325
+ const parsed = CaptureInputSchema.safeParse(input);
326
+ if (!parsed.success) {
327
+ return this.fail("CAPTURE_INVALID_INPUT", parsed.error.message, false);
328
+ }
329
+ const kind = kindOf(input.tool);
330
+ const trace_id = this.newId();
331
+ const warnings = [];
332
+ const argsBuf = Buffer.from(JSON.stringify(input.args));
333
+ const argsBlob = await this.blobs.put(argsBuf, "application/json");
334
+ if (!argsBlob.success) {
335
+ return this.fail("CAPTURE_BLOB_FATAL", `args_blob: ${argsBlob.error.message}`, false);
336
+ }
337
+ const requested = {
338
+ id: this.newId(),
339
+ time: input.started_at,
340
+ trace_id,
341
+ schema_version: 1,
342
+ type: "call.requested",
343
+ payload: {
344
+ tool: input.tool,
345
+ project_id: typeof input.args.projectId === "string" ? input.args.projectId : undefined,
346
+ selected_screen_ids: Array.isArray(input.args.selectedScreenIds) ? input.args.selectedScreenIds : undefined,
347
+ user_prompt: typeof input.args.prompt === "string" ? input.args.prompt : undefined,
348
+ variant_options: input.args.variantOptions && typeof input.args.variantOptions === "object" ? input.args.variantOptions : undefined,
349
+ device_type: typeof input.args.deviceType === "string" ? input.args.deviceType : undefined,
350
+ model_id: typeof input.args.modelId === "string" ? input.args.modelId : undefined,
351
+ args_blob: argsBlob.data
352
+ }
353
+ };
354
+ const ar = await this.append(requested);
355
+ if (!ar.success)
356
+ return this.fail("CAPTURE_APPEND_FAILED", ar.error.message, true);
357
+ const r = input.result;
358
+ if (r && r.isError === true) {
359
+ const errorText = r.content?.find((c) => c.type === "text")?.text ?? "";
360
+ const rawBlob = await this.blobs.put(Buffer.from(JSON.stringify(r)), "application/json");
361
+ const failed = {
362
+ id: this.newId(),
363
+ time: input.finished_at,
364
+ trace_id,
365
+ schema_version: 1,
366
+ type: "call.failed",
367
+ payload: {
368
+ tool: input.tool,
369
+ duration_ms: input.duration_ms,
370
+ is_error: true,
371
+ error_text: errorText,
372
+ raw_blob: rawBlob.success ? rawBlob.data : undefined
373
+ }
374
+ };
375
+ const fr = await this.append(failed);
376
+ if (!fr.success)
377
+ return this.fail("CAPTURE_APPEND_FAILED", fr.error.message, true);
378
+ return { success: true, data: { trace_id, produced_screen_ids: [], warnings } };
379
+ }
380
+ if (kind === "read") {
381
+ const resultBlob = await this.blobs.put(Buffer.from(JSON.stringify(r ?? {})), "application/json");
382
+ if (!resultBlob.success) {
383
+ return this.fail("CAPTURE_BLOB_FATAL", `result_blob: ${resultBlob.error.message}`, false);
384
+ }
385
+ const returned = extractReturnedIds(r);
386
+ const completed2 = {
387
+ id: this.newId(),
388
+ time: input.finished_at,
389
+ trace_id,
390
+ schema_version: 1,
391
+ type: "call.completed",
392
+ payload: {
393
+ tool: input.tool,
394
+ duration_ms: input.duration_ms,
395
+ kind: "read",
396
+ project_id: typeof input.args.projectId === "string" ? input.args.projectId : undefined,
397
+ screen_ids: typeof input.args.screenId === "string" ? [input.args.screenId] : Array.isArray(input.args.selectedScreenIds) ? input.args.selectedScreenIds : undefined,
398
+ returned_project_ids: returned.projects.length > 0 ? returned.projects : undefined,
399
+ returned_screen_ids: returned.screens.length > 0 ? returned.screens : undefined,
400
+ result_blob: resultBlob.data
401
+ }
402
+ };
403
+ const cr2 = await this.append(completed2);
404
+ if (!cr2.success)
405
+ return this.fail("CAPTURE_APPEND_FAILED", cr2.error.message, true);
406
+ return { success: true, data: { trace_id, produced_screen_ids: [], warnings } };
407
+ }
408
+ if (kind === "unknown") {
409
+ const resultBlob = await this.blobs.put(Buffer.from(JSON.stringify(r ?? {})), "application/json");
410
+ if (!resultBlob.success) {
411
+ return this.fail("CAPTURE_BLOB_FATAL", `result_blob: ${resultBlob.error.message}`, false);
412
+ }
413
+ const completed2 = {
414
+ id: this.newId(),
415
+ time: input.finished_at,
416
+ trace_id,
417
+ schema_version: 1,
418
+ type: "call.completed",
419
+ payload: {
420
+ tool: input.tool,
421
+ duration_ms: input.duration_ms,
422
+ kind: "unknown",
423
+ project_id: typeof input.args.projectId === "string" ? input.args.projectId : undefined,
424
+ result_blob: resultBlob.data
425
+ }
426
+ };
427
+ const cr2 = await this.append(completed2);
428
+ if (!cr2.success)
429
+ return this.fail("CAPTURE_APPEND_FAILED", cr2.error.message, true);
430
+ return { success: true, data: { trace_id, produced_screen_ids: [], warnings } };
431
+ }
432
+ const sc = r?.structuredContent ?? null;
433
+ const screens = pickScreens(sc);
434
+ if (screens.length === 0) {
435
+ const rawBlob = await this.blobs.put(Buffer.from(JSON.stringify(r ?? {})), "application/json");
436
+ const failed = {
437
+ id: this.newId(),
438
+ time: input.finished_at,
439
+ trace_id,
440
+ schema_version: 1,
441
+ type: "call.failed",
442
+ payload: {
443
+ tool: input.tool,
444
+ duration_ms: input.duration_ms,
445
+ is_error: "empty",
446
+ raw_blob: rawBlob.success ? rawBlob.data : undefined
447
+ }
448
+ };
449
+ const fr = await this.append(failed);
450
+ if (!fr.success)
451
+ return this.fail("CAPTURE_APPEND_FAILED", fr.error.message, true);
452
+ return { success: true, data: { trace_id, produced_screen_ids: [], warnings } };
453
+ }
454
+ const structuredBlob = await this.blobs.put(Buffer.from(JSON.stringify(sc)), "application/json");
455
+ if (!structuredBlob.success) {
456
+ return this.fail("CAPTURE_BLOB_FATAL", `structured_content_blob: ${structuredBlob.error.message}`, false);
457
+ }
458
+ const dsAsset = pickDesignSystemComponent(sc);
459
+ let dsAssetBlob = null;
460
+ if (dsAsset) {
461
+ const r2 = await this.blobs.put(Buffer.from(JSON.stringify(dsAsset)), "application/json");
462
+ if (r2.success)
463
+ dsAssetBlob = r2.data;
464
+ else
465
+ warnings.push(`design_system_asset put failed: ${r2.error.message}`);
466
+ }
467
+ const allScreenIds = screens.map((s) => s.id ?? "").filter(Boolean);
468
+ const selectedParents = input.args.selectedScreenIds ?? [];
469
+ const parent = selectedParents[0] ?? null;
470
+ const produced = [];
471
+ for (const s of screens) {
472
+ const screenId = s.id ?? "";
473
+ const siblings = allScreenIds.filter((id) => id !== screenId);
474
+ let themeBlob = null;
475
+ if (s.theme && Object.keys(s.theme).length > 0) {
476
+ const tr = await this.blobs.put(Buffer.from(JSON.stringify(s.theme)), "application/json");
477
+ if (tr.success)
478
+ themeBlob = tr.data;
479
+ else
480
+ warnings.push(`screen ${screenId} theme: ${tr.error.message}`);
481
+ }
482
+ let dsBlob = null;
483
+ if (s.designSystem) {
484
+ const dr = await this.blobs.put(Buffer.from(JSON.stringify(s.designSystem)), "application/json");
485
+ if (dr.success)
486
+ dsBlob = dr.data;
487
+ else
488
+ warnings.push(`screen ${screenId} design_system: ${dr.error.message}`);
489
+ } else if (dsAssetBlob) {
490
+ dsBlob = dsAssetBlob;
491
+ }
492
+ let htmlBlob = null;
493
+ if (s.htmlCode?.downloadUrl) {
494
+ const fr = await this.blobs.fetch(s.htmlCode.downloadUrl, s.htmlCode.mimeType ?? "text/html");
495
+ if (fr.success)
496
+ htmlBlob = fr.data;
497
+ else
498
+ warnings.push(`screen ${screenId} html: ${fr.error.code} ${fr.error.message}`);
499
+ }
500
+ let shotBlob = null;
501
+ if (s.screenshot?.downloadUrl) {
502
+ const fr = await this.blobs.fetch(s.screenshot.downloadUrl);
503
+ if (fr.success)
504
+ shotBlob = fr.data;
505
+ else
506
+ warnings.push(`screen ${screenId} screenshot: ${fr.error.code} ${fr.error.message}`);
507
+ }
508
+ produced.push({
509
+ project_id: input.args.projectId ?? sc?.projectId ?? "",
510
+ screen_id: screenId,
511
+ name: s.name ?? "",
512
+ parent_screen_id: parent,
513
+ sibling_screen_ids: siblings,
514
+ effective_prompt: s.prompt ?? "",
515
+ html_blob: htmlBlob,
516
+ screenshot_blob: shotBlob,
517
+ theme_blob: themeBlob,
518
+ design_system_blob: dsBlob
519
+ });
520
+ }
521
+ const completed = {
522
+ id: this.newId(),
523
+ time: input.finished_at,
524
+ trace_id,
525
+ schema_version: 1,
526
+ type: "call.completed",
527
+ payload: {
528
+ tool: input.tool,
529
+ duration_ms: input.duration_ms,
530
+ kind: "generative",
531
+ stitch_session_id: typeof sc?.sessionId !== "undefined" ? String(sc.sessionId) : undefined,
532
+ structured_content_blob: structuredBlob.data,
533
+ produced_screens: produced
534
+ }
535
+ };
536
+ const cr = await this.append(completed);
537
+ if (!cr.success)
538
+ return this.fail("CAPTURE_APPEND_FAILED", cr.error.message, true);
539
+ return {
540
+ success: true,
541
+ data: { trace_id, produced_screen_ids: produced.map((p) => p.screen_id), warnings }
542
+ };
543
+ }
544
+ fail(code, message, recoverable) {
545
+ return { success: false, error: { code, message, recoverable } };
546
+ }
547
+ }
548
+ function pickScreens(sc) {
549
+ const out = [];
550
+ for (const c of sc?.outputComponents ?? []) {
551
+ if (c?.design?.screens)
552
+ for (const s of c.design.screens)
553
+ out.push(s);
554
+ }
555
+ return out;
556
+ }
557
+ function pickDesignSystemComponent(sc) {
558
+ const c = (sc?.outputComponents ?? []).find((x) => x?.designSystem);
559
+ return c?.designSystem ?? null;
560
+ }
561
+ function extractReturnedIds(result) {
562
+ const projects = new Set;
563
+ const screens = new Set;
564
+ const seen = new WeakSet;
565
+ const visit = (node) => {
566
+ if (!node || typeof node !== "object")
567
+ return;
568
+ if (seen.has(node))
569
+ return;
570
+ seen.add(node);
571
+ const name = node.name;
572
+ if (typeof name === "string") {
573
+ if (name.startsWith("projects/"))
574
+ projects.add(name.slice("projects/".length));
575
+ else if (name.startsWith("screens/"))
576
+ screens.add(name.slice("screens/".length));
577
+ }
578
+ if (Array.isArray(node)) {
579
+ for (const v of node)
580
+ visit(v);
581
+ } else {
582
+ for (const v of Object.values(node))
583
+ visit(v);
584
+ }
585
+ };
586
+ visit(result);
587
+ return { projects: Array.from(projects), screens: Array.from(screens) };
588
+ }
589
+
590
+ // src/lib/log/factory.ts
591
+ var DEFAULT_LOG_ROOT = ".stitch-mcp/log";
592
+ function isLogEnabled() {
593
+ return process.env.STITCH_MCP_LOG === "1";
594
+ }
595
+ function createCaptureHandler(root = DEFAULT_LOG_ROOT) {
596
+ const blobs = new BlobStoreHandler(join2(root, "blobs"));
597
+ const eventsPath = join2(root, "events.jsonl");
598
+ return new CaptureHandler({
599
+ blobs,
600
+ append: (event) => appendEvent(eventsPath, event)
601
+ });
602
+ }
603
+
604
+ export { isLogEnabled, createCaptureHandler };
605
+
606
+ //# debugId=FE77B0940D64015064756E2164756E21