@draht/ai 2026.10.20 → 2026.10.23
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/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +155 -111
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/azure-openai-config.d.ts +15 -0
- package/dist/api/azure-openai-config.d.ts.map +1 -0
- package/dist/api/azure-openai-config.js +76 -0
- package/dist/api/azure-openai-config.js.map +1 -0
- package/dist/api/azure-openai-responses.d.ts +3 -6
- package/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/dist/api/azure-openai-responses.js +19 -83
- package/dist/api/azure-openai-responses.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +86 -22
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- package/dist/api/classifier-shared.d.ts +21 -0
- package/dist/api/classifier-shared.d.ts.map +1 -0
- package/dist/api/classifier-shared.js +99 -0
- package/dist/api/classifier-shared.js.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -1
- package/dist/api/cloudflare-workers-ai-system-one.js +15 -9
- package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -1
- package/dist/api/google-generative-ai.js +4 -4
- package/dist/api/google-generative-ai.js.map +1 -1
- package/dist/api/google-shared.d.ts.map +1 -1
- package/dist/api/google-shared.js +3 -1
- package/dist/api/google-shared.js.map +1 -1
- package/dist/api/google-vertex.d.ts.map +1 -1
- package/dist/api/google-vertex.js +9 -9
- package/dist/api/google-vertex.js.map +1 -1
- package/dist/api/lazy.d.ts +7 -2
- package/dist/api/lazy.d.ts.map +1 -1
- package/dist/api/lazy.js +28 -8
- package/dist/api/lazy.js.map +1 -1
- package/dist/api/llama-cpp-classify.d.ts.map +1 -1
- package/dist/api/llama-cpp-classify.js +4 -1
- package/dist/api/llama-cpp-classify.js.map +1 -1
- package/dist/api/mistral-conversations.d.ts.map +1 -1
- package/dist/api/mistral-conversations.js +38 -18
- package/dist/api/mistral-conversations.js.map +1 -1
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +21 -13
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +49 -38
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-decisions.d.ts +4 -0
- package/dist/api/openai-decisions.d.ts.map +1 -0
- package/dist/api/openai-decisions.js +162 -0
- package/dist/api/openai-decisions.js.map +1 -0
- package/dist/api/openai-decisions.lazy.d.ts +3 -0
- package/dist/api/openai-decisions.lazy.d.ts.map +1 -0
- package/dist/api/openai-decisions.lazy.js +4 -0
- package/dist/api/openai-decisions.lazy.js.map +1 -0
- package/dist/api/openai-responses-shared.d.ts +26 -0
- package/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/dist/api/openai-responses-shared.js +82 -16
- package/dist/api/openai-responses-shared.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +47 -18
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/api/openrouter-images.d.ts.map +1 -1
- package/dist/api/openrouter-images.js +4 -3
- package/dist/api/openrouter-images.js.map +1 -1
- package/dist/api/pi-messages.d.ts.map +1 -1
- package/dist/api/pi-messages.js +3 -3
- package/dist/api/pi-messages.js.map +1 -1
- package/dist/api/simple-options.d.ts +2 -1
- package/dist/api/simple-options.d.ts.map +1 -1
- package/dist/api/simple-options.js +12 -2
- package/dist/api/simple-options.js.map +1 -1
- package/dist/api/system-one-shared.d.ts +0 -1
- package/dist/api/system-one-shared.d.ts.map +1 -1
- package/dist/api/system-one-shared.js +5 -89
- package/dist/api/system-one-shared.js.map +1 -1
- package/dist/api/transform-messages.d.ts +16 -1
- package/dist/api/transform-messages.d.ts.map +1 -1
- package/dist/api/transform-messages.js +28 -15
- package/dist/api/transform-messages.js.map +1 -1
- package/dist/api/typesafe-system-one.d.ts.map +1 -1
- package/dist/api/typesafe-system-one.js +2 -1
- package/dist/api/typesafe-system-one.js.map +1 -1
- package/dist/auth/oauth/anthropic.d.ts.map +1 -1
- package/dist/auth/oauth/anthropic.js +65 -7
- package/dist/auth/oauth/anthropic.js.map +1 -1
- package/dist/auth/oauth/load.d.ts +2 -0
- package/dist/auth/oauth/load.d.ts.map +1 -1
- package/dist/auth/oauth/load.js +5 -0
- package/dist/auth/oauth/load.js.map +1 -1
- package/dist/auth/oauth/openai-chatgpt.d.ts.map +1 -1
- package/dist/auth/oauth/openai-chatgpt.js +11 -14
- package/dist/auth/oauth/openai-chatgpt.js.map +1 -1
- package/dist/auth/oauth/openai-codex.d.ts.map +1 -1
- package/dist/auth/oauth/openai-codex.js +7 -5
- package/dist/auth/oauth/openai-codex.js.map +1 -1
- package/dist/auth/oauth/opencode-go.d.ts +3 -12
- package/dist/auth/oauth/opencode-go.d.ts.map +1 -1
- package/dist/auth/oauth/opencode-go.js +229 -34
- package/dist/auth/oauth/opencode-go.js.map +1 -1
- package/dist/auth/resolve.d.ts +16 -1
- package/dist/auth/resolve.d.ts.map +1 -1
- package/dist/auth/resolve.js +51 -27
- package/dist/auth/resolve.js.map +1 -1
- package/dist/auth/types.d.ts +5 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/types.js.map +1 -1
- package/dist/bun-oauth.d.ts.map +1 -1
- package/dist/bun-oauth.js +2 -1
- package/dist/bun-oauth.js.map +1 -1
- package/dist/env-api-keys.js +1 -1
- package/dist/env-api-keys.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +9 -0
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +4 -4
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +4 -4
- package/dist/models.generated.js.map +1 -1
- package/dist/models.js +26 -14
- package/dist/models.js.map +1 -1
- package/dist/providers/all.js +2 -2
- package/dist/providers/all.js.map +1 -1
- package/dist/providers/azure.d.ts +3 -0
- package/dist/providers/azure.d.ts.map +1 -0
- package/dist/providers/azure.js +46 -0
- package/dist/providers/azure.js.map +1 -0
- package/dist/providers/azure.models.d.ts +6 -0
- package/dist/providers/azure.models.d.ts.map +1 -0
- package/dist/providers/azure.models.js +8 -0
- package/dist/providers/azure.models.js.map +1 -0
- package/dist/providers/compat-schema.d.ts +491 -0
- package/dist/providers/compat-schema.d.ts.map +1 -0
- package/dist/providers/compat-schema.js +386 -0
- package/dist/providers/compat-schema.js.map +1 -0
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/amazon-bedrock.json +1 -1
- package/dist/providers/data/anthropic.json +1 -1
- package/dist/providers/data/azure.json +1 -0
- package/dist/providers/data/baseten.json +1 -1
- package/dist/providers/data/cerebras.json +1 -1
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/dist/providers/data/fireworks.json +1 -1
- package/dist/providers/data/github-copilot.json +1 -1
- package/dist/providers/data/google-vertex.json +1 -1
- package/dist/providers/data/google.json +1 -1
- package/dist/providers/data/groq.json +1 -1
- package/dist/providers/data/huggingface.json +1 -1
- package/dist/providers/data/kimi-coding.json +1 -1
- package/dist/providers/data/meta.json +1 -1
- package/dist/providers/data/minimax-cn.json +1 -1
- package/dist/providers/data/minimax.json +1 -1
- package/dist/providers/data/mistral.json +1 -1
- package/dist/providers/data/moonshotai-cn.json +1 -1
- package/dist/providers/data/nvidia.json +1 -1
- package/dist/providers/data/openai-codex.json +1 -1
- package/dist/providers/data/openai.json +1 -1
- package/dist/providers/data/opencode-go.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/dist/providers/data/qwen-token-plan.json +1 -1
- package/dist/providers/data/radius.json +1 -1
- package/dist/providers/data/together.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/providers/data/xai.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
- package/dist/providers/data/xiaomi.json +1 -1
- package/dist/providers/data/zai-coding-cn.json +1 -1
- package/dist/providers/faux.d.ts.map +1 -1
- package/dist/providers/faux.js +25 -8
- package/dist/providers/faux.js.map +1 -1
- package/dist/providers/kimi-coding.d.ts +1 -1
- package/dist/providers/kimi-coding.js +3 -3
- package/dist/providers/kimi-coding.js.map +1 -1
- package/dist/providers/model-schema.d.ts +91 -0
- package/dist/providers/model-schema.d.ts.map +1 -0
- package/dist/providers/model-schema.js +57 -0
- package/dist/providers/model-schema.js.map +1 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +12 -3
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/opencode-go.d.ts +3 -1
- package/dist/providers/opencode-go.d.ts.map +1 -1
- package/dist/providers/opencode-go.js +4 -3
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/providers/opencode.d.ts.map +1 -1
- package/dist/providers/opencode.js +10 -2
- package/dist/providers/opencode.js.map +1 -1
- package/dist/providers/openrouter-api.d.ts +40 -0
- package/dist/providers/openrouter-api.d.ts.map +1 -0
- package/dist/providers/openrouter-api.js +41 -0
- package/dist/providers/openrouter-api.js.map +1 -0
- package/dist/providers/openrouter.d.ts +11 -1
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +52 -1
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/radius.d.ts.map +1 -1
- package/dist/providers/radius.js +4 -12
- package/dist/providers/radius.js.map +1 -1
- package/dist/telemetry.d.ts +288 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +191 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +42 -310
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/estimate.js +1 -1
- package/dist/utils/estimate.js.map +1 -1
- package/dist/utils/event-stream.d.ts +10 -1
- package/dist/utils/event-stream.d.ts.map +1 -1
- package/dist/utils/event-stream.js +25 -0
- package/dist/utils/event-stream.js.map +1 -1
- package/dist/utils/identity.d.ts +65 -0
- package/dist/utils/identity.d.ts.map +1 -0
- package/dist/utils/identity.js +145 -0
- package/dist/utils/identity.js.map +1 -0
- package/dist/utils/json-parse.d.ts +10 -0
- package/dist/utils/json-parse.d.ts.map +1 -1
- package/dist/utils/json-parse.js +26 -1
- package/dist/utils/json-parse.js.map +1 -1
- package/dist/utils/model-operations.d.ts +3 -1
- package/dist/utils/model-operations.d.ts.map +1 -1
- package/dist/utils/model-operations.js +6 -0
- package/dist/utils/model-operations.js.map +1 -1
- package/dist/utils/overflow.d.ts +1 -0
- package/dist/utils/overflow.d.ts.map +1 -1
- package/dist/utils/overflow.js +6 -1
- package/dist/utils/overflow.js.map +1 -1
- package/dist/utils/provider-retry.d.ts +2 -0
- package/dist/utils/provider-retry.d.ts.map +1 -1
- package/dist/utils/provider-retry.js +2 -0
- package/dist/utils/provider-retry.js.map +1 -1
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +30 -10
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/transcript.d.ts +27 -10
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +34 -20
- package/dist/utils/transcript.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +3 -0
- package/dist/utils/validation.js.map +1 -1
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +5 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +5 -5
- package/dist/providers/azure-openai-responses.d.ts +0 -3
- package/dist/providers/azure-openai-responses.d.ts.map +0 -1
- package/dist/providers/azure-openai-responses.js +0 -14
- package/dist/providers/azure-openai-responses.js.map +0 -1
- package/dist/providers/azure-openai-responses.models.d.ts +0 -6
- package/dist/providers/azure-openai-responses.models.d.ts.map +0 -1
- package/dist/providers/azure-openai-responses.models.js +0 -8
- package/dist/providers/azure-openai-responses.models.js.map +0 -1
- package/dist/providers/data/azure-openai-responses.json +0 -1
- package/dist/utils/assistant-message-frame.d.ts +0 -77
- package/dist/utils/assistant-message-frame.d.ts.map +0 -1
- package/dist/utils/assistant-message-frame.js +0 -425
- package/dist/utils/assistant-message-frame.js.map +0 -1
- package/dist/utils/draht-user-agent.d.ts +0 -2
- package/dist/utils/draht-user-agent.d.ts.map +0 -1
- package/dist/utils/draht-user-agent.js +0 -12
- package/dist/utils/draht-user-agent.js.map +0 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { type TelemetrySpan } from "@draht/telemetry";
|
|
2
|
+
import type { LazyStreamObserver } from "./api/lazy.ts";
|
|
3
|
+
import type { Api, Model } from "./types.ts";
|
|
4
|
+
/** Draht-owned request metadata, bounded error status, events, and low-cardinality metrics. */
|
|
5
|
+
export declare const AI_TELEMETRY_SCHEMA: {
|
|
6
|
+
readonly version: 1;
|
|
7
|
+
readonly spans: {
|
|
8
|
+
readonly "pi.ai.request": {
|
|
9
|
+
readonly description: "One logical model request, including authentication and provider setup.";
|
|
10
|
+
readonly parents: {
|
|
11
|
+
readonly kind: "any";
|
|
12
|
+
};
|
|
13
|
+
readonly startAttributes: {
|
|
14
|
+
readonly provider: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly description: "Provider identifier.";
|
|
17
|
+
readonly required: true;
|
|
18
|
+
};
|
|
19
|
+
readonly api: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
readonly description: "API identifier.";
|
|
22
|
+
readonly required: true;
|
|
23
|
+
};
|
|
24
|
+
readonly model: {
|
|
25
|
+
readonly type: "string";
|
|
26
|
+
readonly description: "Requested model identifier.";
|
|
27
|
+
readonly required: true;
|
|
28
|
+
};
|
|
29
|
+
readonly reasoning: {
|
|
30
|
+
readonly type: "string";
|
|
31
|
+
readonly description: "Scalar requested reasoning level.";
|
|
32
|
+
readonly required: false;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
readonly endAttributes: {
|
|
36
|
+
readonly stop: {
|
|
37
|
+
readonly type: "string";
|
|
38
|
+
readonly description: "Normalized stop reason.";
|
|
39
|
+
readonly values: readonly ["pending", "stop", "length", "toolUse", "error", "aborted", "deferred"];
|
|
40
|
+
};
|
|
41
|
+
readonly "usage.input": {
|
|
42
|
+
readonly type: "number";
|
|
43
|
+
readonly description: "Uncached input tokens.";
|
|
44
|
+
};
|
|
45
|
+
readonly "usage.output": {
|
|
46
|
+
readonly type: "number";
|
|
47
|
+
readonly description: "Output tokens.";
|
|
48
|
+
};
|
|
49
|
+
readonly "usage.cache_read": {
|
|
50
|
+
readonly type: "number";
|
|
51
|
+
readonly description: "Cache-read tokens.";
|
|
52
|
+
};
|
|
53
|
+
readonly "usage.cache_write": {
|
|
54
|
+
readonly type: "number";
|
|
55
|
+
readonly description: "Cache-write tokens.";
|
|
56
|
+
};
|
|
57
|
+
readonly "cost.total": {
|
|
58
|
+
readonly type: "number";
|
|
59
|
+
readonly description: "Total request cost in USD.";
|
|
60
|
+
};
|
|
61
|
+
readonly "response.id": {
|
|
62
|
+
readonly type: "string";
|
|
63
|
+
readonly description: "Provider response identifier.";
|
|
64
|
+
readonly cardinality: "high";
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
readonly events: {
|
|
68
|
+
readonly "pi.ai.first_chunk": {
|
|
69
|
+
readonly description: "First normalized stream event delivered.";
|
|
70
|
+
readonly attributes: {};
|
|
71
|
+
};
|
|
72
|
+
readonly "pi.ai.block": {
|
|
73
|
+
readonly description: "A completed content block; content is never recorded.";
|
|
74
|
+
readonly attributes: {
|
|
75
|
+
readonly type: {
|
|
76
|
+
readonly type: "string";
|
|
77
|
+
readonly description: "Block kind.";
|
|
78
|
+
readonly values: readonly ["text", "thinking", "tool_call"];
|
|
79
|
+
readonly required: true;
|
|
80
|
+
};
|
|
81
|
+
readonly index: {
|
|
82
|
+
readonly type: "number";
|
|
83
|
+
readonly description: "Content block index.";
|
|
84
|
+
readonly required: true;
|
|
85
|
+
};
|
|
86
|
+
readonly chars: {
|
|
87
|
+
readonly type: "number";
|
|
88
|
+
readonly description: "UTF-16 character count.";
|
|
89
|
+
readonly required: true;
|
|
90
|
+
};
|
|
91
|
+
readonly tool: {
|
|
92
|
+
readonly type: "string";
|
|
93
|
+
readonly description: "Tool name, for tool-call blocks only.";
|
|
94
|
+
readonly required: false;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
readonly status: {
|
|
100
|
+
readonly default: "ok";
|
|
101
|
+
readonly errorWhen: "Stop reason is error: provider_error with at most 500 error-message characters. Aborted stays ok.";
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
readonly "pi.ai.poll": {
|
|
105
|
+
readonly parents: {
|
|
106
|
+
readonly kind: "any";
|
|
107
|
+
};
|
|
108
|
+
readonly startAttributes: {
|
|
109
|
+
readonly provider: {
|
|
110
|
+
readonly type: "string";
|
|
111
|
+
readonly description: "Provider identifier.";
|
|
112
|
+
readonly required: true;
|
|
113
|
+
};
|
|
114
|
+
readonly api: {
|
|
115
|
+
readonly type: "string";
|
|
116
|
+
readonly description: "API identifier.";
|
|
117
|
+
readonly required: true;
|
|
118
|
+
};
|
|
119
|
+
readonly model: {
|
|
120
|
+
readonly type: "string";
|
|
121
|
+
readonly description: "Requested model identifier.";
|
|
122
|
+
readonly required: true;
|
|
123
|
+
};
|
|
124
|
+
readonly reasoning: {
|
|
125
|
+
readonly type: "string";
|
|
126
|
+
readonly description: "Scalar requested reasoning level.";
|
|
127
|
+
readonly required: false;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
readonly endAttributes: {
|
|
131
|
+
readonly stop: {
|
|
132
|
+
readonly type: "string";
|
|
133
|
+
readonly description: "Normalized stop reason.";
|
|
134
|
+
readonly values: readonly ["pending", "stop", "length", "toolUse", "error", "aborted", "deferred"];
|
|
135
|
+
};
|
|
136
|
+
readonly "usage.input": {
|
|
137
|
+
readonly type: "number";
|
|
138
|
+
readonly description: "Uncached input tokens.";
|
|
139
|
+
};
|
|
140
|
+
readonly "usage.output": {
|
|
141
|
+
readonly type: "number";
|
|
142
|
+
readonly description: "Output tokens.";
|
|
143
|
+
};
|
|
144
|
+
readonly "usage.cache_read": {
|
|
145
|
+
readonly type: "number";
|
|
146
|
+
readonly description: "Cache-read tokens.";
|
|
147
|
+
};
|
|
148
|
+
readonly "usage.cache_write": {
|
|
149
|
+
readonly type: "number";
|
|
150
|
+
readonly description: "Cache-write tokens.";
|
|
151
|
+
};
|
|
152
|
+
readonly "cost.total": {
|
|
153
|
+
readonly type: "number";
|
|
154
|
+
readonly description: "Total request cost in USD.";
|
|
155
|
+
};
|
|
156
|
+
readonly "response.id": {
|
|
157
|
+
readonly type: "string";
|
|
158
|
+
readonly description: "Provider response identifier.";
|
|
159
|
+
readonly cardinality: "high";
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
readonly events: {
|
|
163
|
+
readonly "pi.ai.first_chunk": {
|
|
164
|
+
readonly description: "First normalized stream event delivered.";
|
|
165
|
+
readonly attributes: {};
|
|
166
|
+
};
|
|
167
|
+
readonly "pi.ai.block": {
|
|
168
|
+
readonly description: "A completed content block; content is never recorded.";
|
|
169
|
+
readonly attributes: {
|
|
170
|
+
readonly type: {
|
|
171
|
+
readonly type: "string";
|
|
172
|
+
readonly description: "Block kind.";
|
|
173
|
+
readonly values: readonly ["text", "thinking", "tool_call"];
|
|
174
|
+
readonly required: true;
|
|
175
|
+
};
|
|
176
|
+
readonly index: {
|
|
177
|
+
readonly type: "number";
|
|
178
|
+
readonly description: "Content block index.";
|
|
179
|
+
readonly required: true;
|
|
180
|
+
};
|
|
181
|
+
readonly chars: {
|
|
182
|
+
readonly type: "number";
|
|
183
|
+
readonly description: "UTF-16 character count.";
|
|
184
|
+
readonly required: true;
|
|
185
|
+
};
|
|
186
|
+
readonly tool: {
|
|
187
|
+
readonly type: "string";
|
|
188
|
+
readonly description: "Tool name, for tool-call blocks only.";
|
|
189
|
+
readonly required: false;
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
readonly status: {
|
|
195
|
+
readonly default: "ok";
|
|
196
|
+
readonly errorWhen: "Stop reason is error: provider_error with at most 500 error-message characters. Aborted stays ok.";
|
|
197
|
+
};
|
|
198
|
+
readonly description: "One deferred-response poll, not the deferred request's lifetime.";
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
readonly metrics: {
|
|
202
|
+
readonly "pi.ai.request.duration": {
|
|
203
|
+
readonly kind: "histogram";
|
|
204
|
+
readonly description: "Logical request or poll duration.";
|
|
205
|
+
readonly unit: "ms";
|
|
206
|
+
readonly attributes: {
|
|
207
|
+
readonly provider: {
|
|
208
|
+
readonly type: "string";
|
|
209
|
+
readonly description: "Provider identifier.";
|
|
210
|
+
readonly required: true;
|
|
211
|
+
};
|
|
212
|
+
readonly model: {
|
|
213
|
+
readonly type: "string";
|
|
214
|
+
readonly description: "Requested model identifier.";
|
|
215
|
+
readonly required: true;
|
|
216
|
+
};
|
|
217
|
+
readonly stop: {
|
|
218
|
+
readonly type: "string";
|
|
219
|
+
readonly description: "Normalized stop reason.";
|
|
220
|
+
readonly values: readonly ["pending", "stop", "length", "toolUse", "error", "aborted", "deferred"];
|
|
221
|
+
readonly required: true;
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
readonly "pi.ai.first_chunk.duration": {
|
|
226
|
+
readonly kind: "histogram";
|
|
227
|
+
readonly description: "Time to the first normalized stream event.";
|
|
228
|
+
readonly unit: "ms";
|
|
229
|
+
readonly attributes: {
|
|
230
|
+
readonly provider: {
|
|
231
|
+
readonly type: "string";
|
|
232
|
+
readonly description: "Provider identifier.";
|
|
233
|
+
readonly required: true;
|
|
234
|
+
};
|
|
235
|
+
readonly model: {
|
|
236
|
+
readonly type: "string";
|
|
237
|
+
readonly description: "Requested model identifier.";
|
|
238
|
+
readonly required: true;
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
readonly "pi.ai.tokens": {
|
|
243
|
+
readonly kind: "counter";
|
|
244
|
+
readonly description: "Reported model token usage; pending and deferred polls are excluded.";
|
|
245
|
+
readonly unit: "token";
|
|
246
|
+
readonly attributes: {
|
|
247
|
+
readonly provider: {
|
|
248
|
+
readonly type: "string";
|
|
249
|
+
readonly description: "Provider identifier.";
|
|
250
|
+
readonly required: true;
|
|
251
|
+
};
|
|
252
|
+
readonly model: {
|
|
253
|
+
readonly type: "string";
|
|
254
|
+
readonly description: "Requested model identifier.";
|
|
255
|
+
readonly required: true;
|
|
256
|
+
};
|
|
257
|
+
readonly kind: {
|
|
258
|
+
readonly type: "string";
|
|
259
|
+
readonly description: "Token usage category.";
|
|
260
|
+
readonly values: readonly ["input", "output", "cache_read", "cache_write"];
|
|
261
|
+
readonly required: true;
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
};
|
|
265
|
+
readonly "pi.ai.cost": {
|
|
266
|
+
readonly kind: "counter";
|
|
267
|
+
readonly description: "Reported model cost; pending and deferred polls are excluded.";
|
|
268
|
+
readonly unit: "USD";
|
|
269
|
+
readonly attributes: {
|
|
270
|
+
readonly provider: {
|
|
271
|
+
readonly type: "string";
|
|
272
|
+
readonly description: "Provider identifier.";
|
|
273
|
+
readonly required: true;
|
|
274
|
+
};
|
|
275
|
+
readonly model: {
|
|
276
|
+
readonly type: "string";
|
|
277
|
+
readonly description: "Requested model identifier.";
|
|
278
|
+
readonly required: true;
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
export declare function observeModelRequest(requestedModel: Model<Api>, options: {
|
|
285
|
+
telemetry?: TelemetrySpan;
|
|
286
|
+
reasoning?: unknown;
|
|
287
|
+
} | undefined, poll: boolean): LazyStreamObserver;
|
|
288
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { createTypedMetrics, createTypedSpanStarter, defineTelemetrySchema, NOOP_TELEMETRY_CONTEXT, NOOP_TELEMETRY_METRICS, } from "@draht/telemetry";
|
|
2
|
+
const provider = { type: "string", description: "Provider identifier.", required: true };
|
|
3
|
+
const model = { type: "string", description: "Requested model identifier.", required: true };
|
|
4
|
+
const stop = {
|
|
5
|
+
type: "string",
|
|
6
|
+
description: "Normalized stop reason.",
|
|
7
|
+
values: ["pending", "stop", "length", "toolUse", "error", "aborted", "deferred"],
|
|
8
|
+
};
|
|
9
|
+
const request = {
|
|
10
|
+
description: "One logical model request, including authentication and provider setup.",
|
|
11
|
+
parents: { kind: "any" },
|
|
12
|
+
startAttributes: {
|
|
13
|
+
provider,
|
|
14
|
+
api: { type: "string", description: "API identifier.", required: true },
|
|
15
|
+
model,
|
|
16
|
+
reasoning: { type: "string", description: "Scalar requested reasoning level.", required: false },
|
|
17
|
+
},
|
|
18
|
+
endAttributes: {
|
|
19
|
+
stop,
|
|
20
|
+
"usage.input": { type: "number", description: "Uncached input tokens." },
|
|
21
|
+
"usage.output": { type: "number", description: "Output tokens." },
|
|
22
|
+
"usage.cache_read": { type: "number", description: "Cache-read tokens." },
|
|
23
|
+
"usage.cache_write": { type: "number", description: "Cache-write tokens." },
|
|
24
|
+
"cost.total": { type: "number", description: "Total request cost in USD." },
|
|
25
|
+
"response.id": { type: "string", description: "Provider response identifier.", cardinality: "high" },
|
|
26
|
+
},
|
|
27
|
+
events: {
|
|
28
|
+
"pi.ai.first_chunk": { description: "First normalized stream event delivered.", attributes: {} },
|
|
29
|
+
"pi.ai.block": {
|
|
30
|
+
description: "A completed content block; content is never recorded.",
|
|
31
|
+
attributes: {
|
|
32
|
+
type: {
|
|
33
|
+
type: "string",
|
|
34
|
+
description: "Block kind.",
|
|
35
|
+
values: ["text", "thinking", "tool_call"],
|
|
36
|
+
required: true,
|
|
37
|
+
},
|
|
38
|
+
index: { type: "number", description: "Content block index.", required: true },
|
|
39
|
+
chars: { type: "number", description: "UTF-16 character count.", required: true },
|
|
40
|
+
tool: { type: "string", description: "Tool name, for tool-call blocks only.", required: false },
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
status: {
|
|
45
|
+
default: "ok",
|
|
46
|
+
errorWhen: "Stop reason is error: provider_error with at most 500 error-message characters. Aborted stays ok.",
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
/** Draht-owned request metadata, bounded error status, events, and low-cardinality metrics. */
|
|
50
|
+
export const AI_TELEMETRY_SCHEMA = defineTelemetrySchema({
|
|
51
|
+
version: 1,
|
|
52
|
+
spans: {
|
|
53
|
+
"pi.ai.request": request,
|
|
54
|
+
"pi.ai.poll": { ...request, description: "One deferred-response poll, not the deferred request's lifetime." },
|
|
55
|
+
},
|
|
56
|
+
metrics: {
|
|
57
|
+
"pi.ai.request.duration": {
|
|
58
|
+
kind: "histogram",
|
|
59
|
+
description: "Logical request or poll duration.",
|
|
60
|
+
unit: "ms",
|
|
61
|
+
attributes: { provider, model, stop: { ...stop, required: true } },
|
|
62
|
+
},
|
|
63
|
+
"pi.ai.first_chunk.duration": {
|
|
64
|
+
kind: "histogram",
|
|
65
|
+
description: "Time to the first normalized stream event.",
|
|
66
|
+
unit: "ms",
|
|
67
|
+
attributes: { provider, model },
|
|
68
|
+
},
|
|
69
|
+
"pi.ai.tokens": {
|
|
70
|
+
kind: "counter",
|
|
71
|
+
description: "Reported model token usage; pending and deferred polls are excluded.",
|
|
72
|
+
unit: "token",
|
|
73
|
+
attributes: {
|
|
74
|
+
provider,
|
|
75
|
+
model,
|
|
76
|
+
kind: {
|
|
77
|
+
type: "string",
|
|
78
|
+
description: "Token usage category.",
|
|
79
|
+
values: ["input", "output", "cache_read", "cache_write"],
|
|
80
|
+
required: true,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
"pi.ai.cost": {
|
|
85
|
+
kind: "counter",
|
|
86
|
+
description: "Reported model cost; pending and deferred polls are excluded.",
|
|
87
|
+
unit: "USD",
|
|
88
|
+
attributes: { provider, model },
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
function createInstruments(adapter) {
|
|
93
|
+
const metrics = createTypedMetrics(adapter, [AI_TELEMETRY_SCHEMA]);
|
|
94
|
+
return {
|
|
95
|
+
requestDuration: metrics.histogram("pi.ai.request.duration"),
|
|
96
|
+
firstChunkDuration: metrics.histogram("pi.ai.first_chunk.duration"),
|
|
97
|
+
tokens: metrics.counter("pi.ai.tokens"),
|
|
98
|
+
cost: metrics.counter("pi.ai.cost"),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const instrumentCache = new WeakMap();
|
|
102
|
+
export function observeModelRequest(requestedModel, options, poll) {
|
|
103
|
+
const started = performance.now();
|
|
104
|
+
const attributes = { provider: requestedModel.provider, model: requestedModel.id };
|
|
105
|
+
const adapter = options?.telemetry?.metrics ?? NOOP_TELEMETRY_METRICS;
|
|
106
|
+
let instruments = instrumentCache.get(adapter);
|
|
107
|
+
if (!instruments) {
|
|
108
|
+
instruments = createInstruments(adapter);
|
|
109
|
+
instrumentCache.set(adapter, instruments);
|
|
110
|
+
}
|
|
111
|
+
const { requestDuration, firstChunkDuration, tokens, cost } = instruments;
|
|
112
|
+
let span;
|
|
113
|
+
let finish;
|
|
114
|
+
let first = true;
|
|
115
|
+
const toolChars = new Map();
|
|
116
|
+
const finished = new Promise((resolve) => {
|
|
117
|
+
finish = resolve;
|
|
118
|
+
});
|
|
119
|
+
const run = (activeSpan) => {
|
|
120
|
+
span = activeSpan;
|
|
121
|
+
return finished;
|
|
122
|
+
};
|
|
123
|
+
const startAttributes = {
|
|
124
|
+
...attributes,
|
|
125
|
+
api: requestedModel.api,
|
|
126
|
+
...(typeof options?.reasoning === "string" ? { reasoning: options.reasoning } : {}),
|
|
127
|
+
};
|
|
128
|
+
const start = createTypedSpanStarter(options?.telemetry ?? NOOP_TELEMETRY_CONTEXT, [AI_TELEMETRY_SCHEMA]);
|
|
129
|
+
if (poll)
|
|
130
|
+
void start("pi.ai.poll", startAttributes, run);
|
|
131
|
+
else
|
|
132
|
+
void start("pi.ai.request", startAttributes, run);
|
|
133
|
+
return {
|
|
134
|
+
onEvent(event) {
|
|
135
|
+
if (first) {
|
|
136
|
+
first = false;
|
|
137
|
+
span.addEvent("pi.ai.first_chunk");
|
|
138
|
+
firstChunkDuration.record(performance.now() - started, attributes, span);
|
|
139
|
+
}
|
|
140
|
+
if (event.type === "toolcall_delta") {
|
|
141
|
+
toolChars.set(event.contentIndex, (toolChars.get(event.contentIndex) ?? 0) + event.delta.length);
|
|
142
|
+
}
|
|
143
|
+
else if (event.type === "text_end" || event.type === "thinking_end") {
|
|
144
|
+
span.addEvent("pi.ai.block", {
|
|
145
|
+
type: event.type === "text_end" ? "text" : "thinking",
|
|
146
|
+
index: event.contentIndex,
|
|
147
|
+
chars: event.content.length,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
else if (event.type === "toolcall_end") {
|
|
151
|
+
const chars = toolChars.get(event.contentIndex) ?? 0;
|
|
152
|
+
toolChars.delete(event.contentIndex);
|
|
153
|
+
span.addEvent("pi.ai.block", {
|
|
154
|
+
type: "tool_call",
|
|
155
|
+
index: event.contentIndex,
|
|
156
|
+
chars,
|
|
157
|
+
tool: event.toolCall.name,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
onResult(message) {
|
|
162
|
+
if (message) {
|
|
163
|
+
span.setAttributes({
|
|
164
|
+
stop: message.stopReason,
|
|
165
|
+
"usage.input": message.usage.input,
|
|
166
|
+
"usage.output": message.usage.output,
|
|
167
|
+
"usage.cache_read": message.usage.cacheRead,
|
|
168
|
+
"usage.cache_write": message.usage.cacheWrite,
|
|
169
|
+
"cost.total": message.usage.cost.total,
|
|
170
|
+
"response.id": message.responseId,
|
|
171
|
+
});
|
|
172
|
+
if (message.stopReason === "error") {
|
|
173
|
+
span.setStatus({
|
|
174
|
+
status: "error",
|
|
175
|
+
error: { name: "provider_error", message: message.errorMessage?.slice(0, 500) ?? "" },
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
requestDuration.record(performance.now() - started, { ...attributes, stop: message.stopReason }, span);
|
|
179
|
+
if (!poll || (message.stopReason !== "pending" && message.stopReason !== "deferred")) {
|
|
180
|
+
tokens.add(message.usage.input, { ...attributes, kind: "input" });
|
|
181
|
+
tokens.add(message.usage.output, { ...attributes, kind: "output" });
|
|
182
|
+
tokens.add(message.usage.cacheRead, { ...attributes, kind: "cache_read" });
|
|
183
|
+
tokens.add(message.usage.cacheWrite, { ...attributes, kind: "cache_write" });
|
|
184
|
+
cost.add(message.usage.cost.total, attributes);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
finish();
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcreateTypedMetrics,\n\tcreateTypedSpanStarter,\n\tdefineTelemetrySchema,\n\tNOOP_TELEMETRY_CONTEXT,\n\tNOOP_TELEMETRY_METRICS,\n\ttype SchemaTelemetrySpan,\n\ttype TelemetryMetrics,\n\ttype TelemetrySpan,\n} from \"@draht/telemetry\";\nimport type { LazyStreamObserver } from \"./api/lazy.ts\";\nimport type { Api, Model } from \"./types.ts\";\n\nconst provider = { type: \"string\", description: \"Provider identifier.\", required: true } as const;\nconst model = { type: \"string\", description: \"Requested model identifier.\", required: true } as const;\nconst stop = {\n\ttype: \"string\",\n\tdescription: \"Normalized stop reason.\",\n\tvalues: [\"pending\", \"stop\", \"length\", \"toolUse\", \"error\", \"aborted\", \"deferred\"],\n} as const;\nconst request = {\n\tdescription: \"One logical model request, including authentication and provider setup.\",\n\tparents: { kind: \"any\" },\n\tstartAttributes: {\n\t\tprovider,\n\t\tapi: { type: \"string\", description: \"API identifier.\", required: true },\n\t\tmodel,\n\t\treasoning: { type: \"string\", description: \"Scalar requested reasoning level.\", required: false },\n\t},\n\tendAttributes: {\n\t\tstop,\n\t\t\"usage.input\": { type: \"number\", description: \"Uncached input tokens.\" },\n\t\t\"usage.output\": { type: \"number\", description: \"Output tokens.\" },\n\t\t\"usage.cache_read\": { type: \"number\", description: \"Cache-read tokens.\" },\n\t\t\"usage.cache_write\": { type: \"number\", description: \"Cache-write tokens.\" },\n\t\t\"cost.total\": { type: \"number\", description: \"Total request cost in USD.\" },\n\t\t\"response.id\": { type: \"string\", description: \"Provider response identifier.\", cardinality: \"high\" },\n\t},\n\tevents: {\n\t\t\"pi.ai.first_chunk\": { description: \"First normalized stream event delivered.\", attributes: {} },\n\t\t\"pi.ai.block\": {\n\t\t\tdescription: \"A completed content block; content is never recorded.\",\n\t\t\tattributes: {\n\t\t\t\ttype: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Block kind.\",\n\t\t\t\t\tvalues: [\"text\", \"thinking\", \"tool_call\"],\n\t\t\t\t\trequired: true,\n\t\t\t\t},\n\t\t\t\tindex: { type: \"number\", description: \"Content block index.\", required: true },\n\t\t\t\tchars: { type: \"number\", description: \"UTF-16 character count.\", required: true },\n\t\t\t\ttool: { type: \"string\", description: \"Tool name, for tool-call blocks only.\", required: false },\n\t\t\t},\n\t\t},\n\t},\n\tstatus: {\n\t\tdefault: \"ok\",\n\t\terrorWhen: \"Stop reason is error: provider_error with at most 500 error-message characters. Aborted stays ok.\",\n\t},\n} as const;\n\n/** Draht-owned request metadata, bounded error status, events, and low-cardinality metrics. */\nexport const AI_TELEMETRY_SCHEMA = defineTelemetrySchema({\n\tversion: 1,\n\tspans: {\n\t\t\"pi.ai.request\": request,\n\t\t\"pi.ai.poll\": { ...request, description: \"One deferred-response poll, not the deferred request's lifetime.\" },\n\t},\n\tmetrics: {\n\t\t\"pi.ai.request.duration\": {\n\t\t\tkind: \"histogram\",\n\t\t\tdescription: \"Logical request or poll duration.\",\n\t\t\tunit: \"ms\",\n\t\t\tattributes: { provider, model, stop: { ...stop, required: true } },\n\t\t},\n\t\t\"pi.ai.first_chunk.duration\": {\n\t\t\tkind: \"histogram\",\n\t\t\tdescription: \"Time to the first normalized stream event.\",\n\t\t\tunit: \"ms\",\n\t\t\tattributes: { provider, model },\n\t\t},\n\t\t\"pi.ai.tokens\": {\n\t\t\tkind: \"counter\",\n\t\t\tdescription: \"Reported model token usage; pending and deferred polls are excluded.\",\n\t\t\tunit: \"token\",\n\t\t\tattributes: {\n\t\t\t\tprovider,\n\t\t\t\tmodel,\n\t\t\t\tkind: {\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\tdescription: \"Token usage category.\",\n\t\t\t\t\tvalues: [\"input\", \"output\", \"cache_read\", \"cache_write\"],\n\t\t\t\t\trequired: true,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"pi.ai.cost\": {\n\t\t\tkind: \"counter\",\n\t\t\tdescription: \"Reported model cost; pending and deferred polls are excluded.\",\n\t\t\tunit: \"USD\",\n\t\t\tattributes: { provider, model },\n\t\t},\n\t},\n});\n\ntype RequestSpan = SchemaTelemetrySpan<typeof AI_TELEMETRY_SCHEMA, \"pi.ai.request\">;\n\nfunction createInstruments(adapter: TelemetryMetrics) {\n\tconst metrics = createTypedMetrics(adapter, [AI_TELEMETRY_SCHEMA]);\n\treturn {\n\t\trequestDuration: metrics.histogram(\"pi.ai.request.duration\"),\n\t\tfirstChunkDuration: metrics.histogram(\"pi.ai.first_chunk.duration\"),\n\t\ttokens: metrics.counter(\"pi.ai.tokens\"),\n\t\tcost: metrics.counter(\"pi.ai.cost\"),\n\t};\n}\n\nconst instrumentCache = new WeakMap<TelemetryMetrics, ReturnType<typeof createInstruments>>();\n\nexport function observeModelRequest(\n\trequestedModel: Model<Api>,\n\toptions: { telemetry?: TelemetrySpan; reasoning?: unknown } | undefined,\n\tpoll: boolean,\n): LazyStreamObserver {\n\tconst started = performance.now();\n\tconst attributes = { provider: requestedModel.provider, model: requestedModel.id };\n\tconst adapter = options?.telemetry?.metrics ?? NOOP_TELEMETRY_METRICS;\n\tlet instruments = instrumentCache.get(adapter);\n\tif (!instruments) {\n\t\tinstruments = createInstruments(adapter);\n\t\tinstrumentCache.set(adapter, instruments);\n\t}\n\tconst { requestDuration, firstChunkDuration, tokens, cost } = instruments;\n\tlet span!: RequestSpan;\n\tlet finish!: () => void;\n\tlet first = true;\n\tconst toolChars = new Map<number, number>();\n\tconst finished = new Promise<void>((resolve) => {\n\t\tfinish = resolve;\n\t});\n\tconst run = (activeSpan: RequestSpan): Promise<void> => {\n\t\tspan = activeSpan;\n\t\treturn finished;\n\t};\n\tconst startAttributes = {\n\t\t...attributes,\n\t\tapi: requestedModel.api,\n\t\t...(typeof options?.reasoning === \"string\" ? { reasoning: options.reasoning } : {}),\n\t};\n\tconst start = createTypedSpanStarter(options?.telemetry ?? NOOP_TELEMETRY_CONTEXT, [AI_TELEMETRY_SCHEMA]);\n\tif (poll) void start(\"pi.ai.poll\", startAttributes, run);\n\telse void start(\"pi.ai.request\", startAttributes, run);\n\n\treturn {\n\t\tonEvent(event) {\n\t\t\tif (first) {\n\t\t\t\tfirst = false;\n\t\t\t\tspan.addEvent(\"pi.ai.first_chunk\");\n\t\t\t\tfirstChunkDuration.record(performance.now() - started, attributes, span);\n\t\t\t}\n\t\t\tif (event.type === \"toolcall_delta\") {\n\t\t\t\ttoolChars.set(event.contentIndex, (toolChars.get(event.contentIndex) ?? 0) + event.delta.length);\n\t\t\t} else if (event.type === \"text_end\" || event.type === \"thinking_end\") {\n\t\t\t\tspan.addEvent(\"pi.ai.block\", {\n\t\t\t\t\ttype: event.type === \"text_end\" ? \"text\" : \"thinking\",\n\t\t\t\t\tindex: event.contentIndex,\n\t\t\t\t\tchars: event.content.length,\n\t\t\t\t});\n\t\t\t} else if (event.type === \"toolcall_end\") {\n\t\t\t\tconst chars = toolChars.get(event.contentIndex) ?? 0;\n\t\t\t\ttoolChars.delete(event.contentIndex);\n\t\t\t\tspan.addEvent(\"pi.ai.block\", {\n\t\t\t\t\ttype: \"tool_call\",\n\t\t\t\t\tindex: event.contentIndex,\n\t\t\t\t\tchars,\n\t\t\t\t\ttool: event.toolCall.name,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tonResult(message) {\n\t\t\tif (message) {\n\t\t\t\tspan.setAttributes({\n\t\t\t\t\tstop: message.stopReason,\n\t\t\t\t\t\"usage.input\": message.usage.input,\n\t\t\t\t\t\"usage.output\": message.usage.output,\n\t\t\t\t\t\"usage.cache_read\": message.usage.cacheRead,\n\t\t\t\t\t\"usage.cache_write\": message.usage.cacheWrite,\n\t\t\t\t\t\"cost.total\": message.usage.cost.total,\n\t\t\t\t\t\"response.id\": message.responseId,\n\t\t\t\t});\n\t\t\t\tif (message.stopReason === \"error\") {\n\t\t\t\t\tspan.setStatus({\n\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\terror: { name: \"provider_error\", message: message.errorMessage?.slice(0, 500) ?? \"\" },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\trequestDuration.record(performance.now() - started, { ...attributes, stop: message.stopReason }, span);\n\t\t\t\tif (!poll || (message.stopReason !== \"pending\" && message.stopReason !== \"deferred\")) {\n\t\t\t\t\ttokens.add(message.usage.input, { ...attributes, kind: \"input\" });\n\t\t\t\t\ttokens.add(message.usage.output, { ...attributes, kind: \"output\" });\n\t\t\t\t\ttokens.add(message.usage.cacheRead, { ...attributes, kind: \"cache_read\" });\n\t\t\t\t\ttokens.add(message.usage.cacheWrite, { ...attributes, kind: \"cache_write\" });\n\t\t\t\t\tcost.add(message.usage.cost.total, attributes);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfinish();\n\t\t},\n\t};\n}\n"]}
|