@tanstack/ai 0.41.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/dist/esm/activities/chat/adapter.js +23 -16
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- package/dist/esm/activities/chat/agent-loop-strategies.d.ts +10 -4
- package/dist/esm/activities/chat/agent-loop-strategies.js +75 -17
- package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -1
- package/dist/esm/activities/chat/cancel.d.ts +40 -0
- package/dist/esm/activities/chat/cancel.js +54 -0
- package/dist/esm/activities/chat/cancel.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +28 -16
- package/dist/esm/activities/chat/index.js +2100 -1744
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/mcp/manager.d.ts +2 -2
- package/dist/esm/activities/chat/mcp/manager.js +90 -77
- package/dist/esm/activities/chat/mcp/manager.js.map +1 -1
- package/dist/esm/activities/chat/mcp/types.d.ts +2 -2
- package/dist/esm/activities/chat/messages.js +397 -346
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/builder.js +17 -15
- package/dist/esm/activities/chat/middleware/builder.js.map +1 -1
- package/dist/esm/activities/chat/middleware/capabilities.js +78 -43
- package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.d.ts +94 -1
- package/dist/esm/activities/chat/middleware/compose.js +623 -531
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/define.js +12 -5
- package/dist/esm/activities/chat/middleware/define.js.map +1 -1
- package/dist/esm/activities/chat/middleware/index.d.ts +5 -1
- package/dist/esm/activities/chat/middleware/locks.d.ts +50 -0
- package/dist/esm/activities/chat/middleware/locks.js +71 -0
- package/dist/esm/activities/chat/middleware/locks.js.map +1 -0
- package/dist/esm/activities/chat/middleware/pending-turn.d.ts +15 -0
- package/dist/esm/activities/chat/middleware/pending-turn.js +35 -0
- package/dist/esm/activities/chat/middleware/pending-turn.js.map +1 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.d.ts +23 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.js +42 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.js.map +1 -0
- package/dist/esm/activities/chat/middleware/run-store.d.ts +283 -0
- package/dist/esm/activities/chat/middleware/run-store.js +176 -0
- package/dist/esm/activities/chat/middleware/run-store.js.map +1 -0
- package/dist/esm/activities/chat/middleware/sandbox-runtime.js +14 -8
- package/dist/esm/activities/chat/middleware/sandbox-runtime.js.map +1 -1
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +79 -70
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +59 -2
- package/dist/esm/activities/chat/middleware/validate.js +23 -28
- package/dist/esm/activities/chat/middleware/validate.js.map +1 -1
- package/dist/esm/activities/chat/stream/json-parser.js +39 -25
- package/dist/esm/activities/chat/stream/json-parser.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js +275 -234
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +24 -4
- package/dist/esm/activities/chat/stream/processor.js +1341 -1542
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/stream/strategies.js +69 -53
- package/dist/esm/activities/chat/stream/strategies.js.map +1 -1
- package/dist/esm/activities/chat/tools/approval-schema.d.ts +19 -0
- package/dist/esm/activities/chat/tools/approval-schema.js +117 -0
- package/dist/esm/activities/chat/tools/approval-schema.js.map +1 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js +164 -191
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -1
- package/dist/esm/activities/chat/tools/lazy-tools.js +24 -12
- package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +293 -146
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +18 -2
- package/dist/esm/activities/chat/tools/tool-calls.js +522 -531
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +75 -16
- package/dist/esm/activities/chat/tools/tool-definition.js +95 -23
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
- package/dist/esm/activities/error-payload.js +85 -47
- package/dist/esm/activities/error-payload.js.map +1 -1
- package/dist/esm/activities/generateAudio/adapter.js +22 -15
- package/dist/esm/activities/generateAudio/adapter.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.d.ts +4 -0
- package/dist/esm/activities/generateAudio/index.js +141 -105
- package/dist/esm/activities/generateAudio/index.js.map +1 -1
- package/dist/esm/activities/generateImage/adapter.js +22 -15
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.d.ts +4 -0
- package/dist/esm/activities/generateImage/index.js +155 -111
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateSpeech/adapter.js +22 -15
- package/dist/esm/activities/generateSpeech/adapter.js.map +1 -1
- package/dist/esm/activities/generateSpeech/index.d.ts +4 -0
- package/dist/esm/activities/generateSpeech/index.js +159 -110
- package/dist/esm/activities/generateSpeech/index.js.map +1 -1
- package/dist/esm/activities/generateTranscription/adapter.js +22 -15
- package/dist/esm/activities/generateTranscription/adapter.js.map +1 -1
- package/dist/esm/activities/generateTranscription/index.d.ts +4 -0
- package/dist/esm/activities/generateTranscription/index.js +159 -100
- package/dist/esm/activities/generateTranscription/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/adapter.js +36 -29
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.d.ts +143 -19
- package/dist/esm/activities/generateVideo/index.js +456 -279
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/snap.js +60 -48
- package/dist/esm/activities/generateVideo/snap.js.map +1 -1
- package/dist/esm/activities/index.js +8 -34
- package/dist/esm/activities/middleware/index.d.ts +1 -1
- package/dist/esm/activities/middleware/run.d.ts +10 -0
- package/dist/esm/activities/middleware/run.js +53 -29
- package/dist/esm/activities/middleware/run.js.map +1 -1
- package/dist/esm/activities/middleware/types.d.ts +44 -6
- package/dist/esm/activities/stream-generation-result.d.ts +4 -1
- package/dist/esm/activities/stream-generation-result.js +79 -44
- package/dist/esm/activities/stream-generation-result.js.map +1 -1
- package/dist/esm/activities/summarize/adapter.js +22 -15
- package/dist/esm/activities/summarize/adapter.js.map +1 -1
- package/dist/esm/activities/summarize/chat-stream-summarize.js +252 -202
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/activities/summarize/index.d.ts +27 -0
- package/dist/esm/activities/summarize/index.js +268 -102
- package/dist/esm/activities/summarize/index.js.map +1 -1
- package/dist/esm/adapter-internals.d.ts +2 -1
- package/dist/esm/adapter-internals.js +4 -11
- package/dist/esm/client.d.ts +25 -3
- package/dist/esm/client.js +131 -64
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/custom-events.d.ts +76 -0
- package/dist/esm/custom-events.js +37 -0
- package/dist/esm/custom-events.js.map +1 -0
- package/dist/esm/delivery-detach.d.ts +50 -0
- package/dist/esm/delivery-detach.js +71 -0
- package/dist/esm/delivery-detach.js.map +1 -0
- package/dist/esm/delivery-disconnect.d.ts +62 -0
- package/dist/esm/delivery-disconnect.js +81 -0
- package/dist/esm/delivery-disconnect.js.map +1 -0
- package/dist/esm/extend-adapter.js +19 -17
- package/dist/esm/extend-adapter.js.map +1 -1
- package/dist/esm/index.d.ts +23 -5
- package/dist/esm/index.js +30 -97
- package/dist/esm/interrupt-resume.d.ts +71 -0
- package/dist/esm/interrupt-resume.js +438 -0
- package/dist/esm/interrupt-resume.js.map +1 -0
- package/dist/esm/interrupt-serialization.d.ts +12 -0
- package/dist/esm/interrupt-serialization.js +178 -0
- package/dist/esm/interrupt-serialization.js.map +1 -0
- package/dist/esm/interrupts.d.ts +84 -0
- package/dist/esm/interrupts.js +31 -0
- package/dist/esm/interrupts.js.map +1 -0
- package/dist/esm/locks.d.ts +10 -0
- package/dist/esm/locks.js +2 -0
- package/dist/esm/logger/console-logger.js +101 -78
- package/dist/esm/logger/console-logger.js.map +1 -1
- package/dist/esm/logger/internal-logger.js +104 -89
- package/dist/esm/logger/internal-logger.js.map +1 -1
- package/dist/esm/logger/resolve.js +54 -49
- package/dist/esm/logger/resolve.js.map +1 -1
- package/dist/esm/logger/types.d.ts +1 -1
- package/dist/esm/middlewares/content-guard.js +142 -148
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/middlewares/index.js +2 -6
- package/dist/esm/middlewares/otel.js +598 -732
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/middlewares/usage-attributes.js +47 -40
- package/dist/esm/middlewares/usage-attributes.js.map +1 -1
- package/dist/esm/realtime/event-emitter.js +24 -25
- package/dist/esm/realtime/event-emitter.js.map +1 -1
- package/dist/esm/realtime/index.d.ts +5 -9
- package/dist/esm/realtime/index.js +29 -6
- package/dist/esm/realtime/index.js.map +1 -1
- package/dist/esm/scope.d.ts +47 -0
- package/dist/esm/stream-durability.d.ts +171 -0
- package/dist/esm/stream-durability.js +295 -0
- package/dist/esm/stream-durability.js.map +1 -0
- package/dist/esm/stream-to-response.d.ts +178 -13
- package/dist/esm/stream-to-response.js +663 -115
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js +30 -16
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/system-prompts.js +27 -21
- package/dist/esm/system-prompts.js.map +1 -1
- package/dist/esm/tool-registry.js +72 -45
- package/dist/esm/tool-registry.js.map +1 -1
- package/dist/esm/tools/provider-tool.js +14 -5
- package/dist/esm/tools/provider-tool.js.map +1 -1
- package/dist/esm/types.d.ts +332 -21
- package/dist/esm/types.js +2 -0
- package/dist/esm/utilities/ag-ui-wire.js +79 -93
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/chat-params.d.ts +26 -4
- package/dist/esm/utilities/chat-params.js +218 -92
- package/dist/esm/utilities/chat-params.js.map +1 -1
- package/dist/esm/utilities/errors.js +28 -18
- package/dist/esm/utilities/errors.js.map +1 -1
- package/dist/esm/utilities/media-prompt.js +46 -41
- package/dist/esm/utilities/media-prompt.js.map +1 -1
- package/dist/esm/utilities/numbers.js +13 -10
- package/dist/esm/utilities/numbers.js.map +1 -1
- package/dist/esm/utilities/provider-executed.js +20 -11
- package/dist/esm/utilities/provider-executed.js.map +1 -1
- package/dist/esm/utilities/sampling-keys.js +31 -19
- package/dist/esm/utilities/sampling-keys.js.map +1 -1
- package/dist/esm/utilities/tool-result.js +42 -30
- package/dist/esm/utilities/tool-result.js.map +1 -1
- package/dist/esm/utilities/usage.js +27 -9
- package/dist/esm/utilities/usage.js.map +1 -1
- package/dist/esm/utils.js +26 -18
- package/dist/esm/utils.js.map +1 -1
- package/package.json +10 -6
- package/skills/ai-core/SKILL.md +69 -18
- package/skills/ai-core/adapter-configuration/SKILL.md +44 -21
- package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +1 -3
- package/skills/ai-core/adapter-configuration/references/byteplus-adapter.md +148 -0
- package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +2 -6
- package/skills/ai-core/adapter-configuration/references/groq-adapter.md +2 -6
- package/skills/ai-core/adapter-configuration/references/openai-adapter.md +1 -3
- package/skills/ai-core/ag-ui-protocol/SKILL.md +1 -1
- package/skills/ai-core/chat-experience/SKILL.md +156 -11
- package/skills/ai-core/client-persistence/SKILL.md +277 -0
- package/skills/ai-core/custom-backend-integration/SKILL.md +1 -1
- package/skills/ai-core/debug-logging/SKILL.md +1 -1
- package/skills/ai-core/locks/SKILL.md +143 -0
- package/skills/ai-core/media-generation/SKILL.md +144 -12
- package/skills/ai-core/middleware/SKILL.md +258 -33
- package/skills/ai-core/structured-outputs/SKILL.md +1 -1
- package/skills/ai-core/tool-calling/SKILL.md +54 -59
- package/src/activities/chat/agent-loop-strategies.ts +10 -4
- package/src/activities/chat/cancel.ts +81 -0
- package/src/activities/chat/index.ts +1152 -153
- package/src/activities/chat/mcp/manager.ts +4 -4
- package/src/activities/chat/mcp/types.ts +2 -2
- package/src/activities/chat/messages.ts +5 -3
- package/src/activities/chat/middleware/builder.ts +1 -1
- package/src/activities/chat/middleware/compose.ts +186 -9
- package/src/activities/chat/middleware/index.ts +26 -0
- package/src/activities/chat/middleware/locks.ts +102 -0
- package/src/activities/chat/middleware/pending-turn.ts +47 -0
- package/src/activities/chat/middleware/run-disconnect.ts +62 -0
- package/src/activities/chat/middleware/run-store.ts +412 -0
- package/src/activities/chat/middleware/types.ts +62 -1
- package/src/activities/chat/stream/processor.ts +189 -5
- package/src/activities/chat/tools/approval-schema.ts +205 -0
- package/src/activities/chat/tools/tool-calls.ts +106 -13
- package/src/activities/chat/tools/tool-definition.ts +210 -39
- package/src/activities/generateAudio/index.ts +20 -3
- package/src/activities/generateImage/index.ts +20 -3
- package/src/activities/generateSpeech/index.ts +25 -3
- package/src/activities/generateTranscription/index.ts +26 -3
- package/src/activities/generateVideo/index.ts +345 -82
- package/src/activities/middleware/index.ts +2 -0
- package/src/activities/middleware/run.ts +31 -0
- package/src/activities/middleware/types.ts +49 -5
- package/src/activities/stream-generation-result.ts +30 -2
- package/src/activities/summarize/chat-stream-summarize.ts +5 -0
- package/src/activities/summarize/index.ts +200 -10
- package/src/adapter-internals.ts +10 -1
- package/src/client.ts +244 -0
- package/src/custom-events.ts +107 -0
- package/src/delivery-detach.ts +72 -0
- package/src/delivery-disconnect.ts +84 -0
- package/src/index.ts +138 -0
- package/src/interrupt-resume.ts +824 -0
- package/src/interrupt-serialization.ts +183 -0
- package/src/interrupts.ts +146 -0
- package/src/locks.ts +17 -0
- package/src/logger/types.ts +1 -1
- package/src/middlewares/otel.ts +1 -0
- package/src/realtime/index.ts +5 -9
- package/src/scope.ts +47 -0
- package/src/stream-durability.ts +598 -0
- package/src/stream-to-response.ts +1051 -95
- package/src/strip-to-spec-middleware.ts +3 -3
- package/src/types.ts +416 -24
- package/src/utilities/chat-params.ts +245 -55
- package/dist/esm/activities/index.js.map +0 -1
- package/dist/esm/adapter-internals.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/middlewares/index.js.map +0 -1
|
@@ -1,121 +1,165 @@
|
|
|
1
|
-
import { aiEventClient } from "@tanstack/ai-event-client";
|
|
2
|
-
import { streamGenerationResult } from "../stream-generation-result.js";
|
|
3
1
|
import { resolveDebugOption } from "../../logger/resolve.js";
|
|
4
|
-
import {
|
|
2
|
+
import { streamGenerationResult } from "../stream-generation-result.js";
|
|
3
|
+
import { applyGenerationResultTransforms, createGenerationContext, runGenerationError, runGenerationFinish, runGenerationStart, runGenerationUsage } from "../middleware/run.js";
|
|
5
4
|
import { resolveMediaPrompt } from "../../utilities/media-prompt.js";
|
|
6
|
-
|
|
5
|
+
import "./adapter.js";
|
|
6
|
+
import { aiEventClient } from "@tanstack/ai-event-client";
|
|
7
|
+
//#region src/activities/generateImage/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* Image Activity
|
|
10
|
+
*
|
|
11
|
+
* Generates images from text prompts.
|
|
12
|
+
* This is a self-contained module with implementation, types, and JSDoc.
|
|
13
|
+
*/
|
|
14
|
+
/** The adapter kind this activity handles */
|
|
15
|
+
var kind = "image";
|
|
7
16
|
function createId(prefix) {
|
|
8
|
-
|
|
17
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
9
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Image activity - generates images from text prompts.
|
|
21
|
+
*
|
|
22
|
+
* Uses AI image generation models to create images based on natural language descriptions.
|
|
23
|
+
*
|
|
24
|
+
* @example Generate a single image
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { generateImage } from '@tanstack/ai'
|
|
27
|
+
* import { openaiImage } from '@tanstack/ai-openai'
|
|
28
|
+
*
|
|
29
|
+
* const result = await generateImage({
|
|
30
|
+
* adapter: openaiImage('dall-e-3'),
|
|
31
|
+
* prompt: 'A serene mountain landscape at sunset'
|
|
32
|
+
* })
|
|
33
|
+
*
|
|
34
|
+
* console.log(result.images[0].url)
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example Generate multiple images
|
|
38
|
+
* ```ts
|
|
39
|
+
* const result = await generateImage({
|
|
40
|
+
* adapter: openaiImage('dall-e-2'),
|
|
41
|
+
* prompt: 'A cute robot mascot',
|
|
42
|
+
* numberOfImages: 4,
|
|
43
|
+
* size: '512x512'
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* result.images.forEach((image, i) => {
|
|
47
|
+
* console.log(`Image ${i + 1}: ${image.url}`)
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @example With provider-specific options
|
|
52
|
+
* ```ts
|
|
53
|
+
* const result = await generateImage({
|
|
54
|
+
* adapter: openaiImage('dall-e-3'),
|
|
55
|
+
* prompt: 'A professional headshot photo',
|
|
56
|
+
* size: '1024x1024',
|
|
57
|
+
* modelOptions: {
|
|
58
|
+
* quality: 'hd',
|
|
59
|
+
* style: 'natural'
|
|
60
|
+
* }
|
|
61
|
+
* })
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
10
64
|
function generateImage(options) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return runGenerateImage(options);
|
|
65
|
+
if (options.stream) return streamGenerationResult((resolved) => runGenerateImage({
|
|
66
|
+
...options,
|
|
67
|
+
runId: resolved.runId
|
|
68
|
+
}), options);
|
|
69
|
+
return runGenerateImage(options);
|
|
17
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Internal implementation of image generation (always non-streaming).
|
|
73
|
+
* Contains all devtools event emission logic.
|
|
74
|
+
*/
|
|
18
75
|
async function runGenerateImage(options) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
usage: result.usage
|
|
99
|
-
});
|
|
100
|
-
return result;
|
|
101
|
-
} catch (error) {
|
|
102
|
-
await runGenerationError(middleware, mwCtx, {
|
|
103
|
-
error,
|
|
104
|
-
duration: Date.now() - startTime
|
|
105
|
-
});
|
|
106
|
-
logger.errors("generateImage activity failed", {
|
|
107
|
-
error,
|
|
108
|
-
source: "generateImage"
|
|
109
|
-
});
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
76
|
+
const { adapter, stream: _stream, debug: _debug, middleware, threadId, runId, ...rest } = options;
|
|
77
|
+
const model = adapter.model;
|
|
78
|
+
const requestId = createId("image");
|
|
79
|
+
const startTime = Date.now();
|
|
80
|
+
const logger = resolveDebugOption(options.debug);
|
|
81
|
+
const mwCtx = createGenerationContext({
|
|
82
|
+
requestId,
|
|
83
|
+
activity: "image",
|
|
84
|
+
provider: adapter.name,
|
|
85
|
+
model,
|
|
86
|
+
modelOptions: rest.modelOptions,
|
|
87
|
+
threadId,
|
|
88
|
+
runId,
|
|
89
|
+
artifactInputs: { prompt: rest.prompt },
|
|
90
|
+
createId
|
|
91
|
+
});
|
|
92
|
+
await runGenerationStart(middleware, mwCtx);
|
|
93
|
+
const resolved = resolveMediaPrompt(rest.prompt);
|
|
94
|
+
aiEventClient.emit("image:request:started", {
|
|
95
|
+
requestId,
|
|
96
|
+
provider: adapter.name,
|
|
97
|
+
model,
|
|
98
|
+
prompt: resolved.text,
|
|
99
|
+
numberOfImages: rest.numberOfImages,
|
|
100
|
+
size: rest.size,
|
|
101
|
+
...resolved.images.length > 0 && { imageInputCount: resolved.images.length },
|
|
102
|
+
...resolved.videos.length > 0 && { videoInputCount: resolved.videos.length },
|
|
103
|
+
...resolved.audios.length > 0 && { audioInputCount: resolved.audios.length },
|
|
104
|
+
modelOptions: rest.modelOptions,
|
|
105
|
+
timestamp: startTime
|
|
106
|
+
});
|
|
107
|
+
logger.request(`activity=generateImage provider=${adapter.name}`, {
|
|
108
|
+
provider: adapter.name,
|
|
109
|
+
model
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
const result = await applyGenerationResultTransforms(mwCtx, await adapter.generateImages({
|
|
113
|
+
...rest,
|
|
114
|
+
model,
|
|
115
|
+
logger
|
|
116
|
+
}));
|
|
117
|
+
const duration = Date.now() - startTime;
|
|
118
|
+
aiEventClient.emit("image:request:completed", {
|
|
119
|
+
requestId,
|
|
120
|
+
provider: adapter.name,
|
|
121
|
+
model,
|
|
122
|
+
images: result.images.map((image) => ({
|
|
123
|
+
url: image.url,
|
|
124
|
+
b64Json: image.b64Json
|
|
125
|
+
})),
|
|
126
|
+
duration,
|
|
127
|
+
modelOptions: rest.modelOptions,
|
|
128
|
+
timestamp: Date.now()
|
|
129
|
+
});
|
|
130
|
+
if (result.usage) aiEventClient.emit("image:usage", {
|
|
131
|
+
requestId,
|
|
132
|
+
model,
|
|
133
|
+
usage: result.usage,
|
|
134
|
+
modelOptions: rest.modelOptions,
|
|
135
|
+
timestamp: Date.now()
|
|
136
|
+
});
|
|
137
|
+
logger.output(`activity=generateImage count=${result.images.length}`, { count: result.images.length });
|
|
138
|
+
if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage);
|
|
139
|
+
await runGenerationFinish(middleware, mwCtx, {
|
|
140
|
+
duration,
|
|
141
|
+
usage: result.usage
|
|
142
|
+
});
|
|
143
|
+
return result;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
await runGenerationError(middleware, mwCtx, {
|
|
146
|
+
error,
|
|
147
|
+
duration: Date.now() - startTime
|
|
148
|
+
});
|
|
149
|
+
logger.errors("generateImage activity failed", {
|
|
150
|
+
error,
|
|
151
|
+
source: "generateImage"
|
|
152
|
+
});
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
112
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Create typed options for the generateImage() function without executing.
|
|
158
|
+
*/
|
|
113
159
|
function createImageOptions(options) {
|
|
114
|
-
|
|
160
|
+
return options;
|
|
115
161
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
};
|
|
121
|
-
//# sourceMappingURL=index.js.map
|
|
162
|
+
//#endregion
|
|
163
|
+
export { createImageOptions, generateImage, kind };
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/activities/generateImage/index.ts"],"sourcesContent":["/**\n * Image Activity\n *\n * Generates images from text prompts.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { aiEventClient } from '@tanstack/ai-event-client'\nimport { streamGenerationResult } from '../stream-generation-result.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport {\n createGenerationContext,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport { resolveMediaPrompt } from '../../utilities/media-prompt'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { ImageAdapter } from './adapter'\nimport type {\n ImageGenerationResult,\n MediaPrompt,\n MediaPromptFor,\n StreamChunk,\n} from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'image' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract model-specific provider options from an ImageAdapter via ~types.\n * If the model has specific options defined in ModelProviderOptions (and not just via index signature),\n * use those; otherwise fall back to base provider options.\n */\nexport type ImageProviderOptionsForModel<TAdapter, TModel extends string> =\n TAdapter extends ImageAdapter<any, infer BaseOptions, infer ModelOptions, any>\n ? string extends keyof ModelOptions\n ? // ModelOptions is Record<string, unknown> or has index signature - use BaseOptions\n BaseOptions\n : // ModelOptions has explicit keys - check if TModel is one of them\n TModel extends keyof ModelOptions\n ? ModelOptions[TModel]\n : BaseOptions\n : object\n\n/**\n * Extract model-specific size options from an ImageAdapter via ~types.\n * If the model has specific sizes defined, use those; otherwise fall back to string.\n */\nexport type ImageSizeForModel<TAdapter, TModel extends string> =\n TAdapter extends ImageAdapter<any, any, any, infer SizeByName>\n ? string extends keyof SizeByName\n ? // SizeByName has index signature - fall back to string\n string\n : // SizeByName has explicit keys - check if TModel is one of them\n TModel extends keyof SizeByName\n ? SizeByName[TModel]\n : string\n : string\n\n/**\n * Extract the prompt type a model accepts from an ImageAdapter via ~types.\n * Adapters declare a per-model input-modality map; models in the map get a\n * `prompt` narrowed to text + their supported part types (text-only models\n * accept `string | Array<TextPart>`), so unsupported media parts fail at\n * compile time. Adapters without a map fall back to the full MediaPrompt.\n */\nexport type ImagePromptForModel<TAdapter, TModel extends string> =\n TAdapter extends ImageAdapter<any, any, any, any, infer ModsByName>\n ? string extends keyof ModsByName\n ? // No explicit map - accept the full union\n MediaPrompt\n : TModel extends keyof ModsByName\n ? MediaPromptFor<ModsByName[TModel][number]>\n : MediaPrompt\n : MediaPrompt\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the image activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The image adapter type\n * @template TStream - Whether to stream the output\n */\nexport type ImageActivityOptions<\n TAdapter extends ImageAdapter<string, any, any, any>,\n TStream extends boolean = false,\n> = {\n /** The image adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /**\n * Description of the desired image(s). Either a plain string, or — for\n * models that support image-conditioned generation — an ordered array of\n * content parts interleaving text with image inputs (image-to-image,\n * reference-guided, edit, multi-reference). Media parts may carry\n * `metadata.role` (`'reference' | 'mask' | 'control' | 'character'`) to\n * disambiguate intent. The accepted part types are narrowed per model via\n * the adapter's input-modality map.\n */\n prompt: ImagePromptForModel<TAdapter, TAdapter['model']>\n /** Number of images to generate (default: 1) */\n numberOfImages?: number\n /** Image size in WIDTHxHEIGHT format (e.g., \"1024x1024\") */\n size?: ImageSizeForModel<TAdapter, TAdapter['model']>\n /**\n * Whether to stream the image generation result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<ImageGenerationResult>.\n *\n * @default false\n */\n stream?: TStream\n /**\n * Enable debug logging. Pass `true` to enable all categories, `false` to\n * silence everything including errors, or a `DebugConfig` object for granular\n * control and/or a custom `Logger`.\n */\n debug?: DebugOption\n /**\n * Observe-only middleware notified on start, usage, success, and error. Pass\n * `otelMiddleware()` to emit OpenTelemetry spans, or implement the\n * `GenerationMiddleware` contract for a custom backend.\n */\n middleware?: Array<GenerationMiddleware>\n} & ({} extends ImageProviderOptionsForModel<TAdapter, TAdapter['model']>\n ? {\n /** Provider-specific options for image generation */ modelOptions?: ImageProviderOptionsForModel<\n TAdapter,\n TAdapter['model']\n >\n }\n : {\n /** Provider-specific options for image generation */ modelOptions: ImageProviderOptionsForModel<\n TAdapter,\n TAdapter['model']\n >\n })\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the image activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<ImageGenerationResult>\n */\nexport type ImageActivityResult<TStream extends boolean = false> =\n TStream extends true\n ? AsyncIterable<StreamChunk>\n : Promise<ImageGenerationResult>\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * Image activity - generates images from text prompts.\n *\n * Uses AI image generation models to create images based on natural language descriptions.\n *\n * @example Generate a single image\n * ```ts\n * import { generateImage } from '@tanstack/ai'\n * import { openaiImage } from '@tanstack/ai-openai'\n *\n * const result = await generateImage({\n * adapter: openaiImage('dall-e-3'),\n * prompt: 'A serene mountain landscape at sunset'\n * })\n *\n * console.log(result.images[0].url)\n * ```\n *\n * @example Generate multiple images\n * ```ts\n * const result = await generateImage({\n * adapter: openaiImage('dall-e-2'),\n * prompt: 'A cute robot mascot',\n * numberOfImages: 4,\n * size: '512x512'\n * })\n *\n * result.images.forEach((image, i) => {\n * console.log(`Image ${i + 1}: ${image.url}`)\n * })\n * ```\n *\n * @example With provider-specific options\n * ```ts\n * const result = await generateImage({\n * adapter: openaiImage('dall-e-3'),\n * prompt: 'A professional headshot photo',\n * size: '1024x1024',\n * modelOptions: {\n * quality: 'hd',\n * style: 'natural'\n * }\n * })\n * ```\n */\nexport function generateImage<\n TAdapter extends ImageAdapter<string, any, any, any>,\n TStream extends boolean = false,\n>(\n options: ImageActivityOptions<TAdapter, TStream>,\n): ImageActivityResult<TStream> {\n if (options.stream) {\n return streamGenerationResult(() =>\n runGenerateImage(options),\n ) as ImageActivityResult<TStream>\n }\n\n return runGenerateImage(options) as ImageActivityResult<TStream>\n}\n\n/**\n * Internal implementation of image generation (always non-streaming).\n * Contains all devtools event emission logic.\n */\nasync function runGenerateImage<\n TAdapter extends ImageAdapter<string, any, any, any>,\n>(\n options: ImageActivityOptions<TAdapter, boolean>,\n): Promise<ImageGenerationResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n ...rest\n } = options\n const model = adapter.model\n const requestId = createId('image')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\n\n const mwCtx = createGenerationContext({\n requestId,\n activity: 'image',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n // Devtools events carry the flattened prompt text plus media-part counts —\n // the wire payload stays `prompt: string` regardless of the prompt shape.\n const resolved = resolveMediaPrompt(rest.prompt)\n\n aiEventClient.emit('image:request:started', {\n requestId,\n provider: adapter.name,\n model,\n prompt: resolved.text,\n numberOfImages: rest.numberOfImages,\n size: rest.size,\n ...(resolved.images.length > 0 && {\n imageInputCount: resolved.images.length,\n }),\n ...(resolved.videos.length > 0 && {\n videoInputCount: resolved.videos.length,\n }),\n ...(resolved.audios.length > 0 && {\n audioInputCount: resolved.audios.length,\n }),\n modelOptions: rest.modelOptions,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateImage provider=${adapter.name}`, {\n provider: adapter.name,\n model,\n })\n\n try {\n const result = await adapter.generateImages({ ...rest, model, logger })\n const duration = Date.now() - startTime\n\n aiEventClient.emit('image:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n // GeneratedImage is a discriminated `{ url } | { b64Json }` union, but the\n // wire shape on the devtools event is a plain optional pair. Use\n // conditional spreads so the emitted record only sets the field actually\n // present — `exactOptionalPropertyTypes` rejects `field: undefined`\n // against `field?: string` targets.\n images: result.images.map((image) => ({\n url: image.url,\n b64Json: image.b64Json,\n })),\n duration,\n modelOptions: rest.modelOptions,\n timestamp: Date.now(),\n })\n\n if (result.usage) {\n aiEventClient.emit('image:usage', {\n requestId,\n model,\n usage: result.usage,\n modelOptions: rest.modelOptions,\n timestamp: Date.now(),\n })\n }\n\n logger.output(`activity=generateImage count=${result.images.length}`, {\n count: result.images.length,\n })\n\n if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage)\n await runGenerationFinish(middleware, mwCtx, {\n duration,\n usage: result.usage,\n })\n\n return result\n } catch (error) {\n await runGenerationError(middleware, mwCtx, {\n error,\n duration: Date.now() - startTime,\n })\n logger.errors('generateImage activity failed', {\n error,\n source: 'generateImage',\n })\n throw error\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateImage() function without executing.\n */\nexport function createImageOptions<\n TAdapter extends ImageAdapter<string, any, any, any>,\n TStream extends boolean = false,\n>(\n options: ImageActivityOptions<TAdapter, TStream>,\n): ImageActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n ImageAdapter,\n ImageAdapterConfig,\n AnyImageAdapter,\n} from './adapter'\nexport { BaseImageAdapter } from './adapter'\n"],"names":[],"mappings":";;;;;AAkCO,MAAM,OAAO;AAqIpB,SAAS,SAAS,QAAwB;AACxC,SAAO,GAAG,MAAM,IAAI,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC1E;AAmDO,SAAS,cAId,SAC8B;AAC9B,MAAI,QAAQ,QAAQ;AAClB,WAAO;AAAA,MAAuB,MAC5B,iBAAiB,OAAO;AAAA,IAAA;AAAA,EAE5B;AAEA,SAAO,iBAAiB,OAAO;AACjC;AAMA,eAAe,iBAGb,SACgC;AAChC,QAAM;AAAA,IACJ;AAAA,IACA,QAAQ;AAAA,IACR,OAAO;AAAA,IACP;AAAA,IACA,GAAG;AAAA,EAAA,IACD;AACJ,QAAM,QAAQ,QAAQ;AACtB,QAAM,YAAY,SAAS,OAAO;AAClC,QAAM,YAAY,KAAK,IAAA;AACvB,QAAM,SAAyB,mBAAmB,QAAQ,KAAK;AAE/D,QAAM,QAAQ,wBAAwB;AAAA,IACpC;AAAA,IACA,UAAU;AAAA,IACV,UAAU,QAAQ;AAAA,IAClB;AAAA,IACA,cAAc,KAAK;AAAA,IACnB;AAAA,EAAA,CACD;AAED,QAAM,mBAAmB,YAAY,KAAK;AAI1C,QAAM,WAAW,mBAAmB,KAAK,MAAM;AAE/C,gBAAc,KAAK,yBAAyB;AAAA,IAC1C;AAAA,IACA,UAAU,QAAQ;AAAA,IAClB;AAAA,IACA,QAAQ,SAAS;AAAA,IACjB,gBAAgB,KAAK;AAAA,IACrB,MAAM,KAAK;AAAA,IACX,GAAI,SAAS,OAAO,SAAS,KAAK;AAAA,MAChC,iBAAiB,SAAS,OAAO;AAAA,IAAA;AAAA,IAEnC,GAAI,SAAS,OAAO,SAAS,KAAK;AAAA,MAChC,iBAAiB,SAAS,OAAO;AAAA,IAAA;AAAA,IAEnC,GAAI,SAAS,OAAO,SAAS,KAAK;AAAA,MAChC,iBAAiB,SAAS,OAAO;AAAA,IAAA;AAAA,IAEnC,cAAc,KAAK;AAAA,IACnB,WAAW;AAAA,EAAA,CACZ;AAED,SAAO,QAAQ,mCAAmC,QAAQ,IAAI,IAAI;AAAA,IAChE,UAAU,QAAQ;AAAA,IAClB;AAAA,EAAA,CACD;AAED,MAAI;AACF,UAAM,SAAS,MAAM,QAAQ,eAAe,EAAE,GAAG,MAAM,OAAO,QAAQ;AACtE,UAAM,WAAW,KAAK,IAAA,IAAQ;AAE9B,kBAAc,KAAK,2BAA2B;AAAA,MAC5C;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,QAAQ,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,QACpC,KAAK,MAAM;AAAA,QACX,SAAS,MAAM;AAAA,MAAA,EACf;AAAA,MACF;AAAA,MACA,cAAc,KAAK;AAAA,MACnB,WAAW,KAAK,IAAA;AAAA,IAAI,CACrB;AAED,QAAI,OAAO,OAAO;AAChB,oBAAc,KAAK,eAAe;AAAA,QAChC;AAAA,QACA;AAAA,QACA,OAAO,OAAO;AAAA,QACd,cAAc,KAAK;AAAA,QACnB,WAAW,KAAK,IAAA;AAAA,MAAI,CACrB;AAAA,IACH;AAEA,WAAO,OAAO,gCAAgC,OAAO,OAAO,MAAM,IAAI;AAAA,MACpE,OAAO,OAAO,OAAO;AAAA,IAAA,CACtB;AAED,QAAI,OAAO,MAAO,OAAM,mBAAmB,YAAY,OAAO,OAAO,KAAK;AAC1E,UAAM,oBAAoB,YAAY,OAAO;AAAA,MAC3C;AAAA,MACA,OAAO,OAAO;AAAA,IAAA,CACf;AAED,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,mBAAmB,YAAY,OAAO;AAAA,MAC1C;AAAA,MACA,UAAU,KAAK,QAAQ;AAAA,IAAA,CACxB;AACD,WAAO,OAAO,iCAAiC;AAAA,MAC7C;AAAA,MACA,QAAQ;AAAA,IAAA,CACT;AACD,UAAM;AAAA,EACR;AACF;AASO,SAAS,mBAId,SACyC;AACzC,SAAO;AACT;"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/activities/generateImage/index.ts"],"sourcesContent":["/**\n * Image Activity\n *\n * Generates images from text prompts.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { aiEventClient } from '@tanstack/ai-event-client'\nimport { streamGenerationResult } from '../stream-generation-result.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport {\n applyGenerationResultTransforms,\n createGenerationContext,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport { resolveMediaPrompt } from '../../utilities/media-prompt'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { ImageAdapter } from './adapter'\nimport type {\n ImageGenerationResult,\n MediaPrompt,\n MediaPromptFor,\n StreamChunk,\n} from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'image' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract model-specific provider options from an ImageAdapter via ~types.\n * If the model has specific options defined in ModelProviderOptions (and not just via index signature),\n * use those; otherwise fall back to base provider options.\n */\nexport type ImageProviderOptionsForModel<TAdapter, TModel extends string> =\n TAdapter extends ImageAdapter<any, infer BaseOptions, infer ModelOptions, any>\n ? string extends keyof ModelOptions\n ? // ModelOptions is Record<string, unknown> or has index signature - use BaseOptions\n BaseOptions\n : // ModelOptions has explicit keys - check if TModel is one of them\n TModel extends keyof ModelOptions\n ? ModelOptions[TModel]\n : BaseOptions\n : object\n\n/**\n * Extract model-specific size options from an ImageAdapter via ~types.\n * If the model has specific sizes defined, use those; otherwise fall back to string.\n */\nexport type ImageSizeForModel<TAdapter, TModel extends string> =\n TAdapter extends ImageAdapter<any, any, any, infer SizeByName>\n ? string extends keyof SizeByName\n ? // SizeByName has index signature - fall back to string\n string\n : // SizeByName has explicit keys - check if TModel is one of them\n TModel extends keyof SizeByName\n ? SizeByName[TModel]\n : string\n : string\n\n/**\n * Extract the prompt type a model accepts from an ImageAdapter via ~types.\n * Adapters declare a per-model input-modality map; models in the map get a\n * `prompt` narrowed to text + their supported part types (text-only models\n * accept `string | Array<TextPart>`), so unsupported media parts fail at\n * compile time. Adapters without a map fall back to the full MediaPrompt.\n */\nexport type ImagePromptForModel<TAdapter, TModel extends string> =\n TAdapter extends ImageAdapter<any, any, any, any, infer ModsByName>\n ? string extends keyof ModsByName\n ? // No explicit map - accept the full union\n MediaPrompt\n : TModel extends keyof ModsByName\n ? MediaPromptFor<ModsByName[TModel][number]>\n : MediaPrompt\n : MediaPrompt\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the image activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The image adapter type\n * @template TStream - Whether to stream the output\n */\nexport type ImageActivityOptions<\n TAdapter extends ImageAdapter<string, any, any, any>,\n TStream extends boolean = false,\n> = {\n /** The image adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /**\n * Description of the desired image(s). Either a plain string, or — for\n * models that support image-conditioned generation — an ordered array of\n * content parts interleaving text with image inputs (image-to-image,\n * reference-guided, edit, multi-reference). Media parts may carry\n * `metadata.role` (`'reference' | 'mask' | 'control' | 'character'`) to\n * disambiguate intent. The accepted part types are narrowed per model via\n * the adapter's input-modality map.\n */\n prompt: ImagePromptForModel<TAdapter, TAdapter['model']>\n /** Number of images to generate (default: 1) */\n numberOfImages?: number\n /** Image size in WIDTHxHEIGHT format (e.g., \"1024x1024\") */\n size?: ImageSizeForModel<TAdapter, TAdapter['model']>\n /**\n * Whether to stream the image generation result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<ImageGenerationResult>.\n *\n * @default false\n */\n stream?: TStream\n /**\n * Enable debug logging. Pass `true` to enable all categories, `false` to\n * silence everything including errors, or a `DebugConfig` object for granular\n * control and/or a custom `Logger`.\n */\n debug?: DebugOption\n /**\n * Observe-only middleware notified on start, usage, success, and error. Pass\n * `otelMiddleware()` to emit OpenTelemetry spans, or implement the\n * `GenerationMiddleware` contract for a custom backend.\n */\n middleware?: Array<GenerationMiddleware>\n /** Stable conversation/thread id for correlating this run when persisted. */\n threadId?: string\n /** Stable run id for correlating this run when persisted. */\n runId?: string\n} & ({} extends ImageProviderOptionsForModel<TAdapter, TAdapter['model']>\n ? {\n /** Provider-specific options for image generation */ modelOptions?: ImageProviderOptionsForModel<\n TAdapter,\n TAdapter['model']\n >\n }\n : {\n /** Provider-specific options for image generation */ modelOptions: ImageProviderOptionsForModel<\n TAdapter,\n TAdapter['model']\n >\n })\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the image activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<ImageGenerationResult>\n */\nexport type ImageActivityResult<TStream extends boolean = false> =\n TStream extends true\n ? AsyncIterable<StreamChunk>\n : Promise<ImageGenerationResult>\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * Image activity - generates images from text prompts.\n *\n * Uses AI image generation models to create images based on natural language descriptions.\n *\n * @example Generate a single image\n * ```ts\n * import { generateImage } from '@tanstack/ai'\n * import { openaiImage } from '@tanstack/ai-openai'\n *\n * const result = await generateImage({\n * adapter: openaiImage('dall-e-3'),\n * prompt: 'A serene mountain landscape at sunset'\n * })\n *\n * console.log(result.images[0].url)\n * ```\n *\n * @example Generate multiple images\n * ```ts\n * const result = await generateImage({\n * adapter: openaiImage('dall-e-2'),\n * prompt: 'A cute robot mascot',\n * numberOfImages: 4,\n * size: '512x512'\n * })\n *\n * result.images.forEach((image, i) => {\n * console.log(`Image ${i + 1}: ${image.url}`)\n * })\n * ```\n *\n * @example With provider-specific options\n * ```ts\n * const result = await generateImage({\n * adapter: openaiImage('dall-e-3'),\n * prompt: 'A professional headshot photo',\n * size: '1024x1024',\n * modelOptions: {\n * quality: 'hd',\n * style: 'natural'\n * }\n * })\n * ```\n */\nexport function generateImage<\n TAdapter extends ImageAdapter<string, any, any, any>,\n TStream extends boolean = false,\n>(\n options: ImageActivityOptions<TAdapter, TStream>,\n): ImageActivityResult<TStream> {\n if (options.stream) {\n return streamGenerationResult(\n // Only `runId` is taken from the resolved wire identity. `threadId` stays\n // the CALLER's: `streamGenerationResult` mints one for the RUN_* chunks\n // when none was passed, and spreading that over the options would hand\n // middleware a thread id known to nobody, which persistence would then\n // file the run under. Matches `generateVideo`.\n (resolved) => runGenerateImage({ ...options, runId: resolved.runId }),\n options,\n ) as ImageActivityResult<TStream>\n }\n\n return runGenerateImage(options) as ImageActivityResult<TStream>\n}\n\n/**\n * Internal implementation of image generation (always non-streaming).\n * Contains all devtools event emission logic.\n */\nasync function runGenerateImage<\n TAdapter extends ImageAdapter<string, any, any, any>,\n>(\n options: ImageActivityOptions<TAdapter, boolean>,\n): Promise<ImageGenerationResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n threadId,\n runId,\n ...rest\n } = options\n const model = adapter.model\n const requestId = createId('image')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\n\n const mwCtx = createGenerationContext({\n requestId,\n activity: 'image',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n threadId,\n runId,\n artifactInputs: { prompt: rest.prompt },\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n // Devtools events carry the flattened prompt text plus media-part counts —\n // the wire payload stays `prompt: string` regardless of the prompt shape.\n const resolved = resolveMediaPrompt(rest.prompt)\n\n aiEventClient.emit('image:request:started', {\n requestId,\n provider: adapter.name,\n model,\n prompt: resolved.text,\n numberOfImages: rest.numberOfImages,\n size: rest.size,\n ...(resolved.images.length > 0 && {\n imageInputCount: resolved.images.length,\n }),\n ...(resolved.videos.length > 0 && {\n videoInputCount: resolved.videos.length,\n }),\n ...(resolved.audios.length > 0 && {\n audioInputCount: resolved.audios.length,\n }),\n modelOptions: rest.modelOptions,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateImage provider=${adapter.name}`, {\n provider: adapter.name,\n model,\n })\n\n try {\n const rawResult = await adapter.generateImages({ ...rest, model, logger })\n const result = await applyGenerationResultTransforms(mwCtx, rawResult)\n const duration = Date.now() - startTime\n\n aiEventClient.emit('image:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n // GeneratedImage is a discriminated `{ url } | { b64Json }` union, but the\n // wire shape on the devtools event is a plain optional pair. Use\n // conditional spreads so the emitted record only sets the field actually\n // present — `exactOptionalPropertyTypes` rejects `field: undefined`\n // against `field?: string` targets.\n images: result.images.map((image) => ({\n url: image.url,\n b64Json: image.b64Json,\n })),\n duration,\n modelOptions: rest.modelOptions,\n timestamp: Date.now(),\n })\n\n if (result.usage) {\n aiEventClient.emit('image:usage', {\n requestId,\n model,\n usage: result.usage,\n modelOptions: rest.modelOptions,\n timestamp: Date.now(),\n })\n }\n\n logger.output(`activity=generateImage count=${result.images.length}`, {\n count: result.images.length,\n })\n\n if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage)\n await runGenerationFinish(middleware, mwCtx, {\n duration,\n usage: result.usage,\n })\n\n return result\n } catch (error) {\n await runGenerationError(middleware, mwCtx, {\n error,\n duration: Date.now() - startTime,\n })\n logger.errors('generateImage activity failed', {\n error,\n source: 'generateImage',\n })\n throw error\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateImage() function without executing.\n */\nexport function createImageOptions<\n TAdapter extends ImageAdapter<string, any, any, any>,\n TStream extends boolean = false,\n>(\n options: ImageActivityOptions<TAdapter, TStream>,\n): ImageActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n ImageAdapter,\n ImageAdapterConfig,\n AnyImageAdapter,\n} from './adapter'\nexport { BaseImageAdapter } from './adapter'\n"],"mappings":";;;;;;;;;;;;;;AAmCA,IAAa,OAAO;AAyIpB,SAAS,SAAS,QAAwB;CACxC,OAAO,GAAG,OAAO,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;AACzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,SAAgB,cAId,SAC8B;CAC9B,IAAI,QAAQ,QACV,OAAO,wBAMJ,aAAa,iBAAiB;EAAE,GAAG;EAAS,OAAO,SAAS;CAAM,CAAC,GACpE,OACF;CAGF,OAAO,iBAAiB,OAAO;AACjC;;;;;AAMA,eAAe,iBAGb,SACgC;CAChC,MAAM,EACJ,SACA,QAAQ,SACR,OAAO,QACP,YACA,UACA,OACA,GAAG,SACD;CACJ,MAAM,QAAQ,QAAQ;CACtB,MAAM,YAAY,SAAS,OAAO;CAClC,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,SAAyB,mBAAmB,QAAQ,KAAK;CAE/D,MAAM,QAAQ,wBAAwB;EACpC;EACA,UAAU;EACV,UAAU,QAAQ;EAClB;EACA,cAAc,KAAK;EACnB;EACA;EACA,gBAAgB,EAAE,QAAQ,KAAK,OAAO;EACtC;CACF,CAAC;CAED,MAAM,mBAAmB,YAAY,KAAK;CAI1C,MAAM,WAAW,mBAAmB,KAAK,MAAM;CAE/C,cAAc,KAAK,yBAAyB;EAC1C;EACA,UAAU,QAAQ;EAClB;EACA,QAAQ,SAAS;EACjB,gBAAgB,KAAK;EACrB,MAAM,KAAK;EACX,GAAI,SAAS,OAAO,SAAS,KAAK,EAChC,iBAAiB,SAAS,OAAO,OACnC;EACA,GAAI,SAAS,OAAO,SAAS,KAAK,EAChC,iBAAiB,SAAS,OAAO,OACnC;EACA,GAAI,SAAS,OAAO,SAAS,KAAK,EAChC,iBAAiB,SAAS,OAAO,OACnC;EACA,cAAc,KAAK;EACnB,WAAW;CACb,CAAC;CAED,OAAO,QAAQ,mCAAmC,QAAQ,QAAQ;EAChE,UAAU,QAAQ;EAClB;CACF,CAAC;CAED,IAAI;EAEF,MAAM,SAAS,MAAM,gCAAgC,OAAO,MADpC,QAAQ,eAAe;GAAE,GAAG;GAAM;GAAO;EAAO,CAAC,CACJ;EACrE,MAAM,WAAW,KAAK,IAAI,IAAI;EAE9B,cAAc,KAAK,2BAA2B;GAC5C;GACA,UAAU,QAAQ;GAClB;GAMA,QAAQ,OAAO,OAAO,KAAK,WAAW;IACpC,KAAK,MAAM;IACX,SAAS,MAAM;GACjB,EAAE;GACF;GACA,cAAc,KAAK;GACnB,WAAW,KAAK,IAAI;EACtB,CAAC;EAED,IAAI,OAAO,OACT,cAAc,KAAK,eAAe;GAChC;GACA;GACA,OAAO,OAAO;GACd,cAAc,KAAK;GACnB,WAAW,KAAK,IAAI;EACtB,CAAC;EAGH,OAAO,OAAO,gCAAgC,OAAO,OAAO,UAAU,EACpE,OAAO,OAAO,OAAO,OACvB,CAAC;EAED,IAAI,OAAO,OAAO,MAAM,mBAAmB,YAAY,OAAO,OAAO,KAAK;EAC1E,MAAM,oBAAoB,YAAY,OAAO;GAC3C;GACA,OAAO,OAAO;EAChB,CAAC;EAED,OAAO;CACT,SAAS,OAAO;EACd,MAAM,mBAAmB,YAAY,OAAO;GAC1C;GACA,UAAU,KAAK,IAAI,IAAI;EACzB,CAAC;EACD,OAAO,OAAO,iCAAiC;GAC7C;GACA,QAAQ;EACV,CAAC;EACD,MAAM;CACR;AACF;;;;AASA,SAAgB,mBAId,SACyC;CACzC,OAAO;AACT"}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
//#region src/activities/generateSpeech/adapter.ts
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for text-to-speech adapters.
|
|
4
|
+
* Extend this class to implement a TTS adapter for a specific provider.
|
|
5
|
+
*
|
|
6
|
+
* Generic parameters match TTSAdapter - all pre-resolved by the provider function.
|
|
7
|
+
*/
|
|
8
|
+
var BaseTTSAdapter = class {
|
|
9
|
+
kind = "tts";
|
|
10
|
+
model;
|
|
11
|
+
config;
|
|
12
|
+
constructor(model, config = {}) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
this.model = model;
|
|
15
|
+
}
|
|
16
|
+
generateId() {
|
|
17
|
+
return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
18
|
+
}
|
|
15
19
|
};
|
|
16
|
-
//#
|
|
20
|
+
//#endregion
|
|
21
|
+
export { BaseTTSAdapter };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sources":["../../../../src/activities/generateSpeech/adapter.ts"],"sourcesContent":["import type { TTSOptions, TTSResult } from '../../types'\n\n/**\n * Configuration for TTS adapter instances\n */\nexport interface TTSAdapterConfig {\n apiKey?: string\n baseUrl?: string\n timeout?: number\n maxRetries?: number\n headers?: Record<string, string>\n}\n\n/**\n * TTS adapter interface with pre-resolved generics.\n *\n * An adapter is created by a provider function: `provider('model')` → `adapter`\n * All type resolution happens at the provider call site, not in this interface.\n *\n * Generic parameters:\n * - TModel: The specific model name (e.g., 'tts-1')\n * - TProviderOptions: Provider-specific options (already resolved)\n */\nexport interface TTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> {\n /** Discriminator for adapter kind - used to determine API shape */\n readonly kind: 'tts'\n /** Adapter name identifier */\n readonly name: string\n /** The model this adapter is configured for */\n readonly model: TModel\n\n /**\n * @internal Type-only properties for inference. Not assigned at runtime.\n */\n '~types': {\n providerOptions: TProviderOptions\n }\n\n /**\n * Generate speech from text\n */\n generateSpeech: (options: TTSOptions<TProviderOptions>) => Promise<TTSResult>\n}\n\n/**\n * A TTSAdapter with any/unknown type parameters.\n * Useful as a constraint in generic functions and interfaces.\n */\nexport type AnyTTSAdapter = TTSAdapter<any, any>\n\n/**\n * Abstract base class for text-to-speech adapters.\n * Extend this class to implement a TTS adapter for a specific provider.\n *\n * Generic parameters match TTSAdapter - all pre-resolved by the provider function.\n */\nexport abstract class BaseTTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> implements TTSAdapter<TModel, TProviderOptions> {\n readonly kind = 'tts' as const\n abstract readonly name: string\n readonly model: TModel\n\n // Type-only property - never assigned at runtime\n declare '~types': {\n providerOptions: TProviderOptions\n }\n\n protected config: TTSAdapterConfig\n\n constructor(model: TModel, config: TTSAdapterConfig = {}) {\n this.config = config\n this.model = model\n }\n\n abstract generateSpeech(\n options: TTSOptions<TProviderOptions>,\n ): Promise<TTSResult>\n\n protected generateId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n}\n"],"
|
|
1
|
+
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../src/activities/generateSpeech/adapter.ts"],"sourcesContent":["import type { TTSOptions, TTSResult } from '../../types'\n\n/**\n * Configuration for TTS adapter instances\n */\nexport interface TTSAdapterConfig {\n apiKey?: string\n baseUrl?: string\n timeout?: number\n maxRetries?: number\n headers?: Record<string, string>\n}\n\n/**\n * TTS adapter interface with pre-resolved generics.\n *\n * An adapter is created by a provider function: `provider('model')` → `adapter`\n * All type resolution happens at the provider call site, not in this interface.\n *\n * Generic parameters:\n * - TModel: The specific model name (e.g., 'tts-1')\n * - TProviderOptions: Provider-specific options (already resolved)\n */\nexport interface TTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> {\n /** Discriminator for adapter kind - used to determine API shape */\n readonly kind: 'tts'\n /** Adapter name identifier */\n readonly name: string\n /** The model this adapter is configured for */\n readonly model: TModel\n\n /**\n * @internal Type-only properties for inference. Not assigned at runtime.\n */\n '~types': {\n providerOptions: TProviderOptions\n }\n\n /**\n * Generate speech from text\n */\n generateSpeech: (options: TTSOptions<TProviderOptions>) => Promise<TTSResult>\n}\n\n/**\n * A TTSAdapter with any/unknown type parameters.\n * Useful as a constraint in generic functions and interfaces.\n */\nexport type AnyTTSAdapter = TTSAdapter<any, any>\n\n/**\n * Abstract base class for text-to-speech adapters.\n * Extend this class to implement a TTS adapter for a specific provider.\n *\n * Generic parameters match TTSAdapter - all pre-resolved by the provider function.\n */\nexport abstract class BaseTTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> implements TTSAdapter<TModel, TProviderOptions> {\n readonly kind = 'tts' as const\n abstract readonly name: string\n readonly model: TModel\n\n // Type-only property - never assigned at runtime\n declare '~types': {\n providerOptions: TProviderOptions\n }\n\n protected config: TTSAdapterConfig\n\n constructor(model: TModel, config: TTSAdapterConfig = {}) {\n this.config = config\n this.model = model\n }\n\n abstract generateSpeech(\n options: TTSOptions<TProviderOptions>,\n ): Promise<TTSResult>\n\n protected generateId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n}\n"],"mappings":";;;;;;;AA2DA,IAAsB,iBAAtB,MAGkD;CAChD,OAAgB;CAEhB;CAOA;CAEA,YAAY,OAAe,SAA2B,CAAC,GAAG;EACxD,KAAK,SAAS;EACd,KAAK,QAAQ;CACf;CAMA,aAA+B;EAC7B,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;CAC7E;AACF"}
|
|
@@ -50,6 +50,10 @@ export interface TTSActivityOptions<TAdapter extends TTSAdapter<string, TTSProvi
|
|
|
50
50
|
* `GenerationMiddleware` contract for a custom backend.
|
|
51
51
|
*/
|
|
52
52
|
middleware?: Array<GenerationMiddleware>;
|
|
53
|
+
/** Stable conversation/thread id for correlating this run when persisted. */
|
|
54
|
+
threadId?: string;
|
|
55
|
+
/** Stable run id for correlating this run when persisted. */
|
|
56
|
+
runId?: string;
|
|
53
57
|
}
|
|
54
58
|
/**
|
|
55
59
|
* Result type for the TTS activity.
|