aibroker 0.6.1 → 0.6.2
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 +263 -104
- package/dist/adapters/iterm/sessions.d.ts +1 -0
- package/dist/adapters/iterm/sessions.d.ts.map +1 -1
- package/dist/adapters/iterm/sessions.js +23 -0
- package/dist/adapters/iterm/sessions.js.map +1 -1
- package/dist/adapters/pailot/gateway.d.ts.map +1 -1
- package/dist/adapters/pailot/gateway.js +267 -52
- package/dist/adapters/pailot/gateway.js.map +1 -1
- package/dist/aibp/bridge.d.ts +123 -0
- package/dist/aibp/bridge.d.ts.map +1 -0
- package/dist/aibp/bridge.js +363 -0
- package/dist/aibp/bridge.js.map +1 -0
- package/dist/aibp/envelope.d.ts +26 -0
- package/dist/aibp/envelope.d.ts.map +1 -0
- package/dist/aibp/envelope.js +101 -0
- package/dist/aibp/envelope.js.map +1 -0
- package/dist/aibp/index.d.ts +11 -0
- package/dist/aibp/index.d.ts.map +1 -0
- package/dist/aibp/index.js +10 -0
- package/dist/aibp/index.js.map +1 -0
- package/dist/aibp/registry.d.ts +71 -0
- package/dist/aibp/registry.d.ts.map +1 -0
- package/dist/aibp/registry.js +408 -0
- package/dist/aibp/registry.js.map +1 -0
- package/dist/aibp/types.d.ts +91 -0
- package/dist/aibp/types.d.ts.map +1 -0
- package/dist/aibp/types.js +8 -0
- package/dist/aibp/types.js.map +1 -0
- package/dist/core/state.d.ts +12 -0
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/state.js +34 -0
- package/dist/core/state.js.map +1 -1
- package/dist/daemon/adapter-registry.d.ts.map +1 -1
- package/dist/daemon/adapter-registry.js +32 -3
- package/dist/daemon/adapter-registry.js.map +1 -1
- package/dist/daemon/command-context.d.ts +4 -0
- package/dist/daemon/command-context.d.ts.map +1 -1
- package/dist/daemon/commands.d.ts.map +1 -1
- package/dist/daemon/commands.js +239 -22
- package/dist/daemon/commands.js.map +1 -1
- package/dist/daemon/core-handlers.d.ts.map +1 -1
- package/dist/daemon/core-handlers.js +276 -15
- package/dist/daemon/core-handlers.js.map +1 -1
- package/dist/daemon/image-context.d.ts +56 -0
- package/dist/daemon/image-context.d.ts.map +1 -0
- package/dist/daemon/image-context.js +116 -0
- package/dist/daemon/image-context.js.map +1 -0
- package/dist/daemon/image-gen/index.d.ts +22 -0
- package/dist/daemon/image-gen/index.d.ts.map +1 -0
- package/dist/daemon/image-gen/index.js +129 -0
- package/dist/daemon/image-gen/index.js.map +1 -0
- package/dist/daemon/image-gen/providers/cloudflare.d.ts +13 -0
- package/dist/daemon/image-gen/providers/cloudflare.d.ts.map +1 -0
- package/dist/daemon/image-gen/providers/cloudflare.js +63 -0
- package/dist/daemon/image-gen/providers/cloudflare.js.map +1 -0
- package/dist/daemon/image-gen/providers/huggingface.d.ts +12 -0
- package/dist/daemon/image-gen/providers/huggingface.d.ts.map +1 -0
- package/dist/daemon/image-gen/providers/huggingface.js +58 -0
- package/dist/daemon/image-gen/providers/huggingface.js.map +1 -0
- package/dist/daemon/image-gen/providers/pollinations.d.ts +11 -0
- package/dist/daemon/image-gen/providers/pollinations.d.ts.map +1 -0
- package/dist/daemon/image-gen/providers/pollinations.js +39 -0
- package/dist/daemon/image-gen/providers/pollinations.js.map +1 -0
- package/dist/daemon/image-gen/providers/replicate.d.ts +9 -0
- package/dist/daemon/image-gen/providers/replicate.d.ts.map +1 -0
- package/dist/daemon/image-gen/providers/replicate.js +158 -0
- package/dist/daemon/image-gen/providers/replicate.js.map +1 -0
- package/dist/daemon/image-gen/types.d.ts +41 -0
- package/dist/daemon/image-gen/types.d.ts.map +1 -0
- package/dist/daemon/image-gen/types.js +5 -0
- package/dist/daemon/image-gen/types.js.map +1 -0
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +157 -4
- package/dist/daemon/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.js +129 -2
- package/dist/mcp/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).d.ts +0 -49
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).d.ts.map +0 -1
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).js +0 -632
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).js.map +0 -1
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-59).js +0 -632
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).d.ts +0 -49
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +0 -1
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).js +0 -614
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).js.map +0 -1
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-46).js +0 -614
- package/dist/adapters/pailot/gateway.d.ts (SFConflict mnott 2026-03-06-21-13-59).map +0 -1
- package/dist/adapters/pailot/gateway.d.ts (SFConflict mnott 2026-03-06-21-15-46).map +0 -1
- package/dist/adapters/pailot/gateway.js (SFConflict mnott 2026-03-06-21-13-59).map +0 -1
- package/dist/adapters/pailot/gateway.js (SFConflict mnott 2026-03-06-21-15-46).map +0 -1
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).d.ts +0 -63
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +0 -1
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).js +0 -229
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).js.map +0 -1
- package/dist/daemon/image-gen.d.ts +0 -28
- package/dist/daemon/image-gen.d.ts.map +0 -1
- package/dist/daemon/image-gen.js +0 -97
- package/dist/daemon/image-gen.js.map +0 -1
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).d.ts +0 -12
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).d.ts.map +0 -1
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).js +0 -252
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).js.map +0 -1
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-59).js +0 -252
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).d.ts +0 -12
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +0 -1
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).js +0 -240
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).js.map +0 -1
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-46).js +0 -240
- package/dist/daemon/screenshot.d.ts (SFConflict mnott 2026-03-06-21-13-59).map +0 -1
- package/dist/daemon/screenshot.d.ts (SFConflict mnott 2026-03-06-21-15-46).map +0 -1
- package/dist/daemon/screenshot.js (SFConflict mnott 2026-03-06-21-13-59).map +0 -1
- package/dist/daemon/screenshot.js (SFConflict mnott 2026-03-06-21-15-46).map +0 -1
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).d.ts +0 -23
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).d.ts.map +0 -1
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).js +0 -595
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).js.map +0 -1
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-59).js +0 -595
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).d.ts +0 -23
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +0 -1
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).js +0 -592
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).js.map +0 -1
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-46).js +0 -592
- package/dist/mcp/index.js (SFConflict mnott 2026-03-06-21-13-59).map +0 -1
- package/dist/mcp/index.js (SFConflict mnott 2026-03-06-21-15-46).map +0 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-context.ts — Per-session image context for conversational refinement.
|
|
3
|
+
*
|
|
4
|
+
* Tracks prompt history and the last generated image per routing context.
|
|
5
|
+
* The composite key (source:recipient:sessionId) ensures complete isolation
|
|
6
|
+
* between users, adapters, and sessions.
|
|
7
|
+
*/
|
|
8
|
+
const MAX_HISTORY = 8;
|
|
9
|
+
const DEFAULT_TTL_MS = 30 * 60 * 1000; // 30 minutes
|
|
10
|
+
const store = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* Build the composite routing key for image context lookup.
|
|
13
|
+
* Format: "{source}:{recipient}:{sessionId}"
|
|
14
|
+
*/
|
|
15
|
+
export function buildImageContextKey(source, recipient, sessionId) {
|
|
16
|
+
return `${source}:${recipient ?? ""}:${sessionId ?? ""}`;
|
|
17
|
+
}
|
|
18
|
+
export function getImageContext(key) {
|
|
19
|
+
return store.get(key);
|
|
20
|
+
}
|
|
21
|
+
export function setImageContext(key, ctx) {
|
|
22
|
+
store.set(key, ctx);
|
|
23
|
+
}
|
|
24
|
+
export function clearImageContext(key) {
|
|
25
|
+
store.delete(key);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Remove image contexts that haven't been updated within the TTL window.
|
|
29
|
+
* Returns the number of evicted entries.
|
|
30
|
+
*/
|
|
31
|
+
export function pruneStaleContexts(ttlMs = DEFAULT_TTL_MS) {
|
|
32
|
+
const cutoff = Date.now() - ttlMs;
|
|
33
|
+
let evicted = 0;
|
|
34
|
+
for (const [key, ctx] of store) {
|
|
35
|
+
if (ctx.updatedAt < cutoff) {
|
|
36
|
+
store.delete(key);
|
|
37
|
+
evicted++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return evicted;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Classify an incoming text message as a new image request, a refinement
|
|
44
|
+
* of the current image context, or unrelated to image generation.
|
|
45
|
+
*
|
|
46
|
+
* Only returns "refine" when there is an actual signal — a pronoun
|
|
47
|
+
* referencing the image, a modification verb, or a style keyword.
|
|
48
|
+
* Messages that don't contain any image-related signal fall through
|
|
49
|
+
* as "unrelated" so they reach normal routing (Claude, slash commands, etc.).
|
|
50
|
+
*/
|
|
51
|
+
export function classifyImageRequest(text, context) {
|
|
52
|
+
// No context — always new
|
|
53
|
+
if (!context || context.promptHistory.length === 0) {
|
|
54
|
+
return { type: "new", prompt: text };
|
|
55
|
+
}
|
|
56
|
+
const lower = text.toLowerCase().trim();
|
|
57
|
+
// Explicit new-image signals (English + German)
|
|
58
|
+
if (/^(new image|different image|new picture|start over|forget the image|neues bild|vergiss das bild)[:\s]/i.test(text) ||
|
|
59
|
+
/^(new image|different image|new picture|start over|forget the image|neues bild|vergiss das bild)$/i.test(text)) {
|
|
60
|
+
const prompt = text.replace(/^[^:]+:\s*/i, "").trim();
|
|
61
|
+
return { type: "new", prompt: prompt || text };
|
|
62
|
+
}
|
|
63
|
+
// Refinement signals: pronouns + modification verbs (English)
|
|
64
|
+
if (/\b(it|the image|the picture|that)\b/i.test(text) ||
|
|
65
|
+
/^(put|add|remove|change|make|give|turn|render|show)\b/i.test(text) ||
|
|
66
|
+
/\b(style|as a|in a|black and white|watercolor|oil paint(ing)?|sketch|pixelated|cartoon|anime)\b/i.test(lower) ||
|
|
67
|
+
/\b(more|less|brighter|darker|bigger|smaller|closer|farther)\b/i.test(lower)) {
|
|
68
|
+
return { type: "refine", prompt: text };
|
|
69
|
+
}
|
|
70
|
+
// Refinement signals: German
|
|
71
|
+
if (/\b(das bild|das foto)\b/i.test(lower) ||
|
|
72
|
+
/^(mach|ändere|füge hinzu|entferne|gib|zeig|setz)\b/i.test(lower)) {
|
|
73
|
+
return { type: "refine", prompt: text };
|
|
74
|
+
}
|
|
75
|
+
// Prepositional phrases that only make sense as image modifications
|
|
76
|
+
// e.g., "with a hat", "in watercolor", "but bigger", "without the chair"
|
|
77
|
+
if (/^(with|without|in|but|and|plus|minus)\b/i.test(lower)) {
|
|
78
|
+
return { type: "refine", prompt: text };
|
|
79
|
+
}
|
|
80
|
+
if (/^(mit|ohne|in|aber|und|als)\b/i.test(lower)) {
|
|
81
|
+
return { type: "refine", prompt: text };
|
|
82
|
+
}
|
|
83
|
+
// No image-related signal — this message is not about the image
|
|
84
|
+
return { type: "unrelated", prompt: text };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Build a combined prompt from the full prompt history using prompt chaining.
|
|
88
|
+
*
|
|
89
|
+
* The first entry is the base description; subsequent entries are refinement
|
|
90
|
+
* phrases appended with ", ". Cap at MAX_HISTORY entries.
|
|
91
|
+
*/
|
|
92
|
+
export function buildChainedPrompt(history) {
|
|
93
|
+
const capped = history.slice(0, MAX_HISTORY);
|
|
94
|
+
if (capped.length === 1)
|
|
95
|
+
return capped[0];
|
|
96
|
+
const [base, ...modifications] = capped;
|
|
97
|
+
return `${base}, ${modifications.join(", ")}`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Append a new prompt phrase to the context's history, enforcing the cap.
|
|
101
|
+
* Returns an updated context object (does NOT mutate the original).
|
|
102
|
+
*/
|
|
103
|
+
export function appendPromptToContext(existing, prompt, imageBuffer, imageMime = "image/png") {
|
|
104
|
+
const history = existing ? [...existing.promptHistory] : [];
|
|
105
|
+
history.push(prompt);
|
|
106
|
+
// Enforce cap
|
|
107
|
+
while (history.length > MAX_HISTORY)
|
|
108
|
+
history.shift();
|
|
109
|
+
return {
|
|
110
|
+
promptHistory: history,
|
|
111
|
+
lastImage: imageBuffer ?? existing?.lastImage,
|
|
112
|
+
lastImageMime: imageBuffer ? imageMime : (existing?.lastImageMime ?? "image/png"),
|
|
113
|
+
updatedAt: Date.now(),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=image-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-context.js","sourceRoot":"","sources":["../../src/daemon/image-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/index.ts — Provider-pluggable image generation.
|
|
3
|
+
*
|
|
4
|
+
* Public interface: generateImage() — identical signature to the old image-gen.ts.
|
|
5
|
+
* Callers only need to update their import path.
|
|
6
|
+
*
|
|
7
|
+
* Provider resolution order:
|
|
8
|
+
* 1. ~/.aibroker/image-gen.json (explicit config)
|
|
9
|
+
* 2. Env var detection: REPLICATE_API_TOKEN → CLOUDFLARE_AI_TOKEN → HF_API_TOKEN
|
|
10
|
+
* 3. Fallback: Pollinations (no auth, always works)
|
|
11
|
+
*/
|
|
12
|
+
import type { GenerateImageOptions, GenerateImageResult, ImageProvider, ImageProviderConfig } from "./types.js";
|
|
13
|
+
export type { GenerateImageOptions, GenerateImageResult, ImageProvider, ImageProviderConfig };
|
|
14
|
+
/**
|
|
15
|
+
* Generate an image from a text prompt.
|
|
16
|
+
*
|
|
17
|
+
* Provider is resolved from ~/.aibroker/image-gen.json, then env vars,
|
|
18
|
+
* then falls back to Pollinations (no auth needed).
|
|
19
|
+
*/
|
|
20
|
+
export declare function generateImage(opts: GenerateImageOptions): Promise<GenerateImageResult>;
|
|
21
|
+
export declare function getConfiguredProvider(): ImageProvider;
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/daemon/image-gen/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAMhH,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC;AAI9F;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAG5F;AAED,wBAAgB,qBAAqB,IAAI,aAAa,CA0BrD"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/index.ts — Provider-pluggable image generation.
|
|
3
|
+
*
|
|
4
|
+
* Public interface: generateImage() — identical signature to the old image-gen.ts.
|
|
5
|
+
* Callers only need to update their import path.
|
|
6
|
+
*
|
|
7
|
+
* Provider resolution order:
|
|
8
|
+
* 1. ~/.aibroker/image-gen.json (explicit config)
|
|
9
|
+
* 2. Env var detection: REPLICATE_API_TOKEN → CLOUDFLARE_AI_TOKEN → HF_API_TOKEN
|
|
10
|
+
* 3. Fallback: Pollinations (no auth, always works)
|
|
11
|
+
*/
|
|
12
|
+
import { readFileSync } from "fs";
|
|
13
|
+
import { homedir } from "os";
|
|
14
|
+
import { join } from "path";
|
|
15
|
+
import { log } from "../../core/log.js";
|
|
16
|
+
import { createReplicateProvider } from "./providers/replicate.js";
|
|
17
|
+
import { createCloudflareProvider } from "./providers/cloudflare.js";
|
|
18
|
+
import { createHuggingFaceProvider } from "./providers/huggingface.js";
|
|
19
|
+
import { createPollinationsProvider } from "./providers/pollinations.js";
|
|
20
|
+
const CONFIG_PATH = join(homedir(), ".aibroker", "image-gen.json");
|
|
21
|
+
/**
|
|
22
|
+
* Generate an image from a text prompt.
|
|
23
|
+
*
|
|
24
|
+
* Provider is resolved from ~/.aibroker/image-gen.json, then env vars,
|
|
25
|
+
* then falls back to Pollinations (no auth needed).
|
|
26
|
+
*/
|
|
27
|
+
export async function generateImage(opts) {
|
|
28
|
+
const provider = getConfiguredProvider();
|
|
29
|
+
return provider.generate(opts);
|
|
30
|
+
}
|
|
31
|
+
export function getConfiguredProvider() {
|
|
32
|
+
// 1. Explicit config file
|
|
33
|
+
const config = loadConfig();
|
|
34
|
+
if (config) {
|
|
35
|
+
return buildProvider(config);
|
|
36
|
+
}
|
|
37
|
+
// 2. Env var detection
|
|
38
|
+
if (process.env.REPLICATE_API_TOKEN) {
|
|
39
|
+
log("Image gen: detected REPLICATE_API_TOKEN, using replicate");
|
|
40
|
+
return createReplicateProvider();
|
|
41
|
+
}
|
|
42
|
+
if (process.env.CLOUDFLARE_AI_TOKEN) {
|
|
43
|
+
log("Image gen: detected CLOUDFLARE_AI_TOKEN, using cloudflare");
|
|
44
|
+
return createCloudflareProvider();
|
|
45
|
+
}
|
|
46
|
+
if (process.env.HF_API_TOKEN) {
|
|
47
|
+
log("Image gen: detected HF_API_TOKEN, using huggingface");
|
|
48
|
+
return createHuggingFaceProvider();
|
|
49
|
+
}
|
|
50
|
+
// 3. Fallback: Pollinations (no auth needed)
|
|
51
|
+
log("Image gen: no token detected, falling back to pollinations");
|
|
52
|
+
return createPollinationsProvider();
|
|
53
|
+
}
|
|
54
|
+
function buildProvider(config) {
|
|
55
|
+
switch (config.provider) {
|
|
56
|
+
case "replicate":
|
|
57
|
+
return createReplicateProvider(config);
|
|
58
|
+
case "cloudflare":
|
|
59
|
+
return createCloudflareProvider(config);
|
|
60
|
+
case "huggingface":
|
|
61
|
+
return createHuggingFaceProvider(config);
|
|
62
|
+
case "pollinations":
|
|
63
|
+
return createPollinationsProvider();
|
|
64
|
+
case "custom":
|
|
65
|
+
return loadCustomProvider(config);
|
|
66
|
+
default:
|
|
67
|
+
log(`Image gen: unknown provider "${config.provider}", falling back to pollinations`);
|
|
68
|
+
return createPollinationsProvider();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Load a custom image provider from a user-supplied module.
|
|
73
|
+
*
|
|
74
|
+
* The module must export a `createProvider` function:
|
|
75
|
+
* export function createProvider(config: ImageProviderConfig): ImageProvider
|
|
76
|
+
*
|
|
77
|
+
* Example module (my-provider.js):
|
|
78
|
+
* export function createProvider(config) {
|
|
79
|
+
* return {
|
|
80
|
+
* name: "my-provider",
|
|
81
|
+
* async generate(opts) {
|
|
82
|
+
* const res = await fetch("https://my-api.com/generate", { ... });
|
|
83
|
+
* return { images: [Buffer.from(await res.arrayBuffer())], model: "my-model", durationMs: 0 };
|
|
84
|
+
* }
|
|
85
|
+
* };
|
|
86
|
+
* }
|
|
87
|
+
*
|
|
88
|
+
* Config (~/.aibroker/image-gen.json):
|
|
89
|
+
* { "provider": "custom", "modulePath": "/path/to/my-provider.js", "options": { "apiKey": "..." } }
|
|
90
|
+
*/
|
|
91
|
+
function loadCustomProvider(config) {
|
|
92
|
+
if (!config.modulePath) {
|
|
93
|
+
throw new Error('Image gen: custom provider requires "modulePath" in ~/.aibroker/image-gen.json');
|
|
94
|
+
}
|
|
95
|
+
log(`Image gen: loading custom provider from ${config.modulePath}`);
|
|
96
|
+
// Dynamic import is async, so we return a lazy wrapper that loads on first call
|
|
97
|
+
let cached = null;
|
|
98
|
+
return {
|
|
99
|
+
name: `custom (${config.modulePath})`,
|
|
100
|
+
async generate(opts) {
|
|
101
|
+
if (!cached) {
|
|
102
|
+
const mod = await import(config.modulePath);
|
|
103
|
+
if (typeof mod.createProvider !== "function") {
|
|
104
|
+
throw new Error(`Image gen: custom module ${config.modulePath} must export createProvider(config): ImageProvider`);
|
|
105
|
+
}
|
|
106
|
+
cached = mod.createProvider(config);
|
|
107
|
+
log(`Image gen: custom provider "${cached.name}" loaded`);
|
|
108
|
+
}
|
|
109
|
+
return cached.generate(opts);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function loadConfig() {
|
|
114
|
+
try {
|
|
115
|
+
const raw = readFileSync(CONFIG_PATH, "utf8");
|
|
116
|
+
const parsed = JSON.parse(raw);
|
|
117
|
+
if (typeof parsed.provider === "string") {
|
|
118
|
+
log(`Image gen: loaded config from ${CONFIG_PATH} (provider: ${parsed.provider})`);
|
|
119
|
+
return parsed;
|
|
120
|
+
}
|
|
121
|
+
log(`Image gen: config at ${CONFIG_PATH} missing "provider" field, ignoring`);
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// File doesn't exist or is malformed — not an error, just use env/fallback
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/daemon/image-gen/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/providers/cloudflare.ts — Cloudflare Workers AI image generation provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses Cloudflare's AI REST API with the Flux schnell model.
|
|
5
|
+
* Free tier: 10,000 neurons/day.
|
|
6
|
+
*
|
|
7
|
+
* Requires:
|
|
8
|
+
* CLOUDFLARE_AI_TOKEN — API token with AI:Run permission
|
|
9
|
+
* CLOUDFLARE_ACCOUNT_ID — Cloudflare account ID
|
|
10
|
+
*/
|
|
11
|
+
import type { ImageProvider, ImageProviderConfig } from "../types.js";
|
|
12
|
+
export declare function createCloudflareProvider(config?: ImageProviderConfig): ImageProvider;
|
|
13
|
+
//# sourceMappingURL=cloudflare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../../src/daemon/image-gen/providers/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAA6C,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIjH,wBAAgB,wBAAwB,CAAC,MAAM,GAAE,mBAAgD,GAAG,aAAa,CA+DhH"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/providers/cloudflare.ts — Cloudflare Workers AI image generation provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses Cloudflare's AI REST API with the Flux schnell model.
|
|
5
|
+
* Free tier: 10,000 neurons/day.
|
|
6
|
+
*
|
|
7
|
+
* Requires:
|
|
8
|
+
* CLOUDFLARE_AI_TOKEN — API token with AI:Run permission
|
|
9
|
+
* CLOUDFLARE_ACCOUNT_ID — Cloudflare account ID
|
|
10
|
+
*/
|
|
11
|
+
import { log } from "../../../core/log.js";
|
|
12
|
+
const DEFAULT_MODEL = "@cf/black-forest-labs/flux-1-schnell";
|
|
13
|
+
export function createCloudflareProvider(config = { provider: "cloudflare" }) {
|
|
14
|
+
return {
|
|
15
|
+
name: "cloudflare",
|
|
16
|
+
async generate(opts) {
|
|
17
|
+
const tokenEnv = config.apiTokenEnv ?? "CLOUDFLARE_AI_TOKEN";
|
|
18
|
+
const token = config.apiToken ?? process.env[tokenEnv];
|
|
19
|
+
if (!token) {
|
|
20
|
+
throw new Error(`Cloudflare API error: ${tokenEnv} not set`);
|
|
21
|
+
}
|
|
22
|
+
const accountId = config.accountId ?? process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
23
|
+
if (!accountId) {
|
|
24
|
+
throw new Error("Cloudflare API error: CLOUDFLARE_ACCOUNT_ID not set");
|
|
25
|
+
}
|
|
26
|
+
const model = opts.model ?? config.model ?? DEFAULT_MODEL;
|
|
27
|
+
const startMs = Date.now();
|
|
28
|
+
const endpoint = `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/run/${model}`;
|
|
29
|
+
log(`Image gen: using cloudflare (${model})`);
|
|
30
|
+
const body = {
|
|
31
|
+
prompt: opts.prompt,
|
|
32
|
+
num_steps: 4, // Flux schnell optimal
|
|
33
|
+
};
|
|
34
|
+
if (opts.width)
|
|
35
|
+
body.width = opts.width;
|
|
36
|
+
if (opts.height)
|
|
37
|
+
body.height = opts.height;
|
|
38
|
+
const res = await fetch(endpoint, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: {
|
|
41
|
+
Authorization: `Bearer ${token}`,
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify(body),
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
const errText = await res.text();
|
|
48
|
+
throw new Error(`Cloudflare API error (${res.status}): ${errText}`);
|
|
49
|
+
}
|
|
50
|
+
// Cloudflare returns JSON with base64 image
|
|
51
|
+
const data = await res.json();
|
|
52
|
+
if (!data.success || !data.result?.image) {
|
|
53
|
+
const errMsg = data.errors?.map((e) => e.message).join(", ") ?? "unknown error";
|
|
54
|
+
throw new Error(`Cloudflare API error: ${errMsg}`);
|
|
55
|
+
}
|
|
56
|
+
const imageBuffer = Buffer.from(data.result.image, "base64");
|
|
57
|
+
const durationMs = Date.now() - startMs;
|
|
58
|
+
log(`Image gen: completed in ${durationMs}ms, 1 image(s), ${imageBuffer.length} bytes total`);
|
|
59
|
+
return { images: [imageBuffer], model, durationMs };
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=cloudflare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../../src/daemon/image-gen/providers/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAG3C,MAAM,aAAa,GAAG,sCAAsC,CAAC;AAE7D,MAAM,UAAU,wBAAwB,CAAC,SAA8B,EAAE,QAAQ,EAAE,YAAY,EAAE;IAC/F,OAAO;QACL,IAAI,EAAE,YAAY;QAElB,KAAK,CAAC,QAAQ,CAAC,IAA0B;YACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,IAAI,qBAAqB,CAAC;YAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACvD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,UAAU,CAAC,CAAC;YAC/D,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;YACxE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,aAAa,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,iDAAiD,SAAS,WAAW,KAAK,EAAE,CAAC;YAE9F,GAAG,CAAC,gCAAgC,KAAK,GAAG,CAAC,CAAC;YAE9C,MAAM,IAAI,GAA4B;gBACpC,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,SAAS,EAAE,CAAC,EAAG,uBAAuB;aACvC,CAAC;YACF,IAAI,IAAI,CAAC,KAAK;gBAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACxC,IAAI,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAE3C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,KAAK,EAAE;oBAChC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,4CAA4C;YAC5C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAI1B,CAAC;YAEF,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;gBACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC;gBAChF,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,EAAE,CAAC,CAAC;YACrD,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;YAExC,GAAG,CAAC,2BAA2B,UAAU,mBAAmB,WAAW,CAAC,MAAM,cAAc,CAAC,CAAC;YAE9F,OAAO,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACtD,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/providers/huggingface.ts — Hugging Face Inference API image generation provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses the HF Inference API to run image generation models.
|
|
5
|
+
* Default model: black-forest-labs/FLUX.1-schnell
|
|
6
|
+
* Free tier: rate-limited.
|
|
7
|
+
*
|
|
8
|
+
* Requires HF_API_TOKEN env var (or apiToken in config).
|
|
9
|
+
*/
|
|
10
|
+
import type { ImageProvider, ImageProviderConfig } from "../types.js";
|
|
11
|
+
export declare function createHuggingFaceProvider(config?: ImageProviderConfig): ImageProvider;
|
|
12
|
+
//# sourceMappingURL=huggingface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"huggingface.d.ts","sourceRoot":"","sources":["../../../../src/daemon/image-gen/providers/huggingface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAA6C,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAKjH,wBAAgB,yBAAyB,CAAC,MAAM,GAAE,mBAAiD,GAAG,aAAa,CAsDlH"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/providers/huggingface.ts — Hugging Face Inference API image generation provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses the HF Inference API to run image generation models.
|
|
5
|
+
* Default model: black-forest-labs/FLUX.1-schnell
|
|
6
|
+
* Free tier: rate-limited.
|
|
7
|
+
*
|
|
8
|
+
* Requires HF_API_TOKEN env var (or apiToken in config).
|
|
9
|
+
*/
|
|
10
|
+
import { log } from "../../../core/log.js";
|
|
11
|
+
const HF_API_BASE = "https://api-inference.huggingface.co/models";
|
|
12
|
+
const DEFAULT_MODEL = "black-forest-labs/FLUX.1-schnell";
|
|
13
|
+
export function createHuggingFaceProvider(config = { provider: "huggingface" }) {
|
|
14
|
+
return {
|
|
15
|
+
name: "huggingface",
|
|
16
|
+
async generate(opts) {
|
|
17
|
+
const tokenEnv = config.apiTokenEnv ?? "HF_API_TOKEN";
|
|
18
|
+
const token = config.apiToken ?? process.env[tokenEnv];
|
|
19
|
+
if (!token) {
|
|
20
|
+
throw new Error(`Hugging Face API error: ${tokenEnv} not set. Get one at https://huggingface.co/settings/tokens`);
|
|
21
|
+
}
|
|
22
|
+
const model = opts.model ?? config.model ?? DEFAULT_MODEL;
|
|
23
|
+
const startMs = Date.now();
|
|
24
|
+
const endpoint = `${HF_API_BASE}/${model}`;
|
|
25
|
+
log(`Image gen: using huggingface (${model})`);
|
|
26
|
+
const body = {
|
|
27
|
+
inputs: opts.prompt,
|
|
28
|
+
};
|
|
29
|
+
// HF accepts parameters for image dimensions
|
|
30
|
+
if (opts.width || opts.height) {
|
|
31
|
+
body.parameters = {
|
|
32
|
+
...(opts.width ? { width: opts.width } : {}),
|
|
33
|
+
...(opts.height ? { height: opts.height } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const res = await fetch(endpoint, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: {
|
|
39
|
+
Authorization: `Bearer ${token}`,
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
"Accept": "image/*",
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify(body),
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
const errText = await res.text();
|
|
47
|
+
throw new Error(`Hugging Face API error (${res.status}): ${errText}`);
|
|
48
|
+
}
|
|
49
|
+
// HF returns image bytes directly in the response body
|
|
50
|
+
const arrayBuf = await res.arrayBuffer();
|
|
51
|
+
const imageBuffer = Buffer.from(arrayBuf);
|
|
52
|
+
const durationMs = Date.now() - startMs;
|
|
53
|
+
log(`Image gen: completed in ${durationMs}ms, 1 image(s), ${imageBuffer.length} bytes total`);
|
|
54
|
+
return { images: [imageBuffer], model, durationMs };
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=huggingface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"huggingface.js","sourceRoot":"","sources":["../../../../src/daemon/image-gen/providers/huggingface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAG3C,MAAM,WAAW,GAAG,6CAA6C,CAAC;AAClE,MAAM,aAAa,GAAG,kCAAkC,CAAC;AAEzD,MAAM,UAAU,yBAAyB,CAAC,SAA8B,EAAE,QAAQ,EAAE,aAAa,EAAE;IACjG,OAAO;QACL,IAAI,EAAE,aAAa;QAEnB,KAAK,CAAC,QAAQ,CAAC,IAA0B;YACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,IAAI,cAAc,CAAC;YACtD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACvD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,6DAA6D,CAAC,CAAC;YACpH,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,aAAa,CAAC;YAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,GAAG,WAAW,IAAI,KAAK,EAAE,CAAC;YAE3C,GAAG,CAAC,iCAAiC,KAAK,GAAG,CAAC,CAAC;YAE/C,MAAM,IAAI,GAA4B;gBACpC,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;YAEF,6CAA6C;YAC7C,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC9B,IAAI,CAAC,UAAU,GAAG;oBAChB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAChD,CAAC;YACJ,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,KAAK,EAAE;oBAChC,cAAc,EAAE,kBAAkB;oBAClC,QAAQ,EAAE,SAAS;iBACpB;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;YACxE,CAAC;YAED,uDAAuD;YACvD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;YAExC,GAAG,CAAC,2BAA2B,UAAU,mBAAmB,WAAW,CAAC,MAAM,cAAc,CAAC,CAAC;YAE9F,OAAO,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACtD,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/providers/pollinations.ts — Pollinations.ai image generation provider.
|
|
3
|
+
*
|
|
4
|
+
* Free, no authentication required.
|
|
5
|
+
* Endpoint: https://image.pollinations.ai/prompt/{encoded_prompt}
|
|
6
|
+
*
|
|
7
|
+
* Returns image bytes directly — no API key needed.
|
|
8
|
+
*/
|
|
9
|
+
import type { ImageProvider } from "../types.js";
|
|
10
|
+
export declare function createPollinationsProvider(): ImageProvider;
|
|
11
|
+
//# sourceMappingURL=pollinations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pollinations.d.ts","sourceRoot":"","sources":["../../../../src/daemon/image-gen/providers/pollinations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAA6C,aAAa,EAAE,MAAM,aAAa,CAAC;AAK5F,wBAAgB,0BAA0B,IAAI,aAAa,CAmC1D"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/providers/pollinations.ts — Pollinations.ai image generation provider.
|
|
3
|
+
*
|
|
4
|
+
* Free, no authentication required.
|
|
5
|
+
* Endpoint: https://image.pollinations.ai/prompt/{encoded_prompt}
|
|
6
|
+
*
|
|
7
|
+
* Returns image bytes directly — no API key needed.
|
|
8
|
+
*/
|
|
9
|
+
import { log } from "../../../core/log.js";
|
|
10
|
+
const POLLINATIONS_BASE = "https://image.pollinations.ai/prompt";
|
|
11
|
+
const DEFAULT_MODEL = "flux";
|
|
12
|
+
export function createPollinationsProvider() {
|
|
13
|
+
return {
|
|
14
|
+
name: "pollinations",
|
|
15
|
+
async generate(opts) {
|
|
16
|
+
const model = opts.model ?? DEFAULT_MODEL;
|
|
17
|
+
const startMs = Date.now();
|
|
18
|
+
const params = new URLSearchParams({
|
|
19
|
+
nologo: "true",
|
|
20
|
+
model,
|
|
21
|
+
...(opts.width ? { width: String(opts.width) } : {}),
|
|
22
|
+
...(opts.height ? { height: String(opts.height) } : {}),
|
|
23
|
+
});
|
|
24
|
+
const encodedPrompt = encodeURIComponent(opts.prompt);
|
|
25
|
+
const endpoint = `${POLLINATIONS_BASE}/${encodedPrompt}?${params.toString()}`;
|
|
26
|
+
log(`Image gen: using pollinations (${model})`);
|
|
27
|
+
const res = await fetch(endpoint);
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
throw new Error(`Pollinations API error (${res.status}): ${await res.text()}`);
|
|
30
|
+
}
|
|
31
|
+
const arrayBuf = await res.arrayBuffer();
|
|
32
|
+
const imageBuffer = Buffer.from(arrayBuf);
|
|
33
|
+
const durationMs = Date.now() - startMs;
|
|
34
|
+
log(`Image gen: completed in ${durationMs}ms, 1 image(s), ${imageBuffer.length} bytes total`);
|
|
35
|
+
return { images: [imageBuffer], model, durationMs };
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=pollinations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pollinations.js","sourceRoot":"","sources":["../../../../src/daemon/image-gen/providers/pollinations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAG3C,MAAM,iBAAiB,GAAG,sCAAsC,CAAC;AACjE,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,IAAI,EAAE,cAAc;QAEpB,KAAK,CAAC,QAAQ,CAAC,IAA0B;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC;YAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE3B,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;gBACjC,MAAM,EAAE,MAAM;gBACd,KAAK;gBACL,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxD,CAAC,CAAC;YAEH,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACtD,MAAM,QAAQ,GAAG,GAAG,iBAAiB,IAAI,aAAa,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;YAE9E,GAAG,CAAC,kCAAkC,KAAK,GAAG,CAAC,CAAC;YAEhD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;YAElC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACjF,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;YAExC,GAAG,CAAC,2BAA2B,UAAU,mBAAmB,WAAW,CAAC,MAAM,cAAc,CAAC,CAAC;YAE9F,OAAO,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACtD,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/image-gen/providers/replicate.ts — Replicate image generation provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses the Replicate Flux schnell model by default.
|
|
5
|
+
* Requires REPLICATE_API_TOKEN env var (or apiToken in config).
|
|
6
|
+
*/
|
|
7
|
+
import type { ImageProvider, ImageProviderConfig } from "../types.js";
|
|
8
|
+
export declare function createReplicateProvider(config?: ImageProviderConfig): ImageProvider;
|
|
9
|
+
//# sourceMappingURL=replicate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replicate.d.ts","sourceRoot":"","sources":["../../../../src/daemon/image-gen/providers/replicate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAA6C,aAAa,EAAE,mBAAmB,EAAsB,MAAM,aAAa,CAAC;AAKrI,wBAAgB,uBAAuB,CAAC,MAAM,GAAE,mBAA+C,GAAG,aAAa,CAsK9G"}
|