@runappsai/sdk 0.0.0-stage → 0.3.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/LICENSE +21 -0
- package/README.md +274 -2
- package/dist/activity-tracker.d.ts +113 -0
- package/dist/activity-tracker.d.ts.map +1 -0
- package/dist/activity-tracker.js +176 -0
- package/dist/activity-tracker.js.map +1 -0
- package/dist/audio.d.ts +129 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/audio.js +267 -0
- package/dist/audio.js.map +1 -0
- package/dist/browser-auth.d.ts +179 -0
- package/dist/browser-auth.d.ts.map +1 -0
- package/dist/browser-auth.js +1361 -0
- package/dist/browser-auth.js.map +1 -0
- package/dist/chat.d.ts +221 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +155 -0
- package/dist/chat.js.map +1 -0
- package/dist/client.d.ts +155 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +157 -0
- package/dist/client.js.map +1 -0
- package/dist/computer.d.ts +57 -0
- package/dist/computer.d.ts.map +1 -0
- package/dist/computer.js +21 -0
- package/dist/computer.js.map +1 -0
- package/dist/embeddings.d.ts +64 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +30 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/event-wrap.d.ts +59 -0
- package/dist/event-wrap.d.ts.map +1 -0
- package/dist/event-wrap.js +142 -0
- package/dist/event-wrap.js.map +1 -0
- package/dist/events.d.ts +119 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +87 -0
- package/dist/events.js.map +1 -0
- package/dist/files.d.ts +218 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +212 -0
- package/dist/files.js.map +1 -0
- package/dist/image.d.ts +185 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +148 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/media.d.ts +56 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +133 -0
- package/dist/media.js.map +1 -0
- package/dist/model_options.d.ts +165 -0
- package/dist/model_options.d.ts.map +1 -0
- package/dist/model_options.js +59 -0
- package/dist/model_options.js.map +1 -0
- package/dist/models.d.ts +88 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +55 -0
- package/dist/models.js.map +1 -0
- package/dist/sdk.umd.js +4 -0
- package/dist/sdk.umd.js.map +1 -0
- package/dist/transport.d.ts +120 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +214 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +16 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +329 -0
- package/dist/validate.js.map +1 -0
- package/dist/video.d.ts +134 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +60 -0
- package/dist/video.js.map +1 -0
- package/package.json +54 -4
- package/src/activity-tracker.ts +251 -0
- package/src/audio.ts +440 -0
- package/src/browser-auth.ts +1529 -0
- package/src/chat.ts +368 -0
- package/src/client.ts +250 -0
- package/src/computer.ts +80 -0
- package/src/embeddings.ts +97 -0
- package/src/errors.ts +29 -0
- package/src/event-wrap.ts +168 -0
- package/src/events.ts +172 -0
- package/src/files.ts +347 -0
- package/src/image.ts +339 -0
- package/src/index.ts +151 -0
- package/src/media.ts +147 -0
- package/src/model_options.ts +220 -0
- package/src/models.ts +121 -0
- package/src/transport.ts +292 -0
- package/src/types.ts +31 -0
- package/src/validate.ts +364 -0
- package/src/video.ts +215 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Transport } from "./transport.js";
|
|
2
|
+
import { ChatService } from "./chat.js";
|
|
3
|
+
import { ModelsService } from "./models.js";
|
|
4
|
+
import { ImageService } from "./image.js";
|
|
5
|
+
import { AudioService } from "./audio.js";
|
|
6
|
+
import { VideoService } from "./video.js";
|
|
7
|
+
import { ComputerService } from "./computer.js";
|
|
8
|
+
import { FilesService } from "./files.js";
|
|
9
|
+
import { EmbeddingsService } from "./embeddings.js";
|
|
10
|
+
import { BrowserAuth } from "./browser-auth.js";
|
|
11
|
+
import { SDKEvents } from "./events.js";
|
|
12
|
+
// The platform, not the bare gateway: personal rk_ keys are checked and
|
|
13
|
+
// billed by www.runapps.ai, which forwards to the gateway. api.runapps.ai
|
|
14
|
+
// only knows the gateway's own keys.
|
|
15
|
+
const DEFAULT_BASE_URL = "https://www.runapps.ai";
|
|
16
|
+
/**
|
|
17
|
+
* Top-level RunApps SDK client. Construct once, share across services.
|
|
18
|
+
*
|
|
19
|
+
* Browser bundle (resource projects on runapps.ai):
|
|
20
|
+
*
|
|
21
|
+
* ```html
|
|
22
|
+
* <script src="https://cdn.jsdelivr.net/npm/@runappsai/sdk/dist/sdk.umd.js"></script>
|
|
23
|
+
* <script>
|
|
24
|
+
* const client = new RunApps.Client({ authProvider: "runapps" });
|
|
25
|
+
* const res = await client.chat.create({
|
|
26
|
+
* model: "gpt-4o-mini",
|
|
27
|
+
* messages: [{ role: "user", content: "hello" }],
|
|
28
|
+
* });
|
|
29
|
+
* </script>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* Node / server-side:
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { RunApps } from "@runappsai/sdk";
|
|
36
|
+
* const client = new RunApps({ apiKey: process.env.RUNJOBS_API_KEY! });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export class RunApps {
|
|
40
|
+
chat;
|
|
41
|
+
models;
|
|
42
|
+
image;
|
|
43
|
+
audio;
|
|
44
|
+
video;
|
|
45
|
+
computer;
|
|
46
|
+
files;
|
|
47
|
+
embeddings;
|
|
48
|
+
/**
|
|
49
|
+
* Browser auth helper, populated only when `authProvider: "runapps"`.
|
|
50
|
+
* Use `client.signIn()` and `client.user` for the common cases; the
|
|
51
|
+
* full instance is exposed for advanced flows (manual `onTokenChange`
|
|
52
|
+
* subscription, etc.).
|
|
53
|
+
*/
|
|
54
|
+
auth = null;
|
|
55
|
+
/**
|
|
56
|
+
* Runtime event bus for SDK-call telemetry. Every LLM-ish service
|
|
57
|
+
* (chat / embeddings / image / audio / video / computer) fires
|
|
58
|
+
* `request:start`, `request:streamDelta`, `request:end`, and
|
|
59
|
+
* `request:error` events here so UI overlays — like the bottom-right
|
|
60
|
+
* identity badge's activity ring — can render real-time state
|
|
61
|
+
* without business code threading anything through.
|
|
62
|
+
*
|
|
63
|
+
* Zero-cost when nobody subscribes (emit is a few property reads).
|
|
64
|
+
* Subscribe via `client.events.on("request:start", handler)` — the
|
|
65
|
+
* returned closure is the unsubscribe.
|
|
66
|
+
*/
|
|
67
|
+
events = new SDKEvents();
|
|
68
|
+
constructor(options = {}) {
|
|
69
|
+
const provider = options.authProvider ?? "static";
|
|
70
|
+
let apiKeyResolver = options.apiKeyResolver;
|
|
71
|
+
let baseURL = options.baseURL;
|
|
72
|
+
let onUnauthorized;
|
|
73
|
+
if (provider === "runapps" || provider === "runjobs") {
|
|
74
|
+
// The grant page (/api/sdk/grant) and the gateway both live on
|
|
75
|
+
// www.runapps.ai. An explicit baseURL keeps control.
|
|
76
|
+
baseURL = baseURL ?? "https://www.runapps.ai";
|
|
77
|
+
// Badge default: SHOWN. The badge is now a real-time activity
|
|
78
|
+
// indicator (LED + ring + popover) — useful enough that we'd
|
|
79
|
+
// rather have the rare "I already have my own UI" bundle opt
|
|
80
|
+
// OUT with `showIdentityBadge: false` than have every bundle
|
|
81
|
+
// miss the live feedback by default. The legacy
|
|
82
|
+
// `hideIdentityBadge` flag still wins when set, for callers
|
|
83
|
+
// that explicitly suppressed the badge under the old default.
|
|
84
|
+
const showBadge = options.showIdentityBadge !== undefined
|
|
85
|
+
? options.showIdentityBadge
|
|
86
|
+
: options.hideIdentityBadge !== undefined
|
|
87
|
+
? !options.hideIdentityBadge
|
|
88
|
+
: true;
|
|
89
|
+
const auth = new BrowserAuth({
|
|
90
|
+
origin: baseURL,
|
|
91
|
+
hideBadge: !showBadge,
|
|
92
|
+
// Pipe the shared event bus into BrowserAuth so the badge can
|
|
93
|
+
// render its real-time activity ring / LED / popover. Safe to
|
|
94
|
+
// pass even when the caller never subscribes — emit is a few
|
|
95
|
+
// property reads when nobody's listening.
|
|
96
|
+
events: this.events,
|
|
97
|
+
...(options.badgePosition !== undefined && { badgePosition: options.badgePosition }),
|
|
98
|
+
...(options.project !== undefined && { project: options.project }),
|
|
99
|
+
});
|
|
100
|
+
this.auth = auth;
|
|
101
|
+
// The browser auth resolver wins over any caller-supplied one
|
|
102
|
+
// because the auth flow owns token issuance + refresh from now on.
|
|
103
|
+
apiKeyResolver = auth.getToken;
|
|
104
|
+
// 401 from the gateway → token was revoked server-side (typically
|
|
105
|
+
// because the user unsubscribed in another tab). Drop the cached
|
|
106
|
+
// token so the transport's auto-retry hits a fresh signIn() flow.
|
|
107
|
+
onUnauthorized = () => auth.invalidate();
|
|
108
|
+
}
|
|
109
|
+
if (!options.apiKey && !apiKeyResolver) {
|
|
110
|
+
throw new Error("runapps: pass either `apiKey`, `apiKeyResolver`, or `authProvider: \"runapps\"`");
|
|
111
|
+
}
|
|
112
|
+
const transport = new Transport({
|
|
113
|
+
baseURL: baseURL ?? DEFAULT_BASE_URL,
|
|
114
|
+
...(options.apiKey !== undefined && { apiKey: options.apiKey }),
|
|
115
|
+
...(apiKeyResolver !== undefined && { apiKeyResolver }),
|
|
116
|
+
...(onUnauthorized !== undefined && { onUnauthorized }),
|
|
117
|
+
...(options.fetch ? { fetchImpl: options.fetch } : {}),
|
|
118
|
+
});
|
|
119
|
+
// Service constructors receive the shared event bus so each call
|
|
120
|
+
// path (chat/embeddings/image/audio/video/computer) can emit
|
|
121
|
+
// start/end/error around its network operations. Files and Models
|
|
122
|
+
// intentionally don't take it — they're infrastructure, not
|
|
123
|
+
// user-facing LLM calls, and surfacing them would clutter the
|
|
124
|
+
// badge with /v1/models polls.
|
|
125
|
+
this.chat = new ChatService(transport, this.events);
|
|
126
|
+
this.models = new ModelsService(transport);
|
|
127
|
+
this.image = new ImageService(transport, this.events);
|
|
128
|
+
this.audio = new AudioService(transport, this.events);
|
|
129
|
+
this.video = new VideoService(transport, this.events);
|
|
130
|
+
this.computer = new ComputerService(transport, this.events);
|
|
131
|
+
// `project` also scopes the file URLs (/v1/p/<project>/files/...),
|
|
132
|
+
// so two apps never issue byte-identical file requests. Omitted →
|
|
133
|
+
// legacy unscoped /v1/files/... paths.
|
|
134
|
+
this.files = new FilesService(transport, options.project);
|
|
135
|
+
this.embeddings = new EmbeddingsService(transport, this.events);
|
|
136
|
+
}
|
|
137
|
+
/** Force a redirect to the runapps.ai grant page. No-op in static
|
|
138
|
+
* auth mode or in Node. */
|
|
139
|
+
signIn() {
|
|
140
|
+
this.auth?.signIn();
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Clear the cached token + identity from memory and localStorage.
|
|
144
|
+
* The next API call will trigger sign-in again (redirect to grant
|
|
145
|
+
* page). Wire this to a "Sign out" button in your settings UI.
|
|
146
|
+
*
|
|
147
|
+
* No-op in static auth mode or in Node.
|
|
148
|
+
*/
|
|
149
|
+
signOut() {
|
|
150
|
+
this.auth?.signOut();
|
|
151
|
+
}
|
|
152
|
+
/** Currently-authenticated user (runapps auth mode), or null. */
|
|
153
|
+
get user() {
|
|
154
|
+
return this.auth?.user ?? null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Transport } from "./transport.js";
|
|
2
|
+
import type { Usage } from "./types.js";
|
|
3
|
+
import type { SDKEvents } from "./events.js";
|
|
4
|
+
/** Single-step computer-use request — a screenshot + history → next action(s). */
|
|
5
|
+
export interface ComputerStepParams {
|
|
6
|
+
/**
|
|
7
|
+
* Conversation history including screenshots and tool results. Each
|
|
8
|
+
* entry has `role` + `content` (string or array of blocks). Format is
|
|
9
|
+
* intentionally opaque to support both Anthropic and OpenAI computer-use
|
|
10
|
+
* protocols — the gateway adapts.
|
|
11
|
+
*/
|
|
12
|
+
messages: Record<string, unknown>[];
|
|
13
|
+
/** Screen resolution. Defaults to 1920×1080 if omitted. */
|
|
14
|
+
display_width?: number;
|
|
15
|
+
display_height?: number;
|
|
16
|
+
max_tokens?: number;
|
|
17
|
+
enable_zoom?: boolean;
|
|
18
|
+
/** OpenAI Responses-API state chaining. */
|
|
19
|
+
previous_response_id?: string;
|
|
20
|
+
/** Follow-up `computer_call_output` for OpenAI's Responses API. */
|
|
21
|
+
openai_input?: unknown;
|
|
22
|
+
user?: string;
|
|
23
|
+
}
|
|
24
|
+
/** One block of a computer-use response: text, tool_use (Anthropic), or computer_call (OpenAI). */
|
|
25
|
+
export interface ComputerContentBlock {
|
|
26
|
+
type: string;
|
|
27
|
+
text?: string;
|
|
28
|
+
id?: string;
|
|
29
|
+
name?: string;
|
|
30
|
+
/** Anthropic tool input (raw JSON). */
|
|
31
|
+
input?: unknown;
|
|
32
|
+
call_id?: string;
|
|
33
|
+
/** OpenAI computer-call action. */
|
|
34
|
+
action?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
export interface ComputerResponse {
|
|
37
|
+
content: ComputerContentBlock[];
|
|
38
|
+
stop_reason?: string;
|
|
39
|
+
usage: Usage;
|
|
40
|
+
response_id?: string;
|
|
41
|
+
/** "anthropic" | "openai" — which protocol the upstream returned. */
|
|
42
|
+
protocol?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare class ComputerService {
|
|
45
|
+
private readonly transport;
|
|
46
|
+
private readonly events;
|
|
47
|
+
constructor(transport: Transport, events: SDKEvents);
|
|
48
|
+
/**
|
|
49
|
+
* Execute one step of a computer-use agent loop. Given a screenshot
|
|
50
|
+
* and conversation history, returns the next action(s) the model
|
|
51
|
+
* wants the caller to execute.
|
|
52
|
+
*/
|
|
53
|
+
step(model: string, params: ComputerStepParams, init?: {
|
|
54
|
+
signal?: AbortSignal;
|
|
55
|
+
}): Promise<ComputerResponse>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=computer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computer.d.ts","sourceRoot":"","sources":["../src/computer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mEAAmE;IACnE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mGAAmG;AACnG,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,SAAS;IAGpC;;;;OAIG;IACG,IAAI,CACR,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,kBAAkB,EAC1B,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,gBAAgB,CAAC;CAgB7B"}
|
package/dist/computer.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { wrapEvents } from "./event-wrap.js";
|
|
2
|
+
export class ComputerService {
|
|
3
|
+
transport;
|
|
4
|
+
events;
|
|
5
|
+
constructor(transport, events) {
|
|
6
|
+
this.transport = transport;
|
|
7
|
+
this.events = events;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Execute one step of a computer-use agent loop. Given a screenshot
|
|
11
|
+
* and conversation history, returns the next action(s) the model
|
|
12
|
+
* wants the caller to execute.
|
|
13
|
+
*/
|
|
14
|
+
async step(model, params, init) {
|
|
15
|
+
return wrapEvents(this.events, { model, capability: "computer_use" }, () => this.transport.postJSON("/v1/computer/step", { model, ...params }, init), (r) => ({
|
|
16
|
+
totalTokens: r.usage?.completion_tokens,
|
|
17
|
+
costUSD: r.usage?.total_cost,
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=computer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computer.js","sourceRoot":"","sources":["../src/computer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA6C7C,MAAM,OAAO,eAAe;IAEP;IACA;IAFnB,YACmB,SAAoB,EACpB,MAAiB;QADjB,cAAS,GAAT,SAAS,CAAW;QACpB,WAAM,GAAN,MAAM,CAAW;IACjC,CAAC;IAEJ;;;;OAIG;IACH,KAAK,CAAC,IAAI,CACR,KAAa,EACb,MAA0B,EAC1B,IAA+B;QAE/B,OAAO,UAAU,CACf,IAAI,CAAC,MAAM,EACX,EAAE,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,EACrC,GAAG,EAAE,CACH,IAAI,CAAC,SAAS,CAAC,QAAQ,CACrB,mBAAmB,EACnB,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,EACpB,IAAI,CACL,EACH,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACN,WAAW,EAAE,CAAC,CAAC,KAAK,EAAE,iBAAiB;YACvC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU;SAC7B,CAAC,CACH,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Transport } from "./transport.js";
|
|
2
|
+
import type { Usage } from "./types.js";
|
|
3
|
+
import type { SDKEvents } from "./events.js";
|
|
4
|
+
export interface EmbeddingsParams {
|
|
5
|
+
/** Single string OR array of strings — gateway forwards either
|
|
6
|
+
* shape verbatim. Passing a string returns `data: [{...}]` (1
|
|
7
|
+
* element), passing an array returns one element per input. */
|
|
8
|
+
input: string | string[];
|
|
9
|
+
/** OpenAI per-end-user observability tag. */
|
|
10
|
+
user?: string;
|
|
11
|
+
/** "float" (default) or "base64". `base64` packs vectors as
|
|
12
|
+
* little-endian float32 + base64-encoded — saves bandwidth for
|
|
13
|
+
* high-D embeddings (3072-D × 1000 docs is ~3× smaller than the
|
|
14
|
+
* JSON float-array form). */
|
|
15
|
+
encoding_format?: "float" | "base64";
|
|
16
|
+
/** Truncate the output vector. text-embedding-3-* only — other
|
|
17
|
+
* models reject. */
|
|
18
|
+
dimensions?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface Embedding {
|
|
21
|
+
object: "embedding";
|
|
22
|
+
/** Vector. When `encoding_format` was "float" (default), this is
|
|
23
|
+
* `number[]`. When "base64", this is the encoded `string`. */
|
|
24
|
+
embedding: number[] | string;
|
|
25
|
+
index: number;
|
|
26
|
+
}
|
|
27
|
+
/** OpenAI's usage block plus the gateway's billing extension
|
|
28
|
+
* (`total_cost` in USD).
|
|
29
|
+
*
|
|
30
|
+
* Shape parallels the `Usage` type used by chat / image / video so
|
|
31
|
+
* callers can read `.total_cost` on every response uniformly. */
|
|
32
|
+
export interface EmbeddingsUsage extends Usage {
|
|
33
|
+
prompt_tokens: number;
|
|
34
|
+
total_tokens: number;
|
|
35
|
+
}
|
|
36
|
+
export interface EmbeddingsResponse {
|
|
37
|
+
object: "list";
|
|
38
|
+
data: Embedding[];
|
|
39
|
+
model: string;
|
|
40
|
+
usage: EmbeddingsUsage;
|
|
41
|
+
}
|
|
42
|
+
export declare class EmbeddingsService {
|
|
43
|
+
private readonly transport;
|
|
44
|
+
private readonly events;
|
|
45
|
+
constructor(transport: Transport, events: SDKEvents);
|
|
46
|
+
/**
|
|
47
|
+
* Create one or more embeddings.
|
|
48
|
+
*
|
|
49
|
+
* ```ts
|
|
50
|
+
* const r = await client.embeddings.create("text-embedding-3-small", {
|
|
51
|
+
* input: ["alpha", "beta"],
|
|
52
|
+
* dimensions: 1536,
|
|
53
|
+
* });
|
|
54
|
+
* for (const e of r.data) {
|
|
55
|
+
* console.log(e.index, (e.embedding as number[]).slice(0, 4));
|
|
56
|
+
* }
|
|
57
|
+
* console.log(`Cost: $${r.usage.total_cost.toFixed(6)}`);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
create(model: string, params: EmbeddingsParams, init?: {
|
|
61
|
+
signal?: AbortSignal;
|
|
62
|
+
}): Promise<EmbeddingsResponse>;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=embeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAY7C,MAAM,WAAW,gBAAgB;IAC/B;;oEAEgE;IAChE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;kCAG8B;IAC9B,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC;yBACqB;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB;mEAC+D;IAC/D,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;kEAIkE;AAClE,MAAM,WAAW,eAAgB,SAAQ,KAAK;IAC5C,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,SAAS;IAGpC;;;;;;;;;;;;;OAaG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,EACxB,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAC9B,OAAO,CAAC,kBAAkB,CAAC;CAgB/B"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { wrapEvents } from "./event-wrap.js";
|
|
2
|
+
export class EmbeddingsService {
|
|
3
|
+
transport;
|
|
4
|
+
events;
|
|
5
|
+
constructor(transport, events) {
|
|
6
|
+
this.transport = transport;
|
|
7
|
+
this.events = events;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create one or more embeddings.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const r = await client.embeddings.create("text-embedding-3-small", {
|
|
14
|
+
* input: ["alpha", "beta"],
|
|
15
|
+
* dimensions: 1536,
|
|
16
|
+
* });
|
|
17
|
+
* for (const e of r.data) {
|
|
18
|
+
* console.log(e.index, (e.embedding as number[]).slice(0, 4));
|
|
19
|
+
* }
|
|
20
|
+
* console.log(`Cost: $${r.usage.total_cost.toFixed(6)}`);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
async create(model, params, init) {
|
|
24
|
+
return wrapEvents(this.events, { model, capability: "embedding" }, () => this.transport.postJSON("/v1/embeddings", { model, ...params }, init), (r) => ({
|
|
25
|
+
totalTokens: r.usage?.total_tokens,
|
|
26
|
+
costUSD: r.usage?.total_cost,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAqD7C,MAAM,OAAO,iBAAiB;IAET;IACA;IAFnB,YACmB,SAAoB,EACpB,MAAiB;QADjB,cAAS,GAAT,SAAS,CAAW;QACpB,WAAM,GAAN,MAAM,CAAW;IACjC,CAAC;IAEJ;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,MAAM,CACV,KAAa,EACb,MAAwB,EACxB,IAA+B;QAE/B,OAAO,UAAU,CACf,IAAI,CAAC,MAAM,EACX,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,EAClC,GAAG,EAAE,CACH,IAAI,CAAC,SAAS,CAAC,QAAQ,CACrB,gBAAgB,EAChB,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,EACpB,IAAI,CACL,EACH,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACN,WAAW,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY;YAClC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU;SAC7B,CAAC,CACH,CAAC;IACJ,CAAC;CACF"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APIError represents an error returned by the RunApps gateway.
|
|
3
|
+
*
|
|
4
|
+
* Use `instanceof APIError` (or check `name === "APIError"`) to distinguish
|
|
5
|
+
* gateway errors from network / runtime errors:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* try {
|
|
9
|
+
* await client.chat.create({ model: "...", messages: [...] });
|
|
10
|
+
* } catch (e) {
|
|
11
|
+
* if (e instanceof APIError) {
|
|
12
|
+
* console.error(`API ${e.statusCode}: ${e.message}`);
|
|
13
|
+
* } else {
|
|
14
|
+
* throw e;
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare class APIError extends Error {
|
|
20
|
+
readonly statusCode: number;
|
|
21
|
+
readonly type: string;
|
|
22
|
+
constructor(statusCode: number, type: string, message: string);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAM9D"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APIError represents an error returned by the RunApps gateway.
|
|
3
|
+
*
|
|
4
|
+
* Use `instanceof APIError` (or check `name === "APIError"`) to distinguish
|
|
5
|
+
* gateway errors from network / runtime errors:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* try {
|
|
9
|
+
* await client.chat.create({ model: "...", messages: [...] });
|
|
10
|
+
* } catch (e) {
|
|
11
|
+
* if (e instanceof APIError) {
|
|
12
|
+
* console.error(`API ${e.statusCode}: ${e.message}`);
|
|
13
|
+
* } else {
|
|
14
|
+
* throw e;
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export class APIError extends Error {
|
|
20
|
+
statusCode;
|
|
21
|
+
type;
|
|
22
|
+
constructor(statusCode, type, message) {
|
|
23
|
+
super(`runapps: ${statusCode} ${type}: ${message}`);
|
|
24
|
+
this.name = "APIError";
|
|
25
|
+
this.statusCode = statusCode;
|
|
26
|
+
this.type = type;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjB,UAAU,CAAS;IACnB,IAAI,CAAS;IAE7B,YAAY,UAAkB,EAAE,IAAY,EAAE,OAAe;QAC3D,KAAK,CAAC,YAAY,UAAU,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny wrapper used by every LLM-ish service to fire
|
|
3
|
+
* `request:start` → `request:end` / `request:error` events around a
|
|
4
|
+
* single network call. Centralised here so the service files don't
|
|
5
|
+
* duplicate the try/catch + latency-stopwatch pattern N times.
|
|
6
|
+
*
|
|
7
|
+
* Streaming chat has its own logic (it must yield deltas mid-flight)
|
|
8
|
+
* — see `wrapStream` below.
|
|
9
|
+
*/
|
|
10
|
+
import { type SDKCapability, type SDKEvents } from "./events.js";
|
|
11
|
+
interface CallMeta {
|
|
12
|
+
model: string;
|
|
13
|
+
capability: SDKCapability;
|
|
14
|
+
}
|
|
15
|
+
interface EndInfo {
|
|
16
|
+
totalTokens?: number;
|
|
17
|
+
costUSD?: number;
|
|
18
|
+
finishReason?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run `fn` while emitting start/end/error events around it.
|
|
22
|
+
* `extractEnd` plucks token / cost / finish_reason off the response
|
|
23
|
+
* shape so each service can map its own response type without the
|
|
24
|
+
* helper knowing about it.
|
|
25
|
+
*
|
|
26
|
+
* Re-throws on error so the caller still sees the rejection — the
|
|
27
|
+
* helper only inserts telemetry, it doesn't swallow.
|
|
28
|
+
*/
|
|
29
|
+
export declare function wrapEvents<T>(events: SDKEvents, meta: CallMeta, fn: () => Promise<T>, extractEnd?: (r: T) => EndInfo): Promise<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Token-count estimator for stream deltas. Stream chunks carry text,
|
|
32
|
+
* not tokens — getting an exact count would mean shipping a
|
|
33
|
+
* tokenizer in the SDK (huge), so we use the standard ~4-chars =
|
|
34
|
+
* 1-token English heuristic. Off by 10-30% for code or non-English,
|
|
35
|
+
* but the badge UI shows tokens/sec as a vibe indicator, not for
|
|
36
|
+
* billing, so the imprecision is fine.
|
|
37
|
+
*/
|
|
38
|
+
export declare function estimateTokens(text: string): number;
|
|
39
|
+
/**
|
|
40
|
+
* Stream wrapper — same start/end/error envelope as wrapEvents but
|
|
41
|
+
* also fires `request:streamDelta` for each yielded chunk so the
|
|
42
|
+
* badge's tokens/sec sliding window has samples.
|
|
43
|
+
*
|
|
44
|
+
* Generic over the chunk type because each service's stream
|
|
45
|
+
* (chat / video / etc.) carries its own shape. The caller passes a
|
|
46
|
+
* `extractDelta` that pulls text + cumulative usage off the chunk.
|
|
47
|
+
*
|
|
48
|
+
* Usage:
|
|
49
|
+
* yield* wrapStream(events, {model, capability}, () => transport.postJSONStream(...),
|
|
50
|
+
* (chunk) => ({ deltaText: chunk.choices[0]?.delta?.content, usage: chunk.usage }));
|
|
51
|
+
*/
|
|
52
|
+
export declare function wrapStream<TChunk>(events: SDKEvents, meta: CallMeta, source: () => AsyncIterable<TChunk>, extractDelta: (chunk: TChunk) => {
|
|
53
|
+
deltaText?: string;
|
|
54
|
+
completionTokens?: number;
|
|
55
|
+
costUSD?: number;
|
|
56
|
+
finishReason?: string;
|
|
57
|
+
}): AsyncGenerator<TChunk, void, unknown>;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=event-wrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-wrap.d.ts","sourceRoot":"","sources":["../src/event-wrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE/E,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,aAAa,CAAC;CAC3B;AAED,UAAU,OAAO;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,GAC7B,OAAO,CAAC,CAAC,CAAC,CAmCZ;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAuB,UAAU,CAAC,MAAM,EACtC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,aAAa,CAAC,MAAM,CAAC,EACnC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IAInB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAsDvC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny wrapper used by every LLM-ish service to fire
|
|
3
|
+
* `request:start` → `request:end` / `request:error` events around a
|
|
4
|
+
* single network call. Centralised here so the service files don't
|
|
5
|
+
* duplicate the try/catch + latency-stopwatch pattern N times.
|
|
6
|
+
*
|
|
7
|
+
* Streaming chat has its own logic (it must yield deltas mid-flight)
|
|
8
|
+
* — see `wrapStream` below.
|
|
9
|
+
*/
|
|
10
|
+
import { newRequestId } from "./events.js";
|
|
11
|
+
/**
|
|
12
|
+
* Run `fn` while emitting start/end/error events around it.
|
|
13
|
+
* `extractEnd` plucks token / cost / finish_reason off the response
|
|
14
|
+
* shape so each service can map its own response type without the
|
|
15
|
+
* helper knowing about it.
|
|
16
|
+
*
|
|
17
|
+
* Re-throws on error so the caller still sees the rejection — the
|
|
18
|
+
* helper only inserts telemetry, it doesn't swallow.
|
|
19
|
+
*/
|
|
20
|
+
export async function wrapEvents(events, meta, fn, extractEnd) {
|
|
21
|
+
const id = newRequestId();
|
|
22
|
+
const startedAt = Date.now();
|
|
23
|
+
events.emit("request:start", {
|
|
24
|
+
id,
|
|
25
|
+
model: meta.model,
|
|
26
|
+
capability: meta.capability,
|
|
27
|
+
startedAt,
|
|
28
|
+
streaming: false,
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
const result = await fn();
|
|
32
|
+
const info = extractEnd ? extractEnd(result) : {};
|
|
33
|
+
events.emit("request:end", {
|
|
34
|
+
id,
|
|
35
|
+
model: meta.model,
|
|
36
|
+
capability: meta.capability,
|
|
37
|
+
latencyMs: Date.now() - startedAt,
|
|
38
|
+
totalTokens: info.totalTokens ?? 0,
|
|
39
|
+
...(info.costUSD !== undefined && { costUSD: info.costUSD }),
|
|
40
|
+
...(info.finishReason !== undefined && { finishReason: info.finishReason }),
|
|
41
|
+
});
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
const e = err;
|
|
46
|
+
events.emit("request:error", {
|
|
47
|
+
id,
|
|
48
|
+
model: meta.model,
|
|
49
|
+
capability: meta.capability,
|
|
50
|
+
latencyMs: Date.now() - startedAt,
|
|
51
|
+
error: e,
|
|
52
|
+
...(typeof e.statusCode === "number" && { statusCode: e.statusCode }),
|
|
53
|
+
});
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Token-count estimator for stream deltas. Stream chunks carry text,
|
|
59
|
+
* not tokens — getting an exact count would mean shipping a
|
|
60
|
+
* tokenizer in the SDK (huge), so we use the standard ~4-chars =
|
|
61
|
+
* 1-token English heuristic. Off by 10-30% for code or non-English,
|
|
62
|
+
* but the badge UI shows tokens/sec as a vibe indicator, not for
|
|
63
|
+
* billing, so the imprecision is fine.
|
|
64
|
+
*/
|
|
65
|
+
export function estimateTokens(text) {
|
|
66
|
+
if (!text)
|
|
67
|
+
return 0;
|
|
68
|
+
return Math.max(1, Math.round(text.length / 4));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Stream wrapper — same start/end/error envelope as wrapEvents but
|
|
72
|
+
* also fires `request:streamDelta` for each yielded chunk so the
|
|
73
|
+
* badge's tokens/sec sliding window has samples.
|
|
74
|
+
*
|
|
75
|
+
* Generic over the chunk type because each service's stream
|
|
76
|
+
* (chat / video / etc.) carries its own shape. The caller passes a
|
|
77
|
+
* `extractDelta` that pulls text + cumulative usage off the chunk.
|
|
78
|
+
*
|
|
79
|
+
* Usage:
|
|
80
|
+
* yield* wrapStream(events, {model, capability}, () => transport.postJSONStream(...),
|
|
81
|
+
* (chunk) => ({ deltaText: chunk.choices[0]?.delta?.content, usage: chunk.usage }));
|
|
82
|
+
*/
|
|
83
|
+
export async function* wrapStream(events, meta, source, extractDelta) {
|
|
84
|
+
const id = newRequestId();
|
|
85
|
+
const startedAt = Date.now();
|
|
86
|
+
events.emit("request:start", {
|
|
87
|
+
id,
|
|
88
|
+
model: meta.model,
|
|
89
|
+
capability: meta.capability,
|
|
90
|
+
startedAt,
|
|
91
|
+
streaming: true,
|
|
92
|
+
});
|
|
93
|
+
let totalTokens = 0;
|
|
94
|
+
let lastUsageTokens;
|
|
95
|
+
let costUSD;
|
|
96
|
+
let finishReason;
|
|
97
|
+
try {
|
|
98
|
+
for await (const chunk of source()) {
|
|
99
|
+
const info = extractDelta(chunk);
|
|
100
|
+
if (info.deltaText) {
|
|
101
|
+
const delta = estimateTokens(info.deltaText);
|
|
102
|
+
totalTokens += delta;
|
|
103
|
+
events.emit("request:streamDelta", {
|
|
104
|
+
id,
|
|
105
|
+
deltaTokens: delta,
|
|
106
|
+
totalTokens,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (info.completionTokens !== undefined)
|
|
110
|
+
lastUsageTokens = info.completionTokens;
|
|
111
|
+
if (info.costUSD !== undefined)
|
|
112
|
+
costUSD = info.costUSD;
|
|
113
|
+
if (info.finishReason !== undefined)
|
|
114
|
+
finishReason = info.finishReason;
|
|
115
|
+
yield chunk;
|
|
116
|
+
}
|
|
117
|
+
events.emit("request:end", {
|
|
118
|
+
id,
|
|
119
|
+
model: meta.model,
|
|
120
|
+
capability: meta.capability,
|
|
121
|
+
latencyMs: Date.now() - startedAt,
|
|
122
|
+
// Prefer the exact upstream count over our heuristic when it
|
|
123
|
+
// arrived in the final chunk.
|
|
124
|
+
totalTokens: lastUsageTokens ?? totalTokens,
|
|
125
|
+
...(costUSD !== undefined && { costUSD }),
|
|
126
|
+
...(finishReason !== undefined && { finishReason }),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
const e = err;
|
|
131
|
+
events.emit("request:error", {
|
|
132
|
+
id,
|
|
133
|
+
model: meta.model,
|
|
134
|
+
capability: meta.capability,
|
|
135
|
+
latencyMs: Date.now() - startedAt,
|
|
136
|
+
error: e,
|
|
137
|
+
...(typeof e.statusCode === "number" && { statusCode: e.statusCode }),
|
|
138
|
+
});
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=event-wrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-wrap.js","sourceRoot":"","sources":["../src/event-wrap.ts"],"names":[],"mappings":"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"}
|