@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
@@ -0,0 +1,145 @@
1
+ import { classifyHttpError, describeNetworkError } from '../errors.js';
2
+ import { classifyImageOutput } from '../image-input.js';
3
+ import { withDefaultPath } from '../url.js';
4
+ function bearerHeaders(provider) {
5
+ const headers = {};
6
+ if (provider.apiKey)
7
+ headers.authorization = `Bearer ${provider.apiKey}`;
8
+ if (provider.headers)
9
+ Object.assign(headers, provider.headers);
10
+ return headers;
11
+ }
12
+ /**
13
+ * OpenAI-compatible image API. Used for OpenAI directly, OpenRouter, and any
14
+ * customProvider with `api: 'openai'`.
15
+ *
16
+ * Two endpoints:
17
+ * - POST /v1/images/generations (text-to-image, JSON body)
18
+ * - POST /v1/images/edits (image-to-image, multipart/form-data)
19
+ *
20
+ * The edit path is selected when the caller passes `inputs` (resolved
21
+ * reference images). Mask is intentionally not exposed to keep scope small.
22
+ */
23
+ export const openaiAdapter = {
24
+ async generate(provider, remoteModelId, params, fetchImpl, signal, inputs) {
25
+ if (!provider.apiKey) {
26
+ throw new Error(missingKeyMessage(provider));
27
+ }
28
+ const base = withDefaultPath(provider.baseUrl, '/v1');
29
+ if (inputs && inputs.length > 0) {
30
+ return generateWithImages(provider, base, remoteModelId, params, inputs, fetchImpl, signal);
31
+ }
32
+ return generateFromText(provider, base, remoteModelId, params, fetchImpl, signal);
33
+ },
34
+ };
35
+ async function generateFromText(provider, base, remoteModelId, params, fetchImpl, signal) {
36
+ const url = `${base}/images/generations`;
37
+ const body = {
38
+ model: remoteModelId,
39
+ prompt: params.prompt,
40
+ n: params.n ?? 1,
41
+ };
42
+ if (params.size)
43
+ body.size = params.size;
44
+ let res;
45
+ try {
46
+ res = await fetchImpl(url, {
47
+ method: 'POST',
48
+ headers: { ...bearerHeaders(provider), 'content-type': 'application/json' },
49
+ body: JSON.stringify(body),
50
+ signal: signal ?? null,
51
+ });
52
+ }
53
+ catch (error) {
54
+ throw new Error(describeNetworkError(error, provider));
55
+ }
56
+ return parseImagesResponse(res, url, provider);
57
+ }
58
+ async function generateWithImages(provider, base, remoteModelId, params, inputs, fetchImpl, signal) {
59
+ const url = `${base}/images/edits`;
60
+ const form = new FormData();
61
+ form.append('model', remoteModelId);
62
+ form.append('prompt', params.prompt);
63
+ form.append('n', String(params.n ?? 1));
64
+ if (params.size)
65
+ form.append('size', params.size);
66
+ // OpenAI accepts repeated `image[]` for multi-image edits on gpt-image-1.
67
+ const fieldName = inputs.length > 1 ? 'image[]' : 'image';
68
+ for (const [i, input] of inputs.entries()) {
69
+ const ext = input.mimeType.split('/')[1] ?? 'png';
70
+ const blob = new Blob([input.bytes], { type: input.mimeType });
71
+ form.append(fieldName, blob, `image-${i}.${ext}`);
72
+ }
73
+ let res;
74
+ try {
75
+ res = await fetchImpl(url, {
76
+ method: 'POST',
77
+ headers: bearerHeaders(provider),
78
+ body: form,
79
+ signal: signal ?? null,
80
+ });
81
+ }
82
+ catch (error) {
83
+ throw new Error(describeNetworkError(error, provider));
84
+ }
85
+ return parseImagesResponse(res, url, provider);
86
+ }
87
+ async function parseImagesResponse(res, url, provider) {
88
+ const text = await safeText(res);
89
+ if (!res.ok) {
90
+ throw new Error(classifyHttpError(res, text, provider));
91
+ }
92
+ const contentType = res.headers.get('content-type') ?? '';
93
+ if (!contentType.includes('json')) {
94
+ const preview = text.slice(0, 200).replace(/\s+/g, ' ');
95
+ throw new Error(`${provider.name} returned ${contentType || 'non-JSON'} from ${url}. The endpoint probably doesn't expose the OpenAI-compatible images API at this path. Body: ${preview}`);
96
+ }
97
+ let json;
98
+ try {
99
+ json = JSON.parse(text);
100
+ }
101
+ catch (error) {
102
+ throw new Error(`${provider.name} returned invalid JSON: ${error.message}`);
103
+ }
104
+ const data = json.data ?? [];
105
+ const out = [];
106
+ for (const entry of data) {
107
+ // Prefer explicit b64_json field (OpenAI shape). If absent, classify the
108
+ // `url` field — some gateways return a `data:` URI or even raw base64
109
+ // there instead of a real URL.
110
+ let payload = null;
111
+ if (entry.b64_json) {
112
+ payload = { kind: 'base64', bytes: entry.b64_json, mimeType: 'image/png' };
113
+ }
114
+ else {
115
+ const classified = classifyImageOutput(entry.url);
116
+ if (classified)
117
+ payload = classified;
118
+ }
119
+ if (!payload)
120
+ continue;
121
+ const item = { data: payload };
122
+ if (entry.revised_prompt)
123
+ item.revisedPrompt = entry.revised_prompt;
124
+ out.push(item);
125
+ }
126
+ if (out.length === 0) {
127
+ throw new Error(`${provider.name} returned no usable images. Response had ${data.length} entries but none had b64_json or a valid url. Raw: ${text.slice(0, 300).replace(/\s+/g, ' ')}`);
128
+ }
129
+ return out;
130
+ }
131
+ function missingKeyMessage(provider) {
132
+ if (provider.builtIn) {
133
+ return `Provider "${provider.id}" has no API key. Tell the user to set OPENAI_API_KEY (or pi-image-gen.providers.${provider.id}.apiKey in settings.json).`;
134
+ }
135
+ return `Provider "${provider.id}" has no API key. Tell the user to set pi-image-gen.customProviders.${provider.id}.apiKey in settings.json.`;
136
+ }
137
+ async function safeText(res) {
138
+ try {
139
+ return await res.text();
140
+ }
141
+ catch {
142
+ return '<unreadable response body>';
143
+ }
144
+ }
145
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ export type ApiStyle = 'openai' | 'gemini' | 'dashscope' | 'openrouter';
2
+ /** Built-in provider id. Currently 1:1 with ApiStyle. */
3
+ export type BuiltInProviderId = ApiStyle;
4
+ /** A user-defined image-generation provider. */
5
+ export type CustomImageProvider = {
6
+ /**
7
+ * Image-API wire shape this provider speaks. Determines which adapter
8
+ * is used to call it. Required.
9
+ *
10
+ * Note: this is NOT the same as pi.dev custom providers' `api` field — pi.dev's
11
+ * values (`openai-completions`, `anthropic-messages`, ...) are LLM streaming
12
+ * formats. The values here are image-generation API shapes.
13
+ */
14
+ api: ApiStyle;
15
+ /** Override the API base URL. Optional; defaults to the api's default. */
16
+ baseUrl?: string;
17
+ /**
18
+ * API key. Supports `$ENV_VAR` and `${ENV_VAR}` syntax — resolved at load time.
19
+ * Required unless the api does not need one.
20
+ */
21
+ apiKey?: string;
22
+ /** Optional display name. */
23
+ name?: string;
24
+ /** Extra headers merged into every outbound request. */
25
+ headers?: Record<string, string>;
26
+ /** Models routed through this provider. Each entry is a model id (string) or an object. */
27
+ models?: Array<string | CustomImageModel>;
28
+ };
29
+ export type CustomImageModel = {
30
+ /** Model id sent to the provider (e.g. "qwen-image-2.0"). */
31
+ id: string;
32
+ /** Optional alias the agent / user can refer to. Defaults to id. */
33
+ alias?: string;
34
+ /** Optional display name. */
35
+ name?: string;
36
+ };
37
+ /** Per-built-in-provider override (api key, base url, custom headers). */
38
+ export type BuiltInProviderOverride = {
39
+ apiKey?: string;
40
+ baseUrl?: string;
41
+ headers?: Record<string, string>;
42
+ };
43
+ export type ImageGenSettings = {
44
+ /** Default model id when the tool call does not pass `model`. */
45
+ defaultModel?: string;
46
+ /**
47
+ * Where to write generated images. Relative paths resolve against the session cwd.
48
+ * Default: `.pi/images`.
49
+ */
50
+ outputDir?: string;
51
+ /** Per-built-in-provider overrides keyed by provider id. */
52
+ providers?: Partial<Record<BuiltInProviderId, BuiltInProviderOverride>>;
53
+ /** User-defined custom providers keyed by provider name. */
54
+ customProviders?: Record<string, CustomImageProvider>;
55
+ };
56
+ export type GenerateImageParams = {
57
+ prompt: string;
58
+ /**
59
+ * Optional reference / input images for image-to-image, editing, style
60
+ * transfer, or character preservation. Each entry MUST be either:
61
+ * - an absolute or relative file path on the local filesystem, or
62
+ * - an http(s) URL.
63
+ *
64
+ * `data:` URIs and raw base64 strings are intentionally rejected — tool
65
+ * arguments don't survive megabyte-sized strings cleanly across providers.
66
+ * If you have raw image bytes, write them to a file first.
67
+ */
68
+ image?: string[];
69
+ /** Number of images to generate. Default 1. */
70
+ n?: number;
71
+ /** Image size hint (e.g. "1024x1024"). Provider may ignore. */
72
+ size?: string;
73
+ /** Output filename prefix. */
74
+ filename?: string;
75
+ /** Override settings.outputDir for this call. */
76
+ outputDir?: string;
77
+ };
78
+ /** Materialized reference image, ready for adapters to encode. */
79
+ export type ResolvedImageInput = {
80
+ bytes: Uint8Array;
81
+ mimeType: string;
82
+ };
83
+ export type GeneratedImage = {
84
+ /** Absolute path on disk where the image was saved. */
85
+ path: string;
86
+ /** Image MIME type, e.g. "image/png". */
87
+ mimeType: string;
88
+ /** Pass-through revised prompt if the provider returned one (e.g. OpenAI). */
89
+ revisedPrompt?: string;
90
+ };
91
+ export type ImageGenResult = {
92
+ model: string;
93
+ provider: string;
94
+ images: GeneratedImage[];
95
+ };
96
+ /** Resolved provider entry: either a built-in or a custom one. */
97
+ export type ResolvedProvider = {
98
+ /** Provider key as referenced by the user (e.g. "openai", "my-stable-diffusion"). */
99
+ id: string;
100
+ api: ApiStyle;
101
+ baseUrl: string;
102
+ apiKey?: string;
103
+ headers?: Record<string, string>;
104
+ /** Display label. */
105
+ name: string;
106
+ /** True for built-in providers (openai/gemini/dashscope/openrouter). */
107
+ builtIn: boolean;
108
+ };
109
+ /** Result of resolving a model string to a provider + remote model id. */
110
+ export type ResolvedModel = {
111
+ provider: ResolvedProvider;
112
+ /** The id passed to the remote provider. */
113
+ remoteId: string;
114
+ /** The id the user asked for (alias or remoteId). */
115
+ requestedId: string;
116
+ };
117
+ /** Adapter interface implemented by each api shape. */
118
+ export type ImageProviderAdapter = {
119
+ generate(provider: ResolvedProvider, remoteModelId: string, params: GenerateImageParams, fetchImpl: typeof fetch, signal?: AbortSignal, inputs?: ResolvedImageInput[]): Promise<RawImageResult[]>;
120
+ };
121
+ export type RawImageResult = {
122
+ /** Either base64 PNG bytes or a URL to fetch. */
123
+ data: {
124
+ kind: 'base64';
125
+ bytes: string;
126
+ mimeType?: string;
127
+ } | {
128
+ kind: 'url';
129
+ url: string;
130
+ };
131
+ revisedPrompt?: string;
132
+ };
133
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/url.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Strip trailing slash, then append `defaultPath` only when the user's URL has
3
+ * no meaningful path of its own.
4
+ *
5
+ * "No meaningful path" = pathname is `""` or `"/"`. If the user wrote
6
+ * `https://api.openai.com/v1` or `http://localhost:8080/openai/v1`, the path
7
+ * is already supplied and we leave it alone — matters for self-hosted OpenAI
8
+ * compatible servers that don't follow the canonical mount point.
9
+ */
10
+ export declare function withDefaultPath(baseUrl: string, defaultPath: string): string;
11
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAa5E"}
package/dist/url.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Strip trailing slash, then append `defaultPath` only when the user's URL has
3
+ * no meaningful path of its own.
4
+ *
5
+ * "No meaningful path" = pathname is `""` or `"/"`. If the user wrote
6
+ * `https://api.openai.com/v1` or `http://localhost:8080/openai/v1`, the path
7
+ * is already supplied and we leave it alone — matters for self-hosted OpenAI
8
+ * compatible servers that don't follow the canonical mount point.
9
+ */
10
+ export function withDefaultPath(baseUrl, defaultPath) {
11
+ const trimmed = baseUrl.replace(/\/+$/, '');
12
+ let parsed;
13
+ try {
14
+ parsed = new URL(trimmed);
15
+ }
16
+ catch {
17
+ return trimmed;
18
+ }
19
+ if (parsed.pathname === '' || parsed.pathname === '/') {
20
+ const suffix = defaultPath.startsWith('/') ? defaultPath : `/${defaultPath}`;
21
+ return `${parsed.origin}${suffix.replace(/\/+$/, '')}`;
22
+ }
23
+ return trimmed;
24
+ }
25
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,WAAmB;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;QACtD,MAAM,MAAM,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC;QAC7E,OAAO,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@amaster.ai/pi-image-gen",
3
+ "version": "0.1.2-beta.15",
4
+ "description": "Pi extension for image generation via OpenAI gpt-image, Google Nano Banana (Gemini), Alibaba Qwen-Image, OpenRouter, and custom providers.",
5
+ "keywords": [
6
+ "pi-package",
7
+ "pi",
8
+ "extension",
9
+ "image-generation",
10
+ "nano-banana",
11
+ "gpt-image",
12
+ "qwen-image",
13
+ "openrouter"
14
+ ],
15
+ "license": "Apache-2.0",
16
+ "type": "module",
17
+ "sideEffects": false,
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "default": "./dist/index.js"
24
+ },
25
+ "./package.json": {
26
+ "default": "./package.json"
27
+ }
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "preview.png",
32
+ "README.md"
33
+ ],
34
+ "pi": {
35
+ "image": "https://raw.githubusercontent.com/TGYD-helige/pi/master/packages/pi-image-gen/preview.png",
36
+ "extensions": [
37
+ "./dist/index.js"
38
+ ]
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/TGYD-helige/pi.git",
46
+ "directory": "packages/pi-image-gen"
47
+ },
48
+ "dependencies": {
49
+ "@amaster.ai/pi-shared": "0.1.2-beta.15"
50
+ },
51
+ "peerDependencies": {
52
+ "@earendil-works/pi-coding-agent": ">=0.74.0",
53
+ "typebox": "*"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "@earendil-works/pi-coding-agent": {
57
+ "optional": true
58
+ },
59
+ "typebox": {
60
+ "optional": true
61
+ }
62
+ },
63
+ "devDependencies": {
64
+ "@earendil-works/pi-coding-agent": "0.74.0",
65
+ "typebox": "*",
66
+ "vitest": "^4.0.0"
67
+ },
68
+ "scripts": {
69
+ "build": "tsc -b",
70
+ "typecheck": "tsc -b --pretty false",
71
+ "test": "vitest run src"
72
+ }
73
+ }
package/preview.png ADDED
Binary file