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,148 @@
1
+ import { open, realpath } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { PluginError } from "../openrouter/errors.js";
5
+ import { throwIfAborted } from "../utils/abort.js";
6
+ import { imageBytesToDataUrl } from "./data-url.js";
7
+ import { detectImageFormat } from "./formats.js";
8
+ function pathKey(value) {
9
+ return process.platform === "win32" ? value.toLocaleLowerCase("en-US") : value;
10
+ }
11
+ export function isPathInside(root, candidate) {
12
+ const relative = path.relative(root, candidate);
13
+ return (relative === "" ||
14
+ (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative)));
15
+ }
16
+ export function assertSafeRelativePath(value) {
17
+ const windowsAbsolute = path.win32.isAbsolute(value);
18
+ const posixAbsolute = path.posix.isAbsolute(value.replaceAll("\\", "/"));
19
+ const segments = value.replaceAll("\\", "/").split("/");
20
+ if (value.trim() === "" ||
21
+ /[\u0000-\u001f\u007f]/u.test(value) ||
22
+ windowsAbsolute ||
23
+ posixAbsolute ||
24
+ segments.includes("..")) {
25
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "Project image paths must be relative and remain inside the worktree.");
26
+ }
27
+ return value;
28
+ }
29
+ async function readValidatedFile(filePath, maximumBytes, signal) {
30
+ throwIfAborted(signal);
31
+ let file;
32
+ try {
33
+ file = await open(filePath, "r");
34
+ }
35
+ catch (error) {
36
+ throwIfAborted(signal);
37
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The referenced image file was not found.", { cause: error });
38
+ }
39
+ let bytes;
40
+ try {
41
+ const initialStats = await file.stat({ bigint: true });
42
+ if (!initialStats.isFile()) {
43
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The referenced path is not a regular file.");
44
+ }
45
+ if (initialStats.size > BigInt(maximumBytes)) {
46
+ throw new PluginError("GENIMAGE_REFERENCE_TOO_LARGE", "The reference image exceeds the configured file-size limit.", {
47
+ details: {
48
+ bytes: Number(initialStats.size),
49
+ maxFileBytes: maximumBytes,
50
+ },
51
+ suggestion: "Resize or compress the reference image.",
52
+ });
53
+ }
54
+ const chunks = [];
55
+ let totalBytes = 0;
56
+ while (totalBytes <= maximumBytes) {
57
+ throwIfAborted(signal);
58
+ const remaining = maximumBytes + 1 - totalBytes;
59
+ const buffer = Buffer.allocUnsafe(Math.min(64 * 1_024, remaining));
60
+ const { bytesRead } = await file.read(buffer, 0, buffer.byteLength, null);
61
+ if (bytesRead === 0)
62
+ break;
63
+ chunks.push(Buffer.from(buffer.subarray(0, bytesRead)));
64
+ totalBytes += bytesRead;
65
+ }
66
+ throwIfAborted(signal);
67
+ if (totalBytes > maximumBytes) {
68
+ throw new PluginError("GENIMAGE_REFERENCE_TOO_LARGE", "The reference image changed while it was being read or is too large.", {
69
+ details: { bytes: totalBytes, maxFileBytes: maximumBytes },
70
+ suggestion: "Resize or compress the reference image.",
71
+ });
72
+ }
73
+ const finalStats = await file.stat({ bigint: true });
74
+ if (finalStats.dev !== initialStats.dev ||
75
+ finalStats.ino !== initialStats.ino ||
76
+ finalStats.size !== initialStats.size ||
77
+ finalStats.mtimeNs !== initialStats.mtimeNs ||
78
+ finalStats.ctimeNs !== initialStats.ctimeNs ||
79
+ BigInt(totalBytes) !== finalStats.size) {
80
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The referenced image changed while it was being read.");
81
+ }
82
+ bytes = Buffer.concat(chunks, totalBytes);
83
+ }
84
+ catch (error) {
85
+ throwIfAborted(signal);
86
+ if (error instanceof PluginError)
87
+ throw error;
88
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The referenced image file could not be read.", { cause: error });
89
+ }
90
+ finally {
91
+ await file.close().catch(() => undefined);
92
+ }
93
+ throwIfAborted(signal);
94
+ const detected = detectImageFormat(bytes);
95
+ if (detected === undefined) {
96
+ throw new PluginError("GENIMAGE_REFERENCE_FORMAT_UNSUPPORTED", "Only PNG, JPEG, and WebP reference images are supported.");
97
+ }
98
+ const canonicalPath = await realpath(filePath);
99
+ return {
100
+ bytes,
101
+ detected,
102
+ dataUrl: imageBytesToDataUrl(bytes, detected.mime),
103
+ canonicalPath,
104
+ };
105
+ }
106
+ export async function loadProjectImage(worktree, relativePath, maximumBytes, signal) {
107
+ assertSafeRelativePath(relativePath);
108
+ throwIfAborted(signal);
109
+ const canonicalRoot = await realpath(worktree);
110
+ const lexicalPath = path.resolve(worktree, relativePath);
111
+ if (!isPathInside(path.resolve(worktree), lexicalPath)) {
112
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The project image path escapes the worktree.");
113
+ }
114
+ let canonicalPath;
115
+ try {
116
+ canonicalPath = await realpath(lexicalPath);
117
+ }
118
+ catch (error) {
119
+ throwIfAborted(signal);
120
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The referenced image file was not found.", { cause: error });
121
+ }
122
+ if (!isPathInside(canonicalRoot, canonicalPath)) {
123
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The project image resolves outside the worktree.");
124
+ }
125
+ const image = await readValidatedFile(canonicalPath, maximumBytes, signal);
126
+ if (!isPathInside(canonicalRoot, image.canonicalPath)) {
127
+ throw new PluginError("GENIMAGE_REFERENCE_NOT_FOUND", "The project image resolves outside the worktree.");
128
+ }
129
+ return image;
130
+ }
131
+ export async function loadTrustedAttachmentFile(fileUrl, maximumBytes, signal) {
132
+ let filePath;
133
+ try {
134
+ const parsed = new URL(fileUrl);
135
+ if (parsed.protocol !== "file:" || parsed.username !== "" || parsed.password !== "") {
136
+ throw new TypeError("not a trusted file URL");
137
+ }
138
+ filePath = fileURLToPath(parsed);
139
+ }
140
+ catch (error) {
141
+ throw new PluginError("GENIMAGE_ATTACHMENT_ACCESS_FAILED", "The OpenCode attachment file URL is invalid.", { cause: error });
142
+ }
143
+ return readValidatedFile(filePath, maximumBytes, signal);
144
+ }
145
+ export function sameCanonicalPath(left, right) {
146
+ return pathKey(path.resolve(left)) === pathKey(path.resolve(right));
147
+ }
148
+ //# sourceMappingURL=project-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-files.js","sourceRoot":"","sources":["../../src/references/project-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const MAX_REFERENCE_URL_LENGTH = 8192;
2
+ export declare function validatePublicHttpsUrl(value: string): string;
3
+ //# sourceMappingURL=remote-urls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-urls.d.ts","sourceRoot":"","sources":["../../src/references/remote-urls.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,wBAAwB,OAAQ,CAAA;AAE7C,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA+B5D"}
@@ -0,0 +1,22 @@
1
+ import { PluginError } from "../openrouter/errors.js";
2
+ export const MAX_REFERENCE_URL_LENGTH = 8_192;
3
+ export function validatePublicHttpsUrl(value) {
4
+ if (value.length === 0 || value.length > MAX_REFERENCE_URL_LENGTH) {
5
+ throw new PluginError("GENIMAGE_REFERENCE_URL_INVALID", "The reference URL is empty or too long.");
6
+ }
7
+ let url;
8
+ try {
9
+ url = new URL(value);
10
+ }
11
+ catch (error) {
12
+ throw new PluginError("GENIMAGE_REFERENCE_URL_INVALID", "The reference URL is invalid.", { cause: error });
13
+ }
14
+ if (url.protocol !== "https:" ||
15
+ url.username !== "" ||
16
+ url.password !== "" ||
17
+ url.hostname === "") {
18
+ throw new PluginError("GENIMAGE_REFERENCE_URL_INVALID", "Reference URLs must use HTTPS and must not contain credentials.");
19
+ }
20
+ return value;
21
+ }
22
+ //# sourceMappingURL=remote-urls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-urls.js","sourceRoot":"","sources":["../../src/references/remote-urls.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAA;AAE7C,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAClE,MAAM,IAAI,WAAW,CACnB,gCAAgC,EAChC,yCAAyC,CAC1C,CAAA;IACH,CAAC;IAED,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,WAAW,CACnB,gCAAgC,EAChC,+BAA+B,EAC/B,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAA;IACH,CAAC;IAED,IACE,GAAG,CAAC,QAAQ,KAAK,QAAQ;QACzB,GAAG,CAAC,QAAQ,KAAK,EAAE;QACnB,GAAG,CAAC,QAAQ,KAAK,EAAE;QACnB,GAAG,CAAC,QAAQ,KAAK,EAAE,EACnB,CAAC;QACD,MAAM,IAAI,WAAW,CACnB,gCAAgC,EAChC,iEAAiE,CAClE,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ export declare const server: Plugin;
3
+ declare const _default: {
4
+ id: string;
5
+ server: Plugin;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,MAAM,EAIP,MAAM,qBAAqB,CAAA;AAmG5B,eAAO,MAAM,MAAM,EAAE,MA2BpB,CAAA;;;;;AAED,wBAGwB"}
package/dist/server.js ADDED
@@ -0,0 +1,97 @@
1
+ import { OPENROUTER_BALANCE_COMMAND } from "./commands/balance-command.js";
2
+ import { requireResolvedPluginOptions, resolvePluginConfig, } from "./config/resolve.js";
3
+ import { createOpenCodeLogger } from "./logging.js";
4
+ import { ModelCapabilityService } from "./openrouter/capabilities.js";
5
+ import { createOpenRouterClient } from "./openrouter/client.js";
6
+ import { createBalanceTool } from "./tools/balance.js";
7
+ import { createEditImageTool } from "./tools/edit-image.js";
8
+ import { createGenerateImageTool } from "./tools/generate-image.js";
9
+ import { DirectTransport, KoteGatewayTransport, } from "./transport/index.js";
10
+ const TOOL_PERMISSIONS = {
11
+ openrouter_edit_image: "ask",
12
+ openrouter_generate_image: "ask",
13
+ openrouter_balance: "allow",
14
+ };
15
+ function applyDefaultPermissions(config) {
16
+ const current = config.permission;
17
+ if (current !== undefined && (typeof current !== "object" || current === null)) {
18
+ return;
19
+ }
20
+ const permissions = (current ?? {});
21
+ if (!("*" in permissions)) {
22
+ for (const [name, value] of Object.entries(TOOL_PERMISSIONS)) {
23
+ if (!(name in permissions))
24
+ permissions[name] = value;
25
+ }
26
+ }
27
+ config.permission = permissions;
28
+ }
29
+ function applyBalanceCommand(config, logger) {
30
+ config.command ??= {};
31
+ if (config.command["openrouter-balance"] !== undefined) {
32
+ logger.log("warn", "The user-defined openrouter-balance command was preserved; the plugin default was not installed.");
33
+ return;
34
+ }
35
+ config.command["openrouter-balance"] = { ...OPENROUTER_BALANCE_COMMAND };
36
+ }
37
+ function createRuntimeOwner(configState, logger) {
38
+ let runtime;
39
+ let transport;
40
+ return {
41
+ getRuntime() {
42
+ if (runtime !== undefined)
43
+ return runtime;
44
+ const options = requireResolvedPluginOptions(configState);
45
+ transport =
46
+ options.routing === "direct"
47
+ ? new DirectTransport()
48
+ : new KoteGatewayTransport({ logger });
49
+ const client = createOpenRouterClient(options, transport, logger);
50
+ const capabilities = new ModelCapabilityService({
51
+ client,
52
+ pluginOptions: options,
53
+ logger,
54
+ });
55
+ runtime = { options, client, capabilities };
56
+ return runtime;
57
+ },
58
+ async dispose() {
59
+ runtime?.capabilities.clear();
60
+ await transport?.dispose?.();
61
+ runtime = undefined;
62
+ transport = undefined;
63
+ },
64
+ };
65
+ }
66
+ function loggerFromInput(input) {
67
+ return createOpenCodeLogger(input.client, input.directory);
68
+ }
69
+ export const server = async (input, rawOptions) => {
70
+ const logger = loggerFromInput(input);
71
+ const configState = resolvePluginConfig(rawOptions);
72
+ const runtimeOwner = createRuntimeOwner(configState, logger);
73
+ const dependencies = {
74
+ configState,
75
+ getRuntime: () => runtimeOwner.getRuntime(),
76
+ messageClient: input.client,
77
+ serverUrl: input.serverUrl,
78
+ logger,
79
+ };
80
+ return {
81
+ tool: {
82
+ openrouter_edit_image: createEditImageTool(dependencies),
83
+ openrouter_generate_image: createGenerateImageTool(dependencies),
84
+ openrouter_balance: createBalanceTool(dependencies),
85
+ },
86
+ config: async (config) => {
87
+ applyBalanceCommand(config, logger);
88
+ applyDefaultPermissions(config);
89
+ },
90
+ dispose: async () => runtimeOwner.dispose(),
91
+ };
92
+ };
93
+ export default {
94
+ id: "openrouter-genimage-kote-opencode",
95
+ server,
96
+ };
97
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ToolDependencies } from "./types.js";
2
+ export declare function formatMoney(value: number): string;
3
+ export declare function createBalanceTool(dependencies: ToolDependencies): {
4
+ description: string;
5
+ args: {};
6
+ execute(args: Record<string, never>, context: import("@opencode-ai/plugin").ToolContext): Promise<import("@opencode-ai/plugin").ToolResult>;
7
+ };
8
+ //# sourceMappingURL=balance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balance.d.ts","sourceRoot":"","sources":["../../src/tools/balance.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAkBD,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,gBAAgB;;;;EA8H/D"}
@@ -0,0 +1,133 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import { redactSecrets } from "../logging.js";
3
+ import { isPluginError } from "../openrouter/errors.js";
4
+ import { requireResolvedPluginOptions } from "../config/resolve.js";
5
+ import { throwIfAborted } from "../utils/abort.js";
6
+ import { runToolOperation } from "./common.js";
7
+ export function formatMoney(value) {
8
+ if (value !== 0 && Math.abs(value) < 0.000001)
9
+ return value.toExponential(6);
10
+ return value.toFixed(6);
11
+ }
12
+ function addMoneyLine(lines, label, value) {
13
+ if (value !== undefined)
14
+ lines.push(`- ${label}: $${formatMoney(value)}`);
15
+ }
16
+ function addBooleanLine(lines, label, value) {
17
+ if (value !== undefined)
18
+ lines.push(`- ${label}: ${value ? "yes" : "no"}`);
19
+ }
20
+ function safeInlineText(value) {
21
+ return redactSecrets(value)
22
+ .replace(/data:image\/(?:png|jpeg|webp);base64,[A-Za-z0-9+/=]+/giu, "[REDACTED]")
23
+ .replace(/[A-Za-z0-9+/]{96,}={0,2}/gu, "[REDACTED]")
24
+ .replace(/[\u0000-\u001f\u007f]+/gu, " ")
25
+ .slice(0, 160);
26
+ }
27
+ export function createBalanceTool(dependencies) {
28
+ return tool({
29
+ description: "Show usage and spending limits for the configured OpenRouter API key, plus full account credits when a management key is available. This tool does not generate images and does not incur image-generation charges.",
30
+ args: {},
31
+ async execute(_args, context) {
32
+ return runToolOperation(dependencies.logger, async () => {
33
+ const options = requireResolvedPluginOptions(dependencies.configState);
34
+ const runtime = dependencies.getRuntime();
35
+ const key = await runtime.client.getCurrentKey(context.abort);
36
+ const managementApiKey = options.managementApiKey ??
37
+ (key.is_management_key === true ? options.apiKey : undefined);
38
+ let credits;
39
+ let creditsError;
40
+ if (managementApiKey !== undefined) {
41
+ try {
42
+ const result = await runtime.client.getCredits(managementApiKey, context.abort);
43
+ credits = {
44
+ ...result,
45
+ available: result.total_credits - result.total_usage,
46
+ };
47
+ }
48
+ catch (error) {
49
+ throwIfAborted(context.abort);
50
+ creditsError = isPluginError(error) ? error.code : "unavailable";
51
+ }
52
+ }
53
+ const limitReset = typeof key.limit_reset === "string"
54
+ ? safeInlineText(key.limit_reset)
55
+ : key.limit_reset;
56
+ const expiresAt = typeof key.expires_at === "string"
57
+ ? safeInlineText(key.expires_at)
58
+ : key.expires_at;
59
+ const lines = ["OpenRouter API-key usage:"];
60
+ if (key.label !== undefined) {
61
+ lines.push(`- Label: ${safeInlineText(key.label)}`);
62
+ }
63
+ addMoneyLine(lines, "Lifetime usage", key.usage);
64
+ addMoneyLine(lines, "Daily usage", key.usage_daily);
65
+ addMoneyLine(lines, "Weekly usage", key.usage_weekly);
66
+ addMoneyLine(lines, "Monthly usage", key.usage_monthly);
67
+ addMoneyLine(lines, "BYOK lifetime usage", key.byok_usage);
68
+ addMoneyLine(lines, "BYOK daily usage", key.byok_usage_daily);
69
+ addMoneyLine(lines, "BYOK weekly usage", key.byok_usage_weekly);
70
+ addMoneyLine(lines, "BYOK monthly usage", key.byok_usage_monthly);
71
+ if (key.limit === null)
72
+ lines.push("- API-key spending limit: unlimited");
73
+ else
74
+ addMoneyLine(lines, "API-key spending limit", key.limit);
75
+ if (key.limit_remaining === null) {
76
+ lines.push("- Remaining API-key spending limit: unlimited");
77
+ }
78
+ else {
79
+ addMoneyLine(lines, "Remaining API-key spending limit", key.limit_remaining);
80
+ }
81
+ if (limitReset !== undefined) {
82
+ lines.push(`- Limit reset: ${limitReset ?? "none"}`);
83
+ }
84
+ addBooleanLine(lines, "Free tier", key.is_free_tier);
85
+ addBooleanLine(lines, "Management key", key.is_management_key);
86
+ if (expiresAt !== undefined) {
87
+ lines.push(`- Expires at: ${expiresAt ?? "never"}`);
88
+ }
89
+ lines.push("", "OpenRouter account credits:");
90
+ if (credits !== undefined) {
91
+ addMoneyLine(lines, "Total purchased credits", credits.total_credits);
92
+ addMoneyLine(lines, "Total account usage", credits.total_usage);
93
+ addMoneyLine(lines, "Available account credits", credits.available);
94
+ }
95
+ else {
96
+ lines.push("- Account credits: unavailable");
97
+ lines.push(managementApiKey === undefined
98
+ ? "- Reason: OpenRouter management key is not configured"
99
+ : `- Reason: credits request failed (${creditsError ?? "unavailable"})`);
100
+ }
101
+ return {
102
+ title: "OpenRouter balance and usage",
103
+ output: lines.join("\n"),
104
+ metadata: {
105
+ routing: options.routing,
106
+ model: options.model,
107
+ key: {
108
+ usage: key.usage,
109
+ usageDaily: key.usage_daily,
110
+ usageWeekly: key.usage_weekly,
111
+ usageMonthly: key.usage_monthly,
112
+ spendingLimit: key.limit,
113
+ remainingSpendingLimit: key.limit_remaining,
114
+ limitReset,
115
+ isFreeTier: key.is_free_tier,
116
+ isManagementKey: key.is_management_key,
117
+ expiresAt,
118
+ },
119
+ accountCredits: credits === undefined
120
+ ? { available: false, reason: creditsError ?? "not-configured" }
121
+ : {
122
+ available: true,
123
+ totalCredits: credits.total_credits,
124
+ totalUsage: credits.total_usage,
125
+ availableCredits: credits.available,
126
+ },
127
+ },
128
+ };
129
+ });
130
+ },
131
+ });
132
+ }
133
+ //# sourceMappingURL=balance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balance.js","sourceRoot":"","sources":["../../src/tools/balance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAG9C,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,QAAQ;QAAE,OAAO,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;IAC5E,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,YAAY,CAAC,KAAe,EAAE,KAAa,EAAE,KAAyB;IAC7E,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;AAC3E,CAAC;AAED,SAAS,cAAc,CAAC,KAAe,EAAE,KAAa,EAAE,KAA0B;IAChF,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;AAC5E,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,aAAa,CAAC,KAAK,CAAC;SACxB,OAAO,CAAC,yDAAyD,EAAE,YAAY,CAAC;SAChF,OAAO,CAAC,4BAA4B,EAAE,YAAY,CAAC;SACnD,OAAO,CAAC,0BAA0B,EAAE,GAAG,CAAC;SACxC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,YAA8B;IAC9D,OAAO,IAAI,CAAC;QACV,WAAW,EACT,qNAAqN;QACvN,IAAI,EAAE,EAAE;QACR,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO;YAC1B,OAAO,gBAAgB,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;gBACtD,MAAM,OAAO,GAAG,4BAA4B,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;gBACtE,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,CAAA;gBACzC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;gBAC7D,MAAM,gBAAgB,GACpB,OAAO,CAAC,gBAAgB;oBACxB,CAAC,GAAG,CAAC,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;gBAE/D,IAAI,OAES,CAAA;gBACb,IAAI,YAAgC,CAAA;gBACpC,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;oBACnC,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,UAAU,CAC5C,gBAAgB,EAChB,OAAO,CAAC,KAAK,CACd,CAAA;wBACD,OAAO,GAAG;4BACR,GAAG,MAAM;4BACT,SAAS,EAAE,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,WAAW;yBACrD,CAAA;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;wBAC7B,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAA;oBAClE,CAAC;gBACH,CAAC;gBAED,MAAM,UAAU,GACd,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;oBACjC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC;oBACjC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAA;gBACrB,MAAM,SAAS,GACb,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;oBAChC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC;oBAChC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAA;gBAEpB,MAAM,KAAK,GAAG,CAAC,2BAA2B,CAAC,CAAA;gBAC3C,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC5B,KAAK,CAAC,IAAI,CAAC,YAAY,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;gBACrD,CAAC;gBACD,YAAY,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;gBAChD,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC,WAAW,CAAC,CAAA;gBACnD,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,CAAC,YAAY,CAAC,CAAA;gBACrD,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;gBACvD,YAAY,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,CAAC,UAAU,CAAC,CAAA;gBAC1D,YAAY,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;gBAC7D,YAAY,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAA;gBAC/D,YAAY,CAAC,KAAK,EAAE,oBAAoB,EAAE,GAAG,CAAC,kBAAkB,CAAC,CAAA;gBAEjE,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI;oBAAE,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAA;;oBACpE,YAAY,CAAC,KAAK,EAAE,wBAAwB,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;gBAC7D,IAAI,GAAG,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;oBACjC,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAA;gBAC7D,CAAC;qBAAM,CAAC;oBACN,YAAY,CACV,KAAK,EACL,kCAAkC,EAClC,GAAG,CAAC,eAAe,CACpB,CAAA;gBACH,CAAC;gBACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBAC7B,KAAK,CAAC,IAAI,CACR,kBAAkB,UAAU,IAAI,MAAM,EAAE,CACzC,CAAA;gBACH,CAAC;gBACD,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,YAAY,CAAC,CAAA;gBACpD,cAAc,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAA;gBAC9D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;oBAC5B,KAAK,CAAC,IAAI,CACR,iBAAiB,SAAS,IAAI,OAAO,EAAE,CACxC,CAAA;gBACH,CAAC;gBAED,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,6BAA6B,CAAC,CAAA;gBAC7C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC1B,YAAY,CAAC,KAAK,EAAE,yBAAyB,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;oBACrE,YAAY,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;oBAC/D,YAAY,CAAC,KAAK,EAAE,2BAA2B,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;gBACrE,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;oBAC5C,KAAK,CAAC,IAAI,CACR,gBAAgB,KAAK,SAAS;wBAC5B,CAAC,CAAC,uDAAuD;wBACzD,CAAC,CAAC,qCAAqC,YAAY,IAAI,aAAa,GAAG,CAC1E,CAAA;gBACH,CAAC;gBAED,OAAO;oBACL,KAAK,EAAE,8BAA8B;oBACrC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;oBACxB,QAAQ,EAAE;wBACR,OAAO,EAAE,OAAO,CAAC,OAAO;wBACxB,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,GAAG,EAAE;4BACH,KAAK,EAAE,GAAG,CAAC,KAAK;4BAChB,UAAU,EAAE,GAAG,CAAC,WAAW;4BAC3B,WAAW,EAAE,GAAG,CAAC,YAAY;4BAC7B,YAAY,EAAE,GAAG,CAAC,aAAa;4BAC/B,aAAa,EAAE,GAAG,CAAC,KAAK;4BACxB,sBAAsB,EAAE,GAAG,CAAC,eAAe;4BAC3C,UAAU;4BACV,UAAU,EAAE,GAAG,CAAC,YAAY;4BAC5B,eAAe,EAAE,GAAG,CAAC,iBAAiB;4BACtC,SAAS;yBACV;wBACD,cAAc,EACZ,OAAO,KAAK,SAAS;4BACnB,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,IAAI,gBAAgB,EAAE;4BAChE,CAAC,CAAC;gCACE,SAAS,EAAE,IAAI;gCACf,YAAY,EAAE,OAAO,CAAC,aAAa;gCACnC,UAAU,EAAE,OAAO,CAAC,WAAW;gCAC/B,gBAAgB,EAAE,OAAO,CAAC,SAAS;6BACpC;qBACR;iBACF,CAAA;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SafeLogger } from "../logging.js";
2
+ export declare function runToolOperation<Result>(logger: SafeLogger, operation: () => Promise<Result>): Promise<Result>;
3
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/tools/common.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAG/C,wBAAsB,gBAAgB,CAAC,MAAM,EAC3C,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,CAcjB"}
@@ -0,0 +1,18 @@
1
+ import { isPluginError } from "../openrouter/errors.js";
2
+ export async function runToolOperation(logger, operation) {
3
+ try {
4
+ return await operation();
5
+ }
6
+ catch (error) {
7
+ if (isPluginError(error)) {
8
+ logger.log("warn", "OpenRouter image tool failed.", {
9
+ errorCode: error.code,
10
+ ...(typeof error.details?.status === "number"
11
+ ? { httpStatus: error.details.status }
12
+ : {}),
13
+ });
14
+ }
15
+ throw error;
16
+ }
17
+ }
18
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/tools/common.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAEvD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAkB,EAClB,SAAgC;IAEhC,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,EAAE,CAAA;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,+BAA+B,EAAE;gBAClD,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,MAAM,KAAK,QAAQ;oBAC3C,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE;oBACtC,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,90 @@
1
+ import type { ToolDependencies } from "./types.js";
2
+ export declare function createEditImageTool(dependencies: ToolDependencies): {
3
+ description: string;
4
+ args: {
5
+ references: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
6
+ type: import("zod").ZodLiteral<"message_attachment">;
7
+ index: import("zod").ZodNumber;
8
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
9
+ type: import("zod").ZodLiteral<"project_file">;
10
+ path: import("zod").ZodString;
11
+ }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
12
+ type: import("zod").ZodLiteral<"https_url">;
13
+ url: import("zod").ZodString;
14
+ }, import("zod/v4/core").$strict>], "type">>>;
15
+ prompt: import("zod").ZodString;
16
+ output_path: import("zod").ZodOptional<import("zod").ZodString>;
17
+ aspect_ratio: import("zod").ZodOptional<import("zod").ZodEnum<{
18
+ auto: "auto";
19
+ "1:1": "1:1";
20
+ "1:2": "1:2";
21
+ "1:4": "1:4";
22
+ "1:8": "1:8";
23
+ "2:1": "2:1";
24
+ "2:3": "2:3";
25
+ "3:2": "3:2";
26
+ "3:4": "3:4";
27
+ "4:1": "4:1";
28
+ "4:3": "4:3";
29
+ "4:5": "4:5";
30
+ "5:4": "5:4";
31
+ "8:1": "8:1";
32
+ "9:16": "9:16";
33
+ "16:9": "16:9";
34
+ "9:19.5": "9:19.5";
35
+ "19.5:9": "19.5:9";
36
+ "9:20": "9:20";
37
+ "20:9": "20:9";
38
+ "9:21": "9:21";
39
+ "21:9": "21:9";
40
+ }>>;
41
+ background: import("zod").ZodOptional<import("zod").ZodEnum<{
42
+ transparent: "transparent";
43
+ auto: "auto";
44
+ opaque: "opaque";
45
+ }>>;
46
+ n: import("zod").ZodOptional<import("zod").ZodNumber>;
47
+ output_format: import("zod").ZodOptional<import("zod").ZodEnum<{
48
+ png: "png";
49
+ jpeg: "jpeg";
50
+ webp: "webp";
51
+ }>>;
52
+ output_compression: import("zod").ZodOptional<import("zod").ZodNumber>;
53
+ quality: import("zod").ZodOptional<import("zod").ZodEnum<{
54
+ auto: "auto";
55
+ high: "high";
56
+ low: "low";
57
+ medium: "medium";
58
+ }>>;
59
+ resolution: import("zod").ZodOptional<import("zod").ZodEnum<{
60
+ 512: "512";
61
+ "1K": "1K";
62
+ "2K": "2K";
63
+ "4K": "4K";
64
+ }>>;
65
+ seed: import("zod").ZodOptional<import("zod").ZodNumber>;
66
+ };
67
+ execute(args: {
68
+ prompt: string;
69
+ references?: ({
70
+ type: "message_attachment";
71
+ index: number;
72
+ } | {
73
+ type: "project_file";
74
+ path: string;
75
+ } | {
76
+ type: "https_url";
77
+ url: string;
78
+ })[] | undefined;
79
+ output_path?: string | undefined;
80
+ aspect_ratio?: "auto" | "1:1" | "1:2" | "1:4" | "1:8" | "2:1" | "2:3" | "3:2" | "3:4" | "4:1" | "4:3" | "4:5" | "5:4" | "8:1" | "9:16" | "16:9" | "9:19.5" | "19.5:9" | "9:20" | "20:9" | "9:21" | "21:9" | undefined;
81
+ background?: "transparent" | "auto" | "opaque" | undefined;
82
+ n?: number | undefined;
83
+ output_format?: "png" | "jpeg" | "webp" | undefined;
84
+ output_compression?: number | undefined;
85
+ quality?: "auto" | "high" | "low" | "medium" | undefined;
86
+ resolution?: "512" | "1K" | "2K" | "4K" | undefined;
87
+ seed?: number | undefined;
88
+ }, context: import("@opencode-ai/plugin").ToolContext): Promise<import("@opencode-ai/plugin").ToolResult>;
89
+ };
90
+ //# sourceMappingURL=edit-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-image.d.ts","sourceRoot":"","sources":["../../src/tools/edit-image.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+CjE"}