@amaster.ai/pi-image-gen 0.1.2-beta.15

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 (52) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +310 -0
  3. package/dist/config.d.ts +24 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +183 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/errors.d.ts +16 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +70 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/generate.d.ts +12 -0
  12. package/dist/generate.d.ts.map +1 -0
  13. package/dist/generate.js +86 -0
  14. package/dist/generate.js.map +1 -0
  15. package/dist/image-input.d.ts +25 -0
  16. package/dist/image-input.d.ts.map +1 -0
  17. package/dist/image-input.js +153 -0
  18. package/dist/image-input.js.map +1 -0
  19. package/dist/index.d.ts +18 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +147 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/models.d.ts +18 -0
  24. package/dist/models.d.ts.map +1 -0
  25. package/dist/models.js +86 -0
  26. package/dist/models.js.map +1 -0
  27. package/dist/providers/dashscope.d.ts +12 -0
  28. package/dist/providers/dashscope.d.ts.map +1 -0
  29. package/dist/providers/dashscope.js +89 -0
  30. package/dist/providers/dashscope.js.map +1 -0
  31. package/dist/providers/gemini.d.ts +10 -0
  32. package/dist/providers/gemini.d.ts.map +1 -0
  33. package/dist/providers/gemini.js +99 -0
  34. package/dist/providers/gemini.js.map +1 -0
  35. package/dist/providers/index.d.ts +3 -0
  36. package/dist/providers/index.d.ts.map +1 -0
  37. package/dist/providers/index.js +19 -0
  38. package/dist/providers/index.js.map +1 -0
  39. package/dist/providers/openai.d.ts +14 -0
  40. package/dist/providers/openai.d.ts.map +1 -0
  41. package/dist/providers/openai.js +145 -0
  42. package/dist/providers/openai.js.map +1 -0
  43. package/dist/types.d.ts +133 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/dist/url.d.ts +11 -0
  48. package/dist/url.d.ts.map +1 -0
  49. package/dist/url.js +25 -0
  50. package/dist/url.js.map +1 -0
  51. package/package.json +73 -0
  52. package/preview.png +0 -0
package/dist/index.js ADDED
@@ -0,0 +1,147 @@
1
+ import { Type } from 'typebox';
2
+ import { listConfiguredProviders, listKnownModelIds, loadImageGenSettings, resolveModel, } from './config.js';
3
+ import { generateImage } from './generate.js';
4
+ export { loadImageGenSettings, resolveModel } from './config.js';
5
+ export { generateImage } from './generate.js';
6
+ export default function piImageGenExtension(pi) {
7
+ let settings = {};
8
+ let sessionCwd = process.cwd();
9
+ pi.on('session_start', async (_event, ctx) => {
10
+ sessionCwd = ctx.cwd;
11
+ settings = loadImageGenSettings(ctx.cwd);
12
+ const providers = listConfiguredProviders(settings).map((p) => p.id);
13
+ console.debug('[pi-image-gen] session_start', {
14
+ cwd: ctx.cwd,
15
+ providers,
16
+ defaultModel: settings.defaultModel,
17
+ outputDir: settings.outputDir ?? '.pi/images',
18
+ customProviders: Object.keys(settings.customProviders ?? {}),
19
+ });
20
+ });
21
+ pi.registerCommand('image-gen', {
22
+ description: 'Inspect pi-image-gen: /image-gen [list|reload]',
23
+ handler: async (args, ctx) => {
24
+ const tokens = (args ?? '').trim().split(/\s+/).filter(Boolean);
25
+ if (tokens[0] === 'reload') {
26
+ settings = loadImageGenSettings(ctx.cwd);
27
+ ctx.ui.notify('pi-image-gen settings reloaded.', 'info');
28
+ return;
29
+ }
30
+ const providers = listConfiguredProviders(settings);
31
+ const defaultModel = settings.defaultModel?.trim();
32
+ let activeLine = `Default model: ${defaultModel ?? '(not set — configure pi-image-gen.defaultModel in settings.json)'}`;
33
+ if (defaultModel) {
34
+ const resolved = resolveModel(defaultModel, settings);
35
+ if ('error' in resolved) {
36
+ activeLine += `\n ! ${resolved.error}`;
37
+ }
38
+ else {
39
+ const provider = resolved.provider;
40
+ const keyOk = Boolean(provider.apiKey);
41
+ activeLine += `\n routes to: ${provider.id} [${provider.api}] ${provider.builtIn ? '' : '(custom) '}${keyOk ? 'apiKey: set' : 'apiKey: MISSING'}`;
42
+ }
43
+ }
44
+ const lines = [
45
+ activeLine,
46
+ `Output dir: ${settings.outputDir ?? '.pi/images'}`,
47
+ '',
48
+ 'Configured providers:',
49
+ ...(providers.length
50
+ ? providers.map((p) => {
51
+ const tags = [`[${p.api}]`];
52
+ if (!p.builtIn)
53
+ tags.push('(custom)');
54
+ if (p.catchAll)
55
+ tags.push('(catch-all — accepts any model)');
56
+ else if (p.modelCount > 0)
57
+ tags.push(`(${p.modelCount} model${p.modelCount === 1 ? '' : 's'})`);
58
+ return ` - ${p.id} ${tags.join(' ')}`;
59
+ })
60
+ : [
61
+ ' (none — set OPENAI_API_KEY / GEMINI_API_KEY / DASHSCOPE_API_KEY / OPENROUTER_API_KEY)',
62
+ ]),
63
+ '',
64
+ 'Built-in models:',
65
+ ...listKnownModelIds().map((m) => ` - ${m}`),
66
+ ];
67
+ ctx.ui.notify(lines.join('\n'), 'info');
68
+ },
69
+ });
70
+ pi.registerTool({
71
+ name: 'image_generate',
72
+ label: 'ImageGen',
73
+ description: 'Generate or edit images. The image model is fixed by pi-image-gen.defaultModel in settings (this tool does not accept a model parameter). Pass `image` to do image-to-image / edit / style transfer / character preservation: a file path (absolute or relative to cwd) or an http(s) URL. To iterate on a previous result, pass its file path back. Do NOT pass base64 or data: URIs — write bytes to a file first. Saves the output to disk and returns the absolute path(s). When reporting the result to the user, render each generated image as inline markdown `![alt](absolute_path)` (the tool result already includes a copy-pasteable line) so the UI can display it; do not just paste the bare path. Run /image-gen list to see the active model.',
74
+ parameters: Type.Object({
75
+ prompt: Type.String({
76
+ description: 'Text prompt describing what to generate or how to edit.',
77
+ }),
78
+ image: Type.Optional(Type.Array(Type.String(), {
79
+ description: 'Optional reference image(s) for image-to-image / edit / style transfer / character preservation. Each entry MUST be either (a) a file path — absolute or relative to the session cwd — or (b) an http(s) URL. Base64 strings and data: URIs are rejected; write the bytes to a file first if you have raw image data. For a single image pass ["path"]. Multi-image conditioning is supported by OpenAI gpt-image-1, Gemini, and Qwen sync models. To iterate on a previous output, pass that file path here.',
80
+ })),
81
+ n: Type.Optional(Type.Number({
82
+ minimum: 1,
83
+ maximum: 8,
84
+ description: 'Number of images. Default 1 (integer).',
85
+ })),
86
+ size: Type.Optional(Type.String({
87
+ description: 'Image size hint such as "1024x1024". Provider-specific; ignored if unsupported.',
88
+ })),
89
+ filename: Type.Optional(Type.String({ description: 'Filename prefix (without extension).' })),
90
+ outputDir: Type.Optional(Type.String({
91
+ description: 'Directory to write images into. Relative paths resolve against the session cwd.',
92
+ })),
93
+ }),
94
+ async execute(_toolCallId, rawParams, signal, _onUpdate, ctx) {
95
+ const params = rawParams;
96
+ const cwd = ctx?.cwd ?? sessionCwd;
97
+ try {
98
+ const opts = { cwd, settings };
99
+ if (signal)
100
+ opts.signal = signal;
101
+ const result = await generateImage(params, opts);
102
+ return {
103
+ content: [{ type: 'text', text: formatToolResultText(result) }],
104
+ details: result,
105
+ };
106
+ }
107
+ catch (error) {
108
+ const message = error instanceof Error ? error.message : String(error);
109
+ return {
110
+ content: [{ type: 'text', text: `image_generate failed: ${message}` }],
111
+ details: undefined,
112
+ isError: true,
113
+ };
114
+ }
115
+ },
116
+ });
117
+ }
118
+ /**
119
+ * Format a generated-image result as text the LLM can paste verbatim into its
120
+ * reply. Uses inline markdown image syntax with the file stem as the alt text.
121
+ */
122
+ export function formatToolResultText(result) {
123
+ const lines = [
124
+ `Generated ${result.images.length} image(s) via ${result.provider} (${result.model}). Show each one to the user as inline markdown — copy the lines below verbatim into your reply:`,
125
+ '',
126
+ ...result.images.flatMap((img) => {
127
+ const alt = altFromPath(img.path);
128
+ const md = `![${alt}](${img.path})`;
129
+ return img.revisedPrompt ? [md, `> revised prompt: ${img.revisedPrompt}`] : [md];
130
+ }),
131
+ ];
132
+ return lines.join('\n');
133
+ }
134
+ /**
135
+ * Derive a markdown `alt` from the saved file path. We use the filename without
136
+ * its extension so the user-supplied `filename` (or our auto-generated stamp)
137
+ * shows up in the rendered image label, not the model id.
138
+ */
139
+ export function altFromPath(absolutePath) {
140
+ const segments = absolutePath.split(/[\\/]/);
141
+ const base = segments[segments.length - 1] ?? 'image';
142
+ const dot = base.lastIndexOf('.');
143
+ const stem = dot > 0 ? base.slice(0, dot) : base;
144
+ // Escape `]` so the markdown link doesn't break if the filename has one.
145
+ return stem.replace(/\]/g, '\\]') || 'image';
146
+ }
147
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ApiStyle, BuiltInProviderId } from './types.js';
2
+ /**
3
+ * Built-in known image models. Maps a model id (or alias) to its built-in
4
+ * provider. Custom providers may add or override entries via settings.
5
+ */
6
+ export type BuiltInModelEntry = {
7
+ id: string;
8
+ aliases?: string[];
9
+ provider: BuiltInProviderId;
10
+ /** Remote model id sent to the provider (defaults to id). */
11
+ remoteId?: string;
12
+ };
13
+ export declare const BUILT_IN_MODELS: BuiltInModelEntry[];
14
+ export declare const DEFAULT_BASE_URL: Record<BuiltInProviderId, string>;
15
+ export declare const DEFAULT_API_STYLE: Record<BuiltInProviderId, ApiStyle>;
16
+ export declare const ENV_VARS: Record<BuiltInProviderId, string>;
17
+ export declare const PROVIDER_DISPLAY_NAME: Record<BuiltInProviderId, string>;
18
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE9D;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,iBAAiB,EA8D9C,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAK9D,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,QAAQ,CAKjE,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAKtD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAKnE,CAAC"}
package/dist/models.js ADDED
@@ -0,0 +1,86 @@
1
+ export const BUILT_IN_MODELS = [
2
+ // OpenAI image generation. The naming "gpt-image-2" the user mentioned does not
3
+ // currently exist in OpenAI's catalog; the closest stable id is "gpt-image-1".
4
+ // We accept both as aliases so prompts that ask for "gpt-image-2" still work.
5
+ {
6
+ id: 'gpt-image-1',
7
+ aliases: ['gpt-image', 'gpt-image-2'],
8
+ provider: 'openai',
9
+ remoteId: 'gpt-image-1',
10
+ },
11
+ // Google Gemini "Nano Banana" image generation. The `nano-banana` alias
12
+ // points at the most recent stable release; older variants stay addressable
13
+ // by their full id.
14
+ {
15
+ id: 'gemini-3-pro-image',
16
+ aliases: ['nano-banana-pro'],
17
+ provider: 'gemini',
18
+ remoteId: 'gemini-3-pro-image',
19
+ },
20
+ {
21
+ id: 'gemini-3-pro-image-preview',
22
+ provider: 'gemini',
23
+ remoteId: 'gemini-3-pro-image-preview',
24
+ },
25
+ {
26
+ id: 'gemini-3.1-flash-image',
27
+ aliases: ['nano-banana', 'nano-banana-3'],
28
+ provider: 'gemini',
29
+ remoteId: 'gemini-3.1-flash-image',
30
+ },
31
+ {
32
+ id: 'gemini-3.1-flash-image-preview',
33
+ provider: 'gemini',
34
+ remoteId: 'gemini-3.1-flash-image-preview',
35
+ },
36
+ {
37
+ id: 'gemini-2.5-flash-image',
38
+ aliases: ['nano-banana-2', 'gemini-image'],
39
+ provider: 'gemini',
40
+ remoteId: 'gemini-2.5-flash-image',
41
+ },
42
+ {
43
+ id: 'gemini-2.0-flash-image',
44
+ provider: 'gemini',
45
+ remoteId: 'gemini-2.0-flash-image',
46
+ },
47
+ // Alibaba Qwen-Image / WanX series via DashScope. The `qwen-image-2` and
48
+ // `qwen-image` aliases point at the most recent stable Qwen image release.
49
+ {
50
+ id: 'qwen-image-2.0-pro',
51
+ aliases: ['qwen-image-pro'],
52
+ provider: 'dashscope',
53
+ remoteId: 'qwen-image-2.0-pro',
54
+ },
55
+ {
56
+ id: 'qwen-image-2.0',
57
+ aliases: ['qwen-image-2', 'qwen-image'],
58
+ provider: 'dashscope',
59
+ remoteId: 'qwen-image-2.0',
60
+ },
61
+ ];
62
+ export const DEFAULT_BASE_URL = {
63
+ openai: 'https://api.openai.com/v1',
64
+ gemini: 'https://generativelanguage.googleapis.com/v1beta',
65
+ dashscope: 'https://dashscope.aliyuncs.com/api/v1',
66
+ openrouter: 'https://openrouter.ai/api/v1',
67
+ };
68
+ export const DEFAULT_API_STYLE = {
69
+ openai: 'openai',
70
+ gemini: 'gemini',
71
+ dashscope: 'dashscope',
72
+ openrouter: 'openrouter',
73
+ };
74
+ export const ENV_VARS = {
75
+ openai: 'OPENAI_API_KEY',
76
+ gemini: 'GEMINI_API_KEY',
77
+ dashscope: 'DASHSCOPE_API_KEY',
78
+ openrouter: 'OPENROUTER_API_KEY',
79
+ };
80
+ export const PROVIDER_DISPLAY_NAME = {
81
+ openai: 'OpenAI',
82
+ gemini: 'Google Gemini',
83
+ dashscope: 'Alibaba DashScope',
84
+ openrouter: 'OpenRouter',
85
+ };
86
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,eAAe,GAAwB;IAClD,gFAAgF;IAChF,+EAA+E;IAC/E,8EAA8E;IAC9E;QACE,EAAE,EAAE,aAAa;QACjB,OAAO,EAAE,CAAC,WAAW,EAAE,aAAa,CAAC;QACrC,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,aAAa;KACxB;IAED,wEAAwE;IACxE,4EAA4E;IAC5E,oBAAoB;IACpB;QACE,EAAE,EAAE,oBAAoB;QACxB,OAAO,EAAE,CAAC,iBAAiB,CAAC;QAC5B,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,oBAAoB;KAC/B;IACD;QACE,EAAE,EAAE,4BAA4B;QAChC,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,4BAA4B;KACvC;IACD;QACE,EAAE,EAAE,wBAAwB;QAC5B,OAAO,EAAE,CAAC,aAAa,EAAE,eAAe,CAAC;QACzC,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,wBAAwB;KACnC;IACD;QACE,EAAE,EAAE,gCAAgC;QACpC,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,gCAAgC;KAC3C;IACD;QACE,EAAE,EAAE,wBAAwB;QAC5B,OAAO,EAAE,CAAC,eAAe,EAAE,cAAc,CAAC;QAC1C,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,wBAAwB;KACnC;IACD;QACE,EAAE,EAAE,wBAAwB;QAC5B,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,wBAAwB;KACnC;IAED,yEAAyE;IACzE,2EAA2E;IAC3E;QACE,EAAE,EAAE,oBAAoB;QACxB,OAAO,EAAE,CAAC,gBAAgB,CAAC;QAC3B,QAAQ,EAAE,WAAW;QACrB,QAAQ,EAAE,oBAAoB;KAC/B;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,OAAO,EAAE,CAAC,cAAc,EAAE,YAAY,CAAC;QACvC,QAAQ,EAAE,WAAW;QACrB,QAAQ,EAAE,gBAAgB;KAC3B;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAsC;IACjE,MAAM,EAAE,2BAA2B;IACnC,MAAM,EAAE,kDAAkD;IAC1D,SAAS,EAAE,uCAAuC;IAClD,UAAU,EAAE,8BAA8B;CAC3C,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAwC;IACpE,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,YAAY;CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAsC;IACzD,MAAM,EAAE,gBAAgB;IACxB,MAAM,EAAE,gBAAgB;IACxB,SAAS,EAAE,mBAAmB;IAC9B,UAAU,EAAE,oBAAoB;CACjC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAsC;IACtE,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,eAAe;IACvB,SAAS,EAAE,mBAAmB;IAC9B,UAAU,EAAE,YAAY;CACzB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ImageProviderAdapter } from '../types.js';
2
+ /**
3
+ * Alibaba DashScope text-to-image (Qwen-Image series). Sync only:
4
+ *
5
+ * POST /services/aigc/multimodal-generation/generation
6
+ * One request, one response, image URLs / bytes inline.
7
+ *
8
+ * The legacy async task endpoint (text2image/image-synthesis) is not used —
9
+ * it doesn't accept reference images and the supported models there are old.
10
+ */
11
+ export declare const dashscopeAdapter: ImageProviderAdapter;
12
+ //# sourceMappingURL=dashscope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashscope.d.ts","sourceRoot":"","sources":["../../src/providers/dashscope.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AAGrB;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,EAAE,oBAiF9B,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { classifyHttpError, describeNetworkError } from '../errors.js';
2
+ import { classifyImageOutput, toDataUri } from '../image-input.js';
3
+ import { withDefaultPath } from '../url.js';
4
+ /**
5
+ * Alibaba DashScope text-to-image (Qwen-Image series). Sync only:
6
+ *
7
+ * POST /services/aigc/multimodal-generation/generation
8
+ * One request, one response, image URLs / bytes inline.
9
+ *
10
+ * The legacy async task endpoint (text2image/image-synthesis) is not used —
11
+ * it doesn't accept reference images and the supported models there are old.
12
+ */
13
+ export const dashscopeAdapter = {
14
+ async generate(provider, remoteModelId, params, fetchImpl, signal, inputs) {
15
+ if (!provider.apiKey) {
16
+ throw new Error(missingKeyMessage(provider));
17
+ }
18
+ const base = withDefaultPath(provider.baseUrl, '/api/v1');
19
+ const headers = {
20
+ authorization: `Bearer ${provider.apiKey}`,
21
+ 'content-type': 'application/json',
22
+ };
23
+ if (provider.headers)
24
+ Object.assign(headers, provider.headers);
25
+ const userContent = [];
26
+ for (const input of inputs ?? []) {
27
+ userContent.push({ image: toDataUri(input) });
28
+ }
29
+ userContent.push({ text: params.prompt });
30
+ let res;
31
+ try {
32
+ res = await fetchImpl(`${base}/services/aigc/multimodal-generation/generation`, {
33
+ method: 'POST',
34
+ headers,
35
+ body: JSON.stringify({
36
+ model: remoteModelId,
37
+ input: { messages: [{ role: 'user', content: userContent }] },
38
+ parameters: {
39
+ n: params.n ?? 1,
40
+ ...(params.size ? { size: params.size } : {}),
41
+ },
42
+ }),
43
+ signal: signal ?? null,
44
+ });
45
+ }
46
+ catch (error) {
47
+ throw new Error(describeNetworkError(error, provider));
48
+ }
49
+ const text = await safeText(res);
50
+ if (!res.ok) {
51
+ throw new Error(classifyHttpError(res, text, provider));
52
+ }
53
+ let json;
54
+ try {
55
+ json = JSON.parse(text);
56
+ }
57
+ catch (error) {
58
+ throw new Error(`${provider.name} returned invalid JSON: ${error.message}`);
59
+ }
60
+ const out = [];
61
+ for (const choice of json.output?.choices ?? []) {
62
+ for (const part of choice.message?.content ?? []) {
63
+ const candidate = typeof part.image_url === 'string' ? part.image_url : (part.image_url?.url ?? part.image);
64
+ const classified = classifyImageOutput(candidate);
65
+ if (classified)
66
+ out.push({ data: classified });
67
+ }
68
+ }
69
+ if (out.length === 0) {
70
+ throw new Error(`${provider.name} returned no images. The model may have refused the prompt or the response shape changed. Raw: ${text.slice(0, 300).replace(/\s+/g, ' ')}`);
71
+ }
72
+ return out;
73
+ },
74
+ };
75
+ function missingKeyMessage(provider) {
76
+ if (provider.builtIn) {
77
+ return `Provider "${provider.id}" has no API key. Tell the user to set DASHSCOPE_API_KEY (or pi-image-gen.providers.${provider.id}.apiKey in settings.json).`;
78
+ }
79
+ return `Provider "${provider.id}" has no API key. Tell the user to set pi-image-gen.customProviders.${provider.id}.apiKey in settings.json.`;
80
+ }
81
+ async function safeText(res) {
82
+ try {
83
+ return await res.text();
84
+ }
85
+ catch {
86
+ return '<unreadable response body>';
87
+ }
88
+ }
89
+ //# sourceMappingURL=dashscope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashscope.js","sourceRoot":"","sources":["../../src/providers/dashscope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ImageProviderAdapter } from '../types.js';
2
+ /**
3
+ * Google Generative Language API for `gemini-2.5-flash-image` (Nano Banana)
4
+ * and successors.
5
+ * POST {baseUrl}/models/{model}:generateContent
6
+ * Header: x-goog-api-key
7
+ * Response: candidates[].content.parts[].inline_data (base64).
8
+ */
9
+ export declare const geminiAdapter: ImageProviderAdapter;
10
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AAGrB;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,oBA2F3B,CAAC"}
@@ -0,0 +1,99 @@
1
+ import { classifyHttpError, describeNetworkError } from '../errors.js';
2
+ import { withDefaultPath } from '../url.js';
3
+ /**
4
+ * Google Generative Language API for `gemini-2.5-flash-image` (Nano Banana)
5
+ * and successors.
6
+ * POST {baseUrl}/models/{model}:generateContent
7
+ * Header: x-goog-api-key
8
+ * Response: candidates[].content.parts[].inline_data (base64).
9
+ */
10
+ export const geminiAdapter = {
11
+ async generate(provider, remoteModelId, params, fetchImpl, signal, inputs) {
12
+ if (!provider.apiKey) {
13
+ throw new Error(missingKeyMessage(provider));
14
+ }
15
+ const base = withDefaultPath(provider.baseUrl, '/v1beta');
16
+ const url = `${base}/models/${encodeURIComponent(remoteModelId)}:generateContent`;
17
+ const headers = {
18
+ 'content-type': 'application/json',
19
+ 'x-goog-api-key': provider.apiKey,
20
+ };
21
+ if (provider.headers)
22
+ Object.assign(headers, provider.headers);
23
+ const n = params.n ?? 1;
24
+ const userParts = [];
25
+ for (const input of inputs ?? []) {
26
+ userParts.push({
27
+ inline_data: {
28
+ mime_type: input.mimeType,
29
+ data: Buffer.from(input.bytes).toString('base64'),
30
+ },
31
+ });
32
+ }
33
+ userParts.push({ text: params.prompt });
34
+ const body = {
35
+ contents: [{ role: 'user', parts: userParts }],
36
+ generationConfig: {
37
+ responseModalities: ['IMAGE'],
38
+ candidateCount: n,
39
+ },
40
+ };
41
+ let res;
42
+ try {
43
+ res = await fetchImpl(url, {
44
+ method: 'POST',
45
+ headers,
46
+ body: JSON.stringify(body),
47
+ signal: signal ?? null,
48
+ });
49
+ }
50
+ catch (error) {
51
+ throw new Error(describeNetworkError(error, provider));
52
+ }
53
+ const text = await safeText(res);
54
+ if (!res.ok) {
55
+ throw new Error(classifyHttpError(res, text, provider));
56
+ }
57
+ let json;
58
+ try {
59
+ json = JSON.parse(text);
60
+ }
61
+ catch (error) {
62
+ throw new Error(`${provider.name} returned invalid JSON: ${error.message}`);
63
+ }
64
+ const out = [];
65
+ for (const candidate of json.candidates ?? []) {
66
+ for (const part of candidate.content?.parts ?? []) {
67
+ const inline = part.inline_data;
68
+ if (inline?.data) {
69
+ out.push({
70
+ data: {
71
+ kind: 'base64',
72
+ bytes: inline.data,
73
+ mimeType: inline.mime_type ?? 'image/png',
74
+ },
75
+ });
76
+ }
77
+ }
78
+ }
79
+ if (out.length === 0) {
80
+ throw new Error(`${provider.name} returned no image data — the model may have refused to generate. Tell the user to rephrase the prompt or try a different model.`);
81
+ }
82
+ return out;
83
+ },
84
+ };
85
+ function missingKeyMessage(provider) {
86
+ if (provider.builtIn) {
87
+ return `Provider "${provider.id}" has no API key. Tell the user to set GEMINI_API_KEY (or pi-image-gen.providers.${provider.id}.apiKey in settings.json).`;
88
+ }
89
+ return `Provider "${provider.id}" has no API key. Tell the user to set pi-image-gen.customProviders.${provider.id}.apiKey in settings.json.`;
90
+ }
91
+ async function safeText(res) {
92
+ try {
93
+ return await res.text();
94
+ }
95
+ catch {
96
+ return '<unreadable response body>';
97
+ }
98
+ }
99
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ApiStyle, ImageProviderAdapter } from '../types.js';
2
+ export declare function getAdapter(api: ApiStyle): ImageProviderAdapter;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAelE,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,GAAG,oBAAoB,CAI9D"}
@@ -0,0 +1,19 @@
1
+ import { dashscopeAdapter } from './dashscope.js';
2
+ import { geminiAdapter } from './gemini.js';
3
+ import { openaiAdapter } from './openai.js';
4
+ // OpenRouter exposes an OpenAI-compatible image endpoint, so it reuses
5
+ // openaiAdapter — kept as a separate ApiStyle value so users can label intent
6
+ // in customProviders.api without affecting the wire format.
7
+ const ADAPTERS = {
8
+ openai: openaiAdapter,
9
+ gemini: geminiAdapter,
10
+ dashscope: dashscopeAdapter,
11
+ openrouter: openaiAdapter,
12
+ };
13
+ export function getAdapter(api) {
14
+ const adapter = ADAPTERS[api];
15
+ if (!adapter)
16
+ throw new Error(`Unsupported api "${api}".`);
17
+ return adapter;
18
+ }
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,uEAAuE;AACvE,8EAA8E;AAC9E,4DAA4D;AAC5D,MAAM,QAAQ,GAA2C;IACvD,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,aAAa;IACrB,SAAS,EAAE,gBAAgB;IAC3B,UAAU,EAAE,aAAa;CAC1B,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,GAAa;IACtC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC3D,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { ImageProviderAdapter } from '../types.js';
2
+ /**
3
+ * OpenAI-compatible image API. Used for OpenAI directly, OpenRouter, and any
4
+ * customProvider with `api: 'openai'`.
5
+ *
6
+ * Two endpoints:
7
+ * - POST /v1/images/generations (text-to-image, JSON body)
8
+ * - POST /v1/images/edits (image-to-image, multipart/form-data)
9
+ *
10
+ * The edit path is selected when the caller passes `inputs` (resolved
11
+ * reference images). Mask is intentionally not exposed to keep scope small.
12
+ */
13
+ export declare const openaiAdapter: ImageProviderAdapter;
14
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AAUrB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,EAAE,oBAkB3B,CAAC"}