@tangle-network/tcloud 0.1.1 → 0.1.3
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/README.md +4 -4
- package/dist/{chunk-YORNEPCU.js → chunk-G5LUZZKT.js} +1 -1
- package/dist/{chunk-4AOQNUQ3.js → chunk-YKLHAS4E.js} +95 -7
- package/dist/cli.cjs +97 -9
- package/dist/cli.js +4 -4
- package/dist/index.cjs +95 -7
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{shielded-BRhsV-s-.d.cts → shielded-xDNVqK4a.d.cts} +65 -4
- package/dist/{shielded-BRhsV-s-.d.ts → shielded-xDNVqK4a.d.ts} +65 -4
- package/dist/shielded.cjs +95 -7
- package/dist/shielded.d.cts +1 -1
- package/dist/shielded.d.ts +1 -1
- package/dist/shielded.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# tcloud
|
|
2
2
|
|
|
3
|
-
TypeScript SDK and CLI for [Tangle AI Cloud](https://
|
|
3
|
+
TypeScript SDK and CLI for [Tangle AI Cloud](https://router.tangle.tools) — decentralized LLM inference with operator routing, reputation-based selection, and anonymous payments via ShieldedCredits.
|
|
4
4
|
|
|
5
5
|
Zero framework dependencies. Pure `fetch` + SSE. Works in Node.js, Deno, Bun, and edge runtimes.
|
|
6
6
|
|
|
@@ -281,7 +281,7 @@ Wallets use BIP-39 mnemonics with BIP-44 derivation. Private keys are encrypted
|
|
|
281
281
|
Config stored in `~/.tcloud/config.json`:
|
|
282
282
|
|
|
283
283
|
```bash
|
|
284
|
-
tcloud config --api-url https://
|
|
284
|
+
tcloud config --api-url https://router.tangle.tools
|
|
285
285
|
tcloud config --model gpt-4o-mini
|
|
286
286
|
```
|
|
287
287
|
|
|
@@ -299,7 +299,7 @@ import OpenAI from 'openai'
|
|
|
299
299
|
|
|
300
300
|
const client = new OpenAI({
|
|
301
301
|
apiKey: 'sk-tan-...',
|
|
302
|
-
baseURL: 'https://
|
|
302
|
+
baseURL: 'https://router.tangle.tools/v1',
|
|
303
303
|
})
|
|
304
304
|
|
|
305
305
|
const completion = await client.chat.completions.create({
|
|
@@ -318,7 +318,7 @@ import { generateText } from 'ai'
|
|
|
318
318
|
|
|
319
319
|
const tangle = createOpenAI({
|
|
320
320
|
apiKey: 'sk-tan-...',
|
|
321
|
-
baseURL: 'https://
|
|
321
|
+
baseURL: 'https://router.tangle.tools/v1',
|
|
322
322
|
})
|
|
323
323
|
|
|
324
324
|
const { text } = await generateText({
|
|
@@ -3,7 +3,7 @@ import { privateKeyToAccount } from "viem/accounts";
|
|
|
3
3
|
import { keccak256, encodeAbiParameters, parseAbiParameters, concat, toBytes } from "viem";
|
|
4
4
|
|
|
5
5
|
// src/client.ts
|
|
6
|
-
var DEFAULT_BASE_URL = "https://
|
|
6
|
+
var DEFAULT_BASE_URL = "https://router.tangle.tools/v1";
|
|
7
7
|
async function proxiedFetch(privacy, url, init, streaming) {
|
|
8
8
|
if (!privacy || privacy.mode === "direct") {
|
|
9
9
|
return fetch(url, init);
|
|
@@ -60,7 +60,7 @@ var TCloudClient = class {
|
|
|
60
60
|
this.limits = config.limits;
|
|
61
61
|
this.headers = {
|
|
62
62
|
"Content-Type": "application/json",
|
|
63
|
-
"X-Tangle-Client": "tcloud-sdk/0.1.
|
|
63
|
+
"X-Tangle-Client": "tcloud-sdk/0.1.3"
|
|
64
64
|
};
|
|
65
65
|
if (this.apiKey) {
|
|
66
66
|
this.headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
@@ -68,6 +68,12 @@ var TCloudClient = class {
|
|
|
68
68
|
if (config.routing?.prefer) {
|
|
69
69
|
this.headers["X-Tangle-Operator"] = config.routing.prefer;
|
|
70
70
|
}
|
|
71
|
+
if (config.routing?.blueprintId) {
|
|
72
|
+
this.headers["X-Tangle-Blueprint"] = config.routing.blueprintId;
|
|
73
|
+
}
|
|
74
|
+
if (config.routing?.serviceId) {
|
|
75
|
+
this.headers["X-Tangle-Service"] = config.routing.serviceId;
|
|
76
|
+
}
|
|
71
77
|
if (config.routing?.region) {
|
|
72
78
|
this.headers["X-Tangle-Region"] = config.routing.region;
|
|
73
79
|
}
|
|
@@ -104,12 +110,19 @@ var TCloudClient = class {
|
|
|
104
110
|
if (pct >= 0.8) this.limits.onLimitWarning({ type: "total", current: this._totalSpent, limit: this.limits.maxTotalSpend });
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
|
-
/** Track cost after a response */
|
|
108
|
-
trackCost(completion) {
|
|
113
|
+
/** Track cost after a response, using actual pricing from response headers when available */
|
|
114
|
+
trackCost(completion, res) {
|
|
109
115
|
this._requestCount++;
|
|
110
116
|
if (completion.usage) {
|
|
111
|
-
|
|
112
|
-
const
|
|
117
|
+
let estimatedCost;
|
|
118
|
+
const inputPrice = res ? parseFloat(res.headers.get("x-tangle-price-input") || "0") : 0;
|
|
119
|
+
const outputPrice = res ? parseFloat(res.headers.get("x-tangle-price-output") || "0") : 0;
|
|
120
|
+
if (inputPrice > 0 || outputPrice > 0) {
|
|
121
|
+
estimatedCost = (completion.usage.prompt_tokens || 0) * inputPrice + (completion.usage.completion_tokens || 0) * outputPrice;
|
|
122
|
+
} else {
|
|
123
|
+
const tokens = completion.usage.total_tokens || 0;
|
|
124
|
+
estimatedCost = tokens * 1e-6;
|
|
125
|
+
}
|
|
113
126
|
this._totalSpent += estimatedCost;
|
|
114
127
|
if (this.limits?.maxCostPerRequest && estimatedCost > this.limits.maxCostPerRequest) {
|
|
115
128
|
this.limits.onLimitReached?.({ type: "cost", current: estimatedCost, limit: this.limits.maxCostPerRequest });
|
|
@@ -147,7 +160,7 @@ var TCloudClient = class {
|
|
|
147
160
|
throw new TCloudError(res.status, err.error?.message || err.error || err.message || res.statusText);
|
|
148
161
|
}
|
|
149
162
|
const completion = await res.json();
|
|
150
|
-
this.trackCost(completion);
|
|
163
|
+
this.trackCost(completion, res);
|
|
151
164
|
return completion;
|
|
152
165
|
}
|
|
153
166
|
/** Chat completion (streaming) — returns an async iterator of chunks */
|
|
@@ -286,6 +299,81 @@ var TCloudClient = class {
|
|
|
286
299
|
}, false);
|
|
287
300
|
if (!res.ok) throw new TCloudError(res.status, "Failed to revoke key");
|
|
288
301
|
}
|
|
302
|
+
/** Generate embeddings */
|
|
303
|
+
async embeddings(options) {
|
|
304
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/embeddings`, {
|
|
305
|
+
method: "POST",
|
|
306
|
+
headers: this.headers,
|
|
307
|
+
body: JSON.stringify({
|
|
308
|
+
model: options.model || "text-embedding-3-small",
|
|
309
|
+
input: options.input
|
|
310
|
+
})
|
|
311
|
+
}, false);
|
|
312
|
+
if (!res.ok) {
|
|
313
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
314
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
315
|
+
}
|
|
316
|
+
this._requestCount++;
|
|
317
|
+
return res.json();
|
|
318
|
+
}
|
|
319
|
+
/** Generate images */
|
|
320
|
+
async imageGenerate(options) {
|
|
321
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/images/generations`, {
|
|
322
|
+
method: "POST",
|
|
323
|
+
headers: this.headers,
|
|
324
|
+
body: JSON.stringify({
|
|
325
|
+
model: options.model || "dall-e-3",
|
|
326
|
+
prompt: options.prompt,
|
|
327
|
+
n: options.n,
|
|
328
|
+
size: options.size,
|
|
329
|
+
quality: options.quality,
|
|
330
|
+
response_format: options.response_format
|
|
331
|
+
})
|
|
332
|
+
}, false);
|
|
333
|
+
if (!res.ok) {
|
|
334
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
335
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
336
|
+
}
|
|
337
|
+
this._requestCount++;
|
|
338
|
+
return res.json();
|
|
339
|
+
}
|
|
340
|
+
/** Rerank documents by relevance to a query */
|
|
341
|
+
async rerank(options) {
|
|
342
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/rerank`, {
|
|
343
|
+
method: "POST",
|
|
344
|
+
headers: this.headers,
|
|
345
|
+
body: JSON.stringify({
|
|
346
|
+
model: options.model || "rerank-english-v3.0",
|
|
347
|
+
query: options.query,
|
|
348
|
+
documents: options.documents,
|
|
349
|
+
top_n: options.top_n
|
|
350
|
+
})
|
|
351
|
+
}, false);
|
|
352
|
+
if (!res.ok) {
|
|
353
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
354
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
355
|
+
}
|
|
356
|
+
this._requestCount++;
|
|
357
|
+
return res.json();
|
|
358
|
+
}
|
|
359
|
+
/** Text-to-speech */
|
|
360
|
+
async speech(options) {
|
|
361
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/audio/speech`, {
|
|
362
|
+
method: "POST",
|
|
363
|
+
headers: this.headers,
|
|
364
|
+
body: JSON.stringify({
|
|
365
|
+
model: options.model || "tts-1",
|
|
366
|
+
input: options.input,
|
|
367
|
+
voice: options.voice || "alloy"
|
|
368
|
+
})
|
|
369
|
+
}, false);
|
|
370
|
+
if (!res.ok) {
|
|
371
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
372
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
373
|
+
}
|
|
374
|
+
this._requestCount++;
|
|
375
|
+
return res.arrayBuffer();
|
|
376
|
+
}
|
|
289
377
|
/** Search models by name, provider, or capability */
|
|
290
378
|
async searchModels(query) {
|
|
291
379
|
const all = await this.models();
|
package/dist/cli.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
|
|
29
29
|
// src/client.ts
|
|
30
|
-
var DEFAULT_BASE_URL = "https://
|
|
30
|
+
var DEFAULT_BASE_URL = "https://router.tangle.tools/v1";
|
|
31
31
|
async function proxiedFetch(privacy, url, init, streaming) {
|
|
32
32
|
if (!privacy || privacy.mode === "direct") {
|
|
33
33
|
return fetch(url, init);
|
|
@@ -84,7 +84,7 @@ var TCloudClient = class {
|
|
|
84
84
|
this.limits = config.limits;
|
|
85
85
|
this.headers = {
|
|
86
86
|
"Content-Type": "application/json",
|
|
87
|
-
"X-Tangle-Client": "tcloud-sdk/0.1.
|
|
87
|
+
"X-Tangle-Client": "tcloud-sdk/0.1.3"
|
|
88
88
|
};
|
|
89
89
|
if (this.apiKey) {
|
|
90
90
|
this.headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
@@ -92,6 +92,12 @@ var TCloudClient = class {
|
|
|
92
92
|
if (config.routing?.prefer) {
|
|
93
93
|
this.headers["X-Tangle-Operator"] = config.routing.prefer;
|
|
94
94
|
}
|
|
95
|
+
if (config.routing?.blueprintId) {
|
|
96
|
+
this.headers["X-Tangle-Blueprint"] = config.routing.blueprintId;
|
|
97
|
+
}
|
|
98
|
+
if (config.routing?.serviceId) {
|
|
99
|
+
this.headers["X-Tangle-Service"] = config.routing.serviceId;
|
|
100
|
+
}
|
|
95
101
|
if (config.routing?.region) {
|
|
96
102
|
this.headers["X-Tangle-Region"] = config.routing.region;
|
|
97
103
|
}
|
|
@@ -128,12 +134,19 @@ var TCloudClient = class {
|
|
|
128
134
|
if (pct >= 0.8) this.limits.onLimitWarning({ type: "total", current: this._totalSpent, limit: this.limits.maxTotalSpend });
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
|
-
/** Track cost after a response */
|
|
132
|
-
trackCost(completion) {
|
|
137
|
+
/** Track cost after a response, using actual pricing from response headers when available */
|
|
138
|
+
trackCost(completion, res) {
|
|
133
139
|
this._requestCount++;
|
|
134
140
|
if (completion.usage) {
|
|
135
|
-
|
|
136
|
-
const
|
|
141
|
+
let estimatedCost;
|
|
142
|
+
const inputPrice = res ? parseFloat(res.headers.get("x-tangle-price-input") || "0") : 0;
|
|
143
|
+
const outputPrice = res ? parseFloat(res.headers.get("x-tangle-price-output") || "0") : 0;
|
|
144
|
+
if (inputPrice > 0 || outputPrice > 0) {
|
|
145
|
+
estimatedCost = (completion.usage.prompt_tokens || 0) * inputPrice + (completion.usage.completion_tokens || 0) * outputPrice;
|
|
146
|
+
} else {
|
|
147
|
+
const tokens = completion.usage.total_tokens || 0;
|
|
148
|
+
estimatedCost = tokens * 1e-6;
|
|
149
|
+
}
|
|
137
150
|
this._totalSpent += estimatedCost;
|
|
138
151
|
if (this.limits?.maxCostPerRequest && estimatedCost > this.limits.maxCostPerRequest) {
|
|
139
152
|
this.limits.onLimitReached?.({ type: "cost", current: estimatedCost, limit: this.limits.maxCostPerRequest });
|
|
@@ -171,7 +184,7 @@ var TCloudClient = class {
|
|
|
171
184
|
throw new TCloudError(res.status, err.error?.message || err.error || err.message || res.statusText);
|
|
172
185
|
}
|
|
173
186
|
const completion = await res.json();
|
|
174
|
-
this.trackCost(completion);
|
|
187
|
+
this.trackCost(completion, res);
|
|
175
188
|
return completion;
|
|
176
189
|
}
|
|
177
190
|
/** Chat completion (streaming) — returns an async iterator of chunks */
|
|
@@ -310,6 +323,81 @@ var TCloudClient = class {
|
|
|
310
323
|
}, false);
|
|
311
324
|
if (!res.ok) throw new TCloudError(res.status, "Failed to revoke key");
|
|
312
325
|
}
|
|
326
|
+
/** Generate embeddings */
|
|
327
|
+
async embeddings(options) {
|
|
328
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/embeddings`, {
|
|
329
|
+
method: "POST",
|
|
330
|
+
headers: this.headers,
|
|
331
|
+
body: JSON.stringify({
|
|
332
|
+
model: options.model || "text-embedding-3-small",
|
|
333
|
+
input: options.input
|
|
334
|
+
})
|
|
335
|
+
}, false);
|
|
336
|
+
if (!res.ok) {
|
|
337
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
338
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
339
|
+
}
|
|
340
|
+
this._requestCount++;
|
|
341
|
+
return res.json();
|
|
342
|
+
}
|
|
343
|
+
/** Generate images */
|
|
344
|
+
async imageGenerate(options) {
|
|
345
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/images/generations`, {
|
|
346
|
+
method: "POST",
|
|
347
|
+
headers: this.headers,
|
|
348
|
+
body: JSON.stringify({
|
|
349
|
+
model: options.model || "dall-e-3",
|
|
350
|
+
prompt: options.prompt,
|
|
351
|
+
n: options.n,
|
|
352
|
+
size: options.size,
|
|
353
|
+
quality: options.quality,
|
|
354
|
+
response_format: options.response_format
|
|
355
|
+
})
|
|
356
|
+
}, false);
|
|
357
|
+
if (!res.ok) {
|
|
358
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
359
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
360
|
+
}
|
|
361
|
+
this._requestCount++;
|
|
362
|
+
return res.json();
|
|
363
|
+
}
|
|
364
|
+
/** Rerank documents by relevance to a query */
|
|
365
|
+
async rerank(options) {
|
|
366
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/rerank`, {
|
|
367
|
+
method: "POST",
|
|
368
|
+
headers: this.headers,
|
|
369
|
+
body: JSON.stringify({
|
|
370
|
+
model: options.model || "rerank-english-v3.0",
|
|
371
|
+
query: options.query,
|
|
372
|
+
documents: options.documents,
|
|
373
|
+
top_n: options.top_n
|
|
374
|
+
})
|
|
375
|
+
}, false);
|
|
376
|
+
if (!res.ok) {
|
|
377
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
378
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
379
|
+
}
|
|
380
|
+
this._requestCount++;
|
|
381
|
+
return res.json();
|
|
382
|
+
}
|
|
383
|
+
/** Text-to-speech */
|
|
384
|
+
async speech(options) {
|
|
385
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/audio/speech`, {
|
|
386
|
+
method: "POST",
|
|
387
|
+
headers: this.headers,
|
|
388
|
+
body: JSON.stringify({
|
|
389
|
+
model: options.model || "tts-1",
|
|
390
|
+
input: options.input,
|
|
391
|
+
voice: options.voice || "alloy"
|
|
392
|
+
})
|
|
393
|
+
}, false);
|
|
394
|
+
if (!res.ok) {
|
|
395
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
396
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
397
|
+
}
|
|
398
|
+
this._requestCount++;
|
|
399
|
+
return res.arrayBuffer();
|
|
400
|
+
}
|
|
313
401
|
/** Search models by name, provider, or capability */
|
|
314
402
|
async searchModels(query) {
|
|
315
403
|
const all = await this.models();
|
|
@@ -642,7 +730,7 @@ function ensureDir() {
|
|
|
642
730
|
function loadConfig() {
|
|
643
731
|
ensureDir();
|
|
644
732
|
if (fs.existsSync(CONFIG_FILE)) return JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
645
|
-
return { apiUrl: "https://
|
|
733
|
+
return { apiUrl: "https://router.tangle.tools", defaultModel: "gpt-4o-mini", chainId: 3799 };
|
|
646
734
|
}
|
|
647
735
|
function saveConfig(c) {
|
|
648
736
|
ensureDir();
|
|
@@ -859,7 +947,7 @@ credits.command("add").description("Add credits").argument("<amount>").action(as
|
|
|
859
947
|
});
|
|
860
948
|
credits.command("fund").description("Fund shielded credits from pool").action(() => {
|
|
861
949
|
console.log("Shielded credit funding requires integration with the VAnchor pool.");
|
|
862
|
-
console.log("See: https://docs.
|
|
950
|
+
console.log("See: https://docs.tangle.tools/privacy/funding");
|
|
863
951
|
});
|
|
864
952
|
var keys = program.command("keys").description("API key management");
|
|
865
953
|
keys.command("create").description("Create API key").argument("<name>").action(async (name) => {
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
TCloud
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-G5LUZZKT.js";
|
|
5
5
|
import {
|
|
6
6
|
generateWallet
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YKLHAS4E.js";
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
import { Command } from "commander";
|
|
@@ -20,7 +20,7 @@ function ensureDir() {
|
|
|
20
20
|
function loadConfig() {
|
|
21
21
|
ensureDir();
|
|
22
22
|
if (fs.existsSync(CONFIG_FILE)) return JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
23
|
-
return { apiUrl: "https://
|
|
23
|
+
return { apiUrl: "https://router.tangle.tools", defaultModel: "gpt-4o-mini", chainId: 3799 };
|
|
24
24
|
}
|
|
25
25
|
function saveConfig(c) {
|
|
26
26
|
ensureDir();
|
|
@@ -237,7 +237,7 @@ credits.command("add").description("Add credits").argument("<amount>").action(as
|
|
|
237
237
|
});
|
|
238
238
|
credits.command("fund").description("Fund shielded credits from pool").action(() => {
|
|
239
239
|
console.log("Shielded credit funding requires integration with the VAnchor pool.");
|
|
240
|
-
console.log("See: https://docs.
|
|
240
|
+
console.log("See: https://docs.tangle.tools/privacy/funding");
|
|
241
241
|
});
|
|
242
242
|
var keys = program.command("keys").description("API key management");
|
|
243
243
|
keys.command("create").description("Create API key").argument("<name>").action(async (name) => {
|
package/dist/index.cjs
CHANGED
|
@@ -41,7 +41,7 @@ __export(index_exports, {
|
|
|
41
41
|
module.exports = __toCommonJS(index_exports);
|
|
42
42
|
|
|
43
43
|
// src/client.ts
|
|
44
|
-
var DEFAULT_BASE_URL = "https://
|
|
44
|
+
var DEFAULT_BASE_URL = "https://router.tangle.tools/v1";
|
|
45
45
|
async function proxiedFetch(privacy, url, init, streaming) {
|
|
46
46
|
if (!privacy || privacy.mode === "direct") {
|
|
47
47
|
return fetch(url, init);
|
|
@@ -98,7 +98,7 @@ var TCloudClient = class {
|
|
|
98
98
|
this.limits = config.limits;
|
|
99
99
|
this.headers = {
|
|
100
100
|
"Content-Type": "application/json",
|
|
101
|
-
"X-Tangle-Client": "tcloud-sdk/0.1.
|
|
101
|
+
"X-Tangle-Client": "tcloud-sdk/0.1.3"
|
|
102
102
|
};
|
|
103
103
|
if (this.apiKey) {
|
|
104
104
|
this.headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
@@ -106,6 +106,12 @@ var TCloudClient = class {
|
|
|
106
106
|
if (config.routing?.prefer) {
|
|
107
107
|
this.headers["X-Tangle-Operator"] = config.routing.prefer;
|
|
108
108
|
}
|
|
109
|
+
if (config.routing?.blueprintId) {
|
|
110
|
+
this.headers["X-Tangle-Blueprint"] = config.routing.blueprintId;
|
|
111
|
+
}
|
|
112
|
+
if (config.routing?.serviceId) {
|
|
113
|
+
this.headers["X-Tangle-Service"] = config.routing.serviceId;
|
|
114
|
+
}
|
|
109
115
|
if (config.routing?.region) {
|
|
110
116
|
this.headers["X-Tangle-Region"] = config.routing.region;
|
|
111
117
|
}
|
|
@@ -142,12 +148,19 @@ var TCloudClient = class {
|
|
|
142
148
|
if (pct >= 0.8) this.limits.onLimitWarning({ type: "total", current: this._totalSpent, limit: this.limits.maxTotalSpend });
|
|
143
149
|
}
|
|
144
150
|
}
|
|
145
|
-
/** Track cost after a response */
|
|
146
|
-
trackCost(completion) {
|
|
151
|
+
/** Track cost after a response, using actual pricing from response headers when available */
|
|
152
|
+
trackCost(completion, res) {
|
|
147
153
|
this._requestCount++;
|
|
148
154
|
if (completion.usage) {
|
|
149
|
-
|
|
150
|
-
const
|
|
155
|
+
let estimatedCost;
|
|
156
|
+
const inputPrice = res ? parseFloat(res.headers.get("x-tangle-price-input") || "0") : 0;
|
|
157
|
+
const outputPrice = res ? parseFloat(res.headers.get("x-tangle-price-output") || "0") : 0;
|
|
158
|
+
if (inputPrice > 0 || outputPrice > 0) {
|
|
159
|
+
estimatedCost = (completion.usage.prompt_tokens || 0) * inputPrice + (completion.usage.completion_tokens || 0) * outputPrice;
|
|
160
|
+
} else {
|
|
161
|
+
const tokens = completion.usage.total_tokens || 0;
|
|
162
|
+
estimatedCost = tokens * 1e-6;
|
|
163
|
+
}
|
|
151
164
|
this._totalSpent += estimatedCost;
|
|
152
165
|
if (this.limits?.maxCostPerRequest && estimatedCost > this.limits.maxCostPerRequest) {
|
|
153
166
|
this.limits.onLimitReached?.({ type: "cost", current: estimatedCost, limit: this.limits.maxCostPerRequest });
|
|
@@ -185,7 +198,7 @@ var TCloudClient = class {
|
|
|
185
198
|
throw new TCloudError(res.status, err.error?.message || err.error || err.message || res.statusText);
|
|
186
199
|
}
|
|
187
200
|
const completion = await res.json();
|
|
188
|
-
this.trackCost(completion);
|
|
201
|
+
this.trackCost(completion, res);
|
|
189
202
|
return completion;
|
|
190
203
|
}
|
|
191
204
|
/** Chat completion (streaming) — returns an async iterator of chunks */
|
|
@@ -324,6 +337,81 @@ var TCloudClient = class {
|
|
|
324
337
|
}, false);
|
|
325
338
|
if (!res.ok) throw new TCloudError(res.status, "Failed to revoke key");
|
|
326
339
|
}
|
|
340
|
+
/** Generate embeddings */
|
|
341
|
+
async embeddings(options) {
|
|
342
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/embeddings`, {
|
|
343
|
+
method: "POST",
|
|
344
|
+
headers: this.headers,
|
|
345
|
+
body: JSON.stringify({
|
|
346
|
+
model: options.model || "text-embedding-3-small",
|
|
347
|
+
input: options.input
|
|
348
|
+
})
|
|
349
|
+
}, false);
|
|
350
|
+
if (!res.ok) {
|
|
351
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
352
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
353
|
+
}
|
|
354
|
+
this._requestCount++;
|
|
355
|
+
return res.json();
|
|
356
|
+
}
|
|
357
|
+
/** Generate images */
|
|
358
|
+
async imageGenerate(options) {
|
|
359
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/images/generations`, {
|
|
360
|
+
method: "POST",
|
|
361
|
+
headers: this.headers,
|
|
362
|
+
body: JSON.stringify({
|
|
363
|
+
model: options.model || "dall-e-3",
|
|
364
|
+
prompt: options.prompt,
|
|
365
|
+
n: options.n,
|
|
366
|
+
size: options.size,
|
|
367
|
+
quality: options.quality,
|
|
368
|
+
response_format: options.response_format
|
|
369
|
+
})
|
|
370
|
+
}, false);
|
|
371
|
+
if (!res.ok) {
|
|
372
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
373
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
374
|
+
}
|
|
375
|
+
this._requestCount++;
|
|
376
|
+
return res.json();
|
|
377
|
+
}
|
|
378
|
+
/** Rerank documents by relevance to a query */
|
|
379
|
+
async rerank(options) {
|
|
380
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/rerank`, {
|
|
381
|
+
method: "POST",
|
|
382
|
+
headers: this.headers,
|
|
383
|
+
body: JSON.stringify({
|
|
384
|
+
model: options.model || "rerank-english-v3.0",
|
|
385
|
+
query: options.query,
|
|
386
|
+
documents: options.documents,
|
|
387
|
+
top_n: options.top_n
|
|
388
|
+
})
|
|
389
|
+
}, false);
|
|
390
|
+
if (!res.ok) {
|
|
391
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
392
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
393
|
+
}
|
|
394
|
+
this._requestCount++;
|
|
395
|
+
return res.json();
|
|
396
|
+
}
|
|
397
|
+
/** Text-to-speech */
|
|
398
|
+
async speech(options) {
|
|
399
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/audio/speech`, {
|
|
400
|
+
method: "POST",
|
|
401
|
+
headers: this.headers,
|
|
402
|
+
body: JSON.stringify({
|
|
403
|
+
model: options.model || "tts-1",
|
|
404
|
+
input: options.input,
|
|
405
|
+
voice: options.voice || "alloy"
|
|
406
|
+
})
|
|
407
|
+
}, false);
|
|
408
|
+
if (!res.ok) {
|
|
409
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
410
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
411
|
+
}
|
|
412
|
+
this._requestCount++;
|
|
413
|
+
return res.arrayBuffer();
|
|
414
|
+
}
|
|
327
415
|
/** Search models by name, provider, or capability */
|
|
328
416
|
async searchModels(query) {
|
|
329
417
|
const all = await this.models();
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TCloudClient, a as TCloudConfig, S as ShieldedWallet, g as generateWallet } from './shielded-
|
|
2
|
-
export { C as ChatCompletion, b as ChatCompletionChunk, c as ChatMessage, d as ChatOptions, e as CreditBalance, M as Model, O as Operator, P as PrivacyConfig, R as RoutingConfig,
|
|
1
|
+
import { T as TCloudClient, a as TCloudConfig, S as ShieldedWallet, g as generateWallet } from './shielded-xDNVqK4a.cjs';
|
|
2
|
+
export { C as ChatCompletion, b as ChatCompletionChunk, c as ChatMessage, d as ChatOptions, e as CreditBalance, E as EmbeddingOptions, f as EmbeddingResponse, I as ImageGenerateOptions, h as ImageResponse, M as Model, O as Operator, P as PrivacyConfig, R as RerankOptions, i as RerankResponse, j as RoutingConfig, k as ShieldedConfig, l as SpendAuth, m as SpendingLimits, n as TCloudError, o as createShieldedClient, p as estimateCost, s as signSpendAuth } from './shielded-xDNVqK4a.cjs';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class TCloud extends TCloudClient {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TCloudClient, a as TCloudConfig, S as ShieldedWallet, g as generateWallet } from './shielded-
|
|
2
|
-
export { C as ChatCompletion, b as ChatCompletionChunk, c as ChatMessage, d as ChatOptions, e as CreditBalance, M as Model, O as Operator, P as PrivacyConfig, R as RoutingConfig,
|
|
1
|
+
import { T as TCloudClient, a as TCloudConfig, S as ShieldedWallet, g as generateWallet } from './shielded-xDNVqK4a.js';
|
|
2
|
+
export { C as ChatCompletion, b as ChatCompletionChunk, c as ChatMessage, d as ChatOptions, e as CreditBalance, E as EmbeddingOptions, f as EmbeddingResponse, I as ImageGenerateOptions, h as ImageResponse, M as Model, O as Operator, P as PrivacyConfig, R as RerankOptions, i as RerankResponse, j as RoutingConfig, k as ShieldedConfig, l as SpendAuth, m as SpendingLimits, n as TCloudError, o as createShieldedClient, p as estimateCost, s as signSpendAuth } from './shielded-xDNVqK4a.js';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class TCloud extends TCloudClient {
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TCloud
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-G5LUZZKT.js";
|
|
4
4
|
import {
|
|
5
5
|
TCloudClient,
|
|
6
6
|
TCloudError,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
estimateCost,
|
|
9
9
|
generateWallet,
|
|
10
10
|
signSpendAuth
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-YKLHAS4E.js";
|
|
12
12
|
export {
|
|
13
13
|
TCloud,
|
|
14
14
|
TCloudClient,
|
|
@@ -2,7 +2,7 @@ import { Hex } from 'viem';
|
|
|
2
2
|
|
|
3
3
|
/** Core types for the tcloud SDK */
|
|
4
4
|
interface TCloudConfig {
|
|
5
|
-
/** API base URL (default: https://
|
|
5
|
+
/** API base URL (default: https://router.tangle.tools/v1) */
|
|
6
6
|
baseURL?: string;
|
|
7
7
|
/** API key for standard (non-private) mode */
|
|
8
8
|
apiKey?: string;
|
|
@@ -38,8 +38,12 @@ interface SpendingLimits {
|
|
|
38
38
|
}) => void;
|
|
39
39
|
}
|
|
40
40
|
interface RoutingConfig {
|
|
41
|
-
/** Preferred operator slug */
|
|
41
|
+
/** Preferred operator slug or address */
|
|
42
42
|
prefer?: string;
|
|
43
|
+
/** Blueprint ID — route to operators under this Blueprint */
|
|
44
|
+
blueprintId?: string;
|
|
45
|
+
/** Service instance ID — route to a specific service instance */
|
|
46
|
+
serviceId?: string;
|
|
43
47
|
/** Routing strategy */
|
|
44
48
|
strategy?: 'lowest-latency' | 'lowest-price' | 'highest-reputation' | 'round-robin';
|
|
45
49
|
/** Region filter */
|
|
@@ -47,6 +51,51 @@ interface RoutingConfig {
|
|
|
47
51
|
/** Fallback operator slugs (tried in order) */
|
|
48
52
|
fallback?: string[];
|
|
49
53
|
}
|
|
54
|
+
interface EmbeddingOptions {
|
|
55
|
+
model?: string;
|
|
56
|
+
input: string | string[];
|
|
57
|
+
}
|
|
58
|
+
interface EmbeddingResponse {
|
|
59
|
+
object: string;
|
|
60
|
+
data: {
|
|
61
|
+
object: string;
|
|
62
|
+
embedding: number[];
|
|
63
|
+
index: number;
|
|
64
|
+
}[];
|
|
65
|
+
model: string;
|
|
66
|
+
usage: {
|
|
67
|
+
prompt_tokens: number;
|
|
68
|
+
total_tokens: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
interface ImageGenerateOptions {
|
|
72
|
+
model?: string;
|
|
73
|
+
prompt: string;
|
|
74
|
+
n?: number;
|
|
75
|
+
size?: string;
|
|
76
|
+
quality?: string;
|
|
77
|
+
response_format?: 'url' | 'b64_json';
|
|
78
|
+
}
|
|
79
|
+
interface ImageResponse {
|
|
80
|
+
created: number;
|
|
81
|
+
data: {
|
|
82
|
+
url?: string;
|
|
83
|
+
b64_json?: string;
|
|
84
|
+
revised_prompt?: string;
|
|
85
|
+
}[];
|
|
86
|
+
}
|
|
87
|
+
interface RerankOptions {
|
|
88
|
+
model?: string;
|
|
89
|
+
query: string;
|
|
90
|
+
documents: string[];
|
|
91
|
+
top_n?: number;
|
|
92
|
+
}
|
|
93
|
+
interface RerankResponse {
|
|
94
|
+
results: {
|
|
95
|
+
index: number;
|
|
96
|
+
relevance_score: number;
|
|
97
|
+
}[];
|
|
98
|
+
}
|
|
50
99
|
interface PrivacyConfig {
|
|
51
100
|
/** 'direct' — no proxy (default). 'relayer' — route through tcloud-relayer. 'socks5' — route through SOCKS5 proxy (e.g. Tor). */
|
|
52
101
|
mode: 'direct' | 'relayer' | 'socks5';
|
|
@@ -225,7 +274,7 @@ declare class TCloudClient {
|
|
|
225
274
|
};
|
|
226
275
|
/** Check spending limits before a request. Throws TCloudError if blocked. */
|
|
227
276
|
private checkLimits;
|
|
228
|
-
/** Track cost after a response */
|
|
277
|
+
/** Track cost after a response, using actual pricing from response headers when available */
|
|
229
278
|
private trackCost;
|
|
230
279
|
/** Chat completion (non-streaming) */
|
|
231
280
|
chat(options: ChatOptions): Promise<ChatCompletion>;
|
|
@@ -265,6 +314,18 @@ declare class TCloudClient {
|
|
|
265
314
|
}[]>;
|
|
266
315
|
/** Revoke an API key */
|
|
267
316
|
revokeKey(id: string): Promise<void>;
|
|
317
|
+
/** Generate embeddings */
|
|
318
|
+
embeddings(options: EmbeddingOptions): Promise<EmbeddingResponse>;
|
|
319
|
+
/** Generate images */
|
|
320
|
+
imageGenerate(options: ImageGenerateOptions): Promise<ImageResponse>;
|
|
321
|
+
/** Rerank documents by relevance to a query */
|
|
322
|
+
rerank(options: RerankOptions): Promise<RerankResponse>;
|
|
323
|
+
/** Text-to-speech */
|
|
324
|
+
speech(options: {
|
|
325
|
+
model?: string;
|
|
326
|
+
input: string;
|
|
327
|
+
voice?: string;
|
|
328
|
+
}): Promise<ArrayBuffer>;
|
|
268
329
|
/** Search models by name, provider, or capability */
|
|
269
330
|
searchModels(query: string): Promise<Model[]>;
|
|
270
331
|
/** Estimate cost for a request (without sending it) */
|
|
@@ -340,4 +401,4 @@ declare function createShieldedClient(config?: TCloudConfig & {
|
|
|
340
401
|
stopAutoReplenish: () => void;
|
|
341
402
|
};
|
|
342
403
|
|
|
343
|
-
export { type AutoReplenishOptions as A, type ChatCompletion as C, type Model as M, type Operator as O, type PrivacyConfig as P, type
|
|
404
|
+
export { type AutoReplenishOptions as A, type ChatCompletion as C, type EmbeddingOptions as E, type ImageGenerateOptions as I, type Model as M, type Operator as O, type PrivacyConfig as P, type RerankOptions as R, type ShieldedWallet as S, TCloudClient as T, type TCloudConfig as a, type ChatCompletionChunk as b, type ChatMessage as c, type ChatOptions as d, type CreditBalance as e, type EmbeddingResponse as f, generateWallet as g, type ImageResponse as h, type RerankResponse as i, type RoutingConfig as j, type ShieldedConfig as k, type SpendAuth as l, type SpendingLimits as m, TCloudError as n, createShieldedClient as o, estimateCost as p, signSpendAuth as s };
|
|
@@ -2,7 +2,7 @@ import { Hex } from 'viem';
|
|
|
2
2
|
|
|
3
3
|
/** Core types for the tcloud SDK */
|
|
4
4
|
interface TCloudConfig {
|
|
5
|
-
/** API base URL (default: https://
|
|
5
|
+
/** API base URL (default: https://router.tangle.tools/v1) */
|
|
6
6
|
baseURL?: string;
|
|
7
7
|
/** API key for standard (non-private) mode */
|
|
8
8
|
apiKey?: string;
|
|
@@ -38,8 +38,12 @@ interface SpendingLimits {
|
|
|
38
38
|
}) => void;
|
|
39
39
|
}
|
|
40
40
|
interface RoutingConfig {
|
|
41
|
-
/** Preferred operator slug */
|
|
41
|
+
/** Preferred operator slug or address */
|
|
42
42
|
prefer?: string;
|
|
43
|
+
/** Blueprint ID — route to operators under this Blueprint */
|
|
44
|
+
blueprintId?: string;
|
|
45
|
+
/** Service instance ID — route to a specific service instance */
|
|
46
|
+
serviceId?: string;
|
|
43
47
|
/** Routing strategy */
|
|
44
48
|
strategy?: 'lowest-latency' | 'lowest-price' | 'highest-reputation' | 'round-robin';
|
|
45
49
|
/** Region filter */
|
|
@@ -47,6 +51,51 @@ interface RoutingConfig {
|
|
|
47
51
|
/** Fallback operator slugs (tried in order) */
|
|
48
52
|
fallback?: string[];
|
|
49
53
|
}
|
|
54
|
+
interface EmbeddingOptions {
|
|
55
|
+
model?: string;
|
|
56
|
+
input: string | string[];
|
|
57
|
+
}
|
|
58
|
+
interface EmbeddingResponse {
|
|
59
|
+
object: string;
|
|
60
|
+
data: {
|
|
61
|
+
object: string;
|
|
62
|
+
embedding: number[];
|
|
63
|
+
index: number;
|
|
64
|
+
}[];
|
|
65
|
+
model: string;
|
|
66
|
+
usage: {
|
|
67
|
+
prompt_tokens: number;
|
|
68
|
+
total_tokens: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
interface ImageGenerateOptions {
|
|
72
|
+
model?: string;
|
|
73
|
+
prompt: string;
|
|
74
|
+
n?: number;
|
|
75
|
+
size?: string;
|
|
76
|
+
quality?: string;
|
|
77
|
+
response_format?: 'url' | 'b64_json';
|
|
78
|
+
}
|
|
79
|
+
interface ImageResponse {
|
|
80
|
+
created: number;
|
|
81
|
+
data: {
|
|
82
|
+
url?: string;
|
|
83
|
+
b64_json?: string;
|
|
84
|
+
revised_prompt?: string;
|
|
85
|
+
}[];
|
|
86
|
+
}
|
|
87
|
+
interface RerankOptions {
|
|
88
|
+
model?: string;
|
|
89
|
+
query: string;
|
|
90
|
+
documents: string[];
|
|
91
|
+
top_n?: number;
|
|
92
|
+
}
|
|
93
|
+
interface RerankResponse {
|
|
94
|
+
results: {
|
|
95
|
+
index: number;
|
|
96
|
+
relevance_score: number;
|
|
97
|
+
}[];
|
|
98
|
+
}
|
|
50
99
|
interface PrivacyConfig {
|
|
51
100
|
/** 'direct' — no proxy (default). 'relayer' — route through tcloud-relayer. 'socks5' — route through SOCKS5 proxy (e.g. Tor). */
|
|
52
101
|
mode: 'direct' | 'relayer' | 'socks5';
|
|
@@ -225,7 +274,7 @@ declare class TCloudClient {
|
|
|
225
274
|
};
|
|
226
275
|
/** Check spending limits before a request. Throws TCloudError if blocked. */
|
|
227
276
|
private checkLimits;
|
|
228
|
-
/** Track cost after a response */
|
|
277
|
+
/** Track cost after a response, using actual pricing from response headers when available */
|
|
229
278
|
private trackCost;
|
|
230
279
|
/** Chat completion (non-streaming) */
|
|
231
280
|
chat(options: ChatOptions): Promise<ChatCompletion>;
|
|
@@ -265,6 +314,18 @@ declare class TCloudClient {
|
|
|
265
314
|
}[]>;
|
|
266
315
|
/** Revoke an API key */
|
|
267
316
|
revokeKey(id: string): Promise<void>;
|
|
317
|
+
/** Generate embeddings */
|
|
318
|
+
embeddings(options: EmbeddingOptions): Promise<EmbeddingResponse>;
|
|
319
|
+
/** Generate images */
|
|
320
|
+
imageGenerate(options: ImageGenerateOptions): Promise<ImageResponse>;
|
|
321
|
+
/** Rerank documents by relevance to a query */
|
|
322
|
+
rerank(options: RerankOptions): Promise<RerankResponse>;
|
|
323
|
+
/** Text-to-speech */
|
|
324
|
+
speech(options: {
|
|
325
|
+
model?: string;
|
|
326
|
+
input: string;
|
|
327
|
+
voice?: string;
|
|
328
|
+
}): Promise<ArrayBuffer>;
|
|
268
329
|
/** Search models by name, provider, or capability */
|
|
269
330
|
searchModels(query: string): Promise<Model[]>;
|
|
270
331
|
/** Estimate cost for a request (without sending it) */
|
|
@@ -340,4 +401,4 @@ declare function createShieldedClient(config?: TCloudConfig & {
|
|
|
340
401
|
stopAutoReplenish: () => void;
|
|
341
402
|
};
|
|
342
403
|
|
|
343
|
-
export { type AutoReplenishOptions as A, type ChatCompletion as C, type Model as M, type Operator as O, type PrivacyConfig as P, type
|
|
404
|
+
export { type AutoReplenishOptions as A, type ChatCompletion as C, type EmbeddingOptions as E, type ImageGenerateOptions as I, type Model as M, type Operator as O, type PrivacyConfig as P, type RerankOptions as R, type ShieldedWallet as S, TCloudClient as T, type TCloudConfig as a, type ChatCompletionChunk as b, type ChatMessage as c, type ChatOptions as d, type CreditBalance as e, type EmbeddingResponse as f, generateWallet as g, type ImageResponse as h, type RerankResponse as i, type RoutingConfig as j, type ShieldedConfig as k, type SpendAuth as l, type SpendingLimits as m, TCloudError as n, createShieldedClient as o, estimateCost as p, signSpendAuth as s };
|
package/dist/shielded.cjs
CHANGED
|
@@ -40,7 +40,7 @@ var import_accounts = require("viem/accounts");
|
|
|
40
40
|
var import_viem = require("viem");
|
|
41
41
|
|
|
42
42
|
// src/client.ts
|
|
43
|
-
var DEFAULT_BASE_URL = "https://
|
|
43
|
+
var DEFAULT_BASE_URL = "https://router.tangle.tools/v1";
|
|
44
44
|
async function proxiedFetch(privacy, url, init, streaming) {
|
|
45
45
|
if (!privacy || privacy.mode === "direct") {
|
|
46
46
|
return fetch(url, init);
|
|
@@ -97,7 +97,7 @@ var TCloudClient = class {
|
|
|
97
97
|
this.limits = config.limits;
|
|
98
98
|
this.headers = {
|
|
99
99
|
"Content-Type": "application/json",
|
|
100
|
-
"X-Tangle-Client": "tcloud-sdk/0.1.
|
|
100
|
+
"X-Tangle-Client": "tcloud-sdk/0.1.3"
|
|
101
101
|
};
|
|
102
102
|
if (this.apiKey) {
|
|
103
103
|
this.headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
@@ -105,6 +105,12 @@ var TCloudClient = class {
|
|
|
105
105
|
if (config.routing?.prefer) {
|
|
106
106
|
this.headers["X-Tangle-Operator"] = config.routing.prefer;
|
|
107
107
|
}
|
|
108
|
+
if (config.routing?.blueprintId) {
|
|
109
|
+
this.headers["X-Tangle-Blueprint"] = config.routing.blueprintId;
|
|
110
|
+
}
|
|
111
|
+
if (config.routing?.serviceId) {
|
|
112
|
+
this.headers["X-Tangle-Service"] = config.routing.serviceId;
|
|
113
|
+
}
|
|
108
114
|
if (config.routing?.region) {
|
|
109
115
|
this.headers["X-Tangle-Region"] = config.routing.region;
|
|
110
116
|
}
|
|
@@ -141,12 +147,19 @@ var TCloudClient = class {
|
|
|
141
147
|
if (pct >= 0.8) this.limits.onLimitWarning({ type: "total", current: this._totalSpent, limit: this.limits.maxTotalSpend });
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
|
-
/** Track cost after a response */
|
|
145
|
-
trackCost(completion) {
|
|
150
|
+
/** Track cost after a response, using actual pricing from response headers when available */
|
|
151
|
+
trackCost(completion, res) {
|
|
146
152
|
this._requestCount++;
|
|
147
153
|
if (completion.usage) {
|
|
148
|
-
|
|
149
|
-
const
|
|
154
|
+
let estimatedCost;
|
|
155
|
+
const inputPrice = res ? parseFloat(res.headers.get("x-tangle-price-input") || "0") : 0;
|
|
156
|
+
const outputPrice = res ? parseFloat(res.headers.get("x-tangle-price-output") || "0") : 0;
|
|
157
|
+
if (inputPrice > 0 || outputPrice > 0) {
|
|
158
|
+
estimatedCost = (completion.usage.prompt_tokens || 0) * inputPrice + (completion.usage.completion_tokens || 0) * outputPrice;
|
|
159
|
+
} else {
|
|
160
|
+
const tokens = completion.usage.total_tokens || 0;
|
|
161
|
+
estimatedCost = tokens * 1e-6;
|
|
162
|
+
}
|
|
150
163
|
this._totalSpent += estimatedCost;
|
|
151
164
|
if (this.limits?.maxCostPerRequest && estimatedCost > this.limits.maxCostPerRequest) {
|
|
152
165
|
this.limits.onLimitReached?.({ type: "cost", current: estimatedCost, limit: this.limits.maxCostPerRequest });
|
|
@@ -184,7 +197,7 @@ var TCloudClient = class {
|
|
|
184
197
|
throw new TCloudError(res.status, err.error?.message || err.error || err.message || res.statusText);
|
|
185
198
|
}
|
|
186
199
|
const completion = await res.json();
|
|
187
|
-
this.trackCost(completion);
|
|
200
|
+
this.trackCost(completion, res);
|
|
188
201
|
return completion;
|
|
189
202
|
}
|
|
190
203
|
/** Chat completion (streaming) — returns an async iterator of chunks */
|
|
@@ -323,6 +336,81 @@ var TCloudClient = class {
|
|
|
323
336
|
}, false);
|
|
324
337
|
if (!res.ok) throw new TCloudError(res.status, "Failed to revoke key");
|
|
325
338
|
}
|
|
339
|
+
/** Generate embeddings */
|
|
340
|
+
async embeddings(options) {
|
|
341
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/embeddings`, {
|
|
342
|
+
method: "POST",
|
|
343
|
+
headers: this.headers,
|
|
344
|
+
body: JSON.stringify({
|
|
345
|
+
model: options.model || "text-embedding-3-small",
|
|
346
|
+
input: options.input
|
|
347
|
+
})
|
|
348
|
+
}, false);
|
|
349
|
+
if (!res.ok) {
|
|
350
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
351
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
352
|
+
}
|
|
353
|
+
this._requestCount++;
|
|
354
|
+
return res.json();
|
|
355
|
+
}
|
|
356
|
+
/** Generate images */
|
|
357
|
+
async imageGenerate(options) {
|
|
358
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/images/generations`, {
|
|
359
|
+
method: "POST",
|
|
360
|
+
headers: this.headers,
|
|
361
|
+
body: JSON.stringify({
|
|
362
|
+
model: options.model || "dall-e-3",
|
|
363
|
+
prompt: options.prompt,
|
|
364
|
+
n: options.n,
|
|
365
|
+
size: options.size,
|
|
366
|
+
quality: options.quality,
|
|
367
|
+
response_format: options.response_format
|
|
368
|
+
})
|
|
369
|
+
}, false);
|
|
370
|
+
if (!res.ok) {
|
|
371
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
372
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
373
|
+
}
|
|
374
|
+
this._requestCount++;
|
|
375
|
+
return res.json();
|
|
376
|
+
}
|
|
377
|
+
/** Rerank documents by relevance to a query */
|
|
378
|
+
async rerank(options) {
|
|
379
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/rerank`, {
|
|
380
|
+
method: "POST",
|
|
381
|
+
headers: this.headers,
|
|
382
|
+
body: JSON.stringify({
|
|
383
|
+
model: options.model || "rerank-english-v3.0",
|
|
384
|
+
query: options.query,
|
|
385
|
+
documents: options.documents,
|
|
386
|
+
top_n: options.top_n
|
|
387
|
+
})
|
|
388
|
+
}, false);
|
|
389
|
+
if (!res.ok) {
|
|
390
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
391
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
392
|
+
}
|
|
393
|
+
this._requestCount++;
|
|
394
|
+
return res.json();
|
|
395
|
+
}
|
|
396
|
+
/** Text-to-speech */
|
|
397
|
+
async speech(options) {
|
|
398
|
+
const res = await proxiedFetch(this.privacy, `${this.baseURL}/audio/speech`, {
|
|
399
|
+
method: "POST",
|
|
400
|
+
headers: this.headers,
|
|
401
|
+
body: JSON.stringify({
|
|
402
|
+
model: options.model || "tts-1",
|
|
403
|
+
input: options.input,
|
|
404
|
+
voice: options.voice || "alloy"
|
|
405
|
+
})
|
|
406
|
+
}, false);
|
|
407
|
+
if (!res.ok) {
|
|
408
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
409
|
+
throw new TCloudError(res.status, err.error?.message || err.error || res.statusText);
|
|
410
|
+
}
|
|
411
|
+
this._requestCount++;
|
|
412
|
+
return res.arrayBuffer();
|
|
413
|
+
}
|
|
326
414
|
/** Search models by name, provider, or capability */
|
|
327
415
|
async searchModels(query) {
|
|
328
416
|
const all = await this.models();
|
package/dist/shielded.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import 'viem';
|
|
2
|
-
export { A as AutoReplenishOptions, S as ShieldedWallet,
|
|
2
|
+
export { A as AutoReplenishOptions, S as ShieldedWallet, l as SpendAuth, o as createShieldedClient, p as estimateCost, g as generateWallet, s as signSpendAuth } from './shielded-xDNVqK4a.cjs';
|
package/dist/shielded.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import 'viem';
|
|
2
|
-
export { A as AutoReplenishOptions, S as ShieldedWallet,
|
|
2
|
+
export { A as AutoReplenishOptions, S as ShieldedWallet, l as SpendAuth, o as createShieldedClient, p as estimateCost, g as generateWallet, s as signSpendAuth } from './shielded-xDNVqK4a.js';
|
package/dist/shielded.js
CHANGED