torque-assistant 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Torque
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # torque-assistant
2
+
3
+ Official **server-side** client for Torque Assistant (Platform API v1).
4
+
5
+ Uses the same business API key as Checkout (`sk_live_…`). Targets BFF / backend integrators — not in-app browser sessions.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ yarn add torque-assistant @torquefi/types
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```ts
16
+ import { createTorqueAssistantFromEnv } from 'torque-assistant'
17
+
18
+ const assistant = createTorqueAssistantFromEnv()
19
+
20
+ const reply = await assistant.chat({
21
+ messages: [{ role: 'user', content: 'Summarize my BTC exposure' }],
22
+ context: { walletAddress: '0x…', chainId: 8453 },
23
+ })
24
+
25
+ console.log(reply.content, reply.functionResults)
26
+ ```
27
+
28
+ ## Streaming (SSE)
29
+
30
+ ```ts
31
+ for await (const event of assistant.chatStream({
32
+ messages: [{ role: 'user', content: 'What moved today?' }],
33
+ context: { walletAddress: '0x…', chainId: 8453 },
34
+ })) {
35
+ if (event.type === 'delta') process.stdout.write(event.text)
36
+ if (event.type === 'done') console.log(event.functionResults)
37
+ if (event.type === 'error') throw new Error(event.message)
38
+ }
39
+ ```
40
+
41
+ Pass `signal` via the second argument to cancel:
42
+
43
+ ```ts
44
+ const controller = new AbortController()
45
+ const stream = assistant.chatStream(request, { signal: controller.signal })
46
+ ```
47
+
48
+ ## Configuration
49
+
50
+ ```ts
51
+ import { createTorqueAssistant } from 'torque-assistant'
52
+
53
+ const assistant = createTorqueAssistant({
54
+ apiKey: process.env.TORQUE_API_KEY!,
55
+ baseUrl: 'https://app.torque.fi', // optional
56
+ timeout: 180_000, // optional — Gemini tool rounds can be slow
57
+ })
58
+ ```
59
+
60
+ **Environment variables:** `TORQUE_API_KEY`, optional `TORQUE_BASE_URL`.
61
+
62
+ ## Endpoint
63
+
64
+ | Method | SDK | HTTP |
65
+ |--------|-----|------|
66
+ | `chat` | JSON response | `POST /api/v1/assistant/chat` |
67
+ | `chatStream` | Async iterator over SSE | `POST /api/v1/assistant/chat?stream=true` |
68
+
69
+ ## Errors
70
+
71
+ | Status | Code | Class |
72
+ |--------|------|-------|
73
+ | `402` | `assistant_credits_exhausted` | `TorqueAssistantCreditsError` |
74
+ | v1 JSON | `{ error: { code, message } }` | `TorqueAssistantError` |
75
+
76
+ ```ts
77
+ import {
78
+ TorqueAssistantCreditsError,
79
+ TorqueAssistantError,
80
+ ASSISTANT_CREDITS_ERROR_CODE,
81
+ } from 'torque-assistant'
82
+
83
+ try {
84
+ await assistant.chat({ messages, context })
85
+ } catch (e) {
86
+ if (e instanceof TorqueAssistantCreditsError) {
87
+ console.log(e.remaining, '/', e.limit, 'messages left')
88
+ }
89
+ }
90
+ ```
91
+
92
+ ## Actions / signing
93
+
94
+ `functionResults` may include confirmable swap, transfer, lend, or borrow payloads. This SDK does **not** sign or submit transactions — implement confirmation in your client (same contract as in-app `AssistantTransactionHandler`).
95
+
96
+ ## Docs
97
+
98
+ - [SDK roadmap](../../public/docs/developer/SDK_ROADMAP.md)
99
+ - [Torque API v1 — Assistant](../../public/docs/developer/TORQUE_API_V1.md)
100
+
101
+ ## License
102
+
103
+ MIT
@@ -0,0 +1,25 @@
1
+ export interface TorqueAssistantErrorDetails {
2
+ code: string;
3
+ statusCode: number;
4
+ details?: Record<string, unknown>;
5
+ }
6
+ export declare class TorqueAssistantError extends Error {
7
+ code: string;
8
+ statusCode: number;
9
+ details?: Record<string, unknown>;
10
+ constructor(message: string, options: TorqueAssistantErrorDetails);
11
+ }
12
+ export declare class TorqueAssistantCreditsError extends TorqueAssistantError {
13
+ upgrade?: boolean;
14
+ remaining?: number;
15
+ limit?: number;
16
+ resetAt?: number | null;
17
+ constructor(message: string, options: {
18
+ statusCode: number;
19
+ upgrade?: boolean;
20
+ remaining?: number;
21
+ limit?: number;
22
+ resetAt?: number | null;
23
+ });
24
+ }
25
+ export declare function parseAssistantError(body: unknown, statusCode: number, fallbackMessage: string): TorqueAssistantError;
package/dist/http.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { AssistantChatPostBody, AssistantChatResponse } from '@torquefi/types/assistant';
2
+ export interface TorqueAssistantHttpConfig {
3
+ apiKey: string;
4
+ baseUrl: string;
5
+ timeout: number;
6
+ }
7
+ export declare function torqueAssistantPost<T>(config: TorqueAssistantHttpConfig, path: string, body: AssistantChatPostBody, signal?: AbortSignal): Promise<T>;
8
+ export declare function torqueAssistantChat(config: TorqueAssistantHttpConfig, body: AssistantChatPostBody, signal?: AbortSignal): Promise<AssistantChatResponse>;
@@ -0,0 +1,29 @@
1
+ import type { AssistantChatPostBody, AssistantChatResponse, AssistantChatStreamEvent } from '@torquefi/types/assistant';
2
+ import type { TorquePlatformClientConfig } from '@torquefi/types/platform';
3
+ export type { TorquePlatformClientConfig as TorqueAssistantConfig } from '@torquefi/types/platform';
4
+ export interface TorqueAssistantOptions extends TorquePlatformClientConfig {
5
+ }
6
+ export type AssistantChatRequest = AssistantChatPostBody;
7
+ export interface AssistantChatStreamOptions {
8
+ signal?: AbortSignal;
9
+ }
10
+ export { TorqueAssistantError, TorqueAssistantCreditsError, } from './errors';
11
+ export { ASSISTANT_CREDITS_ERROR_CODE } from '@torquefi/types/assistant';
12
+ export type { AssistantChatContext, AssistantChatFunctionResult, AssistantChatMessage, AssistantChatPostBody, AssistantChatResponse, AssistantChatStreamEvent, } from '@torquefi/types/assistant';
13
+ export declare class TorqueAssistant {
14
+ private readonly http;
15
+ constructor(config: TorqueAssistantOptions);
16
+ /**
17
+ * Non-streaming chat. POST /api/v1/assistant/chat
18
+ */
19
+ chat(request: AssistantChatRequest, options?: AssistantChatStreamOptions): Promise<AssistantChatResponse>;
20
+ /**
21
+ * Streaming chat over SSE. POST /api/v1/assistant/chat?stream=true
22
+ */
23
+ chatStream(request: AssistantChatRequest, options?: AssistantChatStreamOptions): AsyncGenerator<AssistantChatStreamEvent>;
24
+ }
25
+ export declare function createTorqueAssistant(config: TorqueAssistantOptions): TorqueAssistant;
26
+ /**
27
+ * Reads TORQUE_API_KEY and optional TORQUE_BASE_URL from the environment.
28
+ */
29
+ export declare function createTorqueAssistantFromEnv(overrides?: Partial<TorqueAssistantOptions>): TorqueAssistant;
@@ -0,0 +1,307 @@
1
+ import { ASSISTANT_CREDITS_ERROR_CODE } from '@torquefi/types/assistant';
2
+ export { ASSISTANT_CREDITS_ERROR_CODE } from '@torquefi/types/assistant';
3
+
4
+ class TorqueAssistantError extends Error {
5
+ constructor(message, options) {
6
+ super(message);
7
+ this.name = 'TorqueAssistantError';
8
+ this.code = options.code;
9
+ this.statusCode = options.statusCode;
10
+ this.details = options.details;
11
+ Object.setPrototypeOf(this, TorqueAssistantError.prototype);
12
+ }
13
+ }
14
+ class TorqueAssistantCreditsError extends TorqueAssistantError {
15
+ constructor(message, options) {
16
+ super(message, {
17
+ code: ASSISTANT_CREDITS_ERROR_CODE,
18
+ statusCode: options.statusCode,
19
+ details: {
20
+ upgrade: options.upgrade,
21
+ remaining: options.remaining,
22
+ limit: options.limit,
23
+ resetAt: options.resetAt,
24
+ },
25
+ });
26
+ this.name = 'TorqueAssistantCreditsError';
27
+ this.upgrade = options.upgrade;
28
+ this.remaining = options.remaining;
29
+ this.limit = options.limit;
30
+ this.resetAt = options.resetAt;
31
+ Object.setPrototypeOf(this, TorqueAssistantCreditsError.prototype);
32
+ }
33
+ }
34
+ function parseAssistantError(body, statusCode, fallbackMessage) {
35
+ const payload = body;
36
+ if (statusCode === 402 &&
37
+ typeof payload?.error === 'string' &&
38
+ payload.error === ASSISTANT_CREDITS_ERROR_CODE) {
39
+ return new TorqueAssistantCreditsError(typeof payload.message === 'string' ? payload.message : fallbackMessage, {
40
+ statusCode,
41
+ upgrade: payload.upgrade,
42
+ remaining: payload.remaining,
43
+ limit: payload.limit,
44
+ resetAt: payload.resetAt,
45
+ });
46
+ }
47
+ if (payload?.error && typeof payload.error === 'object') {
48
+ const err = payload.error;
49
+ return new TorqueAssistantError(typeof err.message === 'string' ? err.message : fallbackMessage, {
50
+ code: typeof err.code === 'string' ? err.code : 'API_ERROR',
51
+ statusCode,
52
+ details: err.details,
53
+ });
54
+ }
55
+ if (typeof payload?.error === 'string') {
56
+ return new TorqueAssistantError(typeof payload.message === 'string' ? payload.message : fallbackMessage, {
57
+ code: payload.error,
58
+ statusCode,
59
+ });
60
+ }
61
+ return new TorqueAssistantError(fallbackMessage, {
62
+ code: 'API_ERROR',
63
+ statusCode,
64
+ });
65
+ }
66
+
67
+ async function torqueAssistantPost(config, path, body, signal) {
68
+ const url = `${config.baseUrl}${path}`;
69
+ const controller = new AbortController();
70
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
71
+ const onAbort = () => controller.abort();
72
+ if (signal) {
73
+ if (signal.aborted)
74
+ controller.abort();
75
+ else
76
+ signal.addEventListener('abort', onAbort, { once: true });
77
+ }
78
+ try {
79
+ const response = await fetch(url, {
80
+ method: 'POST',
81
+ headers: {
82
+ Accept: 'application/json',
83
+ 'Content-Type': 'application/json',
84
+ Authorization: `Bearer ${config.apiKey}`,
85
+ },
86
+ body: JSON.stringify(body),
87
+ signal: controller.signal,
88
+ });
89
+ clearTimeout(timeoutId);
90
+ signal?.removeEventListener('abort', onAbort);
91
+ const payload = await response.json().catch(() => ({}));
92
+ if (!response.ok) {
93
+ throw parseAssistantError(payload, response.status, `HTTP ${response.status}: ${response.statusText}`);
94
+ }
95
+ return payload;
96
+ }
97
+ catch (error) {
98
+ clearTimeout(timeoutId);
99
+ signal?.removeEventListener('abort', onAbort);
100
+ if (error instanceof TorqueAssistantError) {
101
+ throw error;
102
+ }
103
+ if (error instanceof Error) {
104
+ if (error.name === 'AbortError') {
105
+ throw new TorqueAssistantError('Request timeout', {
106
+ code: 'TIMEOUT',
107
+ statusCode: 408,
108
+ });
109
+ }
110
+ throw new TorqueAssistantError(error.message, {
111
+ code: 'NETWORK_ERROR',
112
+ statusCode: 500,
113
+ });
114
+ }
115
+ throw new TorqueAssistantError('Request failed', {
116
+ code: 'UNKNOWN_ERROR',
117
+ statusCode: 500,
118
+ });
119
+ }
120
+ }
121
+ async function torqueAssistantChat(config, body, signal) {
122
+ return torqueAssistantPost(config, '/api/v1/assistant/chat', body, signal);
123
+ }
124
+
125
+ function parseJsonContent(content) {
126
+ if (typeof content === 'string')
127
+ return content;
128
+ if (Array.isArray(content)) {
129
+ return content
130
+ .map((part) => part?.text ?? '')
131
+ .join('');
132
+ }
133
+ return '';
134
+ }
135
+ function* eventsFromJsonPayload(payload) {
136
+ const text = parseJsonContent(payload.content);
137
+ if (text) {
138
+ yield { type: 'delta', text };
139
+ }
140
+ yield { type: 'done', functionResults: payload.functionResults };
141
+ }
142
+ async function* torqueAssistantChatStream(config, body, signal) {
143
+ const url = `${config.baseUrl}/api/v1/assistant/chat?stream=true`;
144
+ const controller = new AbortController();
145
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
146
+ const onAbort = () => controller.abort();
147
+ if (signal) {
148
+ if (signal.aborted)
149
+ controller.abort();
150
+ else
151
+ signal.addEventListener('abort', onAbort, { once: true });
152
+ }
153
+ try {
154
+ const response = await fetch(url, {
155
+ method: 'POST',
156
+ headers: {
157
+ Accept: 'text/event-stream, application/json',
158
+ 'Content-Type': 'application/json',
159
+ Authorization: `Bearer ${config.apiKey}`,
160
+ },
161
+ body: JSON.stringify(body),
162
+ signal: controller.signal,
163
+ });
164
+ clearTimeout(timeoutId);
165
+ signal?.removeEventListener('abort', onAbort);
166
+ if (!response.ok) {
167
+ const payload = await response.json().catch(() => ({}));
168
+ throw parseAssistantError(payload, response.status, `HTTP ${response.status}: ${response.statusText}`);
169
+ }
170
+ const contentType = response.headers.get('content-type') ?? '';
171
+ if (contentType.includes('application/json')) {
172
+ const payload = (await response.json().catch(() => ({})));
173
+ yield* eventsFromJsonPayload(payload);
174
+ return;
175
+ }
176
+ if (!response.body) {
177
+ yield { type: 'error', message: 'No response body.' };
178
+ return;
179
+ }
180
+ const reader = response.body.getReader();
181
+ const decoder = new TextDecoder();
182
+ let buf = '';
183
+ while (true) {
184
+ const { done, value } = await reader.read();
185
+ if (done)
186
+ break;
187
+ buf += decoder.decode(value, { stream: true });
188
+ const lines = buf.split('\n');
189
+ buf = lines.pop() ?? '';
190
+ for (const line of lines) {
191
+ if (!line.startsWith('data: '))
192
+ continue;
193
+ const raw = line.slice(6).trim();
194
+ if (raw === '[DONE]') {
195
+ yield { type: 'done' };
196
+ return;
197
+ }
198
+ let event;
199
+ try {
200
+ event = JSON.parse(raw);
201
+ }
202
+ catch {
203
+ continue;
204
+ }
205
+ if (event.type === 'delta' && event.text) {
206
+ yield { type: 'delta', text: event.text };
207
+ }
208
+ else if (event.type === 'correction' && event.text) {
209
+ yield { type: 'correction', text: event.text };
210
+ }
211
+ else if (event.type === 'done') {
212
+ yield { type: 'done', functionResults: event.functionResults };
213
+ return;
214
+ }
215
+ else if (event.type === 'error') {
216
+ yield { type: 'error', message: event.message };
217
+ return;
218
+ }
219
+ }
220
+ }
221
+ yield { type: 'done' };
222
+ }
223
+ catch (error) {
224
+ clearTimeout(timeoutId);
225
+ signal?.removeEventListener('abort', onAbort);
226
+ if (error instanceof TorqueAssistantError) {
227
+ throw error;
228
+ }
229
+ if (error instanceof Error && error.name === 'AbortError') {
230
+ yield { type: 'done' };
231
+ return;
232
+ }
233
+ if (error instanceof Error) {
234
+ throw new TorqueAssistantError(error.message, {
235
+ code: 'NETWORK_ERROR',
236
+ statusCode: 500,
237
+ });
238
+ }
239
+ throw new TorqueAssistantError('Stream failed', {
240
+ code: 'UNKNOWN_ERROR',
241
+ statusCode: 500,
242
+ });
243
+ }
244
+ }
245
+
246
+ function validateConfig(config) {
247
+ if (!config.apiKey?.trim()) {
248
+ throw new TorqueAssistantError('API key is required', {
249
+ code: 'INVALID_CONFIG',
250
+ statusCode: 400,
251
+ });
252
+ }
253
+ if (config.timeout != null && (typeof config.timeout !== 'number' || config.timeout <= 0)) {
254
+ throw new TorqueAssistantError('Timeout must be a positive number', {
255
+ code: 'INVALID_CONFIG',
256
+ statusCode: 400,
257
+ });
258
+ }
259
+ }
260
+ function toHttpConfig(config) {
261
+ return {
262
+ apiKey: config.apiKey.trim(),
263
+ baseUrl: (config.baseUrl || 'https://app.torque.fi').replace(/\/$/, ''),
264
+ timeout: config.timeout ?? 180000,
265
+ };
266
+ }
267
+ class TorqueAssistant {
268
+ constructor(config) {
269
+ validateConfig(config);
270
+ this.http = toHttpConfig(config);
271
+ }
272
+ /**
273
+ * Non-streaming chat. POST /api/v1/assistant/chat
274
+ */
275
+ async chat(request, options) {
276
+ return torqueAssistantChat(this.http, request, options?.signal);
277
+ }
278
+ /**
279
+ * Streaming chat over SSE. POST /api/v1/assistant/chat?stream=true
280
+ */
281
+ chatStream(request, options) {
282
+ return torqueAssistantChatStream(this.http, request, options?.signal);
283
+ }
284
+ }
285
+ function createTorqueAssistant(config) {
286
+ return new TorqueAssistant(config);
287
+ }
288
+ /**
289
+ * Reads TORQUE_API_KEY and optional TORQUE_BASE_URL from the environment.
290
+ */
291
+ function createTorqueAssistantFromEnv(overrides) {
292
+ const apiKey = process.env.TORQUE_API_KEY || overrides?.apiKey;
293
+ if (!apiKey) {
294
+ throw new TorqueAssistantError('TORQUE_API_KEY environment variable is required', {
295
+ code: 'MISSING_ENV_VARS',
296
+ statusCode: 400,
297
+ });
298
+ }
299
+ return new TorqueAssistant({
300
+ apiKey,
301
+ baseUrl: process.env.TORQUE_BASE_URL || overrides?.baseUrl,
302
+ timeout: overrides?.timeout,
303
+ });
304
+ }
305
+
306
+ export { TorqueAssistant, TorqueAssistantCreditsError, TorqueAssistantError, createTorqueAssistant, createTorqueAssistantFromEnv };
307
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/errors.ts","../src/http.ts","../src/stream.ts","../src/index.ts"],"sourcesContent":["import { ASSISTANT_CREDITS_ERROR_CODE } from '@torquefi/types/assistant'\n\nexport interface TorqueAssistantErrorDetails {\n code: string\n statusCode: number\n details?: Record<string, unknown>\n}\n\nexport class TorqueAssistantError extends Error {\n code: string\n statusCode: number\n details?: Record<string, unknown>\n\n constructor(message: string, options: TorqueAssistantErrorDetails) {\n super(message)\n this.name = 'TorqueAssistantError'\n this.code = options.code\n this.statusCode = options.statusCode\n this.details = options.details\n Object.setPrototypeOf(this, TorqueAssistantError.prototype)\n }\n}\n\nexport class TorqueAssistantCreditsError extends TorqueAssistantError {\n upgrade?: boolean\n remaining?: number\n limit?: number\n resetAt?: number | null\n\n constructor(\n message: string,\n options: {\n statusCode: number\n upgrade?: boolean\n remaining?: number\n limit?: number\n resetAt?: number | null\n },\n ) {\n super(message, {\n code: ASSISTANT_CREDITS_ERROR_CODE,\n statusCode: options.statusCode,\n details: {\n upgrade: options.upgrade,\n remaining: options.remaining,\n limit: options.limit,\n resetAt: options.resetAt,\n },\n })\n this.name = 'TorqueAssistantCreditsError'\n this.upgrade = options.upgrade\n this.remaining = options.remaining\n this.limit = options.limit\n this.resetAt = options.resetAt\n Object.setPrototypeOf(this, TorqueAssistantCreditsError.prototype)\n }\n}\n\nexport function parseAssistantError(\n body: unknown,\n statusCode: number,\n fallbackMessage: string,\n): TorqueAssistantError {\n const payload = body as {\n error?: string | { code?: string; message?: string; details?: Record<string, unknown> }\n message?: string\n upgrade?: boolean\n remaining?: number\n limit?: number\n resetAt?: number | null\n } | null\n\n if (\n statusCode === 402 &&\n typeof payload?.error === 'string' &&\n payload.error === ASSISTANT_CREDITS_ERROR_CODE\n ) {\n return new TorqueAssistantCreditsError(\n typeof payload.message === 'string' ? payload.message : fallbackMessage,\n {\n statusCode,\n upgrade: payload.upgrade,\n remaining: payload.remaining,\n limit: payload.limit,\n resetAt: payload.resetAt,\n },\n )\n }\n\n if (payload?.error && typeof payload.error === 'object') {\n const err = payload.error\n return new TorqueAssistantError(\n typeof err.message === 'string' ? err.message : fallbackMessage,\n {\n code: typeof err.code === 'string' ? err.code : 'API_ERROR',\n statusCode,\n details: err.details,\n },\n )\n }\n\n if (typeof payload?.error === 'string') {\n return new TorqueAssistantError(\n typeof payload.message === 'string' ? payload.message : fallbackMessage,\n {\n code: payload.error,\n statusCode,\n },\n )\n }\n\n return new TorqueAssistantError(fallbackMessage, {\n code: 'API_ERROR',\n statusCode,\n })\n}\n","import type { AssistantChatPostBody, AssistantChatResponse } from '@torquefi/types/assistant'\n\nimport { parseAssistantError, TorqueAssistantError } from './errors'\n\nexport interface TorqueAssistantHttpConfig {\n apiKey: string\n baseUrl: string\n timeout: number\n}\n\nexport async function torqueAssistantPost<T>(\n config: TorqueAssistantHttpConfig,\n path: string,\n body: AssistantChatPostBody,\n signal?: AbortSignal,\n): Promise<T> {\n const url = `${config.baseUrl}${path}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), config.timeout)\n\n const onAbort = () => controller.abort()\n if (signal) {\n if (signal.aborted) controller.abort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n const payload: unknown = await response.json().catch(() => ({}))\n\n if (!response.ok) {\n throw parseAssistantError(\n payload,\n response.status,\n `HTTP ${response.status}: ${response.statusText}`,\n )\n }\n\n return payload as T\n } catch (error) {\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n if (error instanceof TorqueAssistantError) {\n throw error\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new TorqueAssistantError('Request timeout', {\n code: 'TIMEOUT',\n statusCode: 408,\n })\n }\n throw new TorqueAssistantError(error.message, {\n code: 'NETWORK_ERROR',\n statusCode: 500,\n })\n }\n\n throw new TorqueAssistantError('Request failed', {\n code: 'UNKNOWN_ERROR',\n statusCode: 500,\n })\n }\n}\n\nexport async function torqueAssistantChat(\n config: TorqueAssistantHttpConfig,\n body: AssistantChatPostBody,\n signal?: AbortSignal,\n): Promise<AssistantChatResponse> {\n return torqueAssistantPost<AssistantChatResponse>(\n config,\n '/api/v1/assistant/chat',\n body,\n signal,\n )\n}\n","import type {\n AssistantChatFunctionResult,\n AssistantChatPostBody,\n AssistantChatStreamEvent,\n} from '@torquefi/types/assistant'\n\nimport { parseAssistantError, TorqueAssistantError } from './errors'\nimport type { TorqueAssistantHttpConfig } from './http'\n\ntype AssistantChatSsePayload = {\n type: string\n text?: string\n message?: string\n functionResults?: AssistantChatFunctionResult[]\n}\n\nfunction parseJsonContent(content: unknown): string {\n if (typeof content === 'string') return content\n if (Array.isArray(content)) {\n return (content as Array<{ text?: string }>)\n .map((part) => part?.text ?? '')\n .join('')\n }\n return ''\n}\n\nfunction* eventsFromJsonPayload(payload: {\n content?: unknown\n functionResults?: AssistantChatFunctionResult[]\n}): Generator<AssistantChatStreamEvent> {\n const text = parseJsonContent(payload.content)\n if (text) {\n yield { type: 'delta', text }\n }\n yield { type: 'done', functionResults: payload.functionResults }\n}\n\nexport async function* torqueAssistantChatStream(\n config: TorqueAssistantHttpConfig,\n body: AssistantChatPostBody,\n signal?: AbortSignal,\n): AsyncGenerator<AssistantChatStreamEvent> {\n const url = `${config.baseUrl}/api/v1/assistant/chat?stream=true`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), config.timeout)\n\n const onAbort = () => controller.abort()\n if (signal) {\n if (signal.aborted) controller.abort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'text/event-stream, application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n if (!response.ok) {\n const payload: unknown = await response.json().catch(() => ({}))\n throw parseAssistantError(\n payload,\n response.status,\n `HTTP ${response.status}: ${response.statusText}`,\n )\n }\n\n const contentType = response.headers.get('content-type') ?? ''\n\n if (contentType.includes('application/json')) {\n const payload = (await response.json().catch(() => ({}))) as {\n content?: unknown\n functionResults?: AssistantChatFunctionResult[]\n }\n yield* eventsFromJsonPayload(payload)\n return\n }\n\n if (!response.body) {\n yield { type: 'error', message: 'No response body.' }\n return\n }\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buf += decoder.decode(value, { stream: true })\n const lines = buf.split('\\n')\n buf = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n\n const raw = line.slice(6).trim()\n if (raw === '[DONE]') {\n yield { type: 'done' }\n return\n }\n\n let event: AssistantChatSsePayload\n try {\n event = JSON.parse(raw) as AssistantChatSsePayload\n } catch {\n continue\n }\n\n if (event.type === 'delta' && event.text) {\n yield { type: 'delta', text: event.text }\n } else if (event.type === 'correction' && event.text) {\n yield { type: 'correction', text: event.text }\n } else if (event.type === 'done') {\n yield { type: 'done', functionResults: event.functionResults }\n return\n } else if (event.type === 'error') {\n yield { type: 'error', message: event.message }\n return\n }\n }\n }\n\n yield { type: 'done' }\n } catch (error) {\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n if (error instanceof TorqueAssistantError) {\n throw error\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n yield { type: 'done' }\n return\n }\n\n if (error instanceof Error) {\n throw new TorqueAssistantError(error.message, {\n code: 'NETWORK_ERROR',\n statusCode: 500,\n })\n }\n\n throw new TorqueAssistantError('Stream failed', {\n code: 'UNKNOWN_ERROR',\n statusCode: 500,\n })\n }\n}\n","import type { AssistantChatPostBody, AssistantChatResponse, AssistantChatStreamEvent } from '@torquefi/types/assistant'\nimport type { TorquePlatformClientConfig } from '@torquefi/types/platform'\n\nimport { TorqueAssistantCreditsError, TorqueAssistantError } from './errors'\nimport { torqueAssistantChat, type TorqueAssistantHttpConfig } from './http'\nimport { torqueAssistantChatStream } from './stream'\n\nexport type { TorquePlatformClientConfig as TorqueAssistantConfig } from '@torquefi/types/platform'\n\nexport interface TorqueAssistantOptions extends TorquePlatformClientConfig {}\n\nexport type AssistantChatRequest = AssistantChatPostBody\n\nexport interface AssistantChatStreamOptions {\n signal?: AbortSignal\n}\n\nexport {\n TorqueAssistantError,\n TorqueAssistantCreditsError,\n} from './errors'\nexport { ASSISTANT_CREDITS_ERROR_CODE } from '@torquefi/types/assistant'\nexport type {\n AssistantChatContext,\n AssistantChatFunctionResult,\n AssistantChatMessage,\n AssistantChatPostBody,\n AssistantChatResponse,\n AssistantChatStreamEvent,\n} from '@torquefi/types/assistant'\n\nfunction validateConfig(config: TorqueAssistantOptions): void {\n if (!config.apiKey?.trim()) {\n throw new TorqueAssistantError('API key is required', {\n code: 'INVALID_CONFIG',\n statusCode: 400,\n })\n }\n if (config.timeout != null && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n throw new TorqueAssistantError('Timeout must be a positive number', {\n code: 'INVALID_CONFIG',\n statusCode: 400,\n })\n }\n}\n\nfunction toHttpConfig(config: TorqueAssistantOptions): TorqueAssistantHttpConfig {\n return {\n apiKey: config.apiKey.trim(),\n baseUrl: (config.baseUrl || 'https://app.torque.fi').replace(/\\/$/, ''),\n timeout: config.timeout ?? 180_000,\n }\n}\n\nexport class TorqueAssistant {\n private readonly http: TorqueAssistantHttpConfig\n\n constructor(config: TorqueAssistantOptions) {\n validateConfig(config)\n this.http = toHttpConfig(config)\n }\n\n /**\n * Non-streaming chat. POST /api/v1/assistant/chat\n */\n async chat(\n request: AssistantChatRequest,\n options?: AssistantChatStreamOptions,\n ): Promise<AssistantChatResponse> {\n return torqueAssistantChat(this.http, request, options?.signal)\n }\n\n /**\n * Streaming chat over SSE. POST /api/v1/assistant/chat?stream=true\n */\n chatStream(\n request: AssistantChatRequest,\n options?: AssistantChatStreamOptions,\n ): AsyncGenerator<AssistantChatStreamEvent> {\n return torqueAssistantChatStream(this.http, request, options?.signal)\n }\n}\n\nexport function createTorqueAssistant(config: TorqueAssistantOptions): TorqueAssistant {\n return new TorqueAssistant(config)\n}\n\n/**\n * Reads TORQUE_API_KEY and optional TORQUE_BASE_URL from the environment.\n */\nexport function createTorqueAssistantFromEnv(\n overrides?: Partial<TorqueAssistantOptions>,\n): TorqueAssistant {\n const apiKey = process.env.TORQUE_API_KEY || overrides?.apiKey\n if (!apiKey) {\n throw new TorqueAssistantError('TORQUE_API_KEY environment variable is required', {\n code: 'MISSING_ENV_VARS',\n statusCode: 400,\n })\n }\n\n return new TorqueAssistant({\n apiKey,\n baseUrl: process.env.TORQUE_BASE_URL || overrides?.baseUrl,\n timeout: overrides?.timeout,\n })\n}\n"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,316 @@
1
+ 'use strict';
2
+
3
+ var assistant = require('@torquefi/types/assistant');
4
+
5
+ class TorqueAssistantError extends Error {
6
+ constructor(message, options) {
7
+ super(message);
8
+ this.name = 'TorqueAssistantError';
9
+ this.code = options.code;
10
+ this.statusCode = options.statusCode;
11
+ this.details = options.details;
12
+ Object.setPrototypeOf(this, TorqueAssistantError.prototype);
13
+ }
14
+ }
15
+ class TorqueAssistantCreditsError extends TorqueAssistantError {
16
+ constructor(message, options) {
17
+ super(message, {
18
+ code: assistant.ASSISTANT_CREDITS_ERROR_CODE,
19
+ statusCode: options.statusCode,
20
+ details: {
21
+ upgrade: options.upgrade,
22
+ remaining: options.remaining,
23
+ limit: options.limit,
24
+ resetAt: options.resetAt,
25
+ },
26
+ });
27
+ this.name = 'TorqueAssistantCreditsError';
28
+ this.upgrade = options.upgrade;
29
+ this.remaining = options.remaining;
30
+ this.limit = options.limit;
31
+ this.resetAt = options.resetAt;
32
+ Object.setPrototypeOf(this, TorqueAssistantCreditsError.prototype);
33
+ }
34
+ }
35
+ function parseAssistantError(body, statusCode, fallbackMessage) {
36
+ const payload = body;
37
+ if (statusCode === 402 &&
38
+ typeof payload?.error === 'string' &&
39
+ payload.error === assistant.ASSISTANT_CREDITS_ERROR_CODE) {
40
+ return new TorqueAssistantCreditsError(typeof payload.message === 'string' ? payload.message : fallbackMessage, {
41
+ statusCode,
42
+ upgrade: payload.upgrade,
43
+ remaining: payload.remaining,
44
+ limit: payload.limit,
45
+ resetAt: payload.resetAt,
46
+ });
47
+ }
48
+ if (payload?.error && typeof payload.error === 'object') {
49
+ const err = payload.error;
50
+ return new TorqueAssistantError(typeof err.message === 'string' ? err.message : fallbackMessage, {
51
+ code: typeof err.code === 'string' ? err.code : 'API_ERROR',
52
+ statusCode,
53
+ details: err.details,
54
+ });
55
+ }
56
+ if (typeof payload?.error === 'string') {
57
+ return new TorqueAssistantError(typeof payload.message === 'string' ? payload.message : fallbackMessage, {
58
+ code: payload.error,
59
+ statusCode,
60
+ });
61
+ }
62
+ return new TorqueAssistantError(fallbackMessage, {
63
+ code: 'API_ERROR',
64
+ statusCode,
65
+ });
66
+ }
67
+
68
+ async function torqueAssistantPost(config, path, body, signal) {
69
+ const url = `${config.baseUrl}${path}`;
70
+ const controller = new AbortController();
71
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
72
+ const onAbort = () => controller.abort();
73
+ if (signal) {
74
+ if (signal.aborted)
75
+ controller.abort();
76
+ else
77
+ signal.addEventListener('abort', onAbort, { once: true });
78
+ }
79
+ try {
80
+ const response = await fetch(url, {
81
+ method: 'POST',
82
+ headers: {
83
+ Accept: 'application/json',
84
+ 'Content-Type': 'application/json',
85
+ Authorization: `Bearer ${config.apiKey}`,
86
+ },
87
+ body: JSON.stringify(body),
88
+ signal: controller.signal,
89
+ });
90
+ clearTimeout(timeoutId);
91
+ signal?.removeEventListener('abort', onAbort);
92
+ const payload = await response.json().catch(() => ({}));
93
+ if (!response.ok) {
94
+ throw parseAssistantError(payload, response.status, `HTTP ${response.status}: ${response.statusText}`);
95
+ }
96
+ return payload;
97
+ }
98
+ catch (error) {
99
+ clearTimeout(timeoutId);
100
+ signal?.removeEventListener('abort', onAbort);
101
+ if (error instanceof TorqueAssistantError) {
102
+ throw error;
103
+ }
104
+ if (error instanceof Error) {
105
+ if (error.name === 'AbortError') {
106
+ throw new TorqueAssistantError('Request timeout', {
107
+ code: 'TIMEOUT',
108
+ statusCode: 408,
109
+ });
110
+ }
111
+ throw new TorqueAssistantError(error.message, {
112
+ code: 'NETWORK_ERROR',
113
+ statusCode: 500,
114
+ });
115
+ }
116
+ throw new TorqueAssistantError('Request failed', {
117
+ code: 'UNKNOWN_ERROR',
118
+ statusCode: 500,
119
+ });
120
+ }
121
+ }
122
+ async function torqueAssistantChat(config, body, signal) {
123
+ return torqueAssistantPost(config, '/api/v1/assistant/chat', body, signal);
124
+ }
125
+
126
+ function parseJsonContent(content) {
127
+ if (typeof content === 'string')
128
+ return content;
129
+ if (Array.isArray(content)) {
130
+ return content
131
+ .map((part) => part?.text ?? '')
132
+ .join('');
133
+ }
134
+ return '';
135
+ }
136
+ function* eventsFromJsonPayload(payload) {
137
+ const text = parseJsonContent(payload.content);
138
+ if (text) {
139
+ yield { type: 'delta', text };
140
+ }
141
+ yield { type: 'done', functionResults: payload.functionResults };
142
+ }
143
+ async function* torqueAssistantChatStream(config, body, signal) {
144
+ const url = `${config.baseUrl}/api/v1/assistant/chat?stream=true`;
145
+ const controller = new AbortController();
146
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
147
+ const onAbort = () => controller.abort();
148
+ if (signal) {
149
+ if (signal.aborted)
150
+ controller.abort();
151
+ else
152
+ signal.addEventListener('abort', onAbort, { once: true });
153
+ }
154
+ try {
155
+ const response = await fetch(url, {
156
+ method: 'POST',
157
+ headers: {
158
+ Accept: 'text/event-stream, application/json',
159
+ 'Content-Type': 'application/json',
160
+ Authorization: `Bearer ${config.apiKey}`,
161
+ },
162
+ body: JSON.stringify(body),
163
+ signal: controller.signal,
164
+ });
165
+ clearTimeout(timeoutId);
166
+ signal?.removeEventListener('abort', onAbort);
167
+ if (!response.ok) {
168
+ const payload = await response.json().catch(() => ({}));
169
+ throw parseAssistantError(payload, response.status, `HTTP ${response.status}: ${response.statusText}`);
170
+ }
171
+ const contentType = response.headers.get('content-type') ?? '';
172
+ if (contentType.includes('application/json')) {
173
+ const payload = (await response.json().catch(() => ({})));
174
+ yield* eventsFromJsonPayload(payload);
175
+ return;
176
+ }
177
+ if (!response.body) {
178
+ yield { type: 'error', message: 'No response body.' };
179
+ return;
180
+ }
181
+ const reader = response.body.getReader();
182
+ const decoder = new TextDecoder();
183
+ let buf = '';
184
+ while (true) {
185
+ const { done, value } = await reader.read();
186
+ if (done)
187
+ break;
188
+ buf += decoder.decode(value, { stream: true });
189
+ const lines = buf.split('\n');
190
+ buf = lines.pop() ?? '';
191
+ for (const line of lines) {
192
+ if (!line.startsWith('data: '))
193
+ continue;
194
+ const raw = line.slice(6).trim();
195
+ if (raw === '[DONE]') {
196
+ yield { type: 'done' };
197
+ return;
198
+ }
199
+ let event;
200
+ try {
201
+ event = JSON.parse(raw);
202
+ }
203
+ catch {
204
+ continue;
205
+ }
206
+ if (event.type === 'delta' && event.text) {
207
+ yield { type: 'delta', text: event.text };
208
+ }
209
+ else if (event.type === 'correction' && event.text) {
210
+ yield { type: 'correction', text: event.text };
211
+ }
212
+ else if (event.type === 'done') {
213
+ yield { type: 'done', functionResults: event.functionResults };
214
+ return;
215
+ }
216
+ else if (event.type === 'error') {
217
+ yield { type: 'error', message: event.message };
218
+ return;
219
+ }
220
+ }
221
+ }
222
+ yield { type: 'done' };
223
+ }
224
+ catch (error) {
225
+ clearTimeout(timeoutId);
226
+ signal?.removeEventListener('abort', onAbort);
227
+ if (error instanceof TorqueAssistantError) {
228
+ throw error;
229
+ }
230
+ if (error instanceof Error && error.name === 'AbortError') {
231
+ yield { type: 'done' };
232
+ return;
233
+ }
234
+ if (error instanceof Error) {
235
+ throw new TorqueAssistantError(error.message, {
236
+ code: 'NETWORK_ERROR',
237
+ statusCode: 500,
238
+ });
239
+ }
240
+ throw new TorqueAssistantError('Stream failed', {
241
+ code: 'UNKNOWN_ERROR',
242
+ statusCode: 500,
243
+ });
244
+ }
245
+ }
246
+
247
+ function validateConfig(config) {
248
+ if (!config.apiKey?.trim()) {
249
+ throw new TorqueAssistantError('API key is required', {
250
+ code: 'INVALID_CONFIG',
251
+ statusCode: 400,
252
+ });
253
+ }
254
+ if (config.timeout != null && (typeof config.timeout !== 'number' || config.timeout <= 0)) {
255
+ throw new TorqueAssistantError('Timeout must be a positive number', {
256
+ code: 'INVALID_CONFIG',
257
+ statusCode: 400,
258
+ });
259
+ }
260
+ }
261
+ function toHttpConfig(config) {
262
+ return {
263
+ apiKey: config.apiKey.trim(),
264
+ baseUrl: (config.baseUrl || 'https://app.torque.fi').replace(/\/$/, ''),
265
+ timeout: config.timeout ?? 180000,
266
+ };
267
+ }
268
+ class TorqueAssistant {
269
+ constructor(config) {
270
+ validateConfig(config);
271
+ this.http = toHttpConfig(config);
272
+ }
273
+ /**
274
+ * Non-streaming chat. POST /api/v1/assistant/chat
275
+ */
276
+ async chat(request, options) {
277
+ return torqueAssistantChat(this.http, request, options?.signal);
278
+ }
279
+ /**
280
+ * Streaming chat over SSE. POST /api/v1/assistant/chat?stream=true
281
+ */
282
+ chatStream(request, options) {
283
+ return torqueAssistantChatStream(this.http, request, options?.signal);
284
+ }
285
+ }
286
+ function createTorqueAssistant(config) {
287
+ return new TorqueAssistant(config);
288
+ }
289
+ /**
290
+ * Reads TORQUE_API_KEY and optional TORQUE_BASE_URL from the environment.
291
+ */
292
+ function createTorqueAssistantFromEnv(overrides) {
293
+ const apiKey = process.env.TORQUE_API_KEY || overrides?.apiKey;
294
+ if (!apiKey) {
295
+ throw new TorqueAssistantError('TORQUE_API_KEY environment variable is required', {
296
+ code: 'MISSING_ENV_VARS',
297
+ statusCode: 400,
298
+ });
299
+ }
300
+ return new TorqueAssistant({
301
+ apiKey,
302
+ baseUrl: process.env.TORQUE_BASE_URL || overrides?.baseUrl,
303
+ timeout: overrides?.timeout,
304
+ });
305
+ }
306
+
307
+ Object.defineProperty(exports, "ASSISTANT_CREDITS_ERROR_CODE", {
308
+ enumerable: true,
309
+ get: function () { return assistant.ASSISTANT_CREDITS_ERROR_CODE; }
310
+ });
311
+ exports.TorqueAssistant = TorqueAssistant;
312
+ exports.TorqueAssistantCreditsError = TorqueAssistantCreditsError;
313
+ exports.TorqueAssistantError = TorqueAssistantError;
314
+ exports.createTorqueAssistant = createTorqueAssistant;
315
+ exports.createTorqueAssistantFromEnv = createTorqueAssistantFromEnv;
316
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/errors.ts","../src/http.ts","../src/stream.ts","../src/index.ts"],"sourcesContent":["import { ASSISTANT_CREDITS_ERROR_CODE } from '@torquefi/types/assistant'\n\nexport interface TorqueAssistantErrorDetails {\n code: string\n statusCode: number\n details?: Record<string, unknown>\n}\n\nexport class TorqueAssistantError extends Error {\n code: string\n statusCode: number\n details?: Record<string, unknown>\n\n constructor(message: string, options: TorqueAssistantErrorDetails) {\n super(message)\n this.name = 'TorqueAssistantError'\n this.code = options.code\n this.statusCode = options.statusCode\n this.details = options.details\n Object.setPrototypeOf(this, TorqueAssistantError.prototype)\n }\n}\n\nexport class TorqueAssistantCreditsError extends TorqueAssistantError {\n upgrade?: boolean\n remaining?: number\n limit?: number\n resetAt?: number | null\n\n constructor(\n message: string,\n options: {\n statusCode: number\n upgrade?: boolean\n remaining?: number\n limit?: number\n resetAt?: number | null\n },\n ) {\n super(message, {\n code: ASSISTANT_CREDITS_ERROR_CODE,\n statusCode: options.statusCode,\n details: {\n upgrade: options.upgrade,\n remaining: options.remaining,\n limit: options.limit,\n resetAt: options.resetAt,\n },\n })\n this.name = 'TorqueAssistantCreditsError'\n this.upgrade = options.upgrade\n this.remaining = options.remaining\n this.limit = options.limit\n this.resetAt = options.resetAt\n Object.setPrototypeOf(this, TorqueAssistantCreditsError.prototype)\n }\n}\n\nexport function parseAssistantError(\n body: unknown,\n statusCode: number,\n fallbackMessage: string,\n): TorqueAssistantError {\n const payload = body as {\n error?: string | { code?: string; message?: string; details?: Record<string, unknown> }\n message?: string\n upgrade?: boolean\n remaining?: number\n limit?: number\n resetAt?: number | null\n } | null\n\n if (\n statusCode === 402 &&\n typeof payload?.error === 'string' &&\n payload.error === ASSISTANT_CREDITS_ERROR_CODE\n ) {\n return new TorqueAssistantCreditsError(\n typeof payload.message === 'string' ? payload.message : fallbackMessage,\n {\n statusCode,\n upgrade: payload.upgrade,\n remaining: payload.remaining,\n limit: payload.limit,\n resetAt: payload.resetAt,\n },\n )\n }\n\n if (payload?.error && typeof payload.error === 'object') {\n const err = payload.error\n return new TorqueAssistantError(\n typeof err.message === 'string' ? err.message : fallbackMessage,\n {\n code: typeof err.code === 'string' ? err.code : 'API_ERROR',\n statusCode,\n details: err.details,\n },\n )\n }\n\n if (typeof payload?.error === 'string') {\n return new TorqueAssistantError(\n typeof payload.message === 'string' ? payload.message : fallbackMessage,\n {\n code: payload.error,\n statusCode,\n },\n )\n }\n\n return new TorqueAssistantError(fallbackMessage, {\n code: 'API_ERROR',\n statusCode,\n })\n}\n","import type { AssistantChatPostBody, AssistantChatResponse } from '@torquefi/types/assistant'\n\nimport { parseAssistantError, TorqueAssistantError } from './errors'\n\nexport interface TorqueAssistantHttpConfig {\n apiKey: string\n baseUrl: string\n timeout: number\n}\n\nexport async function torqueAssistantPost<T>(\n config: TorqueAssistantHttpConfig,\n path: string,\n body: AssistantChatPostBody,\n signal?: AbortSignal,\n): Promise<T> {\n const url = `${config.baseUrl}${path}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), config.timeout)\n\n const onAbort = () => controller.abort()\n if (signal) {\n if (signal.aborted) controller.abort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n const payload: unknown = await response.json().catch(() => ({}))\n\n if (!response.ok) {\n throw parseAssistantError(\n payload,\n response.status,\n `HTTP ${response.status}: ${response.statusText}`,\n )\n }\n\n return payload as T\n } catch (error) {\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n if (error instanceof TorqueAssistantError) {\n throw error\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new TorqueAssistantError('Request timeout', {\n code: 'TIMEOUT',\n statusCode: 408,\n })\n }\n throw new TorqueAssistantError(error.message, {\n code: 'NETWORK_ERROR',\n statusCode: 500,\n })\n }\n\n throw new TorqueAssistantError('Request failed', {\n code: 'UNKNOWN_ERROR',\n statusCode: 500,\n })\n }\n}\n\nexport async function torqueAssistantChat(\n config: TorqueAssistantHttpConfig,\n body: AssistantChatPostBody,\n signal?: AbortSignal,\n): Promise<AssistantChatResponse> {\n return torqueAssistantPost<AssistantChatResponse>(\n config,\n '/api/v1/assistant/chat',\n body,\n signal,\n )\n}\n","import type {\n AssistantChatFunctionResult,\n AssistantChatPostBody,\n AssistantChatStreamEvent,\n} from '@torquefi/types/assistant'\n\nimport { parseAssistantError, TorqueAssistantError } from './errors'\nimport type { TorqueAssistantHttpConfig } from './http'\n\ntype AssistantChatSsePayload = {\n type: string\n text?: string\n message?: string\n functionResults?: AssistantChatFunctionResult[]\n}\n\nfunction parseJsonContent(content: unknown): string {\n if (typeof content === 'string') return content\n if (Array.isArray(content)) {\n return (content as Array<{ text?: string }>)\n .map((part) => part?.text ?? '')\n .join('')\n }\n return ''\n}\n\nfunction* eventsFromJsonPayload(payload: {\n content?: unknown\n functionResults?: AssistantChatFunctionResult[]\n}): Generator<AssistantChatStreamEvent> {\n const text = parseJsonContent(payload.content)\n if (text) {\n yield { type: 'delta', text }\n }\n yield { type: 'done', functionResults: payload.functionResults }\n}\n\nexport async function* torqueAssistantChatStream(\n config: TorqueAssistantHttpConfig,\n body: AssistantChatPostBody,\n signal?: AbortSignal,\n): AsyncGenerator<AssistantChatStreamEvent> {\n const url = `${config.baseUrl}/api/v1/assistant/chat?stream=true`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), config.timeout)\n\n const onAbort = () => controller.abort()\n if (signal) {\n if (signal.aborted) controller.abort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'text/event-stream, application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n if (!response.ok) {\n const payload: unknown = await response.json().catch(() => ({}))\n throw parseAssistantError(\n payload,\n response.status,\n `HTTP ${response.status}: ${response.statusText}`,\n )\n }\n\n const contentType = response.headers.get('content-type') ?? ''\n\n if (contentType.includes('application/json')) {\n const payload = (await response.json().catch(() => ({}))) as {\n content?: unknown\n functionResults?: AssistantChatFunctionResult[]\n }\n yield* eventsFromJsonPayload(payload)\n return\n }\n\n if (!response.body) {\n yield { type: 'error', message: 'No response body.' }\n return\n }\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buf += decoder.decode(value, { stream: true })\n const lines = buf.split('\\n')\n buf = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n\n const raw = line.slice(6).trim()\n if (raw === '[DONE]') {\n yield { type: 'done' }\n return\n }\n\n let event: AssistantChatSsePayload\n try {\n event = JSON.parse(raw) as AssistantChatSsePayload\n } catch {\n continue\n }\n\n if (event.type === 'delta' && event.text) {\n yield { type: 'delta', text: event.text }\n } else if (event.type === 'correction' && event.text) {\n yield { type: 'correction', text: event.text }\n } else if (event.type === 'done') {\n yield { type: 'done', functionResults: event.functionResults }\n return\n } else if (event.type === 'error') {\n yield { type: 'error', message: event.message }\n return\n }\n }\n }\n\n yield { type: 'done' }\n } catch (error) {\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', onAbort)\n\n if (error instanceof TorqueAssistantError) {\n throw error\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n yield { type: 'done' }\n return\n }\n\n if (error instanceof Error) {\n throw new TorqueAssistantError(error.message, {\n code: 'NETWORK_ERROR',\n statusCode: 500,\n })\n }\n\n throw new TorqueAssistantError('Stream failed', {\n code: 'UNKNOWN_ERROR',\n statusCode: 500,\n })\n }\n}\n","import type { AssistantChatPostBody, AssistantChatResponse, AssistantChatStreamEvent } from '@torquefi/types/assistant'\nimport type { TorquePlatformClientConfig } from '@torquefi/types/platform'\n\nimport { TorqueAssistantCreditsError, TorqueAssistantError } from './errors'\nimport { torqueAssistantChat, type TorqueAssistantHttpConfig } from './http'\nimport { torqueAssistantChatStream } from './stream'\n\nexport type { TorquePlatformClientConfig as TorqueAssistantConfig } from '@torquefi/types/platform'\n\nexport interface TorqueAssistantOptions extends TorquePlatformClientConfig {}\n\nexport type AssistantChatRequest = AssistantChatPostBody\n\nexport interface AssistantChatStreamOptions {\n signal?: AbortSignal\n}\n\nexport {\n TorqueAssistantError,\n TorqueAssistantCreditsError,\n} from './errors'\nexport { ASSISTANT_CREDITS_ERROR_CODE } from '@torquefi/types/assistant'\nexport type {\n AssistantChatContext,\n AssistantChatFunctionResult,\n AssistantChatMessage,\n AssistantChatPostBody,\n AssistantChatResponse,\n AssistantChatStreamEvent,\n} from '@torquefi/types/assistant'\n\nfunction validateConfig(config: TorqueAssistantOptions): void {\n if (!config.apiKey?.trim()) {\n throw new TorqueAssistantError('API key is required', {\n code: 'INVALID_CONFIG',\n statusCode: 400,\n })\n }\n if (config.timeout != null && (typeof config.timeout !== 'number' || config.timeout <= 0)) {\n throw new TorqueAssistantError('Timeout must be a positive number', {\n code: 'INVALID_CONFIG',\n statusCode: 400,\n })\n }\n}\n\nfunction toHttpConfig(config: TorqueAssistantOptions): TorqueAssistantHttpConfig {\n return {\n apiKey: config.apiKey.trim(),\n baseUrl: (config.baseUrl || 'https://app.torque.fi').replace(/\\/$/, ''),\n timeout: config.timeout ?? 180_000,\n }\n}\n\nexport class TorqueAssistant {\n private readonly http: TorqueAssistantHttpConfig\n\n constructor(config: TorqueAssistantOptions) {\n validateConfig(config)\n this.http = toHttpConfig(config)\n }\n\n /**\n * Non-streaming chat. POST /api/v1/assistant/chat\n */\n async chat(\n request: AssistantChatRequest,\n options?: AssistantChatStreamOptions,\n ): Promise<AssistantChatResponse> {\n return torqueAssistantChat(this.http, request, options?.signal)\n }\n\n /**\n * Streaming chat over SSE. POST /api/v1/assistant/chat?stream=true\n */\n chatStream(\n request: AssistantChatRequest,\n options?: AssistantChatStreamOptions,\n ): AsyncGenerator<AssistantChatStreamEvent> {\n return torqueAssistantChatStream(this.http, request, options?.signal)\n }\n}\n\nexport function createTorqueAssistant(config: TorqueAssistantOptions): TorqueAssistant {\n return new TorqueAssistant(config)\n}\n\n/**\n * Reads TORQUE_API_KEY and optional TORQUE_BASE_URL from the environment.\n */\nexport function createTorqueAssistantFromEnv(\n overrides?: Partial<TorqueAssistantOptions>,\n): TorqueAssistant {\n const apiKey = process.env.TORQUE_API_KEY || overrides?.apiKey\n if (!apiKey) {\n throw new TorqueAssistantError('TORQUE_API_KEY environment variable is required', {\n code: 'MISSING_ENV_VARS',\n statusCode: 400,\n })\n }\n\n return new TorqueAssistant({\n apiKey,\n baseUrl: process.env.TORQUE_BASE_URL || overrides?.baseUrl,\n timeout: overrides?.timeout,\n })\n}\n"],"names":["ASSISTANT_CREDITS_ERROR_CODE"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AssistantChatPostBody, AssistantChatStreamEvent } from '@torquefi/types/assistant';
2
+ import type { TorqueAssistantHttpConfig } from './http';
3
+ export declare function torqueAssistantChatStream(config: TorqueAssistantHttpConfig, body: AssistantChatPostBody, signal?: AbortSignal): AsyncGenerator<AssistantChatStreamEvent>;
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "torque-assistant",
3
+ "version": "0.1.0",
4
+ "description": "Official Torque Assistant SDK — server-side chat and SSE streaming for Platform API v1",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.esm.js",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "rollup -c",
23
+ "dev": "rollup -c -w",
24
+ "clean": "rimraf dist",
25
+ "prepublishOnly": "yarn clean && yarn build"
26
+ },
27
+ "keywords": [
28
+ "torque",
29
+ "assistant",
30
+ "chat",
31
+ "sse",
32
+ "fintech",
33
+ "api",
34
+ "typescript",
35
+ "sdk"
36
+ ],
37
+ "author": "Torque <hello@torque.fi>",
38
+ "license": "MIT",
39
+ "homepage": "https://torque.fi",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/torque-fi/torque_webapp.git",
43
+ "directory": "packages/torque-assistant"
44
+ },
45
+ "dependencies": {
46
+ "@torquefi/types": "^0.1.0"
47
+ },
48
+ "devDependencies": {
49
+ "@rollup/plugin-typescript": "^12.1.4",
50
+ "@types/node": "^20.0.0",
51
+ "rimraf": "^5.0.0",
52
+ "rollup": "^4.0.0",
53
+ "typescript": "^5.0.0"
54
+ },
55
+ "engines": {
56
+ "node": ">=16.0.0"
57
+ }
58
+ }