openrouter-genimage-kote-opencode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/.opencode/skills/openrouter-image-generation/SKILL.md +379 -0
  2. package/CHANGELOG.md +10 -0
  3. package/LICENSE +21 -0
  4. package/README.md +229 -0
  5. package/README.ru.md +229 -0
  6. package/SECURITY.md +31 -0
  7. package/THIRD_PARTY_NOTICES.md +16 -0
  8. package/dist/cli.d.ts +20 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +277 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/balance-command.d.ts +5 -0
  13. package/dist/commands/balance-command.d.ts.map +1 -0
  14. package/dist/commands/balance-command.js +20 -0
  15. package/dist/commands/balance-command.js.map +1 -0
  16. package/dist/config/resolve.d.ts +5 -0
  17. package/dist/config/resolve.d.ts.map +1 -0
  18. package/dist/config/resolve.js +113 -0
  19. package/dist/config/resolve.js.map +1 -0
  20. package/dist/config/schema.d.ts +188 -0
  21. package/dist/config/schema.d.ts.map +1 -0
  22. package/dist/config/schema.js +144 -0
  23. package/dist/config/schema.js.map +1 -0
  24. package/dist/config/types.d.ts +75 -0
  25. package/dist/config/types.d.ts.map +1 -0
  26. package/dist/config/types.js +30 -0
  27. package/dist/config/types.js.map +1 -0
  28. package/dist/logging.d.ts +46 -0
  29. package/dist/logging.d.ts.map +1 -0
  30. package/dist/logging.js +58 -0
  31. package/dist/logging.js.map +1 -0
  32. package/dist/openrouter/capabilities.d.ts +22 -0
  33. package/dist/openrouter/capabilities.d.ts.map +1 -0
  34. package/dist/openrouter/capabilities.js +137 -0
  35. package/dist/openrouter/capabilities.js.map +1 -0
  36. package/dist/openrouter/client.d.ts +54 -0
  37. package/dist/openrouter/client.d.ts.map +1 -0
  38. package/dist/openrouter/client.js +440 -0
  39. package/dist/openrouter/client.js.map +1 -0
  40. package/dist/openrouter/errors.d.ts +22 -0
  41. package/dist/openrouter/errors.d.ts.map +1 -0
  42. package/dist/openrouter/errors.js +75 -0
  43. package/dist/openrouter/errors.js.map +1 -0
  44. package/dist/openrouter/models.d.ts +37 -0
  45. package/dist/openrouter/models.d.ts.map +1 -0
  46. package/dist/openrouter/models.js +113 -0
  47. package/dist/openrouter/models.js.map +1 -0
  48. package/dist/openrouter/requests.d.ts +6 -0
  49. package/dist/openrouter/requests.d.ts.map +1 -0
  50. package/dist/openrouter/requests.js +74 -0
  51. package/dist/openrouter/requests.js.map +1 -0
  52. package/dist/openrouter/schemas.d.ts +37 -0
  53. package/dist/openrouter/schemas.d.ts.map +1 -0
  54. package/dist/openrouter/schemas.js +2 -0
  55. package/dist/openrouter/schemas.js.map +1 -0
  56. package/dist/output/attachments.d.ts +10 -0
  57. package/dist/output/attachments.d.ts.map +1 -0
  58. package/dist/output/attachments.js +13 -0
  59. package/dist/output/attachments.js.map +1 -0
  60. package/dist/output/formats.d.ts +42 -0
  61. package/dist/output/formats.d.ts.map +1 -0
  62. package/dist/output/formats.js +126 -0
  63. package/dist/output/formats.js.map +1 -0
  64. package/dist/output/index.d.ts +5 -0
  65. package/dist/output/index.d.ts.map +1 -0
  66. package/dist/output/index.js +5 -0
  67. package/dist/output/index.js.map +1 -0
  68. package/dist/output/paths.d.ts +38 -0
  69. package/dist/output/paths.d.ts.map +1 -0
  70. package/dist/output/paths.js +296 -0
  71. package/dist/output/paths.js.map +1 -0
  72. package/dist/output/writer.d.ts +33 -0
  73. package/dist/output/writer.d.ts.map +1 -0
  74. package/dist/output/writer.js +176 -0
  75. package/dist/output/writer.js.map +1 -0
  76. package/dist/references/attachments.d.ts +82 -0
  77. package/dist/references/attachments.d.ts.map +1 -0
  78. package/dist/references/attachments.js +238 -0
  79. package/dist/references/attachments.js.map +1 -0
  80. package/dist/references/data-url.d.ts +12 -0
  81. package/dist/references/data-url.d.ts.map +1 -0
  82. package/dist/references/data-url.js +75 -0
  83. package/dist/references/data-url.js.map +1 -0
  84. package/dist/references/formats.d.ts +13 -0
  85. package/dist/references/formats.d.ts.map +1 -0
  86. package/dist/references/formats.js +50 -0
  87. package/dist/references/formats.js.map +1 -0
  88. package/dist/references/index.d.ts +7 -0
  89. package/dist/references/index.d.ts.map +1 -0
  90. package/dist/references/index.js +7 -0
  91. package/dist/references/index.js.map +1 -0
  92. package/dist/references/limits.d.ts +15 -0
  93. package/dist/references/limits.d.ts.map +1 -0
  94. package/dist/references/limits.js +62 -0
  95. package/dist/references/limits.js.map +1 -0
  96. package/dist/references/project-files.d.ts +13 -0
  97. package/dist/references/project-files.d.ts.map +1 -0
  98. package/dist/references/project-files.js +148 -0
  99. package/dist/references/project-files.js.map +1 -0
  100. package/dist/references/remote-urls.d.ts +3 -0
  101. package/dist/references/remote-urls.d.ts.map +1 -0
  102. package/dist/references/remote-urls.js +22 -0
  103. package/dist/references/remote-urls.js.map +1 -0
  104. package/dist/server.d.ts +8 -0
  105. package/dist/server.d.ts.map +1 -0
  106. package/dist/server.js +97 -0
  107. package/dist/server.js.map +1 -0
  108. package/dist/tools/balance.d.ts +8 -0
  109. package/dist/tools/balance.d.ts.map +1 -0
  110. package/dist/tools/balance.js +133 -0
  111. package/dist/tools/balance.js.map +1 -0
  112. package/dist/tools/common.d.ts +3 -0
  113. package/dist/tools/common.d.ts.map +1 -0
  114. package/dist/tools/common.js +18 -0
  115. package/dist/tools/common.js.map +1 -0
  116. package/dist/tools/edit-image.d.ts +90 -0
  117. package/dist/tools/edit-image.d.ts.map +1 -0
  118. package/dist/tools/edit-image.js +47 -0
  119. package/dist/tools/edit-image.js.map +1 -0
  120. package/dist/tools/generate-image.d.ts +70 -0
  121. package/dist/tools/generate-image.d.ts.map +1 -0
  122. package/dist/tools/generate-image.js +36 -0
  123. package/dist/tools/generate-image.js.map +1 -0
  124. package/dist/tools/generation.d.ts +19 -0
  125. package/dist/tools/generation.d.ts.map +1 -0
  126. package/dist/tools/generation.js +154 -0
  127. package/dist/tools/generation.js.map +1 -0
  128. package/dist/tools/schema.d.ts +127 -0
  129. package/dist/tools/schema.d.ts.map +1 -0
  130. package/dist/tools/schema.js +47 -0
  131. package/dist/tools/schema.js.map +1 -0
  132. package/dist/tools/types.d.ts +18 -0
  133. package/dist/tools/types.d.ts.map +1 -0
  134. package/dist/tools/types.js +2 -0
  135. package/dist/tools/types.js.map +1 -0
  136. package/dist/transport/direct.d.ts +10 -0
  137. package/dist/transport/direct.d.ts.map +1 -0
  138. package/dist/transport/direct.js +15 -0
  139. package/dist/transport/direct.js.map +1 -0
  140. package/dist/transport/index.d.ts +4 -0
  141. package/dist/transport/index.d.ts.map +1 -0
  142. package/dist/transport/index.js +4 -0
  143. package/dist/transport/index.js.map +1 -0
  144. package/dist/transport/kote-gateway.d.ts +19 -0
  145. package/dist/transport/kote-gateway.d.ts.map +1 -0
  146. package/dist/transport/kote-gateway.js +224 -0
  147. package/dist/transport/kote-gateway.js.map +1 -0
  148. package/dist/transport/types.d.ts +10 -0
  149. package/dist/transport/types.d.ts.map +1 -0
  150. package/dist/transport/types.js +9 -0
  151. package/dist/transport/types.js.map +1 -0
  152. package/dist/utils/abort.d.ts +19 -0
  153. package/dist/utils/abort.d.ts.map +1 -0
  154. package/dist/utils/abort.js +121 -0
  155. package/dist/utils/abort.js.map +1 -0
  156. package/docs/architecture.md +75 -0
  157. package/docs/configuration.md +110 -0
  158. package/docs/image-to-image.md +101 -0
  159. package/docs/security.md +49 -0
  160. package/docs/testing.md +81 -0
  161. package/docs/troubleshooting.md +73 -0
  162. package/package.json +88 -0
  163. package/schema/plugin-options.schema.json +182 -0
@@ -0,0 +1,238 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { PluginError } from "../openrouter/errors.js";
3
+ import { abortableStreamRead, throwIfAborted } from "../utils/abort.js";
4
+ import { imageBytesToDataUrl, parseImageDataUrl } from "./data-url.js";
5
+ import { detectImageFormat, isSupportedImageMime, } from "./formats.js";
6
+ import { ReferenceBudget } from "./limits.js";
7
+ import { loadProjectImage, loadTrustedAttachmentFile, } from "./project-files.js";
8
+ import { validatePublicHttpsUrl } from "./remote-urls.js";
9
+ function isImagePart(part) {
10
+ return (part.type === "file" &&
11
+ typeof part.mime === "string" &&
12
+ part.mime.startsWith("image/") &&
13
+ typeof part.url === "string");
14
+ }
15
+ async function getMessage(client, sessionID, messageID, directory, signal) {
16
+ throwIfAborted(signal);
17
+ try {
18
+ const response = await client.session.message({
19
+ path: { id: sessionID, messageID },
20
+ query: { directory },
21
+ signal,
22
+ });
23
+ if (response.data === undefined)
24
+ throw new TypeError("message unavailable");
25
+ return response.data;
26
+ }
27
+ catch (error) {
28
+ throwIfAborted(signal);
29
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "OpenCode could not provide the current message attachments.", { cause: error });
30
+ }
31
+ }
32
+ export async function getCurrentUserImageParts(client, context) {
33
+ const assistant = await getMessage(client, context.sessionID, context.messageID, context.directory, context.abort);
34
+ if (assistant.info.role !== "assistant" || typeof assistant.info.parentID !== "string") {
35
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "The current assistant message does not identify its parent user message.");
36
+ }
37
+ const user = await getMessage(client, context.sessionID, assistant.info.parentID, context.directory, context.abort);
38
+ if (user.info.role !== "user") {
39
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "The parent OpenCode message is not a user message.");
40
+ }
41
+ return user.parts.filter(isImagePart);
42
+ }
43
+ async function readAttachmentResponse(response, maximumBytes, signal) {
44
+ if (!response.ok || response.status >= 300) {
45
+ await response.body?.cancel().catch(() => { });
46
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "OpenCode could not read the managed image attachment.", { details: { status: response.status } });
47
+ }
48
+ const contentLength = response.headers.get("content-length");
49
+ if (contentLength !== null) {
50
+ const parsed = Number(contentLength);
51
+ if (Number.isFinite(parsed) && parsed > maximumBytes) {
52
+ await response.body?.cancel().catch(() => { });
53
+ throw new PluginError("GENIMAGE_REFERENCE_TOO_LARGE", "The managed attachment exceeds the configured file-size limit.", { details: { maxFileBytes: maximumBytes } });
54
+ }
55
+ }
56
+ if (response.body === null) {
57
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "The managed image attachment has no response body.");
58
+ }
59
+ const reader = response.body.getReader();
60
+ const chunks = [];
61
+ let total = 0;
62
+ try {
63
+ for (;;) {
64
+ throwIfAborted(signal);
65
+ const chunk = await abortableStreamRead(reader, signal);
66
+ if (chunk.done)
67
+ break;
68
+ total += chunk.value.byteLength;
69
+ if (total > maximumBytes) {
70
+ await reader.cancel("attachment size limit exceeded").catch(() => { });
71
+ throw new PluginError("GENIMAGE_REFERENCE_TOO_LARGE", "The managed attachment exceeds the configured file-size limit.", { details: { maxFileBytes: maximumBytes } });
72
+ }
73
+ chunks.push(chunk.value);
74
+ }
75
+ }
76
+ finally {
77
+ try {
78
+ reader.releaseLock();
79
+ }
80
+ catch {
81
+ void reader.cancel().catch(() => { });
82
+ }
83
+ }
84
+ return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)), total);
85
+ }
86
+ async function loadManagedAttachment(part, url, maximumBytes, signal, fetchImplementation) {
87
+ if (!isSupportedImageMime(part.mime)) {
88
+ throw new PluginError("GENIMAGE_REFERENCE_FORMAT_UNSUPPORTED", "Only PNG, JPEG, and WebP attachments are supported.");
89
+ }
90
+ let response;
91
+ try {
92
+ response = await fetchImplementation(url, {
93
+ method: "GET",
94
+ redirect: "manual",
95
+ signal,
96
+ headers: { Accept: "image/png, image/jpeg, image/webp" },
97
+ });
98
+ }
99
+ catch (error) {
100
+ throwIfAborted(signal);
101
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "OpenCode could not read the managed image attachment.", { cause: error });
102
+ }
103
+ const bytes = await readAttachmentResponse(response, maximumBytes, signal);
104
+ const detected = detectImageFormat(bytes);
105
+ if (detected === undefined) {
106
+ throw new PluginError("GENIMAGE_REFERENCE_FORMAT_UNSUPPORTED", "The attachment is not a supported PNG, JPEG, or WebP image.");
107
+ }
108
+ if (detected.mime !== part.mime) {
109
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The attachment MIME type does not match its binary format.");
110
+ }
111
+ return {
112
+ bytes,
113
+ detected,
114
+ dataUrl: imageBytesToDataUrl(bytes, detected.mime),
115
+ canonicalPath: "",
116
+ };
117
+ }
118
+ function fromLocalImage(source, image) {
119
+ return {
120
+ source,
121
+ openRouterReference: {
122
+ type: "image_url",
123
+ image_url: { url: image.dataUrl },
124
+ },
125
+ byteLength: image.bytes.byteLength,
126
+ detected: image.detected,
127
+ ...(image.canonicalPath === "" ? {} : { canonicalSourcePath: image.canonicalPath }),
128
+ };
129
+ }
130
+ async function resolveMessagePart(part, serverUrl, maximumBytes, signal, fetchImplementation) {
131
+ if (part.url.startsWith("data:")) {
132
+ const decoded = parseImageDataUrl(part.url, maximumBytes);
133
+ if (decoded.detected.mime !== part.mime) {
134
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The attachment MIME type does not match its data URL.");
135
+ }
136
+ return {
137
+ source: "message_attachment",
138
+ openRouterReference: {
139
+ type: "image_url",
140
+ image_url: { url: decoded.dataUrl },
141
+ },
142
+ byteLength: decoded.bytes.byteLength,
143
+ detected: decoded.detected,
144
+ };
145
+ }
146
+ let url;
147
+ try {
148
+ url = new URL(part.url);
149
+ }
150
+ catch (error) {
151
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "The OpenCode attachment URL is invalid.", { cause: error });
152
+ }
153
+ if (url.username !== "" || url.password !== "") {
154
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "The OpenCode attachment URL contains credentials.");
155
+ }
156
+ if (url.protocol === "file:") {
157
+ return fromLocalImage("message_attachment", await loadTrustedAttachmentFile(part.url, maximumBytes, signal));
158
+ }
159
+ const isManaged = url.origin === serverUrl.origin || url.protocol === "blob:";
160
+ if (isManaged) {
161
+ return fromLocalImage("message_attachment", await loadManagedAttachment(part, url, maximumBytes, signal, fetchImplementation));
162
+ }
163
+ if (url.protocol === "https:") {
164
+ validatePublicHttpsUrl(part.url);
165
+ return {
166
+ source: "message_attachment",
167
+ openRouterReference: {
168
+ type: "image_url",
169
+ image_url: { url: part.url },
170
+ },
171
+ };
172
+ }
173
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "The OpenCode attachment uses an unsupported URL scheme.");
174
+ }
175
+ export async function resolveImageReferences(options) {
176
+ const fetchImplementation = options.fetch ?? globalThis.fetch.bind(globalThis);
177
+ const budget = new ReferenceBudget(options.limits);
178
+ const parts = options.references === undefined ||
179
+ options.references.some((reference) => reference.type === "message_attachment")
180
+ ? await getCurrentUserImageParts(options.client, options.context)
181
+ : [];
182
+ const requested = options.references ?? parts.map((_, index) => ({ type: "message_attachment", index: index + 1 }));
183
+ if (requested.length === 0) {
184
+ throw new PluginError("GENIMAGE_REFERENCE_REQUIRED", "Image editing requires at least one visual reference.");
185
+ }
186
+ if (requested.length > options.limits.maxReferences || requested.length > 16) {
187
+ throw new PluginError("GENIMAGE_TOO_MANY_REFERENCES", "Too many image references were supplied.", { details: { maxReferences: Math.min(options.limits.maxReferences, 16) } });
188
+ }
189
+ const resolved = [];
190
+ let urlCharacters = 0;
191
+ for (const reference of requested) {
192
+ throwIfAborted(options.context.abort);
193
+ let item;
194
+ switch (reference.type) {
195
+ case "message_attachment": {
196
+ if (!Number.isInteger(reference.index) || reference.index < 1) {
197
+ throw new PluginError("GENIMAGE_REFERENCE_INDEX_INVALID", "Attachment indexes start at 1 and must be integers.");
198
+ }
199
+ const part = parts[reference.index - 1];
200
+ if (part === undefined) {
201
+ throw new PluginError("GENIMAGE_REFERENCE_INDEX_INVALID", "The requested image attachment index does not exist in the current user message.", { details: { index: reference.index, available: parts.length } });
202
+ }
203
+ item = await resolveMessagePart(part, options.serverUrl, options.limits.maxFileBytes, options.context.abort, fetchImplementation);
204
+ break;
205
+ }
206
+ case "project_file":
207
+ item = fromLocalImage("project_file", await loadProjectImage(options.context.worktree, reference.path, options.limits.maxFileBytes, options.context.abort));
208
+ break;
209
+ case "https_url": {
210
+ const url = validatePublicHttpsUrl(reference.url);
211
+ item = {
212
+ source: "https_url",
213
+ openRouterReference: {
214
+ type: "image_url",
215
+ image_url: { url },
216
+ },
217
+ };
218
+ break;
219
+ }
220
+ }
221
+ if (item.byteLength === undefined) {
222
+ budget.addRemoteReference();
223
+ urlCharacters += item.openRouterReference.image_url.url.length;
224
+ }
225
+ else {
226
+ budget.addLocalReference(item.byteLength);
227
+ }
228
+ resolved.push(item);
229
+ }
230
+ budget.assertEstimatedRequestSize(options.promptLength, urlCharacters);
231
+ return {
232
+ references: resolved,
233
+ inputReferences: resolved.map((item) => item.openRouterReference),
234
+ canonicalSourcePaths: new Set(resolved.flatMap((item) => item.canonicalSourcePath === undefined ? [] : [item.canonicalSourcePath])),
235
+ localBytes: budget.localBytes,
236
+ };
237
+ }
238
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../src/references/attachments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { type DetectedImageFormat, type RasterImageMime } from "./formats.js";
3
+ export interface DecodedImageData {
4
+ bytes: Buffer;
5
+ detected: DetectedImageFormat;
6
+ dataUrl: string;
7
+ }
8
+ export declare function estimatedDecodedBase64Bytes(value: string): number;
9
+ export declare function decodeStrictBase64(value: string, maximumBytes?: number): Buffer;
10
+ export declare function imageBytesToDataUrl(bytes: Uint8Array, mime: RasterImageMime): string;
11
+ export declare function parseImageDataUrl(value: string, maximumBytes?: number): DecodedImageData;
12
+ //# sourceMappingURL=data-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-url.d.ts","sourceRoot":"","sources":["../../src/references/data-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGpC,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACrB,MAAM,cAAc,CAAA;AAErB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,OAAO,EAAE,MAAM,CAAA;CAChB;AAmCD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAuB/E;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,eAAe,GACpB,MAAM,CAER;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,GACpB,gBAAgB,CAoDlB"}
@@ -0,0 +1,75 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { PluginError } from "../openrouter/errors.js";
3
+ import { detectImageFormat, isSupportedImageMime, } from "./formats.js";
4
+ function normalizeBase64(value) {
5
+ if (value === "" || /\s/u.test(value) || /[^A-Za-z0-9+/=]/u.test(value)) {
6
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The image contains invalid base64 data.");
7
+ }
8
+ const firstPadding = value.indexOf("=");
9
+ if (firstPadding !== -1 && !/^={1,2}$/u.test(value.slice(firstPadding))) {
10
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The image contains invalid base64 padding.");
11
+ }
12
+ const unpadded = firstPadding === -1 ? value : value.slice(0, firstPadding);
13
+ if (unpadded.length % 4 === 1) {
14
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The image contains invalid base64 data.");
15
+ }
16
+ const padded = `${unpadded}${"=".repeat((4 - (unpadded.length % 4)) % 4)}`;
17
+ if (firstPadding !== -1 && padded !== value) {
18
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The image contains non-canonical base64 padding.");
19
+ }
20
+ return padded;
21
+ }
22
+ export function estimatedDecodedBase64Bytes(value) {
23
+ const padded = normalizeBase64(value);
24
+ const padding = padded.endsWith("==") ? 2 : padded.endsWith("=") ? 1 : 0;
25
+ return (padded.length / 4) * 3 - padding;
26
+ }
27
+ export function decodeStrictBase64(value, maximumBytes) {
28
+ const padded = normalizeBase64(value);
29
+ const estimated = estimatedDecodedBase64Bytes(padded);
30
+ if (maximumBytes !== undefined && estimated > maximumBytes) {
31
+ throw new PluginError("GENIMAGE_REFERENCE_TOO_LARGE", "The reference image exceeds the configured file-size limit.", {
32
+ details: { maxFileBytes: maximumBytes },
33
+ suggestion: "Resize or compress the image, use fewer references, or provide a public HTTPS URL.",
34
+ });
35
+ }
36
+ const bytes = Buffer.from(padded, "base64");
37
+ if (bytes.toString("base64") !== padded) {
38
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The image contains invalid base64 data.");
39
+ }
40
+ return bytes;
41
+ }
42
+ export function imageBytesToDataUrl(bytes, mime) {
43
+ return `data:${mime};base64,${Buffer.from(bytes).toString("base64")}`;
44
+ }
45
+ export function parseImageDataUrl(value, maximumBytes) {
46
+ if (maximumBytes !== undefined &&
47
+ value.length > Math.ceil(maximumBytes / 3) * 4 + 64) {
48
+ throw new PluginError("GENIMAGE_REFERENCE_TOO_LARGE", "The reference image exceeds the configured file-size limit.", { details: { maxFileBytes: maximumBytes } });
49
+ }
50
+ const match = /^data:([^;,]+);base64,([A-Za-z0-9+/=]+)$/u.exec(value);
51
+ if (match === null) {
52
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The attachment is not a valid base64 image data URL.");
53
+ }
54
+ const declaredMime = match[1];
55
+ const encoded = match[2];
56
+ if (declaredMime === undefined ||
57
+ encoded === undefined ||
58
+ !isSupportedImageMime(declaredMime)) {
59
+ throw new PluginError("GENIMAGE_REFERENCE_FORMAT_UNSUPPORTED", "Only PNG, JPEG, and WebP reference images are supported.");
60
+ }
61
+ const bytes = decodeStrictBase64(encoded, maximumBytes);
62
+ const detected = detectImageFormat(bytes);
63
+ if (detected === undefined) {
64
+ throw new PluginError("GENIMAGE_REFERENCE_FORMAT_UNSUPPORTED", "The reference image is not a supported PNG, JPEG, or WebP file.");
65
+ }
66
+ if (detected.mime !== declaredMime) {
67
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The reference image MIME type does not match its binary format.");
68
+ }
69
+ return {
70
+ bytes,
71
+ detected,
72
+ dataUrl: imageBytesToDataUrl(bytes, detected.mime),
73
+ };
74
+ }
75
+ //# sourceMappingURL=data-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-url.js","sourceRoot":"","sources":["../../src/references/data-url.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export type RasterImageFormat = "png" | "jpeg" | "webp";
2
+ export type RasterImageMime = "image/png" | "image/jpeg" | "image/webp";
3
+ export interface DetectedImageFormat {
4
+ format: RasterImageFormat;
5
+ mime: RasterImageMime;
6
+ extension: ".png" | ".jpeg" | ".webp";
7
+ }
8
+ export declare function detectImageFormat(bytes: Uint8Array): DetectedImageFormat | undefined;
9
+ export declare function isSupportedImageMime(value: string): value is RasterImageMime;
10
+ export declare function formatFromExtension(extension: string): RasterImageFormat | undefined;
11
+ export declare function mimeForFormat(format: RasterImageFormat): RasterImageMime;
12
+ export declare function extensionForFormat(format: RasterImageFormat): DetectedImageFormat["extension"];
13
+ //# sourceMappingURL=formats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formats.d.ts","sourceRoot":"","sources":["../../src/references/formats.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AACvD,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,CAAA;AAEvE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,iBAAiB,CAAA;IACzB,IAAI,EAAE,eAAe,CAAA;IACrB,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;CACtC;AASD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,mBAAmB,GAAG,SAAS,CAuBpF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,eAAe,CAE5E;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAYpF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAMxE;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,GACxB,mBAAmB,CAAC,WAAW,CAAC,CAElC"}
@@ -0,0 +1,50 @@
1
+ const PNG_SIGNATURE = Uint8Array.from([137, 80, 78, 71, 13, 10, 26, 10]);
2
+ function startsWith(bytes, signature) {
3
+ if (bytes.byteLength < signature.byteLength)
4
+ return false;
5
+ return signature.every((value, index) => bytes[index] === value);
6
+ }
7
+ export function detectImageFormat(bytes) {
8
+ if (startsWith(bytes, PNG_SIGNATURE)) {
9
+ return { format: "png", mime: "image/png", extension: ".png" };
10
+ }
11
+ if (bytes.byteLength >= 3 &&
12
+ bytes[0] === 0xff &&
13
+ bytes[1] === 0xd8 &&
14
+ bytes[2] === 0xff) {
15
+ return { format: "jpeg", mime: "image/jpeg", extension: ".jpeg" };
16
+ }
17
+ if (bytes.byteLength >= 12 &&
18
+ String.fromCharCode(...bytes.subarray(0, 4)) === "RIFF" &&
19
+ String.fromCharCode(...bytes.subarray(8, 12)) === "WEBP") {
20
+ return { format: "webp", mime: "image/webp", extension: ".webp" };
21
+ }
22
+ return undefined;
23
+ }
24
+ export function isSupportedImageMime(value) {
25
+ return value === "image/png" || value === "image/jpeg" || value === "image/webp";
26
+ }
27
+ export function formatFromExtension(extension) {
28
+ switch (extension.toLowerCase()) {
29
+ case ".png":
30
+ return "png";
31
+ case ".jpg":
32
+ case ".jpeg":
33
+ return "jpeg";
34
+ case ".webp":
35
+ return "webp";
36
+ default:
37
+ return undefined;
38
+ }
39
+ }
40
+ export function mimeForFormat(format) {
41
+ return format === "png"
42
+ ? "image/png"
43
+ : format === "jpeg"
44
+ ? "image/jpeg"
45
+ : "image/webp";
46
+ }
47
+ export function extensionForFormat(format) {
48
+ return format === "png" ? ".png" : format === "jpeg" ? ".jpeg" : ".webp";
49
+ }
50
+ //# sourceMappingURL=formats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formats.js","sourceRoot":"","sources":["../../src/references/formats.ts"],"names":[],"mappings":"AASA,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;AAExE,SAAS,UAAU,CAAC,KAAiB,EAAE,SAAqB;IAC1D,IAAI,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU;QAAE,OAAO,KAAK,CAAA;IACzD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAiB;IACjD,IAAI,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IAChE,CAAC;IAED,IACE,KAAK,CAAC,UAAU,IAAI,CAAC;QACrB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EACjB,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,CAAA;IACnE,CAAC;IAED,IACE,KAAK,CAAC,UAAU,IAAI,EAAE;QACtB,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM;QACvD,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,EACxD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,CAAA;IACnE,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,YAAY,CAAA;AAClF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,QAAQ,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAChC,KAAK,MAAM;YACT,OAAO,KAAK,CAAA;QACd,KAAK,MAAM,CAAC;QACZ,KAAK,OAAO;YACV,OAAO,MAAM,CAAA;QACf,KAAK,OAAO;YACV,OAAO,MAAM,CAAA;QACf;YACE,OAAO,SAAS,CAAA;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAyB;IACrD,OAAO,MAAM,KAAK,KAAK;QACrB,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,MAAM,KAAK,MAAM;YACjB,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,YAAY,CAAA;AACpB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAyB;IAEzB,OAAO,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAA;AAC1E,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { getCurrentUserImageParts, resolveImageReferences, type HttpsUrlReference, type ImageReference, type MessageAttachmentReference, type OpenCodeFilePart, type OpenCodeMessageClient, type ProjectFileReference, type ReferenceToolContext, type ResolvedReference, type ResolvedReferences, type ResolveReferencesOptions, } from "./attachments.js";
2
+ export { decodeStrictBase64, estimatedDecodedBase64Bytes, imageBytesToDataUrl, parseImageDataUrl, type DecodedImageData, } from "./data-url.js";
3
+ export { detectImageFormat, extensionForFormat, formatFromExtension, isSupportedImageMime, mimeForFormat, type DetectedImageFormat, type RasterImageFormat, type RasterImageMime, } from "./formats.js";
4
+ export { ReferenceBudget, type ReferenceLimits } from "./limits.js";
5
+ export { assertSafeRelativePath, isPathInside, loadProjectImage, loadTrustedAttachmentFile, sameCanonicalPath, type LoadedLocalImage, } from "./project-files.js";
6
+ export { MAX_REFERENCE_URL_LENGTH, validatePublicHttpsUrl } from "./remote-urls.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/references/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,7 @@
1
+ export { getCurrentUserImageParts, resolveImageReferences, } from "./attachments.js";
2
+ export { decodeStrictBase64, estimatedDecodedBase64Bytes, imageBytesToDataUrl, parseImageDataUrl, } from "./data-url.js";
3
+ export { detectImageFormat, extensionForFormat, formatFromExtension, isSupportedImageMime, mimeForFormat, } from "./formats.js";
4
+ export { ReferenceBudget } from "./limits.js";
5
+ export { assertSafeRelativePath, isPathInside, loadProjectImage, loadTrustedAttachmentFile, sameCanonicalPath, } from "./project-files.js";
6
+ export { MAX_REFERENCE_URL_LENGTH, validatePublicHttpsUrl } from "./remote-urls.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/references/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GAWvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,iBAAiB,GAElB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,GAId,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,eAAe,EAAwB,MAAM,aAAa,CAAA;AACnE,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,yBAAyB,EACzB,iBAAiB,GAElB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,15 @@
1
+ export interface ReferenceLimits {
2
+ maxReferences: number;
3
+ maxFileBytes: number;
4
+ maxTotalBytes: number;
5
+ }
6
+ export declare class ReferenceBudget {
7
+ #private;
8
+ constructor(limits: ReferenceLimits);
9
+ get referenceCount(): number;
10
+ get localBytes(): number;
11
+ addRemoteReference(): void;
12
+ addLocalReference(bytes: number): void;
13
+ assertEstimatedRequestSize(promptCharacters: number, urlCharacters: number): void;
14
+ }
15
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/references/limits.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,qBAAa,eAAe;;gBAKd,MAAM,EAAE,eAAe;IAInC,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,kBAAkB,IAAI,IAAI;IAI1B,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAoCtC,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;CA+BlF"}
@@ -0,0 +1,62 @@
1
+ import { PluginError } from "../openrouter/errors.js";
2
+ export class ReferenceBudget {
3
+ #limits;
4
+ #referenceCount = 0;
5
+ #localBytes = 0;
6
+ constructor(limits) {
7
+ this.#limits = limits;
8
+ }
9
+ get referenceCount() {
10
+ return this.#referenceCount;
11
+ }
12
+ get localBytes() {
13
+ return this.#localBytes;
14
+ }
15
+ addRemoteReference() {
16
+ this.#addReferenceCount();
17
+ }
18
+ addLocalReference(bytes) {
19
+ if (!Number.isSafeInteger(bytes) || bytes < 0) {
20
+ throw new PluginError("GENIMAGE_REFERENCE_INVALID", "The reference image has an invalid byte size.");
21
+ }
22
+ if (bytes > this.#limits.maxFileBytes) {
23
+ throw new PluginError("GENIMAGE_REFERENCE_TOO_LARGE", "The reference image exceeds the configured file-size limit.", {
24
+ details: { bytes, maxFileBytes: this.#limits.maxFileBytes },
25
+ suggestion: "Resize or compress the image, use fewer references, or provide a public HTTPS URL.",
26
+ });
27
+ }
28
+ if (this.#localBytes + bytes > this.#limits.maxTotalBytes) {
29
+ throw new PluginError("GENIMAGE_TOTAL_REFERENCE_SIZE_EXCEEDED", "The combined local reference images exceed the configured size limit.", {
30
+ details: {
31
+ bytes: this.#localBytes + bytes,
32
+ maxTotalBytes: this.#limits.maxTotalBytes,
33
+ },
34
+ suggestion: "Resize or compress images, use fewer references, or provide public HTTPS URLs.",
35
+ });
36
+ }
37
+ this.#addReferenceCount();
38
+ this.#localBytes += bytes;
39
+ }
40
+ assertEstimatedRequestSize(promptCharacters, urlCharacters) {
41
+ const estimatedBase64Bytes = Math.ceil(this.#localBytes / 3) * 4;
42
+ const overhead = 64 * 1024 + promptCharacters * 4 + urlCharacters * 4;
43
+ const maximum = Math.ceil(this.#limits.maxTotalBytes / 3) * 4 + 1024 * 1024;
44
+ if (estimatedBase64Bytes + overhead > maximum) {
45
+ throw new PluginError("GENIMAGE_TOTAL_REFERENCE_SIZE_EXCEEDED", "The encoded reference payload exceeds the safe request-size limit.", {
46
+ suggestion: "Resize or compress images, use fewer references, or provide public HTTPS URLs.",
47
+ });
48
+ }
49
+ }
50
+ #addReferenceCount() {
51
+ this.#referenceCount += 1;
52
+ if (this.#referenceCount > this.#limits.maxReferences || this.#referenceCount > 16) {
53
+ throw new PluginError("GENIMAGE_TOO_MANY_REFERENCES", "Too many image references were supplied.", {
54
+ details: {
55
+ maxReferences: Math.min(this.#limits.maxReferences, 16),
56
+ },
57
+ suggestion: "Use fewer references.",
58
+ });
59
+ }
60
+ }
61
+ }
62
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/references/limits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAQrD,MAAM,OAAO,eAAe;IACjB,OAAO,CAAiB;IACjC,eAAe,GAAG,CAAC,CAAA;IACnB,WAAW,GAAG,CAAC,CAAA;IAEf,YAAY,MAAuB;QACjC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;IACvB,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAA;IAC7B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,kBAAkB,EAAE,CAAA;IAC3B,CAAC;IAED,iBAAiB,CAAC,KAAa;QAC7B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,WAAW,CACnB,4BAA4B,EAC5B,+CAA+C,CAChD,CAAA;QACH,CAAC;QACD,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YACtC,MAAM,IAAI,WAAW,CACnB,8BAA8B,EAC9B,6DAA6D,EAC7D;gBACE,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;gBAC3D,UAAU,EACR,oFAAoF;aACvF,CACF,CAAA;QACH,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,GAAG,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1D,MAAM,IAAI,WAAW,CACnB,wCAAwC,EACxC,uEAAuE,EACvE;gBACE,OAAO,EAAE;oBACP,KAAK,EAAE,IAAI,CAAC,WAAW,GAAG,KAAK;oBAC/B,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;iBAC1C;gBACD,UAAU,EACR,gFAAgF;aACnF,CACF,CAAA;QACH,CAAC;QACD,IAAI,CAAC,kBAAkB,EAAE,CAAA;QACzB,IAAI,CAAC,WAAW,IAAI,KAAK,CAAA;IAC3B,CAAC;IAED,0BAA0B,CAAC,gBAAwB,EAAE,aAAqB;QACxE,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;QAChE,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,GAAG,gBAAgB,GAAG,CAAC,GAAG,aAAa,GAAG,CAAC,CAAA;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;QAC3E,IAAI,oBAAoB,GAAG,QAAQ,GAAG,OAAO,EAAE,CAAC;YAC9C,MAAM,IAAI,WAAW,CACnB,wCAAwC,EACxC,oEAAoE,EACpE;gBACE,UAAU,EACR,gFAAgF;aACnF,CACF,CAAA;QACH,CAAC;IACH,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,eAAe,IAAI,CAAC,CAAA;QACzB,IAAI,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC,eAAe,GAAG,EAAE,EAAE,CAAC;YACnF,MAAM,IAAI,WAAW,CACnB,8BAA8B,EAC9B,0CAA0C,EAC1C;gBACE,OAAO,EAAE;oBACP,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;iBACxD;gBACD,UAAU,EAAE,uBAAuB;aACpC,CACF,CAAA;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import { type DetectedImageFormat } from "./formats.js";
2
+ export interface LoadedLocalImage {
3
+ bytes: Buffer;
4
+ detected: DetectedImageFormat;
5
+ dataUrl: string;
6
+ canonicalPath: string;
7
+ }
8
+ export declare function isPathInside(root: string, candidate: string): boolean;
9
+ export declare function assertSafeRelativePath(value: string): string;
10
+ export declare function loadProjectImage(worktree: string, relativePath: string, maximumBytes: number, signal: AbortSignal): Promise<LoadedLocalImage>;
11
+ export declare function loadTrustedAttachmentFile(fileUrl: string, maximumBytes: number, signal: AbortSignal): Promise<LoadedLocalImage>;
12
+ export declare function sameCanonicalPath(left: string, right: string): boolean;
13
+ //# sourceMappingURL=project-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-files.d.ts","sourceRoot":"","sources":["../../src/references/project-files.ts"],"names":[],"mappings":"AAOA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;CACtB;AAMD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAMrE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB5D;AA6GD,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAqC3B;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAgB3B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtE"}