opencode-img 0.1.1 → 0.2.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 +63 -15
- package/dist/config.d.ts +4 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -15
- package/dist/config.js.map +1 -1
- package/dist/gemini-provider.d.ts +17 -0
- package/dist/gemini-provider.d.ts.map +1 -0
- package/dist/gemini-provider.js +130 -0
- package/dist/gemini-provider.js.map +1 -0
- package/dist/grok-provider.d.ts +17 -0
- package/dist/grok-provider.d.ts.map +1 -0
- package/dist/grok-provider.js +94 -0
- package/dist/grok-provider.js.map +1 -0
- package/dist/http.d.ts +23 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +55 -0
- package/dist/http.js.map +1 -0
- package/dist/image.d.ts +11 -2
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +42 -15
- package/dist/image.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -6
- package/dist/index.js.map +1 -1
- package/dist/openai-provider.d.ts +12 -7
- package/dist/openai-provider.d.ts.map +1 -1
- package/dist/openai-provider.js +34 -48
- package/dist/openai-provider.js.map +1 -1
- package/dist/provider.d.ts +9 -3
- package/dist/provider.d.ts.map +1 -1
- package/dist/providers.d.ts +32 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +60 -0
- package/dist/providers.js.map +1 -0
- package/dist/tool.d.ts +9 -5
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js +27 -31
- package/dist/tool.js.map +1 -1
- package/package.json +5 -4
package/dist/image.d.ts
CHANGED
|
@@ -3,18 +3,27 @@ export interface DecodedImage {
|
|
|
3
3
|
data: Uint8Array;
|
|
4
4
|
revisedPrompt?: string;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Decode a base64 image payload, rejecting empty or invalid data so a
|
|
8
|
+
* zero-byte or corrupt image never reaches the filesystem.
|
|
9
|
+
*/
|
|
10
|
+
export declare function decodeBase64Image(encoded: unknown): Uint8Array;
|
|
6
11
|
/**
|
|
7
12
|
* Pull the first image out of an OpenAI Images response.
|
|
8
13
|
*
|
|
9
14
|
* GPT image models and DALL·E models configured with `response_format=b64_json`
|
|
10
|
-
* both return `data[0].b64_json`.
|
|
11
|
-
* emptiness so a zero-byte or corrupt payload never reaches the filesystem.
|
|
15
|
+
* both return `data[0].b64_json`.
|
|
12
16
|
*/
|
|
13
17
|
export declare function decodeImageResponse(payload: unknown): DecodedImage;
|
|
14
18
|
/** The MIME type OpenAI returns for a given output format. */
|
|
15
19
|
export declare function mimeTypeForOutputFormat(format: OutputFormat | undefined): string;
|
|
16
20
|
/** The MIME type of a reference image, or `undefined` for an unsupported type. */
|
|
17
21
|
export declare function mimeTypeForReferencePath(filePath: string): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* The MIME type implied by an image's magic bytes, for adapters that cannot
|
|
24
|
+
* name the output format up front. Defaults to PNG.
|
|
25
|
+
*/
|
|
26
|
+
export declare function mimeTypeForImageBytes(bytes: Uint8Array): string;
|
|
18
27
|
/** The extensions the edits endpoint accepts for reference images. */
|
|
19
28
|
export declare const SUPPORTED_REFERENCE_EXTENSIONS: string[];
|
|
20
29
|
//# sourceMappingURL=image.d.ts.map
|
package/dist/image.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAYD
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAYD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAY9D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAgBlE;AAED,8DAA8D;AAC9D,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,CAUhF;AASD,kFAAkF;AAClF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI7E;AAOD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAW/D;AAED,sEAAsE;AACtE,eAAO,MAAM,8BAA8B,UAAiC,CAAA"}
|
package/dist/image.js
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
import { ImageToolError } from "./errors.js";
|
|
2
2
|
const BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
3
3
|
function malformed(detail) {
|
|
4
|
-
return new ImageToolError("malformed_response", "decode image response", `
|
|
4
|
+
return new ImageToolError("malformed_response", "decode image response", `The image response could not be read: ${detail}.`);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Decode a base64 image payload, rejecting empty or invalid data so a
|
|
8
|
+
* zero-byte or corrupt image never reaches the filesystem.
|
|
9
|
+
*/
|
|
10
|
+
export function decodeBase64Image(encoded) {
|
|
11
|
+
if (typeof encoded !== "string" || encoded === "") {
|
|
12
|
+
throw malformed("the image entry had no base64 payload");
|
|
13
|
+
}
|
|
14
|
+
if (encoded.length % 4 !== 0 || !BASE64_PATTERN.test(encoded)) {
|
|
15
|
+
throw malformed("the base64 payload was not valid base64");
|
|
16
|
+
}
|
|
17
|
+
const bytes = Buffer.from(encoded, "base64");
|
|
18
|
+
if (bytes.byteLength === 0) {
|
|
19
|
+
throw malformed("the decoded image was empty");
|
|
20
|
+
}
|
|
21
|
+
return bytes;
|
|
5
22
|
}
|
|
6
23
|
/**
|
|
7
24
|
* Pull the first image out of an OpenAI Images response.
|
|
8
25
|
*
|
|
9
26
|
* GPT image models and DALL·E models configured with `response_format=b64_json`
|
|
10
|
-
* both return `data[0].b64_json`.
|
|
11
|
-
* emptiness so a zero-byte or corrupt payload never reaches the filesystem.
|
|
27
|
+
* both return `data[0].b64_json`.
|
|
12
28
|
*/
|
|
13
29
|
export function decodeImageResponse(payload) {
|
|
14
30
|
if (typeof payload !== "object" || payload === null) {
|
|
@@ -19,18 +35,7 @@ export function decodeImageResponse(payload) {
|
|
|
19
35
|
throw malformed("the response contained no images");
|
|
20
36
|
}
|
|
21
37
|
const first = data[0];
|
|
22
|
-
const
|
|
23
|
-
if (typeof encoded !== "string" || encoded === "") {
|
|
24
|
-
throw malformed("the image entry had no base64 payload");
|
|
25
|
-
}
|
|
26
|
-
if (encoded.length % 4 !== 0 || !BASE64_PATTERN.test(encoded)) {
|
|
27
|
-
throw malformed("the base64 payload was not valid base64");
|
|
28
|
-
}
|
|
29
|
-
const bytes = Buffer.from(encoded, "base64");
|
|
30
|
-
if (bytes.byteLength === 0) {
|
|
31
|
-
throw malformed("the decoded image was empty");
|
|
32
|
-
}
|
|
33
|
-
const decoded = { data: bytes };
|
|
38
|
+
const decoded = { data: decodeBase64Image(first?.b64_json) };
|
|
34
39
|
if (typeof first.revised_prompt === "string" && first.revised_prompt !== "") {
|
|
35
40
|
decoded.revisedPrompt = first.revised_prompt;
|
|
36
41
|
}
|
|
@@ -61,6 +66,28 @@ export function mimeTypeForReferencePath(filePath) {
|
|
|
61
66
|
return undefined;
|
|
62
67
|
return MIME_BY_EXTENSION[filePath.slice(dot).toLowerCase()];
|
|
63
68
|
}
|
|
69
|
+
function startsWith(bytes, signature) {
|
|
70
|
+
if (bytes.length < signature.length)
|
|
71
|
+
return false;
|
|
72
|
+
return signature.every((byte, index) => bytes[index] === byte);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The MIME type implied by an image's magic bytes, for adapters that cannot
|
|
76
|
+
* name the output format up front. Defaults to PNG.
|
|
77
|
+
*/
|
|
78
|
+
export function mimeTypeForImageBytes(bytes) {
|
|
79
|
+
if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47]))
|
|
80
|
+
return "image/png";
|
|
81
|
+
if (startsWith(bytes, [0xff, 0xd8, 0xff]))
|
|
82
|
+
return "image/jpeg";
|
|
83
|
+
if (startsWith(bytes, [0x47, 0x49, 0x46, 0x38]))
|
|
84
|
+
return "image/gif";
|
|
85
|
+
if (startsWith(bytes, [0x52, 0x49, 0x46, 0x46]) &&
|
|
86
|
+
startsWith(bytes.subarray(8), [0x57, 0x45, 0x42, 0x50])) {
|
|
87
|
+
return "image/webp";
|
|
88
|
+
}
|
|
89
|
+
return "image/png";
|
|
90
|
+
}
|
|
64
91
|
/** The extensions the edits endpoint accepts for reference images. */
|
|
65
92
|
export const SUPPORTED_REFERENCE_EXTENSIONS = Object.keys(MIME_BY_EXTENSION);
|
|
66
93
|
//# sourceMappingURL=image.js.map
|
package/dist/image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAQ5C,MAAM,cAAc,GAAG,wBAAwB,CAAA;AAE/C,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,IAAI,cAAc,CACvB,oBAAoB,EACpB,uBAAuB,EACvB,
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { Plugin } from "@opencode/plugin";
|
|
|
3
3
|
* opencode-img — an OpenCode V2 plugin that adds the `gpt_imagegen` tool.
|
|
4
4
|
*
|
|
5
5
|
* Relative output and reference-image paths resolve against the session
|
|
6
|
-
* directory.
|
|
7
|
-
* connection the user made with `/connect`.
|
|
6
|
+
* directory. Each provider's API key comes from its environment variable, then
|
|
7
|
+
* the OpenCode integration connection the user made with `/connect`.
|
|
8
8
|
*/
|
|
9
9
|
declare const _default: Plugin.Plugin;
|
|
10
10
|
export default _default;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAgCzC;;;;;;GAMG;;AACH,wBA2BE"}
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,42 @@
|
|
|
1
1
|
import { Plugin } from "@opencode/plugin";
|
|
2
2
|
import { createGptImagegenTool } from "./tool.js";
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Read the plugin options into the tool's defaults.
|
|
5
|
+
*
|
|
6
|
+
* A malformed option is ignored rather than failing the load; the provider id
|
|
7
|
+
* and the model are validated when the tool runs, where the error can name the
|
|
8
|
+
* call.
|
|
9
|
+
*/
|
|
10
|
+
function readDefaults(options) {
|
|
11
|
+
const provider = options.provider;
|
|
12
|
+
const defaultProvider = typeof provider === "string" && provider.trim() !== "" ? provider : undefined;
|
|
13
|
+
const models = options.models;
|
|
14
|
+
const defaultModels = typeof models === "object" && models !== null
|
|
15
|
+
? Object.fromEntries(Object.entries(models).filter((entry) => typeof entry[1] === "string" && entry[1] !== ""))
|
|
16
|
+
: undefined;
|
|
17
|
+
return { defaultProvider, defaultModels };
|
|
18
|
+
}
|
|
5
19
|
/**
|
|
6
20
|
* opencode-img — an OpenCode V2 plugin that adds the `gpt_imagegen` tool.
|
|
7
21
|
*
|
|
8
22
|
* Relative output and reference-image paths resolve against the session
|
|
9
|
-
* directory.
|
|
10
|
-
* connection the user made with `/connect`.
|
|
23
|
+
* directory. Each provider's API key comes from its environment variable, then
|
|
24
|
+
* the OpenCode integration connection the user made with `/connect`.
|
|
11
25
|
*/
|
|
12
26
|
export default Plugin.define({
|
|
13
27
|
id: "opencode-img",
|
|
14
28
|
async setup(ctx) {
|
|
29
|
+
const { defaultProvider, defaultModels } = readDefaults(ctx.options);
|
|
15
30
|
await ctx.tool.transform((editor) => {
|
|
16
31
|
editor.add(createGptImagegenTool({
|
|
32
|
+
defaultProvider,
|
|
33
|
+
defaultModels,
|
|
17
34
|
resolveSessionDirectory: async (sessionID) => {
|
|
18
35
|
const session = await ctx.session.get({ sessionID });
|
|
19
36
|
return session.location.directory;
|
|
20
37
|
},
|
|
21
|
-
|
|
22
|
-
const connection = await ctx.integration.connection.active(
|
|
38
|
+
resolveConnectionKey: async (integrationID) => {
|
|
39
|
+
const connection = await ctx.integration.connection.active(integrationID);
|
|
23
40
|
if (!connection)
|
|
24
41
|
return undefined;
|
|
25
42
|
const credential = await ctx.integration.connection.resolve(connection);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AAEjD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AAEjD;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,OAA0C;IAI9D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;IACjC,MAAM,eAAe,GACnB,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;IAE/E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC7B,MAAM,aAAa,GACjB,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAC3C,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAC3B,CAAC,KAAK,EAA6B,EAAE,CACnC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAClD,CACF;QACH,CAAC,CAAC,SAAS,CAAA;IAEf,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,CAAA;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,eAAe,MAAM,CAAC,MAAM,CAAC;IAC3B,EAAE,EAAE,cAAc;IAClB,KAAK,CAAC,KAAK,CAAC,GAAG;QACb,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAEpE,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,MAAM,CAAC,GAAG,CACR,qBAAqB,CAAC;gBACpB,eAAe;gBACf,aAAa;gBACb,uBAAuB,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;oBAC3C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;oBACpD,OAAO,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAA;gBACnC,CAAC;gBACD,oBAAoB,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE;oBAC5C,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;oBACzE,IAAI,CAAC,UAAU;wBAAE,OAAO,SAAS,CAAA;oBACjC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;oBACvE,IAAI,UAAU,EAAE,IAAI,KAAK,KAAK,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;wBACrE,OAAO,UAAU,CAAC,GAAG,CAAA;oBACvB,CAAC;oBACD,OAAO,SAAS,CAAA;gBAClB,CAAC;aACF,CAAC,CACH,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type GenerationSettings, type GenerationSettingsInput } from "./config.ts";
|
|
2
|
+
import type { ImageProvider, ImageProviderOptions } from "./provider.ts";
|
|
2
3
|
export declare const DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/** The OpenAI image model used when the caller does not name one. */
|
|
5
|
+
export declare const OPENAI_DEFAULT_MODEL = "gpt-image-1.5";
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the generation settings for the OpenAI models.
|
|
8
|
+
*
|
|
9
|
+
* The OpenAI path keeps two model-family rules: an explicit `outputFormat` is
|
|
10
|
+
* rejected for DALL·E, and the output format is reconciled with the output path.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveOpenAISettings(input: GenerationSettingsInput, targetPath: string): GenerationSettings;
|
|
8
13
|
/**
|
|
9
14
|
* Create the OpenAI adapter for the internal {@link ImageProvider} seam.
|
|
10
15
|
*
|
|
@@ -12,5 +17,5 @@ export interface OpenAIImageProviderOptions {
|
|
|
12
17
|
* With reference images it becomes a multipart request to `/images/edits` and
|
|
13
18
|
* every image is attached under the `image[]` field.
|
|
14
19
|
*/
|
|
15
|
-
export declare function createOpenAIImageProvider(options:
|
|
20
|
+
export declare function createOpenAIImageProvider(options: ImageProviderOptions): ImageProvider;
|
|
16
21
|
//# sourceMappingURL=openai-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../src/openai-provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"openai-provider.d.ts","sourceRoot":"","sources":["../src/openai-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAA6B,MAAM,eAAe,CAAA;AAEnG,eAAO,MAAM,gBAAgB,8BAA8B,CAAA;AAE3D,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,kBAAkB,CAAA;AAEnD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,uBAAuB,EAC9B,UAAU,EAAE,MAAM,GACjB,kBAAkB,CAmBpB;AAuCD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAkDtF"}
|
package/dist/openai-provider.js
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
import { isGptImageModel } from "./config.js";
|
|
2
|
-
import {
|
|
1
|
+
import { isGptImageModel, outputFormatForExtension, reconcileOutputFormat, resolveSettings, } from "./config.js";
|
|
2
|
+
import { invalidArgument } from "./errors.js";
|
|
3
|
+
import { sendJsonRequest } from "./http.js";
|
|
3
4
|
import { decodeImageResponse, mimeTypeForOutputFormat } from "./image.js";
|
|
4
5
|
export const DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
/** The OpenAI image model used when the caller does not name one. */
|
|
7
|
+
export const OPENAI_DEFAULT_MODEL = "gpt-image-1.5";
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the generation settings for the OpenAI models.
|
|
10
|
+
*
|
|
11
|
+
* The OpenAI path keeps two model-family rules: an explicit `outputFormat` is
|
|
12
|
+
* rejected for DALL·E, and the output format is reconciled with the output path.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveOpenAISettings(input, targetPath) {
|
|
15
|
+
const settings = resolveSettings(input, OPENAI_DEFAULT_MODEL);
|
|
16
|
+
if (isGptImageModel(settings.model)) {
|
|
17
|
+
return reconcileOutputFormat(settings, targetPath);
|
|
18
|
+
}
|
|
19
|
+
if (settings.outputFormat !== undefined) {
|
|
20
|
+
throw invalidArgument("`outputFormat` is only supported by the GPT image models; DALL·E models always return PNG.");
|
|
19
21
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
const extensionFormat = outputFormatForExtension(targetPath);
|
|
23
|
+
if (extensionFormat !== undefined && extensionFormat !== "png") {
|
|
24
|
+
throw invalidArgument(`DALL·E models always return PNG, so \`outputPath\` cannot end in \`.${extensionFormat}\`.`);
|
|
22
25
|
}
|
|
23
|
-
return
|
|
26
|
+
return settings;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* The settings the request carries, as ordered field/value pairs. One mapping
|
|
@@ -75,44 +78,27 @@ export function createOpenAIImageProvider(options) {
|
|
|
75
78
|
async function send(request, operation, signal) {
|
|
76
79
|
const hasReferences = (request.references?.length ?? 0) > 0;
|
|
77
80
|
const url = hasReferences ? `${baseUrl}/images/edits` : `${baseUrl}/images/generations`;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
const payload = await sendJsonRequest({
|
|
82
|
+
provider: "OpenAI",
|
|
83
|
+
operation,
|
|
84
|
+
fetchImpl,
|
|
85
|
+
url,
|
|
86
|
+
init: hasReferences
|
|
87
|
+
? {
|
|
82
88
|
method: "POST",
|
|
83
89
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
84
90
|
body: buildEditForm(request),
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
: await fetchImpl(url, {
|
|
91
|
+
}
|
|
92
|
+
: {
|
|
88
93
|
method: "POST",
|
|
89
94
|
headers: {
|
|
90
95
|
Authorization: `Bearer ${apiKey}`,
|
|
91
96
|
"Content-Type": "application/json",
|
|
92
97
|
},
|
|
93
98
|
body: JSON.stringify(buildGenerationBody(request)),
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
if (isAbort(error, signal)) {
|
|
99
|
-
throw new ImageToolError("cancelled", operation, "The image request was cancelled.", {
|
|
100
|
-
cause: error,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
throw new ImageToolError("api_error", operation, `Could not reach OpenAI while trying to ${operation}: ${error.message}.`, { cause: error });
|
|
104
|
-
}
|
|
105
|
-
if (!response.ok) {
|
|
106
|
-
const detail = safeErrorDetail(await response.text().catch(() => ""));
|
|
107
|
-
throw new ImageToolError("api_error", operation, `OpenAI returned HTTP ${response.status} while trying to ${operation}: ${detail}`);
|
|
108
|
-
}
|
|
109
|
-
let payload;
|
|
110
|
-
try {
|
|
111
|
-
payload = await response.json();
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
throw new ImageToolError("malformed_response", operation, "OpenAI returned a response body that was not valid JSON.", { cause: error });
|
|
115
|
-
}
|
|
99
|
+
},
|
|
100
|
+
signal,
|
|
101
|
+
});
|
|
116
102
|
const decoded = decodeImageResponse(payload);
|
|
117
103
|
const result = {
|
|
118
104
|
data: decoded.data,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-provider.js","sourceRoot":"","sources":["../src/openai-provider.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"openai-provider.js","sourceRoot":"","sources":["../src/openai-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/provider.d.ts
CHANGED
|
@@ -15,12 +15,18 @@ export interface ImageResult {
|
|
|
15
15
|
mimeType: string;
|
|
16
16
|
revisedPrompt?: string;
|
|
17
17
|
}
|
|
18
|
+
/** Options a provider factory receives when the tool builds an adapter. */
|
|
19
|
+
export interface ImageProviderOptions {
|
|
20
|
+
apiKey: string;
|
|
21
|
+
baseUrl?: string;
|
|
22
|
+
fetch?: typeof globalThis.fetch;
|
|
23
|
+
}
|
|
18
24
|
/**
|
|
19
25
|
* The internal seam between the tool and an image service.
|
|
20
26
|
*
|
|
21
|
-
* It stays private to the package: the tool
|
|
22
|
-
*
|
|
23
|
-
*
|
|
27
|
+
* It stays private to the package: the tool picks an implementation through the
|
|
28
|
+
* internal registry in `providers.ts`. Adding a service means adding an
|
|
29
|
+
* implementation there, not exposing a public plugin API.
|
|
24
30
|
*/
|
|
25
31
|
export interface ImageProvider {
|
|
26
32
|
generate(request: ImageRequest, signal?: AbortSignal): Promise<ImageResult>;
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErD,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CAC5E"}
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErD,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CAChC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CAC5E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { GenerationSettings, GenerationSettingsInput } from "./config.ts";
|
|
2
|
+
import type { ImageProvider, ImageProviderOptions } from "./provider.ts";
|
|
3
|
+
/** The provider used when the caller does not name one. */
|
|
4
|
+
export declare const DEFAULT_PROVIDER = "openai";
|
|
5
|
+
export interface ImageProviderDefinition {
|
|
6
|
+
/** The id used in the tool's `provider` input. */
|
|
7
|
+
readonly id: string;
|
|
8
|
+
/** Environment variables that can supply the key, checked in order. */
|
|
9
|
+
readonly envVars: readonly string[];
|
|
10
|
+
/** OpenCode integration id whose connection can supply the key. */
|
|
11
|
+
readonly integrationID: string;
|
|
12
|
+
/** Validate the request settings and reconcile the output format with the path. */
|
|
13
|
+
readonly resolveSettings: (input: GenerationSettingsInput, targetPath: string) => GenerationSettings;
|
|
14
|
+
/** Build the adapter for this provider. */
|
|
15
|
+
readonly create: (options: ImageProviderOptions) => ImageProvider;
|
|
16
|
+
}
|
|
17
|
+
/** The registered provider ids. */
|
|
18
|
+
export declare function providerIds(): string[];
|
|
19
|
+
/** Look up a provider definition, or fail with the known ids. */
|
|
20
|
+
export declare function getProvider(id: string): ImageProviderDefinition;
|
|
21
|
+
export interface ApiKeySources {
|
|
22
|
+
/** Environment variables the key can come from. */
|
|
23
|
+
env: Record<string, string | undefined>;
|
|
24
|
+
/** Resolve a key from an OpenCode integration connection. */
|
|
25
|
+
connectionKey?: (integrationID: string) => Promise<string | undefined>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Find a provider's API key: its environment variables first, then its OpenCode
|
|
29
|
+
* integration connection. Fails before any network request when none is present.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveProviderKey(definition: ImageProviderDefinition, sources: ApiKeySources): Promise<string>;
|
|
32
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAc9E,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAExE,2DAA2D;AAC3D,eAAO,MAAM,gBAAgB,WAAW,CAAA;AAExC,MAAM,WAAW,uBAAuB;IACtC,kDAAkD;IAClD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,mEAAmE;IACnE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,eAAe,EAAE,CACxB,KAAK,EAAE,uBAAuB,EAC9B,UAAU,EAAE,MAAM,KACf,kBAAkB,CAAA;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,aAAa,CAAA;CAClE;AAgCD,mCAAmC;AACnC,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAED,iEAAiE;AACjE,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAQ/D;AAED,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvC,6DAA6D;IAC7D,aAAa,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CACvE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,uBAAuB,EACnC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,CAcjB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ImageToolError, invalidArgument } from "./errors.js";
|
|
2
|
+
import { createGeminiImageProvider, resolveGeminiSettings, } from "./gemini-provider.js";
|
|
3
|
+
import { createGrokImageProvider, resolveGrokSettings, } from "./grok-provider.js";
|
|
4
|
+
import { createOpenAIImageProvider, resolveOpenAISettings, } from "./openai-provider.js";
|
|
5
|
+
/** The provider used when the caller does not name one. */
|
|
6
|
+
export const DEFAULT_PROVIDER = "openai";
|
|
7
|
+
/**
|
|
8
|
+
* The internal provider registry.
|
|
9
|
+
*
|
|
10
|
+
* It stays private to the package. The tool routes to an entry here, and adding
|
|
11
|
+
* a service means adding an entry, not exposing a public plugin API.
|
|
12
|
+
*/
|
|
13
|
+
const PROVIDERS = {
|
|
14
|
+
openai: {
|
|
15
|
+
envVars: ["OPENAI_API_KEY"],
|
|
16
|
+
integrationID: "openai",
|
|
17
|
+
resolveSettings: resolveOpenAISettings,
|
|
18
|
+
create: createOpenAIImageProvider,
|
|
19
|
+
},
|
|
20
|
+
gemini: {
|
|
21
|
+
envVars: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
|
|
22
|
+
integrationID: "google",
|
|
23
|
+
resolveSettings: resolveGeminiSettings,
|
|
24
|
+
create: createGeminiImageProvider,
|
|
25
|
+
},
|
|
26
|
+
grok: {
|
|
27
|
+
envVars: ["XAI_API_KEY"],
|
|
28
|
+
integrationID: "xai",
|
|
29
|
+
resolveSettings: resolveGrokSettings,
|
|
30
|
+
create: createGrokImageProvider,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
/** The registered provider ids. */
|
|
34
|
+
export function providerIds() {
|
|
35
|
+
return Object.keys(PROVIDERS);
|
|
36
|
+
}
|
|
37
|
+
/** Look up a provider definition, or fail with the known ids. */
|
|
38
|
+
export function getProvider(id) {
|
|
39
|
+
const spec = PROVIDERS[id];
|
|
40
|
+
if (spec === undefined) {
|
|
41
|
+
throw invalidArgument(`Unknown provider \`${id}\`. Known providers: ${providerIds().join(", ")}.`);
|
|
42
|
+
}
|
|
43
|
+
return { id, ...spec };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Find a provider's API key: its environment variables first, then its OpenCode
|
|
47
|
+
* integration connection. Fails before any network request when none is present.
|
|
48
|
+
*/
|
|
49
|
+
export async function resolveProviderKey(definition, sources) {
|
|
50
|
+
for (const name of definition.envVars) {
|
|
51
|
+
const value = sources.env[name];
|
|
52
|
+
if (typeof value === "string" && value !== "")
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
const fromConnection = await sources.connectionKey?.(definition.integrationID);
|
|
56
|
+
if (typeof fromConnection === "string" && fromConnection !== "")
|
|
57
|
+
return fromConnection;
|
|
58
|
+
throw new ImageToolError("missing_api_key", "validate API key", `No ${definition.id} API key was found. Set ${definition.envVars.join(" or ")}, or connect the ${definition.integrationID} integration in OpenCode (run /connect).`);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EACL,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,sBAAsB,CAAA;AAG7B,2DAA2D;AAC3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAA;AAqBxC;;;;;GAKG;AACH,MAAM,SAAS,GAAgD;IAC7D,MAAM,EAAE;QACN,OAAO,EAAE,CAAC,gBAAgB,CAAC;QAC3B,aAAa,EAAE,QAAQ;QACvB,eAAe,EAAE,qBAAqB;QACtC,MAAM,EAAE,yBAAyB;KAClC;IACD,MAAM,EAAE;QACN,OAAO,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,8BAA8B,CAAC;QAC7E,aAAa,EAAE,QAAQ;QACvB,eAAe,EAAE,qBAAqB;QACtC,MAAM,EAAE,yBAAyB;KAClC;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,CAAC,aAAa,CAAC;QACxB,aAAa,EAAE,KAAK;QACpB,eAAe,EAAE,mBAAmB;QACpC,MAAM,EAAE,uBAAuB;KAChC;CACF,CAAA;AAED,mCAAmC;AACnC,MAAM,UAAU,WAAW;IACzB,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;AAC/B,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAA;IAC1B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,eAAe,CACnB,sBAAsB,EAAE,wBAAwB,WAAW,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5E,CAAA;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,CAAA;AACxB,CAAC;AASD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAAmC,EACnC,OAAsB;IAEtB,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;YAAE,OAAO,KAAK,CAAA;IAC7D,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;IAC9E,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,KAAK,EAAE;QAAE,OAAO,cAAc,CAAA;IAEtF,MAAM,IAAI,cAAc,CACtB,iBAAiB,EACjB,kBAAkB,EAClB,MAAM,UAAU,CAAC,EAAE,2BAA2B,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,oBAAoB,UAAU,CAAC,aAAa,0CAA0C,CACpK,CAAA;AACH,CAAC"}
|
package/dist/tool.d.ts
CHANGED
|
@@ -3,14 +3,18 @@ export declare const TOOL_NAME = "gpt_imagegen";
|
|
|
3
3
|
export interface GptImagegenDependencies {
|
|
4
4
|
/** Resolve the OpenCode session directory used as the base for relative paths. */
|
|
5
5
|
resolveSessionDirectory: (sessionID: string) => Promise<string>;
|
|
6
|
-
/** Environment source for
|
|
6
|
+
/** Environment source for provider keys; defaults to `process.env`. */
|
|
7
7
|
env?: Record<string, string | undefined>;
|
|
8
8
|
/**
|
|
9
|
-
* Resolve a key from OpenCode
|
|
10
|
-
*
|
|
9
|
+
* Resolve a key from an OpenCode integration connection. Consulted only when
|
|
10
|
+
* none of the provider's environment variables are set.
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
12
|
+
resolveConnectionKey?: (integrationID: string) => Promise<string | undefined>;
|
|
13
|
+
/** Provider used when a call does not name one. Defaults to `openai`. */
|
|
14
|
+
defaultProvider?: string;
|
|
15
|
+
/** Per-provider default model, overriding each provider's built-in default. */
|
|
16
|
+
defaultModels?: Readonly<Record<string, string>>;
|
|
17
|
+
/** Override the provider API base URL. */
|
|
14
18
|
baseUrl?: string;
|
|
15
19
|
/** Inject a fetch implementation (used by tests). */
|
|
16
20
|
fetch?: typeof globalThis.fetch;
|
package/dist/tool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAqC,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAqC,MAAM,+BAA+B,CAAA;AAQxG,eAAO,MAAM,SAAS,iBAAiB,CAAA;AASvC,MAAM,WAAW,uBAAuB;IACtC,kFAAkF;IAClF,uBAAuB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/D,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACxC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC7E,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChD,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CAChC;AA2GD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,uBAAuB,GAAG,QAAQ,CA6ErF"}
|