@agent-native/core 0.37.1 → 0.37.3

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 (39) hide show
  1. package/dist/brand-kit/fig/decode.d.ts +33 -0
  2. package/dist/brand-kit/fig/decode.d.ts.map +1 -0
  3. package/dist/brand-kit/fig/decode.js +358 -0
  4. package/dist/brand-kit/fig/decode.js.map +1 -0
  5. package/dist/brand-kit/fig/extract-design-system.d.ts +44 -0
  6. package/dist/brand-kit/fig/extract-design-system.d.ts.map +1 -0
  7. package/dist/brand-kit/fig/extract-design-system.js +752 -0
  8. package/dist/brand-kit/fig/extract-design-system.js.map +1 -0
  9. package/dist/brand-kit/fig/fig-to-html.d.ts +246 -0
  10. package/dist/brand-kit/fig/fig-to-html.d.ts.map +1 -0
  11. package/dist/brand-kit/fig/fig-to-html.js +1506 -0
  12. package/dist/brand-kit/fig/fig-to-html.js.map +1 -0
  13. package/dist/brand-kit/fig/index.d.ts +30 -0
  14. package/dist/brand-kit/fig/index.d.ts.map +1 -0
  15. package/dist/brand-kit/fig/index.js +43 -0
  16. package/dist/brand-kit/fig/index.js.map +1 -0
  17. package/dist/cli/skills.d.ts +4 -0
  18. package/dist/cli/skills.d.ts.map +1 -1
  19. package/dist/cli/skills.js +841 -378
  20. package/dist/cli/skills.js.map +1 -1
  21. package/dist/client/AssistantChat.d.ts.map +1 -1
  22. package/dist/client/AssistantChat.js +6 -104
  23. package/dist/client/AssistantChat.js.map +1 -1
  24. package/dist/client/context-xray/ContextMeter.js +1 -1
  25. package/dist/client/context-xray/ContextMeter.js.map +1 -1
  26. package/dist/client/context-xray/ContextSegmentRow.d.ts.map +1 -1
  27. package/dist/client/context-xray/ContextSegmentRow.js +4 -4
  28. package/dist/client/context-xray/ContextSegmentRow.js.map +1 -1
  29. package/dist/client/context-xray/ContextTreemap.d.ts.map +1 -1
  30. package/dist/client/context-xray/ContextTreemap.js +2 -2
  31. package/dist/client/context-xray/ContextTreemap.js.map +1 -1
  32. package/dist/client/context-xray/ContextXRayPanel.d.ts.map +1 -1
  33. package/dist/client/context-xray/ContextXRayPanel.js +19 -18
  34. package/dist/client/context-xray/ContextXRayPanel.js.map +1 -1
  35. package/dist/client/sharing/ShareButton.d.ts +4 -0
  36. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  37. package/dist/client/sharing/ShareButton.js +6 -4
  38. package/dist/client/sharing/ShareButton.js.map +1 -1
  39. package/package.json +6 -1
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Binary decoder for Figma `.fig` files. Handles both modern fig-kiwi files
3
+ * (a custom container of kiwi-schema chunks, optionally zstd/zlib compressed)
4
+ * and the legacy zip-format archives. Returns the decoded document node tree,
5
+ * extracted image blobs (SHA1-keyed, with magic-byte extensions), and a
6
+ * best-effort thumbnail.
7
+ *
8
+ * Ported faithfully from the ai-services design-systems pipeline. It is a pure
9
+ * function on a Buffer — no storage, queue, or job coupling.
10
+ */
11
+ export interface DecodedFigKiwi {
12
+ version: number;
13
+ schema: Buffer;
14
+ document: Buffer;
15
+ blobs: Buffer[];
16
+ }
17
+ export interface DecodedFigImage {
18
+ /** SHA1 of the blob bytes — matches what the document references. */
19
+ hash: string;
20
+ ext: string;
21
+ bytes: Buffer;
22
+ }
23
+ export interface DecodedFig {
24
+ format: "kiwi" | "zip";
25
+ version?: number;
26
+ document: unknown;
27
+ images: DecodedFigImage[];
28
+ thumbnail: Buffer | null;
29
+ }
30
+ export declare function decodeKiwiContainer(file: Buffer): DecodedFigKiwi;
31
+ export declare function decodeFig(file: Buffer): DecodedFig;
32
+ export declare function buildImageMap(images: DecodedFigImage[]): Map<string, string>;
33
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../../src/brand-kit/fig/decode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAoBH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAkED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAsChE;AA8LD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAyDlD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAM5E"}
@@ -0,0 +1,358 @@
1
+ /**
2
+ * Binary decoder for Figma `.fig` files. Handles both modern fig-kiwi files
3
+ * (a custom container of kiwi-schema chunks, optionally zstd/zlib compressed)
4
+ * and the legacy zip-format archives. Returns the decoded document node tree,
5
+ * extracted image blobs (SHA1-keyed, with magic-byte extensions), and a
6
+ * best-effort thumbnail.
7
+ *
8
+ * Ported faithfully from the ai-services design-systems pipeline. It is a pure
9
+ * function on a Buffer — no storage, queue, or job coupling.
10
+ */
11
+ import * as zlib from "node:zlib";
12
+ import * as crypto from "node:crypto";
13
+ import * as pako from "pako";
14
+ import { decompress as zstdDecompress } from "fzstd";
15
+ import { ByteBuffer, compileSchema, decodeBinarySchema, } from "kiwi-schema";
16
+ const MAX_DECOMPRESSED_BYTES = 512 * 1024 * 1024; // 512 MB cap per chunk to prevent compression bombs
17
+ const ZSTD_MAGIC = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]);
18
+ const FIG_KIWI_MAGIC = Buffer.from("fig-kiwi", "utf8");
19
+ const ZIP_MAGIC = Buffer.from([0x50, 0x4b, 0x03, 0x04]);
20
+ const PNG_MAGIC = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
21
+ const JPEG_MAGIC = Buffer.from([0xff, 0xd8, 0xff]);
22
+ function sha1(buf) {
23
+ return crypto.createHash("sha1").update(buf).digest("hex");
24
+ }
25
+ function detectImageExt(buf) {
26
+ if (buf.length >= 8 && buf.subarray(0, 8).equals(PNG_MAGIC))
27
+ return "png";
28
+ if (buf.length >= 3 && buf.subarray(0, 3).equals(JPEG_MAGIC))
29
+ return "jpg";
30
+ if (buf.length >= 12 &&
31
+ buf.subarray(0, 4).toString("ascii") === "RIFF" &&
32
+ buf.subarray(8, 12).toString("ascii") === "WEBP") {
33
+ return "webp";
34
+ }
35
+ if (buf.length >= 4 && buf.subarray(0, 4).toString("ascii") === "GIF8") {
36
+ return "gif";
37
+ }
38
+ return "bin";
39
+ }
40
+ function checkDecompressedSize(buf) {
41
+ if (buf.length > MAX_DECOMPRESSED_BYTES) {
42
+ throw new Error(`Decompressed chunk exceeds size limit (${buf.length} > ${MAX_DECOMPRESSED_BYTES})`);
43
+ }
44
+ return buf;
45
+ }
46
+ function decompressChunk(buf) {
47
+ if (buf.length >= 4 && buf.subarray(0, 4).equals(ZSTD_MAGIC)) {
48
+ try {
49
+ return checkDecompressedSize(Buffer.from(zstdDecompress(buf)));
50
+ }
51
+ catch {
52
+ /* fall through */
53
+ }
54
+ }
55
+ try {
56
+ return zlib.inflateRawSync(buf, {
57
+ maxOutputLength: MAX_DECOMPRESSED_BYTES,
58
+ });
59
+ }
60
+ catch (e) {
61
+ if (e instanceof RangeError)
62
+ throw e; // output exceeded size cap; don't fall through
63
+ /* fall through for format/data errors */
64
+ }
65
+ try {
66
+ return zlib.inflateSync(buf, { maxOutputLength: MAX_DECOMPRESSED_BYTES });
67
+ }
68
+ catch (e) {
69
+ if (e instanceof RangeError)
70
+ throw e;
71
+ /* fall through */
72
+ }
73
+ try {
74
+ return checkDecompressedSize(Buffer.from(pako.inflateRaw(buf)));
75
+ }
76
+ catch {
77
+ /* fall through */
78
+ }
79
+ try {
80
+ return checkDecompressedSize(Buffer.from(pako.inflate(buf)));
81
+ }
82
+ catch {
83
+ /* fall through */
84
+ }
85
+ return Buffer.from(buf);
86
+ }
87
+ export function decodeKiwiContainer(file) {
88
+ if (!file.subarray(0, 8).equals(FIG_KIWI_MAGIC)) {
89
+ throw new Error("Not a fig-kiwi file (missing magic header)");
90
+ }
91
+ if (file.length < 12) {
92
+ throw new Error("Truncated kiwi header (file too short to contain version)");
93
+ }
94
+ const version = file.readUInt32LE(8);
95
+ let offset = 12;
96
+ const chunks = [];
97
+ while (offset < file.length) {
98
+ if (offset + 4 > file.length) {
99
+ throw new Error(`Truncated chunk header at offset ${offset}`);
100
+ }
101
+ const length = file.readUInt32LE(offset);
102
+ offset += 4;
103
+ if (offset + length > file.length) {
104
+ throw new Error(`Chunk extends past end of file (offset=${offset}, length=${length}, total=${file.length})`);
105
+ }
106
+ const compressed = file.subarray(offset, offset + length);
107
+ offset += length;
108
+ chunks.push(decompressChunk(compressed));
109
+ }
110
+ if (chunks.length < 2) {
111
+ throw new Error(`Expected at least 2 chunks (schema + document), got ${chunks.length}`);
112
+ }
113
+ return {
114
+ version,
115
+ schema: chunks[0],
116
+ document: chunks[1],
117
+ blobs: chunks.slice(2),
118
+ };
119
+ }
120
+ /**
121
+ * Minimal zip reader: supports stored (method 0) and deflate (method 8)
122
+ * entries, no encryption, no zip64. Sufficient for legacy `.fig` archives.
123
+ */
124
+ function readZip(file) {
125
+ const EOCD_SIG = 0x06054b50;
126
+ const maxScan = Math.min(file.length, 65557);
127
+ let eocdOffset = -1;
128
+ for (let i = file.length - 22; i >= file.length - maxScan && i >= 0; i--) {
129
+ if (file.readUInt32LE(i) === EOCD_SIG) {
130
+ eocdOffset = i;
131
+ break;
132
+ }
133
+ }
134
+ if (eocdOffset < 0)
135
+ throw new Error("Zip EOCD record not found");
136
+ const totalEntries = file.readUInt16LE(eocdOffset + 10);
137
+ const cdOffset = file.readUInt32LE(eocdOffset + 16);
138
+ if (cdOffset > file.length) {
139
+ throw new Error(`Central directory offset ${cdOffset} exceeds file length`);
140
+ }
141
+ const entries = [];
142
+ let p = cdOffset;
143
+ for (let i = 0; i < totalEntries; i++) {
144
+ if (p + 46 > file.length) {
145
+ throw new Error(`Truncated central directory entry at offset ${p}`);
146
+ }
147
+ if (file.readUInt32LE(p) !== 0x02014b50) {
148
+ throw new Error(`Bad central directory entry signature at ${p}`);
149
+ }
150
+ const compressionMethod = file.readUInt16LE(p + 10);
151
+ const compressedSize = file.readUInt32LE(p + 20);
152
+ const uncompressedSize = file.readUInt32LE(p + 24);
153
+ const nameLen = file.readUInt16LE(p + 28);
154
+ const extraLen = file.readUInt16LE(p + 30);
155
+ const commentLen = file.readUInt16LE(p + 32);
156
+ const localHeaderOffset = file.readUInt32LE(p + 42);
157
+ const name = file.subarray(p + 46, p + 46 + nameLen).toString("utf8");
158
+ p += 46 + nameLen + extraLen + commentLen;
159
+ const lh = localHeaderOffset;
160
+ if (lh + 30 > file.length) {
161
+ throw new Error(`Local header offset ${lh} out of bounds`);
162
+ }
163
+ if (file.readUInt32LE(lh) !== 0x04034b50) {
164
+ throw new Error(`Bad local file header signature at ${lh}`);
165
+ }
166
+ const lhNameLen = file.readUInt16LE(lh + 26);
167
+ const lhExtraLen = file.readUInt16LE(lh + 28);
168
+ const dataStart = lh + 30 + lhNameLen + lhExtraLen;
169
+ if (dataStart + compressedSize > file.length) {
170
+ throw new Error(`Compressed data for "${name}" extends past end of file`);
171
+ }
172
+ const compressed = file.subarray(dataStart, dataStart + compressedSize);
173
+ let data;
174
+ if (compressionMethod === 0) {
175
+ data = Buffer.from(compressed);
176
+ }
177
+ else if (compressionMethod === 8) {
178
+ data = zlib.inflateRawSync(compressed, {
179
+ maxOutputLength: MAX_DECOMPRESSED_BYTES,
180
+ });
181
+ }
182
+ else {
183
+ throw new Error(`Unsupported zip compression method ${compressionMethod} for entry "${name}"`);
184
+ }
185
+ if (uncompressedSize !== 0 && data.length !== uncompressedSize) {
186
+ throw new Error(`Size mismatch for "${name}": expected ${uncompressedSize}, got ${data.length}`);
187
+ }
188
+ if (name.endsWith("/"))
189
+ continue;
190
+ entries.push({ name, data });
191
+ }
192
+ return entries;
193
+ }
194
+ function isZip(file) {
195
+ return file.length >= 4 && file.subarray(0, 4).equals(ZIP_MAGIC);
196
+ }
197
+ // Recursively normalize a decoded kiwi document into plain, JSON-safe values.
198
+ // We walk the tree directly instead of `JSON.parse(JSON.stringify(...))`:
199
+ // real Figma files decode to hundreds of thousands of nodes, and serializing
200
+ // the whole tree to a single string blows V8's max-string-length limit
201
+ // (RangeError: Invalid string length). A direct walk has no such ceiling.
202
+ function normalizeDecoded(value) {
203
+ if (value instanceof Uint8Array)
204
+ return Buffer.from(value).toString("hex");
205
+ if (typeof value === "bigint")
206
+ return value.toString();
207
+ if (Array.isArray(value)) {
208
+ const arr = new Array(value.length);
209
+ for (let i = 0; i < value.length; i++)
210
+ arr[i] = normalizeDecoded(value[i]);
211
+ return arr;
212
+ }
213
+ if (value && typeof value === "object") {
214
+ const out = {};
215
+ for (const k of Object.keys(value)) {
216
+ const v = value[k];
217
+ if (v === undefined)
218
+ continue;
219
+ out[k] = normalizeDecoded(v);
220
+ }
221
+ return out;
222
+ }
223
+ return value;
224
+ }
225
+ // Returns null on any decode failure so callers can still surface the raw
226
+ // document buffer.
227
+ function decodeKiwiDocument(schemaBuf, documentBuf) {
228
+ let schema;
229
+ try {
230
+ schema = decodeBinarySchema(schemaBuf);
231
+ }
232
+ catch {
233
+ return null;
234
+ }
235
+ const rootMessage = schema.definitions.find((d) => d.name === "Message")?.name ??
236
+ schema.definitions.find((d) => d.kind === "MESSAGE")?.name ??
237
+ null;
238
+ if (!rootMessage)
239
+ return null;
240
+ let compiled;
241
+ try {
242
+ compiled = compileSchema(schema);
243
+ }
244
+ catch {
245
+ return null;
246
+ }
247
+ const decodeKey = `decode${rootMessage}`;
248
+ const decoder = compiled[decodeKey];
249
+ if (typeof decoder !== "function")
250
+ return null;
251
+ try {
252
+ const view = new Uint8Array(documentBuf.buffer, documentBuf.byteOffset, documentBuf.byteLength);
253
+ const bb = new ByteBuffer(view);
254
+ const document = decoder.call(compiled, bb);
255
+ return normalizeDecoded(document);
256
+ }
257
+ catch {
258
+ return null;
259
+ }
260
+ }
261
+ function collectImagesFromBlobs(blobs) {
262
+ const seen = new Map();
263
+ for (const blob of blobs) {
264
+ if (blob.length === 0)
265
+ continue;
266
+ const ext = detectImageExt(blob);
267
+ if (ext === "bin")
268
+ continue;
269
+ const hash = sha1(blob);
270
+ if (seen.has(hash))
271
+ continue;
272
+ seen.set(hash, { hash, ext, bytes: blob });
273
+ }
274
+ return Array.from(seen.values());
275
+ }
276
+ function findThumbnail(documentBuf, blobs) {
277
+ const pngBlobs = blobs
278
+ .filter((b) => b.length >= 8 && b.subarray(0, 8).equals(PNG_MAGIC))
279
+ .sort((a, b) => a.length - b.length);
280
+ if (pngBlobs.length > 0)
281
+ return pngBlobs[0];
282
+ const idx = documentBuf.indexOf(PNG_MAGIC);
283
+ if (idx >= 0) {
284
+ const iend = Buffer.from([0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]);
285
+ const end = documentBuf.indexOf(iend, idx);
286
+ if (end > idx)
287
+ return documentBuf.subarray(idx, end + iend.length);
288
+ }
289
+ return null;
290
+ }
291
+ // Handles both modern fig-kiwi files and legacy zip-format archives.
292
+ // `document` is null if kiwi decoding failed.
293
+ export function decodeFig(file) {
294
+ if (isZip(file)) {
295
+ const entries = readZip(file);
296
+ const canvasEntry = entries.find((e) => e.name === "canvas.fig");
297
+ const imageEntries = entries.filter((e) => e.name.startsWith("images/"));
298
+ let document = null;
299
+ let version;
300
+ let extraBlobs = [];
301
+ if (canvasEntry) {
302
+ try {
303
+ const inner = decodeKiwiContainer(canvasEntry.data);
304
+ version = inner.version;
305
+ extraBlobs = inner.blobs;
306
+ document = decodeKiwiDocument(inner.schema, inner.document);
307
+ }
308
+ catch {
309
+ /* leave document null */
310
+ }
311
+ }
312
+ const images = [];
313
+ const seen = new Set();
314
+ for (const e of imageEntries) {
315
+ const ext = detectImageExt(e.data) || "bin";
316
+ if (ext === "bin")
317
+ continue;
318
+ const hash = sha1(e.data);
319
+ if (seen.has(hash))
320
+ continue;
321
+ seen.add(hash);
322
+ images.push({ hash, ext, bytes: e.data });
323
+ }
324
+ for (const img of collectImagesFromBlobs(extraBlobs)) {
325
+ if (seen.has(img.hash))
326
+ continue;
327
+ seen.add(img.hash);
328
+ images.push(img);
329
+ }
330
+ const thumbnailEntry = entries.find((e) => e.name === "thumbnail.png");
331
+ return {
332
+ format: "zip",
333
+ version,
334
+ document,
335
+ images,
336
+ thumbnail: thumbnailEntry?.data ?? null,
337
+ };
338
+ }
339
+ const decoded = decodeKiwiContainer(file);
340
+ const document = decodeKiwiDocument(decoded.schema, decoded.document);
341
+ const images = collectImagesFromBlobs(decoded.blobs);
342
+ const thumbnail = findThumbnail(decoded.document, decoded.blobs);
343
+ return {
344
+ format: "kiwi",
345
+ version: decoded.version,
346
+ document,
347
+ images,
348
+ thumbnail,
349
+ };
350
+ }
351
+ export function buildImageMap(images) {
352
+ const map = new Map();
353
+ for (const img of images) {
354
+ map.set(img.hash, `${img.hash}.${img.ext}`);
355
+ }
356
+ return map;
357
+ }
358
+ //# sourceMappingURL=decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.js","sourceRoot":"","sources":["../../../src/brand-kit/fig/decode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Binary decoder for Figma `.fig` files. Handles both modern fig-kiwi files\n * (a custom container of kiwi-schema chunks, optionally zstd/zlib compressed)\n * and the legacy zip-format archives. Returns the decoded document node tree,\n * extracted image blobs (SHA1-keyed, with magic-byte extensions), and a\n * best-effort thumbnail.\n *\n * Ported faithfully from the ai-services design-systems pipeline. It is a pure\n * function on a Buffer — no storage, queue, or job coupling.\n */\n\nimport * as zlib from \"node:zlib\";\nimport * as crypto from \"node:crypto\";\nimport * as pako from \"pako\";\nimport { decompress as zstdDecompress } from \"fzstd\";\nimport {\n ByteBuffer,\n compileSchema,\n decodeBinarySchema,\n type Schema,\n} from \"kiwi-schema\";\n\nconst MAX_DECOMPRESSED_BYTES = 512 * 1024 * 1024; // 512 MB cap per chunk to prevent compression bombs\nconst ZSTD_MAGIC = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]);\nconst FIG_KIWI_MAGIC = Buffer.from(\"fig-kiwi\", \"utf8\");\nconst ZIP_MAGIC = Buffer.from([0x50, 0x4b, 0x03, 0x04]);\nconst PNG_MAGIC = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);\nconst JPEG_MAGIC = Buffer.from([0xff, 0xd8, 0xff]);\n\nexport interface DecodedFigKiwi {\n version: number;\n schema: Buffer;\n document: Buffer;\n blobs: Buffer[];\n}\n\nexport interface DecodedFigImage {\n /** SHA1 of the blob bytes — matches what the document references. */\n hash: string;\n ext: string;\n bytes: Buffer;\n}\n\nexport interface DecodedFig {\n format: \"kiwi\" | \"zip\";\n version?: number;\n document: unknown;\n images: DecodedFigImage[];\n thumbnail: Buffer | null;\n}\n\nfunction sha1(buf: Buffer): string {\n return crypto.createHash(\"sha1\").update(buf).digest(\"hex\");\n}\n\nfunction detectImageExt(buf: Buffer): string {\n if (buf.length >= 8 && buf.subarray(0, 8).equals(PNG_MAGIC)) return \"png\";\n if (buf.length >= 3 && buf.subarray(0, 3).equals(JPEG_MAGIC)) return \"jpg\";\n if (\n buf.length >= 12 &&\n buf.subarray(0, 4).toString(\"ascii\") === \"RIFF\" &&\n buf.subarray(8, 12).toString(\"ascii\") === \"WEBP\"\n ) {\n return \"webp\";\n }\n if (buf.length >= 4 && buf.subarray(0, 4).toString(\"ascii\") === \"GIF8\") {\n return \"gif\";\n }\n return \"bin\";\n}\n\nfunction checkDecompressedSize(buf: Buffer): Buffer {\n if (buf.length > MAX_DECOMPRESSED_BYTES) {\n throw new Error(\n `Decompressed chunk exceeds size limit (${buf.length} > ${MAX_DECOMPRESSED_BYTES})`,\n );\n }\n return buf;\n}\n\nfunction decompressChunk(buf: Buffer): Buffer {\n if (buf.length >= 4 && buf.subarray(0, 4).equals(ZSTD_MAGIC)) {\n try {\n return checkDecompressedSize(Buffer.from(zstdDecompress(buf)));\n } catch {\n /* fall through */\n }\n }\n try {\n return zlib.inflateRawSync(buf, {\n maxOutputLength: MAX_DECOMPRESSED_BYTES,\n });\n } catch (e) {\n if (e instanceof RangeError) throw e; // output exceeded size cap; don't fall through\n /* fall through for format/data errors */\n }\n try {\n return zlib.inflateSync(buf, { maxOutputLength: MAX_DECOMPRESSED_BYTES });\n } catch (e) {\n if (e instanceof RangeError) throw e;\n /* fall through */\n }\n try {\n return checkDecompressedSize(Buffer.from(pako.inflateRaw(buf)));\n } catch {\n /* fall through */\n }\n try {\n return checkDecompressedSize(Buffer.from(pako.inflate(buf)));\n } catch {\n /* fall through */\n }\n return Buffer.from(buf);\n}\n\nexport function decodeKiwiContainer(file: Buffer): DecodedFigKiwi {\n if (!file.subarray(0, 8).equals(FIG_KIWI_MAGIC)) {\n throw new Error(\"Not a fig-kiwi file (missing magic header)\");\n }\n if (file.length < 12) {\n throw new Error(\n \"Truncated kiwi header (file too short to contain version)\",\n );\n }\n const version = file.readUInt32LE(8);\n let offset = 12;\n const chunks: Buffer[] = [];\n while (offset < file.length) {\n if (offset + 4 > file.length) {\n throw new Error(`Truncated chunk header at offset ${offset}`);\n }\n const length = file.readUInt32LE(offset);\n offset += 4;\n if (offset + length > file.length) {\n throw new Error(\n `Chunk extends past end of file (offset=${offset}, length=${length}, total=${file.length})`,\n );\n }\n const compressed = file.subarray(offset, offset + length);\n offset += length;\n chunks.push(decompressChunk(compressed));\n }\n if (chunks.length < 2) {\n throw new Error(\n `Expected at least 2 chunks (schema + document), got ${chunks.length}`,\n );\n }\n return {\n version,\n schema: chunks[0]!,\n document: chunks[1]!,\n blobs: chunks.slice(2),\n };\n}\n\ninterface ZipEntry {\n name: string;\n data: Buffer;\n}\n\n/**\n * Minimal zip reader: supports stored (method 0) and deflate (method 8)\n * entries, no encryption, no zip64. Sufficient for legacy `.fig` archives.\n */\nfunction readZip(file: Buffer): ZipEntry[] {\n const EOCD_SIG = 0x06054b50;\n const maxScan = Math.min(file.length, 65557);\n let eocdOffset = -1;\n for (let i = file.length - 22; i >= file.length - maxScan && i >= 0; i--) {\n if (file.readUInt32LE(i) === EOCD_SIG) {\n eocdOffset = i;\n break;\n }\n }\n if (eocdOffset < 0) throw new Error(\"Zip EOCD record not found\");\n\n const totalEntries = file.readUInt16LE(eocdOffset + 10);\n const cdOffset = file.readUInt32LE(eocdOffset + 16);\n if (cdOffset > file.length) {\n throw new Error(`Central directory offset ${cdOffset} exceeds file length`);\n }\n\n const entries: ZipEntry[] = [];\n let p = cdOffset;\n for (let i = 0; i < totalEntries; i++) {\n if (p + 46 > file.length) {\n throw new Error(`Truncated central directory entry at offset ${p}`);\n }\n if (file.readUInt32LE(p) !== 0x02014b50) {\n throw new Error(`Bad central directory entry signature at ${p}`);\n }\n const compressionMethod = file.readUInt16LE(p + 10);\n const compressedSize = file.readUInt32LE(p + 20);\n const uncompressedSize = file.readUInt32LE(p + 24);\n const nameLen = file.readUInt16LE(p + 28);\n const extraLen = file.readUInt16LE(p + 30);\n const commentLen = file.readUInt16LE(p + 32);\n const localHeaderOffset = file.readUInt32LE(p + 42);\n const name = file.subarray(p + 46, p + 46 + nameLen).toString(\"utf8\");\n p += 46 + nameLen + extraLen + commentLen;\n\n const lh = localHeaderOffset;\n if (lh + 30 > file.length) {\n throw new Error(`Local header offset ${lh} out of bounds`);\n }\n if (file.readUInt32LE(lh) !== 0x04034b50) {\n throw new Error(`Bad local file header signature at ${lh}`);\n }\n const lhNameLen = file.readUInt16LE(lh + 26);\n const lhExtraLen = file.readUInt16LE(lh + 28);\n const dataStart = lh + 30 + lhNameLen + lhExtraLen;\n if (dataStart + compressedSize > file.length) {\n throw new Error(`Compressed data for \"${name}\" extends past end of file`);\n }\n const compressed = file.subarray(dataStart, dataStart + compressedSize);\n\n let data: Buffer;\n if (compressionMethod === 0) {\n data = Buffer.from(compressed);\n } else if (compressionMethod === 8) {\n data = zlib.inflateRawSync(compressed, {\n maxOutputLength: MAX_DECOMPRESSED_BYTES,\n });\n } else {\n throw new Error(\n `Unsupported zip compression method ${compressionMethod} for entry \"${name}\"`,\n );\n }\n if (uncompressedSize !== 0 && data.length !== uncompressedSize) {\n throw new Error(\n `Size mismatch for \"${name}\": expected ${uncompressedSize}, got ${data.length}`,\n );\n }\n if (name.endsWith(\"/\")) continue;\n entries.push({ name, data });\n }\n return entries;\n}\n\nfunction isZip(file: Buffer): boolean {\n return file.length >= 4 && file.subarray(0, 4).equals(ZIP_MAGIC);\n}\n\n// Recursively normalize a decoded kiwi document into plain, JSON-safe values.\n// We walk the tree directly instead of `JSON.parse(JSON.stringify(...))`:\n// real Figma files decode to hundreds of thousands of nodes, and serializing\n// the whole tree to a single string blows V8's max-string-length limit\n// (RangeError: Invalid string length). A direct walk has no such ceiling.\nfunction normalizeDecoded(value: unknown): unknown {\n if (value instanceof Uint8Array) return Buffer.from(value).toString(\"hex\");\n if (typeof value === \"bigint\") return value.toString();\n if (Array.isArray(value)) {\n const arr = new Array(value.length);\n for (let i = 0; i < value.length; i++) arr[i] = normalizeDecoded(value[i]);\n return arr;\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>)) {\n const v = (value as Record<string, unknown>)[k];\n if (v === undefined) continue;\n out[k] = normalizeDecoded(v);\n }\n return out;\n }\n return value;\n}\n\n// Returns null on any decode failure so callers can still surface the raw\n// document buffer.\nfunction decodeKiwiDocument(\n schemaBuf: Buffer,\n documentBuf: Buffer,\n): unknown | null {\n let schema: Schema;\n try {\n schema = decodeBinarySchema(schemaBuf);\n } catch {\n return null;\n }\n const rootMessage =\n schema.definitions.find((d) => d.name === \"Message\")?.name ??\n schema.definitions.find((d) => d.kind === \"MESSAGE\")?.name ??\n null;\n if (!rootMessage) return null;\n\n let compiled: Record<string, (bb: ByteBuffer) => unknown>;\n try {\n compiled = compileSchema(schema) as Record<\n string,\n (bb: ByteBuffer) => unknown\n >;\n } catch {\n return null;\n }\n const decodeKey = `decode${rootMessage}`;\n const decoder = compiled[decodeKey];\n if (typeof decoder !== \"function\") return null;\n\n try {\n const view = new Uint8Array(\n documentBuf.buffer,\n documentBuf.byteOffset,\n documentBuf.byteLength,\n );\n const bb = new ByteBuffer(view);\n const document = decoder.call(compiled, bb);\n return normalizeDecoded(document);\n } catch {\n return null;\n }\n}\n\nfunction collectImagesFromBlobs(blobs: Buffer[]): DecodedFigImage[] {\n const seen = new Map<string, DecodedFigImage>();\n for (const blob of blobs) {\n if (blob.length === 0) continue;\n const ext = detectImageExt(blob);\n if (ext === \"bin\") continue;\n const hash = sha1(blob);\n if (seen.has(hash)) continue;\n seen.set(hash, { hash, ext, bytes: blob });\n }\n return Array.from(seen.values());\n}\n\nfunction findThumbnail(documentBuf: Buffer, blobs: Buffer[]): Buffer | null {\n const pngBlobs = blobs\n .filter((b) => b.length >= 8 && b.subarray(0, 8).equals(PNG_MAGIC))\n .sort((a, b) => a.length - b.length);\n if (pngBlobs.length > 0) return pngBlobs[0]!;\n\n const idx = documentBuf.indexOf(PNG_MAGIC);\n if (idx >= 0) {\n const iend = Buffer.from([0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]);\n const end = documentBuf.indexOf(iend, idx);\n if (end > idx) return documentBuf.subarray(idx, end + iend.length);\n }\n return null;\n}\n\n// Handles both modern fig-kiwi files and legacy zip-format archives.\n// `document` is null if kiwi decoding failed.\nexport function decodeFig(file: Buffer): DecodedFig {\n if (isZip(file)) {\n const entries = readZip(file);\n const canvasEntry = entries.find((e) => e.name === \"canvas.fig\");\n const imageEntries = entries.filter((e) => e.name.startsWith(\"images/\"));\n\n let document: unknown = null;\n let version: number | undefined;\n let extraBlobs: Buffer[] = [];\n if (canvasEntry) {\n try {\n const inner = decodeKiwiContainer(canvasEntry.data);\n version = inner.version;\n extraBlobs = inner.blobs;\n document = decodeKiwiDocument(inner.schema, inner.document);\n } catch {\n /* leave document null */\n }\n }\n\n const images: DecodedFigImage[] = [];\n const seen = new Set<string>();\n for (const e of imageEntries) {\n const ext = detectImageExt(e.data) || \"bin\";\n if (ext === \"bin\") continue;\n const hash = sha1(e.data);\n if (seen.has(hash)) continue;\n seen.add(hash);\n images.push({ hash, ext, bytes: e.data });\n }\n for (const img of collectImagesFromBlobs(extraBlobs)) {\n if (seen.has(img.hash)) continue;\n seen.add(img.hash);\n images.push(img);\n }\n\n const thumbnailEntry = entries.find((e) => e.name === \"thumbnail.png\");\n return {\n format: \"zip\",\n version,\n document,\n images,\n thumbnail: thumbnailEntry?.data ?? null,\n };\n }\n\n const decoded = decodeKiwiContainer(file);\n const document = decodeKiwiDocument(decoded.schema, decoded.document);\n const images = collectImagesFromBlobs(decoded.blobs);\n const thumbnail = findThumbnail(decoded.document, decoded.blobs);\n return {\n format: \"kiwi\",\n version: decoded.version,\n document,\n images,\n thumbnail,\n };\n}\n\nexport function buildImageMap(images: DecodedFigImage[]): Map<string, string> {\n const map = new Map<string, string>();\n for (const img of images) {\n map.set(img.hash, `${img.hash}.${img.ext}`);\n }\n return map;\n}\n"]}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Walk a decoded Figma document (the kiwi `Message` tree produced by
3
+ * `decodeFig`) and distil a rich brand profile from it: color roles + palette,
4
+ * a full typographic system (families, weights, scale, letter-spacing, label
5
+ * case), spacing rhythm, corner character, an elevation ramp, and — crucially —
6
+ * the SIGNATURE GRADIENTS and a synthesized brand-character brief.
7
+ *
8
+ * The goal is on-brand generation: not just "use the right fonts and colors",
9
+ * but capture what is distinctive about the brand (its gradient, density,
10
+ * corner language, contrast, type personality) so generated designs feel
11
+ * unmistakably on-brand. The brief is emitted as `customInstructions` (the
12
+ * free-form guidance the generator follows) and the gradients/elevation as
13
+ * `customCSS` tokens.
14
+ *
15
+ * Heuristic by necessity: Figma documents carry no canonical "design system",
16
+ * so we cluster/weight observed values and assign roles by saturation,
17
+ * lightness, contrast, and area. The result is reviewable before saving.
18
+ */
19
+ import type { BrandKitData, BrandKitDefaults } from "../types.js";
20
+ export interface ExtractedFigTokens extends Partial<BrandKitData> {
21
+ /** Surface defaults inferred from the file. Templates map this to their
22
+ * persisted defaults key, e.g. `defaults` or `slideDefaults`. */
23
+ defaults?: BrandKitDefaults;
24
+ /** Raw, de-duplicated color palette (most frequent first) for reference. */
25
+ palette?: {
26
+ hex: string;
27
+ name?: string;
28
+ count: number;
29
+ }[];
30
+ /** Named color styles found in the file (key = style name). */
31
+ namedColors?: Record<string, string>;
32
+ /** Signature gradients found in the file, as ready-to-use CSS. */
33
+ gradients?: string[];
34
+ /**
35
+ * A synthesized brand-character brief — the free-form guidance the generator
36
+ * should follow to produce on-brand designs. Goes into the design system's
37
+ * `customInstructions`.
38
+ */
39
+ customInstructions?: string;
40
+ /** Count of nodes walked, for provenance/preview. */
41
+ nodeCount?: number;
42
+ }
43
+ export declare function extractDesignSystemFromFig(document: unknown): ExtractedFigTokens;
44
+ //# sourceMappingURL=extract-design-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-design-system.d.ts","sourceRoot":"","sources":["../../../src/brand-kit/fig/extract-design-system.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA2SlE,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,YAAY,CAAC;IAC/D;qEACiE;IACjE,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,4EAA4E;IAC5E,OAAO,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1D,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,OAAO,GAChB,kBAAkB,CA0cpB"}