@carbon-js/sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +26 -0
  2. package/dist/ai/anthropic/event-factory.d.mts +22 -0
  3. package/dist/ai/anthropic/event-factory.mjs +97 -0
  4. package/dist/ai/anthropic/fns/message-create.d.mts +15 -0
  5. package/dist/ai/anthropic/fns/message-create.mjs +248 -0
  6. package/dist/ai/anthropic/fns/message-stream.d.mts +15 -0
  7. package/dist/ai/anthropic/fns/message-stream.mjs +59 -0
  8. package/dist/ai/anthropic/types.d.mts +5 -0
  9. package/dist/ai/anthropic/types.mjs +0 -0
  10. package/dist/ai/anthropic/wrap.d.mts +13 -0
  11. package/dist/ai/anthropic/wrap.mjs +17 -0
  12. package/dist/ai/openai/event-factory.d.mts +34 -0
  13. package/dist/ai/openai/event-factory.mjs +189 -0
  14. package/dist/ai/openai/fns/chat-completions-create.d.mts +15 -0
  15. package/dist/ai/openai/fns/chat-completions-create.mjs +219 -0
  16. package/dist/ai/openai/fns/chat-completions-run-tools.d.mts +15 -0
  17. package/dist/ai/openai/fns/chat-completions-run-tools.mjs +112 -0
  18. package/dist/ai/openai/fns/chat-completions-stream.d.mts +15 -0
  19. package/dist/ai/openai/fns/chat-completions-stream.mjs +69 -0
  20. package/dist/ai/openai/fns/response-create.d.mts +15 -0
  21. package/dist/ai/openai/fns/response-create.mjs +137 -0
  22. package/dist/ai/openai/fns/response-stream.d.mts +15 -0
  23. package/dist/ai/openai/fns/response-stream.mjs +59 -0
  24. package/dist/ai/openai/types.d.mts +5 -0
  25. package/dist/ai/openai/types.mjs +0 -0
  26. package/dist/ai/openai/utils/capture-options.d.mts +6 -0
  27. package/dist/ai/openai/utils/capture-options.mjs +4 -0
  28. package/dist/ai/openai/wrap.d.mts +13 -0
  29. package/dist/ai/openai/wrap.mjs +32 -0
  30. package/dist/ai/vercel/event-factory.d.mts +52 -0
  31. package/dist/ai/vercel/event-factory.mjs +140 -0
  32. package/dist/ai/vercel/fns/tool-loop-agent.d.mts +17 -0
  33. package/dist/ai/vercel/fns/tool-loop-agent.mjs +117 -0
  34. package/dist/ai/vercel/recorder.d.mts +37 -0
  35. package/dist/ai/vercel/recorder.mjs +194 -0
  36. package/dist/ai/vercel/types.d.mts +40 -0
  37. package/dist/ai/vercel/types.mjs +1 -0
  38. package/dist/ai/vercel/utils/telemetry.d.mts +31 -0
  39. package/dist/ai/vercel/utils/telemetry.mjs +46 -0
  40. package/dist/ai/vercel/wrap.d.mts +13 -0
  41. package/dist/ai/vercel/wrap.mjs +29 -0
  42. package/dist/ai.d.mts +16 -0
  43. package/dist/ai.mjs +8 -0
  44. package/dist/core/carbon.d.mts +27 -0
  45. package/dist/core/carbon.mjs +35 -0
  46. package/dist/core/events/event-buffer.d.mts +19 -0
  47. package/dist/core/events/event-buffer.mjs +26 -0
  48. package/dist/core/runtime.d.mts +34 -0
  49. package/dist/core/runtime.mjs +119 -0
  50. package/dist/core/schema/carbon-object.d.mts +11 -0
  51. package/dist/core/schema/carbon-object.mjs +0 -0
  52. package/dist/core/tools/wrap-tool.d.mts +16 -0
  53. package/dist/core/tools/wrap-tool.mjs +120 -0
  54. package/dist/core/transport/file-transport.d.mts +16 -0
  55. package/dist/core/transport/file-transport.mjs +17 -0
  56. package/dist/core/transport/http-transport.d.mts +31 -0
  57. package/dist/core/transport/http-transport.mjs +79 -0
  58. package/dist/core/transport/memory-transport.d.mts +12 -0
  59. package/dist/core/transport/memory-transport.mjs +11 -0
  60. package/dist/core/transport/types.d.mts +13 -0
  61. package/dist/core/transport/types.mjs +0 -0
  62. package/dist/core/utils/build-events.d.mts +33 -0
  63. package/dist/core/utils/build-events.mjs +132 -0
  64. package/dist/core/utils/instrumentation.d.mts +12 -0
  65. package/dist/core/utils/instrumentation.mjs +12 -0
  66. package/dist/index.d.mts +10 -0
  67. package/dist/index.mjs +11 -0
  68. package/dist/internal/schema/events.d.mts +315 -0
  69. package/dist/internal/schema/events.mjs +111 -0
  70. package/dist/internal/schema/index.mjs +1 -0
  71. package/dist/lib/constants.d.mts +16 -0
  72. package/dist/lib/constants.mjs +16 -0
  73. package/dist/utils/ids.d.mts +3 -0
  74. package/dist/utils/ids.mjs +4 -0
  75. package/dist/utils/promise.d.mts +8 -0
  76. package/dist/utils/promise.mjs +6 -0
  77. package/dist/utils/retry.d.mts +16 -0
  78. package/dist/utils/retry.mjs +47 -0
  79. package/dist/utils/stringify.d.mts +6 -0
  80. package/dist/utils/stringify.mjs +16 -0
  81. package/dist/utils/timeout.d.mts +9 -0
  82. package/dist/utils/timeout.mjs +27 -0
  83. package/package.json +28 -0
@@ -0,0 +1,189 @@
1
+ import { buildLlmEvent } from "../../core/utils/build-events.mjs";
2
+ import { EMPTY_AI_USAGE } from "../../core/utils/build-events.mjs";
3
+ import { createSdkInstrumentation } from "../../core/utils/instrumentation.mjs";
4
+ import { stringify } from "../../utils/stringify.mjs";
5
+ class OpenAIEventFactory {
6
+ carbonObject;
7
+ constructor(args) {
8
+ this.carbonObject = args.carbonObject;
9
+ }
10
+ createResponseEvents(args) {
11
+ const usage = toResponseAiUsage({ usage: args.response?.usage });
12
+ return [
13
+ buildLlmEvent({
14
+ context: this.carbonObject?.context,
15
+ additionalProperties: this.carbonObject?.additionalProperties,
16
+ endTimeMs: args.endTimeMs,
17
+ instrumentation: createSdkInstrumentation({
18
+ sourceFunction: args.sourceFunction,
19
+ sourcePackage: "openai",
20
+ sourceProvider: "openai"
21
+ }),
22
+ llm: {
23
+ gateway: "openai",
24
+ model: String(args.response?.model ?? args.body.model ?? "unknown"),
25
+ input: this.createResponseLlmInput({ body: args.body }),
26
+ output: {
27
+ mode: args.mode ?? "generate",
28
+ reasoning: stringify({ value: getResponseReasoning({ response: args.response }) }),
29
+ response: getResponseOutputText({ response: args.response }),
30
+ toolCalls: getResponseToolCalls({ response: args.response })
31
+ },
32
+ usage
33
+ },
34
+ startTimeMs: args.startTimeMs,
35
+ status: args.status,
36
+ traceId: this.carbonObject?.traceId
37
+ })
38
+ ];
39
+ }
40
+ createChatCompletionEvents(args) {
41
+ const usage = toCompletionAiUsage({ usage: args.completion?.usage });
42
+ return [
43
+ buildLlmEvent({
44
+ context: this.carbonObject?.context,
45
+ additionalProperties: this.carbonObject?.additionalProperties,
46
+ endTimeMs: args.endTimeMs,
47
+ instrumentation: createSdkInstrumentation({
48
+ sourceFunction: args.sourceFunction,
49
+ sourcePackage: "openai",
50
+ sourceProvider: "openai"
51
+ }),
52
+ llm: {
53
+ gateway: "openai",
54
+ model: String(args.completion?.model ?? args.body.model ?? "unknown"),
55
+ input: this.createChatCompletionLlmInput({ body: args.body }),
56
+ output: {
57
+ mode: args.mode ?? "generate",
58
+ reasoning: "",
59
+ response: stringify({ value: args.completion?.choices[0]?.message.content }),
60
+ toolCalls: args.completion?.choices[0]?.message.tool_calls?.map((toolCall) => ({
61
+ args: stringify({ value: toolCall.type === "function" ? toolCall.function.arguments : toolCall.custom.input }),
62
+ name: toolCall.type === "function" ? toolCall.function.name : toolCall.custom.name
63
+ })) ?? []
64
+ },
65
+ usage
66
+ },
67
+ startTimeMs: args.startTimeMs,
68
+ status: args.status,
69
+ traceId: this.carbonObject?.traceId
70
+ })
71
+ ];
72
+ }
73
+ createResponseLlmInput(args) {
74
+ return {
75
+ prompt: stringify({ value: args.body.input ?? args.body.prompt }),
76
+ system: stringify({ value: args.body.instructions }),
77
+ tools: getResponseToolDescriptions({ tools: args.body.tools })
78
+ };
79
+ }
80
+ createChatCompletionLlmInput(args) {
81
+ const systemMessages = args.body.messages.filter(
82
+ (message) => message.role === "system" || message.role === "developer"
83
+ );
84
+ return {
85
+ prompt: stringify({ value: args.body.messages }),
86
+ system: stringify({ value: systemMessages.length > 0 ? systemMessages : void 0 }),
87
+ tools: getChatCompletionToolDescriptions({ tools: args.body.tools })
88
+ };
89
+ }
90
+ }
91
+ const toResponseAiUsage = (args) => {
92
+ if (!args.usage) {
93
+ return EMPTY_AI_USAGE;
94
+ }
95
+ const cachedTokens = args.usage.input_tokens_details.cached_tokens ?? 0;
96
+ const reasoningTokens = args.usage.output_tokens_details.reasoning_tokens ?? 0;
97
+ return {
98
+ inputTokenDetails: {
99
+ cacheReadTokens: cachedTokens,
100
+ cacheWriteTokens: 0,
101
+ uncachedTokens: Math.max(args.usage.input_tokens - cachedTokens, 0)
102
+ },
103
+ inputTokens: args.usage.input_tokens,
104
+ outputTokenDetails: {
105
+ reasoningTokens,
106
+ responseTokens: Math.max(args.usage.output_tokens - reasoningTokens, 0)
107
+ },
108
+ outputTokens: args.usage.output_tokens,
109
+ totalTokens: args.usage.total_tokens
110
+ };
111
+ };
112
+ const toCompletionAiUsage = (args) => {
113
+ if (!args.usage) {
114
+ return EMPTY_AI_USAGE;
115
+ }
116
+ const cachedTokens = args.usage.prompt_tokens_details?.cached_tokens ?? 0;
117
+ const reasoningTokens = args.usage.completion_tokens_details?.reasoning_tokens ?? 0;
118
+ return {
119
+ inputTokenDetails: {
120
+ cacheReadTokens: cachedTokens,
121
+ cacheWriteTokens: 0,
122
+ uncachedTokens: Math.max(args.usage.prompt_tokens - cachedTokens, 0)
123
+ },
124
+ inputTokens: args.usage.prompt_tokens,
125
+ outputTokenDetails: {
126
+ reasoningTokens,
127
+ responseTokens: Math.max(args.usage.completion_tokens - reasoningTokens, 0)
128
+ },
129
+ outputTokens: args.usage.completion_tokens,
130
+ totalTokens: args.usage.total_tokens
131
+ };
132
+ };
133
+ function getResponseToolDescriptions(args) {
134
+ if (!args.tools) {
135
+ return [];
136
+ }
137
+ return args.tools.map((tool) => ({
138
+ description: "description" in tool && typeof tool.description === "string" ? tool.description : void 0,
139
+ name: "name" in tool && typeof tool.name === "string" ? tool.name : tool.type
140
+ }));
141
+ }
142
+ function getChatCompletionToolDescriptions(args) {
143
+ if (!args.tools) {
144
+ return [];
145
+ }
146
+ return args.tools.map((tool) => ({
147
+ description: tool.type === "function" ? tool.function.description ?? void 0 : typeof tool.custom.description === "string" ? tool.custom.description : void 0,
148
+ name: tool.type === "function" ? tool.function.name : tool.custom.name
149
+ }));
150
+ }
151
+ function getResponseReasoning(args) {
152
+ return args.response?.output.filter((item) => item.type === "reasoning").map((item) => item.summary).filter((summary) => summary.length > 0);
153
+ }
154
+ function getResponseOutputText(args) {
155
+ if (!args.response) {
156
+ return "";
157
+ }
158
+ if (typeof args.response.output_text === "string") {
159
+ return args.response.output_text;
160
+ }
161
+ return args.response.output.flatMap((output) => output.type === "message" ? output.content : []).filter((content) => content.type === "output_text").map((content) => content.text).join("");
162
+ }
163
+ function getResponseToolCalls(args) {
164
+ if (!args.response) {
165
+ return [];
166
+ }
167
+ return args.response.output.flatMap((output) => {
168
+ if (output.type === "function_call") {
169
+ return [
170
+ {
171
+ args: output.arguments,
172
+ name: output.name
173
+ }
174
+ ];
175
+ }
176
+ if (output.type === "custom_tool_call") {
177
+ return [
178
+ {
179
+ args: output.input,
180
+ name: output.name
181
+ }
182
+ ];
183
+ }
184
+ return [];
185
+ });
186
+ }
187
+ export {
188
+ OpenAIEventFactory
189
+ };
@@ -0,0 +1,15 @@
1
+ import { Carbon } from '../../../core/carbon.mjs';
2
+ import OpenAI from 'openai';
3
+ import '../../../core/schema/carbon-object.mjs';
4
+ import '../../../internal/schema/events.mjs';
5
+ import 'zod';
6
+ import '../../../core/runtime.mjs';
7
+ import '../../../core/transport/types.mjs';
8
+ import '../../../core/tools/wrap-tool.mjs';
9
+
10
+ declare function createWrappedChatCompletionCreate(args: {
11
+ client: OpenAI;
12
+ carbon: Carbon;
13
+ }): typeof args.client.chat.completions.create;
14
+
15
+ export { createWrappedChatCompletionCreate };
@@ -0,0 +1,219 @@
1
+ import { createErrorStatus, createOkStatus } from "../../../core/utils/build-events.mjs";
2
+ import { OpenAIEventFactory } from "../event-factory.mjs";
3
+ import { SKIP_CAPTURE_FIELD } from "../utils/capture-options.mjs";
4
+ function createWrappedChatCompletionCreate(args) {
5
+ const createChatCompletion = args.client.chat.completions.create.bind(args.client.chat.completions);
6
+ return ((body, requestOptions) => {
7
+ const { carbon: carbonObject, [SKIP_CAPTURE_FIELD]: skipCapture, ...openAiBody } = body;
8
+ const factory = new OpenAIEventFactory({
9
+ carbonObject
10
+ });
11
+ const startTimeMs = Date.now();
12
+ const bodyWithUsage = openAiBody.stream ? {
13
+ ...openAiBody,
14
+ stream_options: {
15
+ ...openAiBody.stream_options ?? {},
16
+ include_usage: true
17
+ }
18
+ } : openAiBody;
19
+ let completionPromise;
20
+ try {
21
+ completionPromise = createChatCompletion(bodyWithUsage, requestOptions);
22
+ } catch (error) {
23
+ if (!skipCapture) {
24
+ args.carbon.captureEvents({
25
+ events: factory.createChatCompletionEvents({
26
+ body: bodyWithUsage,
27
+ endTimeMs: Date.now(),
28
+ mode: openAiBody.stream ? "stream" : void 0,
29
+ sourceFunction: "chat.completions.create",
30
+ startTimeMs,
31
+ status: createErrorStatus({ error })
32
+ })
33
+ });
34
+ }
35
+ throw error;
36
+ }
37
+ if (skipCapture) {
38
+ return completionPromise;
39
+ }
40
+ if (openAiBody.stream) {
41
+ attachChatCompletionCreateStreamCapture({
42
+ body: bodyWithUsage,
43
+ carbon: args.carbon,
44
+ factory,
45
+ completionPromise,
46
+ startTimeMs
47
+ });
48
+ return completionPromise;
49
+ }
50
+ void Promise.resolve(completionPromise).then(
51
+ (completion) => {
52
+ args.carbon.captureEvents({
53
+ events: factory.createChatCompletionEvents({
54
+ body: openAiBody,
55
+ completion,
56
+ endTimeMs: Date.now(),
57
+ sourceFunction: "chat.completions.create",
58
+ startTimeMs,
59
+ status: createOkStatus()
60
+ })
61
+ });
62
+ },
63
+ (error) => {
64
+ args.carbon.captureEvents({
65
+ events: factory.createChatCompletionEvents({
66
+ body: openAiBody,
67
+ endTimeMs: Date.now(),
68
+ sourceFunction: "chat.completions.create",
69
+ startTimeMs,
70
+ status: createErrorStatus({ error })
71
+ })
72
+ });
73
+ }
74
+ );
75
+ return completionPromise;
76
+ });
77
+ }
78
+ function attachChatCompletionCreateStreamCapture(args) {
79
+ void Promise.resolve(args.completionPromise).then(
80
+ (stream) => {
81
+ captureChatCompletionCreateStream({
82
+ ...args,
83
+ stream
84
+ });
85
+ },
86
+ (error) => {
87
+ args.carbon.captureEvents({
88
+ events: args.factory.createChatCompletionEvents({
89
+ body: args.body,
90
+ endTimeMs: Date.now(),
91
+ mode: "stream",
92
+ sourceFunction: "chat.completions.create",
93
+ startTimeMs: args.startTimeMs,
94
+ status: createErrorStatus({ error })
95
+ })
96
+ });
97
+ }
98
+ );
99
+ }
100
+ function captureChatCompletionCreateStream(args) {
101
+ const streamWithIterator = args.stream;
102
+ const originalIterator = (streamWithIterator.iterator ?? args.stream[Symbol.asyncIterator]).bind(args.stream);
103
+ const accumulator = createChatCompletionAccumulator({ body: args.body });
104
+ let captured = false;
105
+ const wrappedIterator = async function* () {
106
+ try {
107
+ for await (const chunk of {
108
+ [Symbol.asyncIterator]: originalIterator
109
+ }) {
110
+ accumulator.addChunk({ chunk });
111
+ yield chunk;
112
+ }
113
+ captured = true;
114
+ args.carbon.captureEvents({
115
+ events: args.factory.createChatCompletionEvents({
116
+ body: args.body,
117
+ completion: accumulator.toCompletion(),
118
+ endTimeMs: Date.now(),
119
+ mode: "stream",
120
+ sourceFunction: "chat.completions.create",
121
+ startTimeMs: args.startTimeMs,
122
+ status: createOkStatus()
123
+ })
124
+ });
125
+ } catch (error) {
126
+ if (!captured) {
127
+ captured = true;
128
+ args.carbon.captureEvents({
129
+ events: args.factory.createChatCompletionEvents({
130
+ body: args.body,
131
+ endTimeMs: Date.now(),
132
+ mode: "stream",
133
+ sourceFunction: "chat.completions.create",
134
+ startTimeMs: args.startTimeMs,
135
+ status: createErrorStatus({ error })
136
+ })
137
+ });
138
+ }
139
+ throw error;
140
+ }
141
+ };
142
+ if (streamWithIterator.iterator) {
143
+ streamWithIterator.iterator = wrappedIterator;
144
+ return;
145
+ }
146
+ args.stream[Symbol.asyncIterator] = wrappedIterator;
147
+ }
148
+ function createChatCompletionAccumulator(args) {
149
+ const choices = [];
150
+ let created = 0;
151
+ let id = "";
152
+ let model = String(args.body.model ?? "unknown");
153
+ let usage;
154
+ return {
155
+ addChunk(addArgs) {
156
+ id = addArgs.chunk.id || id;
157
+ created = addArgs.chunk.created || created;
158
+ model = addArgs.chunk.model || model;
159
+ usage = addArgs.chunk.usage ?? usage;
160
+ for (const chunkChoice of addArgs.chunk.choices) {
161
+ const choice = choices[chunkChoice.index] ??= {
162
+ finish_reason: chunkChoice.finish_reason ?? "stop",
163
+ index: chunkChoice.index,
164
+ logprobs: chunkChoice.logprobs ?? null,
165
+ message: {
166
+ content: "",
167
+ refusal: null,
168
+ role: "assistant"
169
+ }
170
+ };
171
+ if (chunkChoice.finish_reason) {
172
+ choice.finish_reason = chunkChoice.finish_reason;
173
+ }
174
+ if (chunkChoice.logprobs) {
175
+ choice.logprobs = chunkChoice.logprobs;
176
+ }
177
+ if (chunkChoice.delta.content) {
178
+ choice.message.content = (choice.message.content ?? "") + chunkChoice.delta.content;
179
+ }
180
+ if (chunkChoice.delta.refusal) {
181
+ choice.message.refusal = (choice.message.refusal ?? "") + chunkChoice.delta.refusal;
182
+ }
183
+ if (chunkChoice.delta.role === "assistant") {
184
+ choice.message.role = chunkChoice.delta.role;
185
+ }
186
+ if (chunkChoice.delta.tool_calls) {
187
+ choice.message.tool_calls ??= [];
188
+ for (const toolCallDelta of chunkChoice.delta.tool_calls) {
189
+ const toolCall = choice.message.tool_calls[toolCallDelta.index] ??= {
190
+ function: {
191
+ arguments: "",
192
+ name: ""
193
+ },
194
+ id: "",
195
+ type: "function"
196
+ };
197
+ toolCall.id = toolCallDelta.id ?? toolCall.id;
198
+ toolCall.type = toolCallDelta.type ?? toolCall.type;
199
+ toolCall.function.arguments += toolCallDelta.function?.arguments ?? "";
200
+ toolCall.function.name = toolCallDelta.function?.name ?? toolCall.function.name;
201
+ }
202
+ }
203
+ }
204
+ },
205
+ toCompletion() {
206
+ return {
207
+ choices,
208
+ created,
209
+ id,
210
+ model,
211
+ object: "chat.completion",
212
+ ...usage ? { usage } : {}
213
+ };
214
+ }
215
+ };
216
+ }
217
+ export {
218
+ createWrappedChatCompletionCreate
219
+ };
@@ -0,0 +1,15 @@
1
+ import { Carbon } from '../../../core/carbon.mjs';
2
+ import OpenAI from 'openai';
3
+ import '../../../core/schema/carbon-object.mjs';
4
+ import '../../../internal/schema/events.mjs';
5
+ import 'zod';
6
+ import '../../../core/runtime.mjs';
7
+ import '../../../core/transport/types.mjs';
8
+ import '../../../core/tools/wrap-tool.mjs';
9
+
10
+ declare function createWrappedChatCompletionRunTools(args: {
11
+ client: OpenAI;
12
+ carbon: Carbon;
13
+ }): typeof args.client.chat.completions.runTools;
14
+
15
+ export { createWrappedChatCompletionRunTools };
@@ -0,0 +1,112 @@
1
+ import { buildToolEvent, createErrorStatus, createOkStatus } from "../../../core/utils/build-events.mjs";
2
+ import { createSdkInstrumentation } from "../../../core/utils/instrumentation.mjs";
3
+ import { stringify } from "../../../utils/stringify.mjs";
4
+ import { OpenAIEventFactory } from "../event-factory.mjs";
5
+ import { SKIP_CAPTURE_FIELD } from "../utils/capture-options.mjs";
6
+ function createWrappedChatCompletionRunTools(args) {
7
+ const runTools = args.client.chat.completions.runTools.bind(args.client.chat.completions);
8
+ return ((body, requestOptions) => {
9
+ const { carbon: carbonObject, ...openAiBody } = body;
10
+ const bodyWithInternalCapture = {
11
+ ...openAiBody,
12
+ carbon: carbonObject,
13
+ [SKIP_CAPTURE_FIELD]: true
14
+ };
15
+ const factory = new OpenAIEventFactory({
16
+ carbonObject
17
+ });
18
+ const startTimeMs = Date.now();
19
+ let runner;
20
+ try {
21
+ runner = runTools(bodyWithInternalCapture, requestOptions);
22
+ } catch (error) {
23
+ args.carbon.captureEvents({
24
+ events: factory.createChatCompletionEvents({
25
+ body: openAiBody,
26
+ endTimeMs: Date.now(),
27
+ mode: openAiBody.stream ? "stream" : void 0,
28
+ sourceFunction: "chat.completions.runTools",
29
+ startTimeMs,
30
+ status: createErrorStatus({ error })
31
+ })
32
+ });
33
+ throw error;
34
+ }
35
+ attachRunToolsCapture({
36
+ body: openAiBody,
37
+ carbon: args.carbon,
38
+ carbonObject,
39
+ factory,
40
+ mode: openAiBody.stream ? "stream" : "generate",
41
+ runner
42
+ });
43
+ return runner;
44
+ });
45
+ }
46
+ function attachRunToolsCapture(args) {
47
+ let nextLlmStartTimeMs = Date.now();
48
+ const pendingToolCalls = [];
49
+ args.runner.on("chatCompletion", (completion) => {
50
+ const endTimeMs = Date.now();
51
+ args.carbon.captureEvents({
52
+ events: args.factory.createChatCompletionEvents({
53
+ body: args.body,
54
+ completion,
55
+ endTimeMs,
56
+ mode: args.mode,
57
+ sourceFunction: "chat.completions.runTools",
58
+ startTimeMs: nextLlmStartTimeMs,
59
+ status: createOkStatus()
60
+ })
61
+ });
62
+ nextLlmStartTimeMs = Date.now();
63
+ });
64
+ args.runner.on("functionToolCall", (functionCall) => {
65
+ pendingToolCalls.push({
66
+ args: functionCall.arguments,
67
+ name: functionCall.name,
68
+ startTimeMs: Date.now()
69
+ });
70
+ });
71
+ args.runner.on("functionToolCallResult", (result) => {
72
+ const toolCall = pendingToolCalls.shift();
73
+ const endTimeMs = Date.now();
74
+ args.carbon.captureEvents({
75
+ events: [
76
+ buildToolEvent({
77
+ additionalProperties: args.carbonObject?.additionalProperties,
78
+ context: args.carbonObject?.context,
79
+ endTimeMs,
80
+ instrumentation: createSdkInstrumentation({
81
+ sourceFunction: "chat.completions.runTools",
82
+ sourcePackage: "openai",
83
+ sourceProvider: "openai"
84
+ }),
85
+ startTimeMs: toolCall?.startTimeMs ?? endTimeMs,
86
+ status: createOkStatus(),
87
+ tool: {
88
+ args: toolCall?.args ?? "",
89
+ name: toolCall?.name ?? "unknown",
90
+ result: stringify({ value: result })
91
+ },
92
+ traceId: args.carbonObject?.traceId
93
+ })
94
+ ]
95
+ });
96
+ });
97
+ args.runner.on("error", (error) => {
98
+ args.carbon.captureEvents({
99
+ events: args.factory.createChatCompletionEvents({
100
+ body: args.body,
101
+ endTimeMs: Date.now(),
102
+ mode: args.mode,
103
+ sourceFunction: "chat.completions.runTools",
104
+ startTimeMs: nextLlmStartTimeMs,
105
+ status: createErrorStatus({ error })
106
+ })
107
+ });
108
+ });
109
+ }
110
+ export {
111
+ createWrappedChatCompletionRunTools
112
+ };
@@ -0,0 +1,15 @@
1
+ import { Carbon } from '../../../core/carbon.mjs';
2
+ import OpenAI from 'openai';
3
+ import '../../../core/schema/carbon-object.mjs';
4
+ import '../../../internal/schema/events.mjs';
5
+ import 'zod';
6
+ import '../../../core/runtime.mjs';
7
+ import '../../../core/transport/types.mjs';
8
+ import '../../../core/tools/wrap-tool.mjs';
9
+
10
+ declare function createWrappedChatCompletionStream(args: {
11
+ client: OpenAI;
12
+ carbon: Carbon;
13
+ }): typeof args.client.chat.completions.stream;
14
+
15
+ export { createWrappedChatCompletionStream };
@@ -0,0 +1,69 @@
1
+ import { createErrorStatus, createOkStatus } from "../../../core/utils/build-events.mjs";
2
+ import { OpenAIEventFactory } from "../event-factory.mjs";
3
+ function createWrappedChatCompletionStream(args) {
4
+ const streamChatCompletion = args.client.chat.completions.stream.bind(args.client.chat.completions);
5
+ return ((body, requestOptions) => {
6
+ const { carbon: carbonObject, ...openAiBody } = body;
7
+ const bodyWithUsage = {
8
+ ...openAiBody,
9
+ stream_options: {
10
+ ...openAiBody.stream_options ?? {},
11
+ include_usage: true
12
+ }
13
+ };
14
+ const factory = new OpenAIEventFactory({
15
+ carbonObject
16
+ });
17
+ const startTimeMs = Date.now();
18
+ let completionStream;
19
+ try {
20
+ completionStream = streamChatCompletion(
21
+ bodyWithUsage,
22
+ requestOptions
23
+ );
24
+ } catch (error) {
25
+ args.carbon.captureEvents({
26
+ events: factory.createChatCompletionEvents({
27
+ body: bodyWithUsage,
28
+ endTimeMs: Date.now(),
29
+ mode: "stream",
30
+ sourceFunction: "chat.completions.stream",
31
+ startTimeMs,
32
+ status: createErrorStatus({ error })
33
+ })
34
+ });
35
+ throw error;
36
+ }
37
+ void completionStream.finalChatCompletion().then(
38
+ (completion) => {
39
+ args.carbon.captureEvents({
40
+ events: factory.createChatCompletionEvents({
41
+ body: bodyWithUsage,
42
+ completion,
43
+ endTimeMs: Date.now(),
44
+ mode: "stream",
45
+ sourceFunction: "chat.completions.stream",
46
+ startTimeMs,
47
+ status: createOkStatus()
48
+ })
49
+ });
50
+ },
51
+ (error) => {
52
+ args.carbon.captureEvents({
53
+ events: factory.createChatCompletionEvents({
54
+ body: bodyWithUsage,
55
+ endTimeMs: Date.now(),
56
+ mode: "stream",
57
+ sourceFunction: "chat.completions.stream",
58
+ startTimeMs,
59
+ status: createErrorStatus({ error })
60
+ })
61
+ });
62
+ }
63
+ );
64
+ return completionStream;
65
+ });
66
+ }
67
+ export {
68
+ createWrappedChatCompletionStream
69
+ };
@@ -0,0 +1,15 @@
1
+ import { Carbon } from '../../../core/carbon.mjs';
2
+ import OpenAI from 'openai';
3
+ import '../../../core/schema/carbon-object.mjs';
4
+ import '../../../internal/schema/events.mjs';
5
+ import 'zod';
6
+ import '../../../core/runtime.mjs';
7
+ import '../../../core/transport/types.mjs';
8
+ import '../../../core/tools/wrap-tool.mjs';
9
+
10
+ declare function createWrappedResponseCreate(args: {
11
+ client: OpenAI;
12
+ carbon: Carbon;
13
+ }): typeof args.client.responses.create;
14
+
15
+ export { createWrappedResponseCreate };