@temporalio/ai-sdk 1.17.2 → 1.18.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/lib/activities.d.ts +10 -0
- package/lib/activities.js +167 -0
- package/lib/activities.js.map +1 -1
- package/lib/mcp.js.map +1 -1
- package/lib/provider.d.ts +27 -4
- package/lib/provider.js +54 -2
- package/lib/provider.js.map +1 -1
- package/package.json +13 -11
- package/src/activities.ts +131 -0
- package/src/mcp.ts +1 -1
- package/src/provider.ts +82 -5
package/lib/activities.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LanguageModelV3CallOptions, LanguageModelV3GenerateResult, EmbeddingModelV3Result, SharedV3ProviderOptions, SharedV3Headers, ProviderV3 } from '@ai-sdk/provider';
|
|
2
2
|
import { type Schema, type ToolExecutionOptions } from 'ai';
|
|
3
|
+
import type { Duration } from '@temporalio/common/lib/time';
|
|
3
4
|
import type { McpClientFactories } from './mcp';
|
|
4
5
|
/**
|
|
5
6
|
* Arguments for invoking a language model activity.
|
|
@@ -8,6 +9,15 @@ export interface InvokeModelArgs {
|
|
|
8
9
|
modelId: string;
|
|
9
10
|
options: LanguageModelV3CallOptions;
|
|
10
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Arguments for invoking a streaming language model activity.
|
|
14
|
+
*/
|
|
15
|
+
export interface InvokeModelStreamingArgs extends InvokeModelArgs {
|
|
16
|
+
modelId: string;
|
|
17
|
+
options: LanguageModelV3CallOptions;
|
|
18
|
+
streamingTopic: string;
|
|
19
|
+
streamingBatchInterval?: Duration;
|
|
20
|
+
}
|
|
11
21
|
/**
|
|
12
22
|
* Result from a language model invocation.
|
|
13
23
|
* This is an alias to the AI SDK's LanguageModelV3GenerateResult for type safety.
|
package/lib/activities.js
CHANGED
|
@@ -1,8 +1,63 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
3
|
+
if (value !== null && value !== void 0) {
|
|
4
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
5
|
+
var dispose, inner;
|
|
6
|
+
if (async) {
|
|
7
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
8
|
+
dispose = value[Symbol.asyncDispose];
|
|
9
|
+
}
|
|
10
|
+
if (dispose === void 0) {
|
|
11
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
12
|
+
dispose = value[Symbol.dispose];
|
|
13
|
+
if (async) inner = dispose;
|
|
14
|
+
}
|
|
15
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
16
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
17
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
18
|
+
}
|
|
19
|
+
else if (async) {
|
|
20
|
+
env.stack.push({ async: true });
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
};
|
|
24
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
25
|
+
return function (env) {
|
|
26
|
+
function fail(e) {
|
|
27
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
28
|
+
env.hasError = true;
|
|
29
|
+
}
|
|
30
|
+
var r, s = 0;
|
|
31
|
+
function next() {
|
|
32
|
+
while (r = env.stack.pop()) {
|
|
33
|
+
try {
|
|
34
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
35
|
+
if (r.dispose) {
|
|
36
|
+
var result = r.dispose.call(r.value);
|
|
37
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
38
|
+
}
|
|
39
|
+
else s |= 1;
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
fail(e);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
46
|
+
if (env.hasError) throw env.error;
|
|
47
|
+
}
|
|
48
|
+
return next();
|
|
49
|
+
};
|
|
50
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
51
|
+
var e = new Error(message);
|
|
52
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
53
|
+
});
|
|
2
54
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
55
|
exports.createActivities = createActivities;
|
|
4
56
|
const ai_1 = require("ai");
|
|
5
57
|
const common_1 = require("@temporalio/common");
|
|
58
|
+
const activity_1 = require("@temporalio/activity");
|
|
59
|
+
const client_1 = require("@temporalio/workflow-streams/client");
|
|
60
|
+
const encoder = new TextEncoder();
|
|
6
61
|
/**
|
|
7
62
|
* Creates Temporal activities for AI model invocation using the provided AI SDK provider.
|
|
8
63
|
* These activities allow workflows to call AI models while maintaining Temporal's
|
|
@@ -20,6 +75,118 @@ function createActivities(provider, mcpClientFactories) {
|
|
|
20
75
|
const model = provider.languageModel(args.modelId);
|
|
21
76
|
return await model.doGenerate(args.options);
|
|
22
77
|
},
|
|
78
|
+
/**
|
|
79
|
+
* Streaming-aware model activity.
|
|
80
|
+
*
|
|
81
|
+
* Calls `model.doStream()`, publishes each yielded AI SDK stream part
|
|
82
|
+
* as JSON to the stream side channel, and returns the assembled
|
|
83
|
+
* `LanguageModelV3GenerateResult`. Consumers receive native AI SDK
|
|
84
|
+
* stream-part types (text-delta, reasoning-delta, tool-input-delta,
|
|
85
|
+
* response-metadata, finish, ...); no normalization happens here.
|
|
86
|
+
*/
|
|
87
|
+
async invokeModelStreaming(args) {
|
|
88
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
89
|
+
try {
|
|
90
|
+
const stream = __addDisposableResource(env_1, client_1.WorkflowStreamClient.fromWithinActivity({
|
|
91
|
+
batchInterval: args.streamingBatchInterval ?? '100 milliseconds',
|
|
92
|
+
}), true);
|
|
93
|
+
const events = stream.topic(args.streamingTopic);
|
|
94
|
+
const model = provider.languageModel(args.modelId);
|
|
95
|
+
const streamResult = await model.doStream(args.options);
|
|
96
|
+
const content = [];
|
|
97
|
+
let finishReason = { unified: 'other', raw: undefined };
|
|
98
|
+
let usage = {
|
|
99
|
+
inputTokens: { total: undefined, noCache: undefined, cacheRead: undefined, cacheWrite: undefined },
|
|
100
|
+
outputTokens: { total: undefined, text: undefined, reasoning: undefined },
|
|
101
|
+
};
|
|
102
|
+
const warnings = [];
|
|
103
|
+
let responseMetadata;
|
|
104
|
+
const textBlocks = new Map();
|
|
105
|
+
const reasoningBlocks = new Map();
|
|
106
|
+
const reader = streamResult.stream.getReader();
|
|
107
|
+
while (true) {
|
|
108
|
+
const { done, value: part } = await reader.read();
|
|
109
|
+
if (done)
|
|
110
|
+
break;
|
|
111
|
+
activity_1.Context.current().heartbeat();
|
|
112
|
+
// Publish the raw stream part as JSON so consumers can switch on
|
|
113
|
+
// the native AI SDK type. Accumulation below is for the final
|
|
114
|
+
// assembled result this activity returns.
|
|
115
|
+
events.publish(encoder.encode(JSON.stringify(part)));
|
|
116
|
+
switch (part.type) {
|
|
117
|
+
case 'stream-start':
|
|
118
|
+
warnings.push(...part.warnings);
|
|
119
|
+
break;
|
|
120
|
+
case 'text-start':
|
|
121
|
+
textBlocks.set(part.id, '');
|
|
122
|
+
break;
|
|
123
|
+
case 'text-delta':
|
|
124
|
+
textBlocks.set(part.id, (textBlocks.get(part.id) ?? '') + part.delta);
|
|
125
|
+
break;
|
|
126
|
+
case 'text-end':
|
|
127
|
+
content.push({
|
|
128
|
+
type: 'text',
|
|
129
|
+
text: textBlocks.get(part.id) ?? '',
|
|
130
|
+
providerMetadata: part.providerMetadata,
|
|
131
|
+
});
|
|
132
|
+
textBlocks.delete(part.id);
|
|
133
|
+
break;
|
|
134
|
+
case 'reasoning-start':
|
|
135
|
+
reasoningBlocks.set(part.id, '');
|
|
136
|
+
break;
|
|
137
|
+
case 'reasoning-delta':
|
|
138
|
+
reasoningBlocks.set(part.id, (reasoningBlocks.get(part.id) ?? '') + part.delta);
|
|
139
|
+
break;
|
|
140
|
+
case 'reasoning-end':
|
|
141
|
+
content.push({
|
|
142
|
+
type: 'reasoning',
|
|
143
|
+
text: reasoningBlocks.get(part.id) ?? '',
|
|
144
|
+
providerMetadata: part.providerMetadata,
|
|
145
|
+
});
|
|
146
|
+
reasoningBlocks.delete(part.id);
|
|
147
|
+
break;
|
|
148
|
+
case 'response-metadata':
|
|
149
|
+
responseMetadata = {
|
|
150
|
+
id: part.id,
|
|
151
|
+
timestamp: part.timestamp,
|
|
152
|
+
modelId: part.modelId,
|
|
153
|
+
};
|
|
154
|
+
break;
|
|
155
|
+
case 'finish':
|
|
156
|
+
finishReason = part.finishReason;
|
|
157
|
+
usage = part.usage;
|
|
158
|
+
break;
|
|
159
|
+
default:
|
|
160
|
+
// tool-call, tool-result, file, source — collect as content
|
|
161
|
+
if ('type' in part &&
|
|
162
|
+
(part.type === 'tool-call' ||
|
|
163
|
+
part.type === 'tool-result' ||
|
|
164
|
+
part.type === 'file' ||
|
|
165
|
+
part.type === 'source')) {
|
|
166
|
+
content.push(part);
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
content,
|
|
173
|
+
finishReason,
|
|
174
|
+
usage,
|
|
175
|
+
warnings,
|
|
176
|
+
request: streamResult.request,
|
|
177
|
+
response: responseMetadata ? { ...responseMetadata, ...streamResult.response } : streamResult.response,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
catch (e_1) {
|
|
181
|
+
env_1.error = e_1;
|
|
182
|
+
env_1.hasError = true;
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
const result_1 = __disposeResources(env_1);
|
|
186
|
+
if (result_1)
|
|
187
|
+
await result_1;
|
|
188
|
+
}
|
|
189
|
+
},
|
|
23
190
|
async invokeEmbeddingModel(args) {
|
|
24
191
|
const model = provider.embeddingModel(args.modelId);
|
|
25
192
|
return await model.doEmbed({
|
package/lib/activities.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activities.js","sourceRoot":"","sources":["../src/activities.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"activities.js","sourceRoot":"","sources":["../src/activities.ts"],"names":[],"mappings":"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"}
|
package/lib/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,+DAAiD;AAkBjD;;;;;;;;GAQG;AACH,MAAa,iBAAiB;IACP;IAArB,YAAqB,OAAiC;QAAjC,YAAO,GAAP,OAAO,CAA0B;IAAG,CAAC;IAE1D,KAAK,CAAC,KAAK;QACT,MAAM,UAAU,GAAG,QAAQ,CAAC,eAAe,CAAC;YAC1C,mBAAmB,EAAE,YAAY;YACjC,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe;SAChC,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC;QAClE,MAAM,KAAK,GAAmC,MAAM,YAAa,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAE3G,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC;YACpD,QAAQ;YACR;gBACE,WAAW,EAAE,UAAU,CAAC,WAAW;gBACnC,OAAO,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,+DAAiD;AAkBjD;;;;;;;;GAQG;AACH,MAAa,iBAAiB;IACP;IAArB,YAAqB,OAAiC;QAAjC,YAAO,GAAP,OAAO,CAA0B;IAAG,CAAC;IAE1D,KAAK,CAAC,KAAK;QACT,MAAM,UAAU,GAAG,QAAQ,CAAC,eAAe,CAAC;YAC1C,mBAAmB,EAAE,YAAY;YACjC,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe;SAChC,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC;QAClE,MAAM,KAAK,GAAmC,MAAM,YAAa,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAE3G,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC;YACpD,QAAQ;YACR;gBACE,WAAW,EAAE,UAAU,CAAC,WAAW;gBACnC,OAAO,EAAE,KAAK,EAAE,KAAc,EAAE,OAAgB,EAAE,EAAE;oBAClD,MAAM,UAAU,GAAG,QAAQ,CAAC,eAAe,CAAC;wBAC1C,OAAO,EAAE,QAAQ;wBACjB,mBAAmB,EAAE,YAAY;wBACjC,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe;qBAChC,CAAC,CAAC;oBACH,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,WAAW,CAAE,CAAC;oBAClE,OAAO,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;gBACrG,CAAC;gBACD,yHAAyH;gBACzH,WAAW,EAAE;oBACX,GAAG,UAAU,CAAC,WAAW;oBACzB,KAAK,EAAE,SAAS;oBAChB,QAAQ,EAAE,SAAS;oBACnB,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,EAAE,IAAI;oBACtC,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,EAAE,IAAI;iBAC1C;gBACD,IAAI,EAAE,SAAS;aAChB;SACF,CAAC,CACH,CAAC;IACJ,CAAC;CACF;AAvCD,8CAuCC"}
|
package/lib/provider.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EmbeddingModelV3, EmbeddingModelV3CallOptions, EmbeddingModelV3Result, ImageModelV3, LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult, ProviderV3, TranscriptionModelV3 } from '@ai-sdk/provider';
|
|
2
2
|
import type { ActivityOptions } from '@temporalio/workflow';
|
|
3
|
+
import type { Duration } from '@temporalio/common/lib/time';
|
|
3
4
|
/**
|
|
4
5
|
* Options for configuring the TemporalProvider with per-model activity settings.
|
|
5
6
|
*/
|
|
@@ -13,7 +14,21 @@ export interface TemporalProviderOptions {
|
|
|
13
14
|
* Activity options specific to language model calls.
|
|
14
15
|
* Merged with default options, with these taking precedence.
|
|
15
16
|
*/
|
|
16
|
-
languageModel?: ActivityOptions
|
|
17
|
+
languageModel?: ActivityOptions & {
|
|
18
|
+
/**
|
|
19
|
+
* Topic name on the workflow's stream that streaming model calls publish
|
|
20
|
+
* raw stream parts to. When set, `doStream` is enabled and routes through
|
|
21
|
+
* the streaming activity; when unset, `doStream` throws. Pick a unique
|
|
22
|
+
* name per concurrent streaming call to keep event streams separable.
|
|
23
|
+
*/
|
|
24
|
+
streamingTopic?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Batch interval for the per-activity `WorkflowStreamClient` that
|
|
27
|
+
* publishes stream parts back to the workflow. Lower values reduce
|
|
28
|
+
* latency at the cost of more signal traffic. Defaults to 100ms.
|
|
29
|
+
*/
|
|
30
|
+
streamingBatchInterval?: Duration;
|
|
31
|
+
};
|
|
17
32
|
/**
|
|
18
33
|
* Activity options specific to embedding model calls.
|
|
19
34
|
* Merged with default options, with these taking precedence.
|
|
@@ -28,13 +43,21 @@ export interface TemporalProviderOptions {
|
|
|
28
43
|
*/
|
|
29
44
|
export declare class TemporalLanguageModel implements LanguageModelV3 {
|
|
30
45
|
readonly modelId: string;
|
|
31
|
-
readonly options?: ActivityOptions
|
|
46
|
+
readonly options?: (ActivityOptions & {
|
|
47
|
+
streamingTopic?: string;
|
|
48
|
+
streamingBatchInterval?: Duration;
|
|
49
|
+
}) | undefined;
|
|
32
50
|
readonly specificationVersion = "v3";
|
|
33
51
|
readonly provider = "temporal";
|
|
34
|
-
|
|
52
|
+
private readonly streamingTopic;
|
|
53
|
+
private readonly streamingBatchInterval;
|
|
54
|
+
constructor(modelId: string, options?: (ActivityOptions & {
|
|
55
|
+
streamingTopic?: string;
|
|
56
|
+
streamingBatchInterval?: Duration;
|
|
57
|
+
}) | undefined);
|
|
35
58
|
get supportedUrls(): Record<string, RegExp[]>;
|
|
36
59
|
doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
|
|
37
|
-
doStream(
|
|
60
|
+
doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
|
|
38
61
|
}
|
|
39
62
|
/**
|
|
40
63
|
* An embedding model implementation that delegates embedding generation to Temporal activities.
|
package/lib/provider.js
CHANGED
|
@@ -37,9 +37,13 @@ class TemporalLanguageModel {
|
|
|
37
37
|
options;
|
|
38
38
|
specificationVersion = 'v3';
|
|
39
39
|
provider = 'temporal';
|
|
40
|
+
streamingTopic;
|
|
41
|
+
streamingBatchInterval;
|
|
40
42
|
constructor(modelId, options) {
|
|
41
43
|
this.modelId = modelId;
|
|
42
44
|
this.options = options;
|
|
45
|
+
this.streamingTopic = options?.streamingTopic;
|
|
46
|
+
this.streamingBatchInterval = options?.streamingBatchInterval;
|
|
43
47
|
}
|
|
44
48
|
get supportedUrls() {
|
|
45
49
|
return {};
|
|
@@ -62,8 +66,56 @@ class TemporalLanguageModel {
|
|
|
62
66
|
}
|
|
63
67
|
return result;
|
|
64
68
|
}
|
|
65
|
-
doStream(
|
|
66
|
-
|
|
69
|
+
async doStream(options) {
|
|
70
|
+
if (this.streamingTopic === undefined) {
|
|
71
|
+
throw common_1.ApplicationFailure.nonRetryable('Streaming not enabled. Set streamingTopic in languageModel provider options.');
|
|
72
|
+
}
|
|
73
|
+
// Call the streaming activity, which publishes tokens via stream
|
|
74
|
+
// and returns the accumulated result.
|
|
75
|
+
const activities = workflow.proxyActivities({
|
|
76
|
+
startToCloseTimeout: '10 minutes',
|
|
77
|
+
...this.options,
|
|
78
|
+
});
|
|
79
|
+
const result = await activities.invokeModelStreaming({
|
|
80
|
+
modelId: this.modelId,
|
|
81
|
+
options,
|
|
82
|
+
streamingTopic: this.streamingTopic,
|
|
83
|
+
streamingBatchInterval: this.streamingBatchInterval,
|
|
84
|
+
});
|
|
85
|
+
if (result === undefined) {
|
|
86
|
+
throw common_1.ApplicationFailure.nonRetryable('Received undefined response from streaming model activity.');
|
|
87
|
+
}
|
|
88
|
+
// Wrap the accumulated result as a ReadableStream that replays the content.
|
|
89
|
+
// Real-time token streaming already happened via stream in the activity.
|
|
90
|
+
const stream = new ReadableStream({
|
|
91
|
+
start(controller) {
|
|
92
|
+
controller.enqueue({ type: 'stream-start', warnings: result.warnings ?? [] });
|
|
93
|
+
let partIndex = 0;
|
|
94
|
+
for (const item of result.content ?? []) {
|
|
95
|
+
const id = `part-${partIndex++}`;
|
|
96
|
+
if (item.type === 'text') {
|
|
97
|
+
controller.enqueue({ type: 'text-start', id });
|
|
98
|
+
controller.enqueue({ type: 'text-delta', id, delta: item.text });
|
|
99
|
+
controller.enqueue({ type: 'text-end', id });
|
|
100
|
+
}
|
|
101
|
+
else if (item.type === 'reasoning') {
|
|
102
|
+
controller.enqueue({ type: 'reasoning-start', id });
|
|
103
|
+
controller.enqueue({ type: 'reasoning-delta', id, delta: item.text });
|
|
104
|
+
controller.enqueue({ type: 'reasoning-end', id });
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
controller.enqueue(item);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
controller.enqueue({
|
|
111
|
+
type: 'finish',
|
|
112
|
+
finishReason: result.finishReason,
|
|
113
|
+
usage: result.usage,
|
|
114
|
+
});
|
|
115
|
+
controller.close();
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
return { stream, request: result.request, response: result.response };
|
|
67
119
|
}
|
|
68
120
|
}
|
|
69
121
|
exports.TemporalLanguageModel = TemporalLanguageModel;
|
package/lib/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temporalio/ai-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"description": "Temporal AI SDK integration package",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -23,9 +23,12 @@
|
|
|
23
23
|
"@ungap/structured-clone": "^1.3.0",
|
|
24
24
|
"headers-polyfill": "^4.0.3",
|
|
25
25
|
"web-streams-polyfill": "^4.2.0",
|
|
26
|
-
"@temporalio/
|
|
27
|
-
"@temporalio/
|
|
28
|
-
"@temporalio/
|
|
26
|
+
"@temporalio/client": "1.18.0",
|
|
27
|
+
"@temporalio/activity": "1.18.0",
|
|
28
|
+
"@temporalio/common": "1.18.0",
|
|
29
|
+
"@temporalio/plugin": "1.18.0",
|
|
30
|
+
"@temporalio/workflow": "1.18.0",
|
|
31
|
+
"@temporalio/workflow-streams": "1.18.0"
|
|
29
32
|
},
|
|
30
33
|
"peerDependencies": {
|
|
31
34
|
"@ai-sdk/mcp": "^1.0.0",
|
|
@@ -43,14 +46,13 @@
|
|
|
43
46
|
"@opentelemetry/semantic-conventions": "^1.25.1",
|
|
44
47
|
"ai": "^6.0.0",
|
|
45
48
|
"ava": "^5.3.1",
|
|
46
|
-
"uuid": "^11.1.0",
|
|
47
49
|
"zod": "^3.25.76",
|
|
48
|
-
"@temporalio/
|
|
49
|
-
"@temporalio/
|
|
50
|
-
"@temporalio/
|
|
51
|
-
"@temporalio/proto": "1.
|
|
52
|
-
"@temporalio/
|
|
53
|
-
"@temporalio/testing": "1.
|
|
50
|
+
"@temporalio/client": "1.18.0",
|
|
51
|
+
"@temporalio/interceptors-opentelemetry": "1.18.0",
|
|
52
|
+
"@temporalio/test-helpers": "1.18.0",
|
|
53
|
+
"@temporalio/proto": "1.18.0",
|
|
54
|
+
"@temporalio/worker": "1.18.0",
|
|
55
|
+
"@temporalio/testing": "1.18.0"
|
|
54
56
|
},
|
|
55
57
|
"engines": {
|
|
56
58
|
"node": ">= 20.0.0"
|
package/src/activities.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
LanguageModelV3CallOptions,
|
|
3
|
+
LanguageModelV3Content,
|
|
4
|
+
LanguageModelV3FinishReason,
|
|
3
5
|
LanguageModelV3GenerateResult,
|
|
6
|
+
LanguageModelV3Usage,
|
|
4
7
|
EmbeddingModelV3Result,
|
|
5
8
|
SharedV3ProviderOptions,
|
|
6
9
|
SharedV3Headers,
|
|
10
|
+
SharedV3Warning,
|
|
7
11
|
ProviderV3,
|
|
8
12
|
} from '@ai-sdk/provider';
|
|
9
13
|
import { asSchema, type Schema, type ToolExecutionOptions } from 'ai';
|
|
10
14
|
import { ApplicationFailure } from '@temporalio/common';
|
|
15
|
+
import { Context } from '@temporalio/activity';
|
|
16
|
+
import { WorkflowStreamClient } from '@temporalio/workflow-streams/client';
|
|
17
|
+
import type { Duration } from '@temporalio/common/lib/time';
|
|
11
18
|
import type { McpClientFactories, McpClientFactory } from './mcp';
|
|
12
19
|
|
|
20
|
+
const encoder = new TextEncoder();
|
|
21
|
+
|
|
13
22
|
/**
|
|
14
23
|
* Arguments for invoking a language model activity.
|
|
15
24
|
*/
|
|
@@ -18,6 +27,16 @@ export interface InvokeModelArgs {
|
|
|
18
27
|
options: LanguageModelV3CallOptions;
|
|
19
28
|
}
|
|
20
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Arguments for invoking a streaming language model activity.
|
|
32
|
+
*/
|
|
33
|
+
export interface InvokeModelStreamingArgs extends InvokeModelArgs {
|
|
34
|
+
modelId: string;
|
|
35
|
+
options: LanguageModelV3CallOptions;
|
|
36
|
+
streamingTopic: string;
|
|
37
|
+
streamingBatchInterval?: Duration;
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
/**
|
|
22
41
|
* Result from a language model invocation.
|
|
23
42
|
* This is an alias to the AI SDK's LanguageModelV3GenerateResult for type safety.
|
|
@@ -75,6 +94,118 @@ export function createActivities(provider: ProviderV3, mcpClientFactories?: McpC
|
|
|
75
94
|
const model = provider.languageModel(args.modelId);
|
|
76
95
|
return await model.doGenerate(args.options);
|
|
77
96
|
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Streaming-aware model activity.
|
|
100
|
+
*
|
|
101
|
+
* Calls `model.doStream()`, publishes each yielded AI SDK stream part
|
|
102
|
+
* as JSON to the stream side channel, and returns the assembled
|
|
103
|
+
* `LanguageModelV3GenerateResult`. Consumers receive native AI SDK
|
|
104
|
+
* stream-part types (text-delta, reasoning-delta, tool-input-delta,
|
|
105
|
+
* response-metadata, finish, ...); no normalization happens here.
|
|
106
|
+
*/
|
|
107
|
+
async invokeModelStreaming(args: InvokeModelStreamingArgs): Promise<InvokeModelResult> {
|
|
108
|
+
await using stream = WorkflowStreamClient.fromWithinActivity({
|
|
109
|
+
batchInterval: args.streamingBatchInterval ?? '100 milliseconds',
|
|
110
|
+
});
|
|
111
|
+
const events = stream.topic(args.streamingTopic);
|
|
112
|
+
|
|
113
|
+
const model = provider.languageModel(args.modelId);
|
|
114
|
+
const streamResult = await model.doStream(args.options);
|
|
115
|
+
|
|
116
|
+
const content: LanguageModelV3Content[] = [];
|
|
117
|
+
let finishReason: LanguageModelV3FinishReason = { unified: 'other', raw: undefined };
|
|
118
|
+
let usage: LanguageModelV3Usage = {
|
|
119
|
+
inputTokens: { total: undefined, noCache: undefined, cacheRead: undefined, cacheWrite: undefined },
|
|
120
|
+
outputTokens: { total: undefined, text: undefined, reasoning: undefined },
|
|
121
|
+
};
|
|
122
|
+
const warnings: SharedV3Warning[] = [];
|
|
123
|
+
let responseMetadata: Record<string, unknown> | undefined;
|
|
124
|
+
|
|
125
|
+
const textBlocks = new Map<string, string>();
|
|
126
|
+
const reasoningBlocks = new Map<string, string>();
|
|
127
|
+
|
|
128
|
+
const reader = streamResult.stream.getReader();
|
|
129
|
+
|
|
130
|
+
while (true) {
|
|
131
|
+
const { done, value: part } = await reader.read();
|
|
132
|
+
if (done) break;
|
|
133
|
+
|
|
134
|
+
Context.current().heartbeat();
|
|
135
|
+
|
|
136
|
+
// Publish the raw stream part as JSON so consumers can switch on
|
|
137
|
+
// the native AI SDK type. Accumulation below is for the final
|
|
138
|
+
// assembled result this activity returns.
|
|
139
|
+
events.publish(encoder.encode(JSON.stringify(part)));
|
|
140
|
+
|
|
141
|
+
switch (part.type) {
|
|
142
|
+
case 'stream-start':
|
|
143
|
+
warnings.push(...part.warnings);
|
|
144
|
+
break;
|
|
145
|
+
case 'text-start':
|
|
146
|
+
textBlocks.set(part.id, '');
|
|
147
|
+
break;
|
|
148
|
+
case 'text-delta':
|
|
149
|
+
textBlocks.set(part.id, (textBlocks.get(part.id) ?? '') + part.delta);
|
|
150
|
+
break;
|
|
151
|
+
case 'text-end':
|
|
152
|
+
content.push({
|
|
153
|
+
type: 'text',
|
|
154
|
+
text: textBlocks.get(part.id) ?? '',
|
|
155
|
+
providerMetadata: part.providerMetadata,
|
|
156
|
+
});
|
|
157
|
+
textBlocks.delete(part.id);
|
|
158
|
+
break;
|
|
159
|
+
case 'reasoning-start':
|
|
160
|
+
reasoningBlocks.set(part.id, '');
|
|
161
|
+
break;
|
|
162
|
+
case 'reasoning-delta':
|
|
163
|
+
reasoningBlocks.set(part.id, (reasoningBlocks.get(part.id) ?? '') + part.delta);
|
|
164
|
+
break;
|
|
165
|
+
case 'reasoning-end':
|
|
166
|
+
content.push({
|
|
167
|
+
type: 'reasoning',
|
|
168
|
+
text: reasoningBlocks.get(part.id) ?? '',
|
|
169
|
+
providerMetadata: part.providerMetadata,
|
|
170
|
+
});
|
|
171
|
+
reasoningBlocks.delete(part.id);
|
|
172
|
+
break;
|
|
173
|
+
case 'response-metadata':
|
|
174
|
+
responseMetadata = {
|
|
175
|
+
id: part.id,
|
|
176
|
+
timestamp: part.timestamp,
|
|
177
|
+
modelId: part.modelId,
|
|
178
|
+
};
|
|
179
|
+
break;
|
|
180
|
+
case 'finish':
|
|
181
|
+
finishReason = part.finishReason;
|
|
182
|
+
usage = part.usage;
|
|
183
|
+
break;
|
|
184
|
+
default:
|
|
185
|
+
// tool-call, tool-result, file, source — collect as content
|
|
186
|
+
if (
|
|
187
|
+
'type' in part &&
|
|
188
|
+
(part.type === 'tool-call' ||
|
|
189
|
+
part.type === 'tool-result' ||
|
|
190
|
+
part.type === 'file' ||
|
|
191
|
+
part.type === 'source')
|
|
192
|
+
) {
|
|
193
|
+
content.push(part);
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
content,
|
|
201
|
+
finishReason,
|
|
202
|
+
usage,
|
|
203
|
+
warnings,
|
|
204
|
+
request: streamResult.request,
|
|
205
|
+
response: responseMetadata ? { ...responseMetadata, ...streamResult.response } : streamResult.response,
|
|
206
|
+
};
|
|
207
|
+
},
|
|
208
|
+
|
|
78
209
|
async invokeEmbeddingModel(args: InvokeEmbeddingModelArgs): Promise<InvokeEmbeddingModelResult> {
|
|
79
210
|
const model = provider.embeddingModel(args.modelId);
|
|
80
211
|
return await model.doEmbed({
|
package/src/mcp.ts
CHANGED
|
@@ -44,7 +44,7 @@ export class TemporalMCPClient {
|
|
|
44
44
|
toolName,
|
|
45
45
|
{
|
|
46
46
|
description: toolResult.description,
|
|
47
|
-
execute: async (input, options) => {
|
|
47
|
+
execute: async (input: unknown, options: unknown) => {
|
|
48
48
|
const activities = workflow.proxyActivities({
|
|
49
49
|
summary: toolName,
|
|
50
50
|
startToCloseTimeout: '10 minutes',
|
package/src/provider.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReadableStreamDefaultController } from 'node:stream/web';
|
|
1
2
|
import type {
|
|
2
3
|
EmbeddingModelV3,
|
|
3
4
|
EmbeddingModelV3CallOptions,
|
|
@@ -13,6 +14,11 @@ import type {
|
|
|
13
14
|
import * as workflow from '@temporalio/workflow';
|
|
14
15
|
import type { ActivityOptions } from '@temporalio/workflow';
|
|
15
16
|
import { ApplicationFailure } from '@temporalio/common';
|
|
17
|
+
import type { Duration } from '@temporalio/common/lib/time';
|
|
18
|
+
|
|
19
|
+
// `ReadableStream` is a sandbox global; type-only import keeps `node:stream/web`
|
|
20
|
+
// out of the workflow bundle (es2023 lib has no DOM types).
|
|
21
|
+
declare const ReadableStream: typeof import('node:stream/web').ReadableStream;
|
|
16
22
|
|
|
17
23
|
/**
|
|
18
24
|
* Options for configuring the TemporalProvider with per-model activity settings.
|
|
@@ -28,7 +34,22 @@ export interface TemporalProviderOptions {
|
|
|
28
34
|
* Activity options specific to language model calls.
|
|
29
35
|
* Merged with default options, with these taking precedence.
|
|
30
36
|
*/
|
|
31
|
-
languageModel?: ActivityOptions
|
|
37
|
+
languageModel?: ActivityOptions & {
|
|
38
|
+
/**
|
|
39
|
+
* Topic name on the workflow's stream that streaming model calls publish
|
|
40
|
+
* raw stream parts to. When set, `doStream` is enabled and routes through
|
|
41
|
+
* the streaming activity; when unset, `doStream` throws. Pick a unique
|
|
42
|
+
* name per concurrent streaming call to keep event streams separable.
|
|
43
|
+
*/
|
|
44
|
+
streamingTopic?: string;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Batch interval for the per-activity `WorkflowStreamClient` that
|
|
48
|
+
* publishes stream parts back to the workflow. Lower values reduce
|
|
49
|
+
* latency at the cost of more signal traffic. Defaults to 100ms.
|
|
50
|
+
*/
|
|
51
|
+
streamingBatchInterval?: Duration;
|
|
52
|
+
};
|
|
32
53
|
|
|
33
54
|
/**
|
|
34
55
|
* Activity options specific to embedding model calls.
|
|
@@ -46,11 +67,16 @@ export interface TemporalProviderOptions {
|
|
|
46
67
|
export class TemporalLanguageModel implements LanguageModelV3 {
|
|
47
68
|
readonly specificationVersion = 'v3';
|
|
48
69
|
readonly provider = 'temporal';
|
|
70
|
+
private readonly streamingTopic: string | undefined;
|
|
71
|
+
private readonly streamingBatchInterval: Duration | undefined;
|
|
49
72
|
|
|
50
73
|
constructor(
|
|
51
74
|
readonly modelId: string,
|
|
52
|
-
readonly options?: ActivityOptions
|
|
53
|
-
) {
|
|
75
|
+
readonly options?: ActivityOptions & { streamingTopic?: string; streamingBatchInterval?: Duration }
|
|
76
|
+
) {
|
|
77
|
+
this.streamingTopic = options?.streamingTopic;
|
|
78
|
+
this.streamingBatchInterval = options?.streamingBatchInterval;
|
|
79
|
+
}
|
|
54
80
|
|
|
55
81
|
get supportedUrls(): Record<string, RegExp[]> {
|
|
56
82
|
return {};
|
|
@@ -75,8 +101,59 @@ export class TemporalLanguageModel implements LanguageModelV3 {
|
|
|
75
101
|
return result;
|
|
76
102
|
}
|
|
77
103
|
|
|
78
|
-
doStream(
|
|
79
|
-
|
|
104
|
+
async doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult> {
|
|
105
|
+
if (this.streamingTopic === undefined) {
|
|
106
|
+
throw ApplicationFailure.nonRetryable(
|
|
107
|
+
'Streaming not enabled. Set streamingTopic in languageModel provider options.'
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Call the streaming activity, which publishes tokens via stream
|
|
112
|
+
// and returns the accumulated result.
|
|
113
|
+
const activities = workflow.proxyActivities({
|
|
114
|
+
startToCloseTimeout: '10 minutes',
|
|
115
|
+
...this.options,
|
|
116
|
+
});
|
|
117
|
+
const result = await activities.invokeModelStreaming!({
|
|
118
|
+
modelId: this.modelId,
|
|
119
|
+
options,
|
|
120
|
+
streamingTopic: this.streamingTopic,
|
|
121
|
+
streamingBatchInterval: this.streamingBatchInterval,
|
|
122
|
+
});
|
|
123
|
+
if (result === undefined) {
|
|
124
|
+
throw ApplicationFailure.nonRetryable('Received undefined response from streaming model activity.');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Wrap the accumulated result as a ReadableStream that replays the content.
|
|
128
|
+
// Real-time token streaming already happened via stream in the activity.
|
|
129
|
+
const stream = new ReadableStream({
|
|
130
|
+
start(controller: ReadableStreamDefaultController) {
|
|
131
|
+
controller.enqueue({ type: 'stream-start', warnings: result.warnings ?? [] });
|
|
132
|
+
let partIndex = 0;
|
|
133
|
+
for (const item of result.content ?? []) {
|
|
134
|
+
const id = `part-${partIndex++}`;
|
|
135
|
+
if (item.type === 'text') {
|
|
136
|
+
controller.enqueue({ type: 'text-start', id });
|
|
137
|
+
controller.enqueue({ type: 'text-delta', id, delta: item.text });
|
|
138
|
+
controller.enqueue({ type: 'text-end', id });
|
|
139
|
+
} else if (item.type === 'reasoning') {
|
|
140
|
+
controller.enqueue({ type: 'reasoning-start', id });
|
|
141
|
+
controller.enqueue({ type: 'reasoning-delta', id, delta: item.text });
|
|
142
|
+
controller.enqueue({ type: 'reasoning-end', id });
|
|
143
|
+
} else {
|
|
144
|
+
controller.enqueue(item);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
controller.enqueue({
|
|
148
|
+
type: 'finish',
|
|
149
|
+
finishReason: result.finishReason,
|
|
150
|
+
usage: result.usage,
|
|
151
|
+
});
|
|
152
|
+
controller.close();
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return { stream, request: result.request, response: result.response };
|
|
80
157
|
}
|
|
81
158
|
}
|
|
82
159
|
|