@spinabot/brigade 1.9.0 → 1.10.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.
- package/README.md +12 -10
- package/dist/agents/agent-loop.d.ts +55 -0
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +90 -1
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/channels/inbound-pipeline.d.ts +22 -0
- package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
- package/dist/agents/channels/inbound-pipeline.js +31 -1
- package/dist/agents/channels/inbound-pipeline.js.map +1 -1
- package/dist/agents/channels/media-capture.d.ts +69 -6
- package/dist/agents/channels/media-capture.d.ts.map +1 -1
- package/dist/agents/channels/media-capture.js +125 -8
- package/dist/agents/channels/media-capture.js.map +1 -1
- package/dist/agents/channels/telegram/media.d.ts.map +1 -1
- package/dist/agents/channels/telegram/media.js +16 -4
- package/dist/agents/channels/telegram/media.js.map +1 -1
- package/dist/agents/channels/whatsapp/media.d.ts +19 -0
- package/dist/agents/channels/whatsapp/media.d.ts.map +1 -1
- package/dist/agents/channels/whatsapp/media.js +37 -2
- package/dist/agents/channels/whatsapp/media.js.map +1 -1
- package/dist/agents/media-understanding/anthropic-adapter.d.ts +49 -0
- package/dist/agents/media-understanding/anthropic-adapter.d.ts.map +1 -0
- package/dist/agents/media-understanding/anthropic-adapter.js +162 -0
- package/dist/agents/media-understanding/anthropic-adapter.js.map +1 -0
- package/dist/agents/media-understanding/config.d.ts +57 -0
- package/dist/agents/media-understanding/config.d.ts.map +1 -0
- package/dist/agents/media-understanding/config.js +289 -0
- package/dist/agents/media-understanding/config.js.map +1 -0
- package/dist/agents/media-understanding/gemini-adapter.d.ts +57 -0
- package/dist/agents/media-understanding/gemini-adapter.d.ts.map +1 -0
- package/dist/agents/media-understanding/gemini-adapter.js +343 -0
- package/dist/agents/media-understanding/gemini-adapter.js.map +1 -0
- package/dist/agents/media-understanding/index.d.ts +58 -0
- package/dist/agents/media-understanding/index.d.ts.map +1 -0
- package/dist/agents/media-understanding/index.js +275 -0
- package/dist/agents/media-understanding/index.js.map +1 -0
- package/dist/agents/media-understanding/pi-adapter.d.ts +72 -0
- package/dist/agents/media-understanding/pi-adapter.d.ts.map +1 -0
- package/dist/agents/media-understanding/pi-adapter.js +160 -0
- package/dist/agents/media-understanding/pi-adapter.js.map +1 -0
- package/dist/agents/media-understanding/types.d.ts +189 -0
- package/dist/agents/media-understanding/types.d.ts.map +1 -0
- package/dist/agents/media-understanding/types.js +51 -0
- package/dist/agents/media-understanding/types.js.map +1 -0
- package/dist/agents/session-wiring.d.ts +11 -0
- package/dist/agents/session-wiring.d.ts.map +1 -1
- package/dist/agents/session-wiring.js +1 -0
- package/dist/agents/session-wiring.js.map +1 -1
- package/dist/agents/tools/analyze-media-tool.d.ts +263 -0
- package/dist/agents/tools/analyze-media-tool.d.ts.map +1 -0
- package/dist/agents/tools/analyze-media-tool.js +2321 -0
- package/dist/agents/tools/analyze-media-tool.js.map +1 -0
- package/dist/agents/tools/doc-shared.d.ts +187 -0
- package/dist/agents/tools/doc-shared.d.ts.map +1 -0
- package/dist/agents/tools/doc-shared.js +484 -0
- package/dist/agents/tools/doc-shared.js.map +1 -0
- package/dist/agents/tools/edit-document-tool.d.ts +133 -0
- package/dist/agents/tools/edit-document-tool.d.ts.map +1 -0
- package/dist/agents/tools/edit-document-tool.js +815 -0
- package/dist/agents/tools/edit-document-tool.js.map +1 -0
- package/dist/agents/tools/image-downscale.d.ts +93 -0
- package/dist/agents/tools/image-downscale.d.ts.map +1 -0
- package/dist/agents/tools/image-downscale.js +257 -0
- package/dist/agents/tools/image-downscale.js.map +1 -0
- package/dist/agents/tools/make-document-tool.d.ts +114 -0
- package/dist/agents/tools/make-document-tool.d.ts.map +1 -0
- package/dist/agents/tools/make-document-tool.js +542 -0
- package/dist/agents/tools/make-document-tool.js.map +1 -0
- package/dist/agents/tools/media-cache.d.ts +56 -0
- package/dist/agents/tools/media-cache.d.ts.map +1 -0
- package/dist/agents/tools/media-cache.js +133 -0
- package/dist/agents/tools/media-cache.js.map +1 -0
- package/dist/agents/tools/ooxml-images.d.ts +107 -0
- package/dist/agents/tools/ooxml-images.d.ts.map +1 -0
- package/dist/agents/tools/ooxml-images.js +308 -0
- package/dist/agents/tools/ooxml-images.js.map +1 -0
- package/dist/agents/tools/registry.d.ts +12 -0
- package/dist/agents/tools/registry.d.ts.map +1 -1
- package/dist/agents/tools/registry.js +47 -0
- package/dist/agents/tools/registry.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +41 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/core/console-stream.d.ts.map +1 -1
- package/dist/core/console-stream.js +7 -5
- package/dist/core/console-stream.js.map +1 -1
- package/dist/core/server.js +6 -1
- package/dist/core/server.js.map +1 -1
- package/dist/system-prompt/assembler.d.ts.map +1 -1
- package/dist/system-prompt/assembler.js +25 -1
- package/dist/system-prompt/assembler.js.map +1 -1
- package/dist/system-prompt/guidance.d.ts +30 -0
- package/dist/system-prompt/guidance.d.ts.map +1 -1
- package/dist/system-prompt/guidance.js +50 -0
- package/dist/system-prompt/guidance.js.map +1 -1
- package/package.json +9 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny disk-backed LRU cache for `analyze_media` PROVIDER results.
|
|
3
|
+
*
|
|
4
|
+
* A provider understanding call (Gemini / Anthropic over the media bytes) is the
|
|
5
|
+
* one expensive, billable step in the tool. When the SAME bytes + question +
|
|
6
|
+
* provider + model + token budget are analyzed again (e.g. the operator re-asks,
|
|
7
|
+
* or a cron re-runs over an unchanged attachment), we can return the cached TEXT
|
|
8
|
+
* instead of paying for the call again.
|
|
9
|
+
*
|
|
10
|
+
* Storage model — ONE small JSON file per key under
|
|
11
|
+
* `resolveCacheDir()/analyze-media/`:
|
|
12
|
+
* • mode-aware: `resolveCacheDir()` already returns the OS cache root in
|
|
13
|
+
* convex/strict-zero mode (keeps `~/.brigade` clean) and the state cache dir
|
|
14
|
+
* in filesystem mode.
|
|
15
|
+
* • per-key files (not one shared file) → concurrent agents never clobber each
|
|
16
|
+
* other's writes; a corrupt entry only loses itself.
|
|
17
|
+
* • LRU bound: on write, if the directory exceeds the entry cap, the
|
|
18
|
+
* oldest-by-mtime files are deleted. A TTL also expires stale entries on read.
|
|
19
|
+
*
|
|
20
|
+
* The cache is BEST-EFFORT: any fs error (read, write, mkdir) is swallowed — a
|
|
21
|
+
* cache miss just means the provider gets called, never a tool failure.
|
|
22
|
+
*/
|
|
23
|
+
import { createHash } from "node:crypto";
|
|
24
|
+
import fs from "node:fs";
|
|
25
|
+
import fsp from "node:fs/promises";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import { resolveCacheDir } from "../../config/paths.js";
|
|
28
|
+
/** Max entries kept on disk before LRU eviction (by mtime). */
|
|
29
|
+
const DEFAULT_MAX_ENTRIES = 200;
|
|
30
|
+
/** Entry TTL — a cached provider answer older than this is ignored + cleaned. */
|
|
31
|
+
const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
32
|
+
/** Compute the cache key = sha256 over the identifying parts (hex). */
|
|
33
|
+
export function mediaCacheKey(parts) {
|
|
34
|
+
const h = createHash("sha256");
|
|
35
|
+
h.update(parts.kind);
|
|
36
|
+
h.update("\0");
|
|
37
|
+
h.update(parts.provider);
|
|
38
|
+
h.update("\0");
|
|
39
|
+
h.update(parts.model ?? "");
|
|
40
|
+
h.update("\0");
|
|
41
|
+
h.update(String(parts.maxTokens ?? ""));
|
|
42
|
+
h.update("\0");
|
|
43
|
+
h.update(parts.question);
|
|
44
|
+
h.update("\0");
|
|
45
|
+
// Hash the bytes last (largest input). The content hash is what makes the
|
|
46
|
+
// key change when the underlying media changes.
|
|
47
|
+
h.update(parts.bytes);
|
|
48
|
+
return h.digest("hex");
|
|
49
|
+
}
|
|
50
|
+
/** Resolve (and lazily create) the cache directory. Returns undefined on failure. */
|
|
51
|
+
function cacheDir() {
|
|
52
|
+
try {
|
|
53
|
+
const dir = path.join(resolveCacheDir(), "analyze-media");
|
|
54
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
55
|
+
return dir;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Read a cached provider result. Returns `undefined` on a miss, a corrupt entry,
|
|
63
|
+
* or an expired entry (which is also unlinked). Never throws.
|
|
64
|
+
*/
|
|
65
|
+
export async function readMediaCache(key, opts = {}) {
|
|
66
|
+
const dir = opts.dir ?? cacheDir();
|
|
67
|
+
if (!dir)
|
|
68
|
+
return undefined;
|
|
69
|
+
const file = path.join(dir, `${key}.json`);
|
|
70
|
+
try {
|
|
71
|
+
const stat = await fsp.stat(file);
|
|
72
|
+
const ttl = opts.ttlMs ?? DEFAULT_TTL_MS;
|
|
73
|
+
if (Date.now() - stat.mtimeMs > ttl) {
|
|
74
|
+
void fsp.unlink(file).catch(() => { });
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const raw = await fsp.readFile(file, "utf8");
|
|
78
|
+
const parsed = JSON.parse(raw);
|
|
79
|
+
if (typeof parsed.text === "string" && parsed.text.length > 0) {
|
|
80
|
+
// Touch mtime so LRU treats a cache HIT as recently-used.
|
|
81
|
+
void fsp.utimes(file, new Date(), new Date()).catch(() => { });
|
|
82
|
+
return {
|
|
83
|
+
text: parsed.text,
|
|
84
|
+
provider: typeof parsed.provider === "string" ? parsed.provider : "",
|
|
85
|
+
model: typeof parsed.model === "string" ? parsed.model : "",
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
/* miss / corrupt / unreadable → undefined */
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Write a provider result to the cache + evict the oldest entries when over the
|
|
96
|
+
* cap. Best-effort: any failure is swallowed. Returns nothing.
|
|
97
|
+
*/
|
|
98
|
+
export async function writeMediaCache(key, value, opts = {}) {
|
|
99
|
+
const dir = opts.dir ?? cacheDir();
|
|
100
|
+
if (!dir)
|
|
101
|
+
return;
|
|
102
|
+
const file = path.join(dir, `${key}.json`);
|
|
103
|
+
try {
|
|
104
|
+
await fsp.writeFile(file, JSON.stringify(value), "utf8");
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return; // could not persist — give up silently
|
|
108
|
+
}
|
|
109
|
+
// LRU eviction: if the directory holds more than the cap, delete the oldest
|
|
110
|
+
// by mtime. Cheap (a stat per entry) and only runs on writes.
|
|
111
|
+
try {
|
|
112
|
+
const max = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
113
|
+
const names = (await fsp.readdir(dir)).filter((n) => n.endsWith(".json"));
|
|
114
|
+
if (names.length <= max)
|
|
115
|
+
return;
|
|
116
|
+
const stats = await Promise.all(names.map(async (n) => {
|
|
117
|
+
try {
|
|
118
|
+
const s = await fsp.stat(path.join(dir, n));
|
|
119
|
+
return { n, mtime: s.mtimeMs };
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return { n, mtime: 0 };
|
|
123
|
+
}
|
|
124
|
+
}));
|
|
125
|
+
stats.sort((a, b) => a.mtime - b.mtime); // oldest first
|
|
126
|
+
const toDelete = stats.slice(0, names.length - max);
|
|
127
|
+
await Promise.all(toDelete.map((e) => fsp.unlink(path.join(dir, e.n)).catch(() => { })));
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
/* eviction is best-effort */
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=media-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-cache.js","sourceRoot":"","sources":["../../../src/agents/tools/media-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded-image extraction for OOXML documents (PPTX / DOCX / XLSX) — the
|
|
3
|
+
* "see the wireframes inside the deck" half of `analyze_media`.
|
|
4
|
+
*
|
|
5
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* WHY THIS MODULE (read before changing)
|
|
7
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
8
|
+
* `analyze_media`'s OOXML readers return only the document TEXT (slide titles,
|
|
9
|
+
* paragraph runs, cell strings). But a real deck carries its substance in the
|
|
10
|
+
* PICTURES — wireframes, screenshots, diagrams, charts rendered to images. Asked
|
|
11
|
+
* to "go through the wireframe images in this .pptx", the agent used to have to
|
|
12
|
+
* shell out to `python zipfile` to pull `ppt/media/*.png`, then re-run
|
|
13
|
+
* `analyze_media` on each PNG. This module closes that gap: it extracts the
|
|
14
|
+
* embedded raster images straight from the already-unzipped OOXML entries the
|
|
15
|
+
* reader has in hand, so the tool can route them through the SAME image path it
|
|
16
|
+
* already uses (image blocks on a vision model / a provider on a text-only one).
|
|
17
|
+
*
|
|
18
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
19
|
+
* SLIDE / PAGE SCOPING (the important part for PPTX)
|
|
20
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
21
|
+
* A PPTX maps images to slides through the relationship graph, NOT by filename:
|
|
22
|
+
* presentation.xml → <p:sldId r:id="rIdN"/> in PRESENTATION order
|
|
23
|
+
* presentation.xml.rels → rIdN → ppt/slides/slideK.xml
|
|
24
|
+
* slideK.xml.rels → rIdM → ../media/imageX.png (that slide's images)
|
|
25
|
+
* So slide N's images are exactly the `../media/*` targets in that slide's rels
|
|
26
|
+
* file — which is what the manual workaround discovered ("SLIDE 8 rId3
|
|
27
|
+
* ../media/image16.png"). We resolve slides in presentation order, then honour
|
|
28
|
+
* the existing `pages` range over THAT order, returning only the selected
|
|
29
|
+
* slides' images. (Image filename numbering does NOT track slide order, so a
|
|
30
|
+
* filename-only approach would scope wrong — we never use it for PPTX.)
|
|
31
|
+
*
|
|
32
|
+
* DOCX/XLSX have no robust per-page image mapping (a Word page is a layout-time
|
|
33
|
+
* concept, not in the XML), so we return ALL embedded images (capped) when no
|
|
34
|
+
* scope applies — the `pages` range is honoured only for PPTX.
|
|
35
|
+
*
|
|
36
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
37
|
+
* UNSUPPORTED EMBEDS
|
|
38
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
39
|
+
* Only provider-DECODABLE raster types are surfaced (png/jpeg/gif/webp/bmp/
|
|
40
|
+
* tiff). Vector / exotic embeds — `.emf` / `.wmf` (Windows metafiles) and
|
|
41
|
+
* `.wdp` (JPEG-XR / HD Photo) — cannot be decoded without a native dep, so they
|
|
42
|
+
* are SKIPPED with a count (the real failure case hit `hdphoto1.wdp`). The
|
|
43
|
+
* caller reports "N image(s) skipped (unsupported format)" rather than throwing.
|
|
44
|
+
*
|
|
45
|
+
* Pure functions over an already-unzipped entry map; no I/O, no provider calls.
|
|
46
|
+
*/
|
|
47
|
+
/** An embedded image pulled out of an OOXML document. */
|
|
48
|
+
export interface ExtractedOoxmlImage {
|
|
49
|
+
/** Zip entry name, e.g. `ppt/media/image16.png`. */
|
|
50
|
+
entry: string;
|
|
51
|
+
/** Raw image bytes. */
|
|
52
|
+
bytes: Buffer;
|
|
53
|
+
/** Detected MIME (always a provider-decodable raster type). */
|
|
54
|
+
mime: string;
|
|
55
|
+
/** 1-indexed slide number (PPTX only) when the image is mapped to a slide. */
|
|
56
|
+
slide?: number;
|
|
57
|
+
/** Human label, e.g. "slide 8 image 1" or "image 1". */
|
|
58
|
+
label: string;
|
|
59
|
+
}
|
|
60
|
+
/** Result of an extraction pass. */
|
|
61
|
+
export interface OoxmlImageExtraction {
|
|
62
|
+
/** Images selected (after `pages` scoping) and within the cap. */
|
|
63
|
+
images: ExtractedOoxmlImage[];
|
|
64
|
+
/** How many decodable images matched the scope BEFORE the cap (for "N of M"). */
|
|
65
|
+
matched: number;
|
|
66
|
+
/** How many embeds were skipped because their format is not decodable. */
|
|
67
|
+
skipped: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resolve a relationship Target (relative to a `_rels` file's owning part)
|
|
71
|
+
* against a base directory, collapsing `../` and `./` segments. E.g. base
|
|
72
|
+
* `ppt/slides/` + target `../media/image1.png` → `ppt/media/image1.png`.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveRelTarget(baseDir: string, target: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* Parse a `.rels` XML blob into `[ {id, target} ]`. Tolerant of attribute order
|
|
77
|
+
* (Id before/after Target) and self-closing `<Relationship .../>`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseRelationships(xml: string): Array<{
|
|
80
|
+
id: string;
|
|
81
|
+
target: string;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Resolve slide part paths in PRESENTATION order from `presentation.xml` +
|
|
85
|
+
* `presentation.xml.rels`. Returns `[]` when the presentation graph can't be
|
|
86
|
+
* read (the caller then falls back to filename order).
|
|
87
|
+
*/
|
|
88
|
+
export declare function resolveSlideOrder(entries: Record<string, Uint8Array>): string[];
|
|
89
|
+
/**
|
|
90
|
+
* Extract embedded images from already-unzipped OOXML entries.
|
|
91
|
+
*
|
|
92
|
+
* • PPTX: resolves slide order via the presentation graph and maps images to
|
|
93
|
+
* slides through each slide's rels; honours `inRange` over slide position.
|
|
94
|
+
* Falls back to filename order (all slides) when the graph is unreadable.
|
|
95
|
+
* • DOCX/XLSX: returns all media-folder images (no page scoping).
|
|
96
|
+
*
|
|
97
|
+
* `inRange(slideNum)` is the page-range predicate (from `parsePageRange`) and is
|
|
98
|
+
* applied to PPTX SLIDE numbers only. `cap` bounds the number of images RETURNED
|
|
99
|
+
* (the per-call image cap); `matched` reports how many decodable images were in
|
|
100
|
+
* scope before the cap so the caller can say "showing N of M". `skipped` counts
|
|
101
|
+
* undecodable embeds in scope.
|
|
102
|
+
*/
|
|
103
|
+
export declare function extractOoxmlImages(entries: Record<string, Uint8Array>, kind: "pptx" | "docx" | "xlsx", opts: {
|
|
104
|
+
inRange?: (slideNum: number) => boolean;
|
|
105
|
+
cap: number;
|
|
106
|
+
}): OoxmlImageExtraction;
|
|
107
|
+
//# sourceMappingURL=ooxml-images.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ooxml-images.d.ts","sourceRoot":"","sources":["../../../src/agents/tools/ooxml-images.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IACnC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;CACd;AAED,oCAAoC;AACpC,MAAM,WAAW,oBAAoB;IACpC,kEAAkE;IAClE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;CAChB;AAkDD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAYxE;AAuBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAWrF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,MAAM,EAAE,CAmB/E;AAuDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACnC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAC9B,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC5D,oBAAoB,CA0DtB"}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded-image extraction for OOXML documents (PPTX / DOCX / XLSX) — the
|
|
3
|
+
* "see the wireframes inside the deck" half of `analyze_media`.
|
|
4
|
+
*
|
|
5
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* WHY THIS MODULE (read before changing)
|
|
7
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
8
|
+
* `analyze_media`'s OOXML readers return only the document TEXT (slide titles,
|
|
9
|
+
* paragraph runs, cell strings). But a real deck carries its substance in the
|
|
10
|
+
* PICTURES — wireframes, screenshots, diagrams, charts rendered to images. Asked
|
|
11
|
+
* to "go through the wireframe images in this .pptx", the agent used to have to
|
|
12
|
+
* shell out to `python zipfile` to pull `ppt/media/*.png`, then re-run
|
|
13
|
+
* `analyze_media` on each PNG. This module closes that gap: it extracts the
|
|
14
|
+
* embedded raster images straight from the already-unzipped OOXML entries the
|
|
15
|
+
* reader has in hand, so the tool can route them through the SAME image path it
|
|
16
|
+
* already uses (image blocks on a vision model / a provider on a text-only one).
|
|
17
|
+
*
|
|
18
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
19
|
+
* SLIDE / PAGE SCOPING (the important part for PPTX)
|
|
20
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
21
|
+
* A PPTX maps images to slides through the relationship graph, NOT by filename:
|
|
22
|
+
* presentation.xml → <p:sldId r:id="rIdN"/> in PRESENTATION order
|
|
23
|
+
* presentation.xml.rels → rIdN → ppt/slides/slideK.xml
|
|
24
|
+
* slideK.xml.rels → rIdM → ../media/imageX.png (that slide's images)
|
|
25
|
+
* So slide N's images are exactly the `../media/*` targets in that slide's rels
|
|
26
|
+
* file — which is what the manual workaround discovered ("SLIDE 8 rId3
|
|
27
|
+
* ../media/image16.png"). We resolve slides in presentation order, then honour
|
|
28
|
+
* the existing `pages` range over THAT order, returning only the selected
|
|
29
|
+
* slides' images. (Image filename numbering does NOT track slide order, so a
|
|
30
|
+
* filename-only approach would scope wrong — we never use it for PPTX.)
|
|
31
|
+
*
|
|
32
|
+
* DOCX/XLSX have no robust per-page image mapping (a Word page is a layout-time
|
|
33
|
+
* concept, not in the XML), so we return ALL embedded images (capped) when no
|
|
34
|
+
* scope applies — the `pages` range is honoured only for PPTX.
|
|
35
|
+
*
|
|
36
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
37
|
+
* UNSUPPORTED EMBEDS
|
|
38
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
39
|
+
* Only provider-DECODABLE raster types are surfaced (png/jpeg/gif/webp/bmp/
|
|
40
|
+
* tiff). Vector / exotic embeds — `.emf` / `.wmf` (Windows metafiles) and
|
|
41
|
+
* `.wdp` (JPEG-XR / HD Photo) — cannot be decoded without a native dep, so they
|
|
42
|
+
* are SKIPPED with a count (the real failure case hit `hdphoto1.wdp`). The
|
|
43
|
+
* caller reports "N image(s) skipped (unsupported format)" rather than throwing.
|
|
44
|
+
*
|
|
45
|
+
* Pure functions over an already-unzipped entry map; no I/O, no provider calls.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Extensions of embedded media that providers / jimp can decode. Everything
|
|
49
|
+
* else (`emf`/`wmf` vector metafiles, `wdp` JPEG-XR) is skipped — see header.
|
|
50
|
+
*/
|
|
51
|
+
const DECODABLE_EXT_MIME = {
|
|
52
|
+
png: "image/png",
|
|
53
|
+
jpg: "image/jpeg",
|
|
54
|
+
jpeg: "image/jpeg",
|
|
55
|
+
jpe: "image/jpeg",
|
|
56
|
+
gif: "image/gif",
|
|
57
|
+
webp: "image/webp",
|
|
58
|
+
bmp: "image/bmp",
|
|
59
|
+
tif: "image/tiff",
|
|
60
|
+
tiff: "image/tiff",
|
|
61
|
+
};
|
|
62
|
+
/** Lowercase extension (no dot) of a zip entry path. */
|
|
63
|
+
function entryExt(name) {
|
|
64
|
+
const dot = name.lastIndexOf(".");
|
|
65
|
+
if (dot < 0)
|
|
66
|
+
return "";
|
|
67
|
+
return name.slice(dot + 1).toLowerCase();
|
|
68
|
+
}
|
|
69
|
+
/** The media directory prefix for each OOXML kind. */
|
|
70
|
+
function mediaPrefix(kind) {
|
|
71
|
+
switch (kind) {
|
|
72
|
+
case "pptx":
|
|
73
|
+
return "ppt/media/";
|
|
74
|
+
case "docx":
|
|
75
|
+
return "word/media/";
|
|
76
|
+
case "xlsx":
|
|
77
|
+
return "xl/media/";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Decode `&`-style entities just enough to compare relationship targets
|
|
82
|
+
* (targets rarely contain entities, but `&` in a path would otherwise miss).
|
|
83
|
+
*/
|
|
84
|
+
function decodeRelTarget(s) {
|
|
85
|
+
return s
|
|
86
|
+
.replace(/&/g, "&")
|
|
87
|
+
.replace(/</g, "<")
|
|
88
|
+
.replace(/>/g, ">")
|
|
89
|
+
.replace(/"/g, '"')
|
|
90
|
+
.replace(/'/g, "'");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Resolve a relationship Target (relative to a `_rels` file's owning part)
|
|
94
|
+
* against a base directory, collapsing `../` and `./` segments. E.g. base
|
|
95
|
+
* `ppt/slides/` + target `../media/image1.png` → `ppt/media/image1.png`.
|
|
96
|
+
*/
|
|
97
|
+
export function resolveRelTarget(baseDir, target) {
|
|
98
|
+
const t = decodeRelTarget(target.trim()).replace(/^\/+/, "");
|
|
99
|
+
// Absolute-within-package targets (start with "/") resolve from the root.
|
|
100
|
+
const fromRoot = target.trim().startsWith("/");
|
|
101
|
+
const baseParts = fromRoot ? [] : baseDir.split("/").filter(Boolean);
|
|
102
|
+
const parts = [...baseParts];
|
|
103
|
+
for (const seg of t.split("/")) {
|
|
104
|
+
if (seg === "" || seg === ".")
|
|
105
|
+
continue;
|
|
106
|
+
if (seg === "..")
|
|
107
|
+
parts.pop();
|
|
108
|
+
else
|
|
109
|
+
parts.push(seg);
|
|
110
|
+
}
|
|
111
|
+
return parts.join("/");
|
|
112
|
+
}
|
|
113
|
+
/** Directory portion of a part path (e.g. `ppt/slides/slide1.xml` → `ppt/slides`). */
|
|
114
|
+
function partDir(part) {
|
|
115
|
+
const slash = part.lastIndexOf("/");
|
|
116
|
+
return slash < 0 ? "" : part.slice(0, slash);
|
|
117
|
+
}
|
|
118
|
+
/** The `_rels` sidecar path for a part (e.g. `ppt/slides/slide1.xml` → `ppt/slides/_rels/slide1.xml.rels`). */
|
|
119
|
+
function relsPathFor(part) {
|
|
120
|
+
const dir = partDir(part);
|
|
121
|
+
const file = part.slice(dir.length ? dir.length + 1 : 0);
|
|
122
|
+
return `${dir ? dir + "/" : ""}_rels/${file}.rels`;
|
|
123
|
+
}
|
|
124
|
+
/** Decode a zip entry to a UTF-8 string (entries are Uint8Array). */
|
|
125
|
+
function entryToString(entries, name) {
|
|
126
|
+
const u8 = entries[name];
|
|
127
|
+
if (!u8)
|
|
128
|
+
return undefined;
|
|
129
|
+
// Avoid a fflate import here (keep this module pure/sync); TextDecoder handles UTF-8.
|
|
130
|
+
return new TextDecoder("utf-8").decode(u8);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Parse a `.rels` XML blob into `[ {id, target} ]`. Tolerant of attribute order
|
|
134
|
+
* (Id before/after Target) and self-closing `<Relationship .../>`.
|
|
135
|
+
*/
|
|
136
|
+
export function parseRelationships(xml) {
|
|
137
|
+
const out = [];
|
|
138
|
+
const relRe = /<Relationship\b([^>]*?)\/?>/g;
|
|
139
|
+
let m;
|
|
140
|
+
while ((m = relRe.exec(xml)) !== null) {
|
|
141
|
+
const attrs = m[1] ?? "";
|
|
142
|
+
const id = /\bId="([^"]*)"/.exec(attrs)?.[1];
|
|
143
|
+
const target = /\bTarget="([^"]*)"/.exec(attrs)?.[1];
|
|
144
|
+
if (id && target)
|
|
145
|
+
out.push({ id, target });
|
|
146
|
+
}
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Resolve slide part paths in PRESENTATION order from `presentation.xml` +
|
|
151
|
+
* `presentation.xml.rels`. Returns `[]` when the presentation graph can't be
|
|
152
|
+
* read (the caller then falls back to filename order).
|
|
153
|
+
*/
|
|
154
|
+
export function resolveSlideOrder(entries) {
|
|
155
|
+
const presXml = entryToString(entries, "ppt/presentation.xml");
|
|
156
|
+
const relsXml = entryToString(entries, "ppt/_rels/presentation.xml.rels");
|
|
157
|
+
if (!presXml || !relsXml)
|
|
158
|
+
return [];
|
|
159
|
+
const idToTarget = new Map();
|
|
160
|
+
for (const rel of parseRelationships(relsXml))
|
|
161
|
+
idToTarget.set(rel.id, rel.target);
|
|
162
|
+
const order = [];
|
|
163
|
+
// <p:sldId id="256" r:id="rId2"/> — the r:id ordering IS the slide order.
|
|
164
|
+
const sldIdRe = /<p:sldId\b[^>]*\br:id="([^"]+)"[^>]*\/?>/g;
|
|
165
|
+
let m;
|
|
166
|
+
while ((m = sldIdRe.exec(presXml)) !== null) {
|
|
167
|
+
const rId = m[1];
|
|
168
|
+
const target = idToTarget.get(rId);
|
|
169
|
+
if (!target)
|
|
170
|
+
continue;
|
|
171
|
+
// presentation.xml lives in ppt/, so targets resolve from ppt/.
|
|
172
|
+
const resolved = resolveRelTarget("ppt", target);
|
|
173
|
+
if (entries[resolved])
|
|
174
|
+
order.push(resolved);
|
|
175
|
+
}
|
|
176
|
+
return order;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Map each slide part to the decodable `../media/*` images it references, in
|
|
180
|
+
* presentation order. Returns one entry per slide (slide 1-indexed by position
|
|
181
|
+
* in `slideOrder`). Each slide's images preserve their reference order.
|
|
182
|
+
*/
|
|
183
|
+
function imagesPerSlide(entries, slideOrder) {
|
|
184
|
+
const result = [];
|
|
185
|
+
for (let i = 0; i < slideOrder.length; i++) {
|
|
186
|
+
const slidePart = slideOrder[i];
|
|
187
|
+
const relsXml = entryToString(entries, relsPathFor(slidePart));
|
|
188
|
+
const imgs = [];
|
|
189
|
+
if (relsXml) {
|
|
190
|
+
const base = partDir(slidePart);
|
|
191
|
+
for (const rel of parseRelationships(relsXml)) {
|
|
192
|
+
const resolved = resolveRelTarget(base, rel.target);
|
|
193
|
+
if (!resolved.startsWith("ppt/media/"))
|
|
194
|
+
continue;
|
|
195
|
+
if (!(resolved in entries))
|
|
196
|
+
continue;
|
|
197
|
+
if (!DECODABLE_EXT_MIME[entryExt(resolved)] && !isSkippableMedia(resolved))
|
|
198
|
+
continue;
|
|
199
|
+
imgs.push(resolved);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
result.push({ slide: i + 1, entries: imgs });
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
/** True when a media entry is a known-but-undecodable embed (emf/wmf/wdp/svg/…). */
|
|
207
|
+
function isSkippableMedia(entry) {
|
|
208
|
+
const ext = entryExt(entry);
|
|
209
|
+
return ext === "emf" || ext === "wmf" || ext === "wdp" || ext === "svg" || ext === "emz" || ext === "wmz";
|
|
210
|
+
}
|
|
211
|
+
/** All `<prefix>media/*` entries in stable (numeric-aware) name order. */
|
|
212
|
+
function allMediaEntries(entries, prefix) {
|
|
213
|
+
return Object.keys(entries)
|
|
214
|
+
.filter((n) => n.startsWith(prefix) && entryExt(n).length > 0)
|
|
215
|
+
.sort(numericAwareCompare);
|
|
216
|
+
}
|
|
217
|
+
/** Sort `image2.png` before `image10.png` (numeric-aware on the trailing number). */
|
|
218
|
+
function numericAwareCompare(a, b) {
|
|
219
|
+
const na = /(\d+)\.[^.]+$/.exec(a);
|
|
220
|
+
const nb = /(\d+)\.[^.]+$/.exec(b);
|
|
221
|
+
if (na && nb) {
|
|
222
|
+
const d = parseInt(na[1], 10) - parseInt(nb[1], 10);
|
|
223
|
+
if (d !== 0)
|
|
224
|
+
return d;
|
|
225
|
+
}
|
|
226
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Extract embedded images from already-unzipped OOXML entries.
|
|
230
|
+
*
|
|
231
|
+
* • PPTX: resolves slide order via the presentation graph and maps images to
|
|
232
|
+
* slides through each slide's rels; honours `inRange` over slide position.
|
|
233
|
+
* Falls back to filename order (all slides) when the graph is unreadable.
|
|
234
|
+
* • DOCX/XLSX: returns all media-folder images (no page scoping).
|
|
235
|
+
*
|
|
236
|
+
* `inRange(slideNum)` is the page-range predicate (from `parsePageRange`) and is
|
|
237
|
+
* applied to PPTX SLIDE numbers only. `cap` bounds the number of images RETURNED
|
|
238
|
+
* (the per-call image cap); `matched` reports how many decodable images were in
|
|
239
|
+
* scope before the cap so the caller can say "showing N of M". `skipped` counts
|
|
240
|
+
* undecodable embeds in scope.
|
|
241
|
+
*/
|
|
242
|
+
export function extractOoxmlImages(entries, kind, opts) {
|
|
243
|
+
const prefix = mediaPrefix(kind);
|
|
244
|
+
const inRange = opts.inRange ?? (() => true);
|
|
245
|
+
// Build the ordered, scoped list of candidate entries (+ slide map for pptx).
|
|
246
|
+
const ordered = [];
|
|
247
|
+
if (kind === "pptx") {
|
|
248
|
+
const slideOrder = resolveSlideOrder(entries);
|
|
249
|
+
if (slideOrder.length > 0) {
|
|
250
|
+
const perSlide = imagesPerSlide(entries, slideOrder);
|
|
251
|
+
const seen = new Set();
|
|
252
|
+
for (const { slide, entries: imgs } of perSlide) {
|
|
253
|
+
if (!inRange(slide))
|
|
254
|
+
continue;
|
|
255
|
+
for (const e of imgs) {
|
|
256
|
+
// An image shared across slides (rare) is attributed to its FIRST
|
|
257
|
+
// in-scope slide to avoid duplicate blocks.
|
|
258
|
+
if (seen.has(e))
|
|
259
|
+
continue;
|
|
260
|
+
seen.add(e);
|
|
261
|
+
ordered.push({ entry: e, slide });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
// Presentation graph unreadable → fall back to every media file (no slide
|
|
267
|
+
// scoping possible). This keeps a malformed-but-openable deck working.
|
|
268
|
+
for (const e of allMediaEntries(entries, prefix))
|
|
269
|
+
ordered.push({ entry: e });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
for (const e of allMediaEntries(entries, prefix))
|
|
274
|
+
ordered.push({ entry: e });
|
|
275
|
+
}
|
|
276
|
+
// Partition into decodable (kept) vs skippable (counted), then apply the cap.
|
|
277
|
+
let matched = 0;
|
|
278
|
+
let skipped = 0;
|
|
279
|
+
const images = [];
|
|
280
|
+
const perSlideSeq = new Map();
|
|
281
|
+
for (const cand of ordered) {
|
|
282
|
+
const mime = DECODABLE_EXT_MIME[entryExt(cand.entry)];
|
|
283
|
+
if (!mime) {
|
|
284
|
+
if (isSkippableMedia(cand.entry))
|
|
285
|
+
skipped += 1;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
matched += 1;
|
|
289
|
+
if (images.length >= opts.cap)
|
|
290
|
+
continue; // count toward `matched`, don't emit
|
|
291
|
+
const u8 = entries[cand.entry];
|
|
292
|
+
if (!u8)
|
|
293
|
+
continue;
|
|
294
|
+
const slideKey = cand.slide ?? "none";
|
|
295
|
+
const seq = (perSlideSeq.get(slideKey) ?? 0) + 1;
|
|
296
|
+
perSlideSeq.set(slideKey, seq);
|
|
297
|
+
const label = cand.slide ? `slide ${cand.slide} image ${seq}` : `image ${seq}`;
|
|
298
|
+
images.push({
|
|
299
|
+
entry: cand.entry,
|
|
300
|
+
bytes: Buffer.from(u8),
|
|
301
|
+
mime,
|
|
302
|
+
...(cand.slide ? { slide: cand.slide } : {}),
|
|
303
|
+
label,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return { images, matched, skipped };
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=ooxml-images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ooxml-images.js","sourceRoot":"","sources":["../../../src/agents/tools/ooxml-images.ts"],"names":[],"mappings":"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"}
|
|
@@ -99,6 +99,18 @@ export interface CreateBrigadeToolsOptions {
|
|
|
99
99
|
* narrow per-call gate kicks in.
|
|
100
100
|
*/
|
|
101
101
|
senderIsOwner?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Resolved turn-model context (provider + modelId of the model driving this
|
|
104
|
+
* turn). Threaded into `analyze_media` so it can decide whether returning an
|
|
105
|
+
* IMAGE content block is meaningful (a text-only model can't consume one).
|
|
106
|
+
* Optional — when omitted (tests / legacy call sites) the tool assumes the
|
|
107
|
+
* model is vision-capable but annotates the uncertainty.
|
|
108
|
+
*/
|
|
109
|
+
modelContext?: {
|
|
110
|
+
provider?: string;
|
|
111
|
+
modelId?: string;
|
|
112
|
+
imageInput?: boolean;
|
|
113
|
+
};
|
|
102
114
|
/**
|
|
103
115
|
* Per-turn session metadata (Step 11's `SessionContext`). When supplied,
|
|
104
116
|
* `createBrigadeTools` includes the four sessions tools
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/agents/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/agents/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AA6C5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,yBAAyB;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE;QACjB,uEAAuE;QACvE,gBAAgB,EAAE,MAAM,CAAC;QACzB,2DAA2D;QAC3D,WAAW,EAAE,MAAM,CAAC;QACpB,2CAA2C;QAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,oEAAoE;QACpE,YAAY,CAAC,EAAE,WAAW,CAAC;QAC3B;;;WAGG;QACH,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;;;;OAYG;IACH,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;IACF;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE;QACnB,UAAU,CAAC,EAAE,OAAO,sBAAsB,EAAE,sBAAsB,CAAC;QACnE,SAAS,CAAC,EAAE,OAAO,sBAAsB,EAAE,kBAAkB,CAAC;QAC9D,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;KAClC,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,yBAAyB,GAAG,cAAc,EAAE,CAsbpF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C"}
|