@wice24/tars-sdk 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +33 -8
- package/dist/index.js +30 -7
- package/dist/types.d.ts +53 -3
- package/package.json +10 -10
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { Agent, AgentVersion, ClientTool, CreateAgentInput, FileMeta, ListMcpToolsInput, McpCredentialInput, McpCredentialStatus, McpServerTools, ReasoningConfig, SessionEvent, ModelInfo, SessionInfo, SessionListItem, UpdateAgentInput, UploadFileInput, UsageSummary, SessionUsageRow, DailyUsageRow, McpServer, Skill, SkillVersion, ApiKeyInfo, ClientIdentity, ClientRole, PlatformStats, Tenant } from './types.js';
|
|
1
|
+
import type { Agent, AgentVersion, ClientTool, CreateAgentInput, FileMeta, ListMcpToolsInput, McpCredentialInput, McpCredentialStatus, McpServerTools, ReasoningConfig, SessionEvent, ModelInfo, ProviderKeys, ProviderStatusReport, SessionInfo, SessionListItem, UpdateAgentInput, UploadFileInput, UsageSummary, SessionUsageRow, DailyUsageRow, McpServer, Skill, SkillVersion, ApiKeyInfo, ClientIdentity, ClientRole, PlatformStats, Tenant } from './types.js';
|
|
2
2
|
type ToolHandler = (input: any) => unknown | Promise<unknown>;
|
|
3
3
|
export * from './types.js';
|
|
4
|
+
/** The providers `providerKeys` accepts. */
|
|
5
|
+
export declare const KEYED_PROVIDERS: readonly ["anthropic", "openai", "openrouter", "tensorx"];
|
|
4
6
|
export declare class TarsApiError extends Error {
|
|
5
7
|
readonly status: number;
|
|
6
8
|
readonly body: unknown;
|
|
@@ -23,12 +25,27 @@ export interface TarsClientOptions {
|
|
|
23
25
|
* — use a client WITHOUT this option to administrate.
|
|
24
26
|
*/
|
|
25
27
|
actAsTenant?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Your own LLM provider keys, by provider (`openrouter`, `openai`,
|
|
30
|
+
* `anthropic`, `tensorx`). Sent with EVERY request (one
|
|
31
|
+
* `x-tars-key-<provider>` header each) and used for that request's model
|
|
32
|
+
* calls — session turns, completions, the model catalog — so usage bills to
|
|
33
|
+
* your provider accounts. TARS never stores them. A provider you omit
|
|
34
|
+
* routes on the instance's key only while that instance's cutover fallback
|
|
35
|
+
* is on; otherwise its models are refused with 400
|
|
36
|
+
* `provider_not_configured`. Check with `providerStatus()`.
|
|
37
|
+
*
|
|
38
|
+
* SERVER-SIDE clients only: in a browser these keys would ship to every
|
|
39
|
+
* user of your app.
|
|
40
|
+
*/
|
|
41
|
+
providerKeys?: ProviderKeys;
|
|
26
42
|
}
|
|
27
43
|
export declare class TarsClient {
|
|
28
44
|
private readonly baseUrl;
|
|
29
45
|
private readonly apiKey;
|
|
30
46
|
private readonly fetchImpl;
|
|
31
47
|
private readonly actAsTenant?;
|
|
48
|
+
private readonly providerKeyHeaders;
|
|
32
49
|
constructor(options: TarsClientOptions);
|
|
33
50
|
/** Every request path — JSON, uploads, SSE — sends these, so act-as scoping
|
|
34
51
|
* can never silently miss a surface. */
|
|
@@ -228,20 +245,28 @@ export declare class TarsClient {
|
|
|
228
245
|
}>;
|
|
229
246
|
};
|
|
230
247
|
/**
|
|
231
|
-
* Which model providers
|
|
232
|
-
* `openrouter`, `custom`)
|
|
233
|
-
*
|
|
234
|
-
*
|
|
248
|
+
* Which model providers YOU can route now (`anthropic`, `openai`,
|
|
249
|
+
* `openrouter`, `tensorx`, `custom`): those you passed in `providerKeys`,
|
|
250
|
+
* plus the instance's while its cutover fallback is on, plus `custom` on an
|
|
251
|
+
* instance pointed at a local runtime. Ask before OFFERING models: a picker
|
|
252
|
+
* listing GPT models without an OpenAI key produces turns that all fail.
|
|
235
253
|
*/
|
|
236
254
|
providers(): Promise<string[]>;
|
|
255
|
+
/**
|
|
256
|
+
* Every provider with whether you can route it and on whose key
|
|
257
|
+
* (`request` = your `providerKeys`, `instance` = the deployment's), plus
|
|
258
|
+
* whether the instance still falls back to its own keys. What a settings
|
|
259
|
+
* page shows: all providers, the inactive ones disabled.
|
|
260
|
+
*/
|
|
261
|
+
providerStatus(): Promise<ProviderStatusReport>;
|
|
237
262
|
/**
|
|
238
263
|
* The models this instance can route AND price — ids are full
|
|
239
|
-
* `provider/model` specs. `openrouter/*` entries mirror
|
|
240
|
-
*
|
|
264
|
+
* `provider/model` specs. `openrouter/*` and `tensorx/*` entries mirror
|
|
265
|
+
* those providers' live catalogs, so those ids exist right now; direct entries
|
|
241
266
|
* come from the deployment's curated pricing table. Offer models from this
|
|
242
267
|
* list rather than hardcoding ids that can drift.
|
|
243
268
|
*
|
|
244
|
-
* The list is "what is known now", not "everything routable":
|
|
269
|
+
* The list is "what is known now", not "everything routable": catalog
|
|
245
270
|
* entries are absent before the instance's first successful catalog
|
|
246
271
|
* refresh, and a deployment routing only `custom/*` has no priced entries
|
|
247
272
|
* at all. When it comes back empty, fall back to `providers()` plus your
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
|
+
/** The providers `providerKeys` accepts. */
|
|
3
|
+
export const KEYED_PROVIDERS = ['anthropic', 'openai', 'openrouter', 'tensorx'];
|
|
2
4
|
export class TarsApiError extends Error {
|
|
3
5
|
status;
|
|
4
6
|
body;
|
|
@@ -14,6 +16,7 @@ export class TarsClient {
|
|
|
14
16
|
apiKey;
|
|
15
17
|
fetchImpl;
|
|
16
18
|
actAsTenant;
|
|
19
|
+
providerKeyHeaders;
|
|
17
20
|
constructor(options) {
|
|
18
21
|
if (!options.apiKey)
|
|
19
22
|
throw new Error('TarsClient: apiKey is required');
|
|
@@ -22,6 +25,13 @@ export class TarsClient {
|
|
|
22
25
|
// Bind: an unbound global fetch throws "Illegal invocation" in browsers.
|
|
23
26
|
this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
24
27
|
this.actAsTenant = options.actAsTenant;
|
|
28
|
+
const unknown = Object.keys(options.providerKeys ?? {}).filter((p) => !KEYED_PROVIDERS.includes(p));
|
|
29
|
+
if (unknown.length > 0) {
|
|
30
|
+
throw new Error(`TarsClient: unknown providerKeys ${unknown.join(', ')} (expected ${KEYED_PROVIDERS.join(', ')})`);
|
|
31
|
+
}
|
|
32
|
+
this.providerKeyHeaders = Object.fromEntries(Object.entries(options.providerKeys ?? {})
|
|
33
|
+
.filter(([, key]) => typeof key === 'string' && key.trim() !== '')
|
|
34
|
+
.map(([provider, key]) => [`x-tars-key-${provider}`, key.trim()]));
|
|
25
35
|
}
|
|
26
36
|
// ── low-level HTTP ───────────────────────────────────────────
|
|
27
37
|
/** Every request path — JSON, uploads, SSE — sends these, so act-as scoping
|
|
@@ -30,6 +40,7 @@ export class TarsClient {
|
|
|
30
40
|
return {
|
|
31
41
|
authorization: `Bearer ${this.apiKey}`,
|
|
32
42
|
...(this.actAsTenant ? { 'x-tars-tenant': this.actAsTenant } : {}),
|
|
43
|
+
...this.providerKeyHeaders,
|
|
33
44
|
};
|
|
34
45
|
}
|
|
35
46
|
async request(method, path, body) {
|
|
@@ -176,6 +187,8 @@ export class TarsClient {
|
|
|
176
187
|
params.set('auth', input.auth);
|
|
177
188
|
if (input.endUserId)
|
|
178
189
|
params.set('end_user_id', input.endUserId);
|
|
190
|
+
if (input.schemas)
|
|
191
|
+
params.set('schemas', '1');
|
|
179
192
|
return this.request('GET', `/v1/mcp-servers/tools?${params}`);
|
|
180
193
|
},
|
|
181
194
|
};
|
|
@@ -254,23 +267,33 @@ export class TarsClient {
|
|
|
254
267
|
}),
|
|
255
268
|
};
|
|
256
269
|
/**
|
|
257
|
-
* Which model providers
|
|
258
|
-
* `openrouter`, `custom`)
|
|
259
|
-
*
|
|
260
|
-
*
|
|
270
|
+
* Which model providers YOU can route now (`anthropic`, `openai`,
|
|
271
|
+
* `openrouter`, `tensorx`, `custom`): those you passed in `providerKeys`,
|
|
272
|
+
* plus the instance's while its cutover fallback is on, plus `custom` on an
|
|
273
|
+
* instance pointed at a local runtime. Ask before OFFERING models: a picker
|
|
274
|
+
* listing GPT models without an OpenAI key produces turns that all fail.
|
|
261
275
|
*/
|
|
262
276
|
async providers() {
|
|
263
277
|
const body = await this.request('GET', '/v1/providers');
|
|
264
278
|
return body.providers ?? [];
|
|
265
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Every provider with whether you can route it and on whose key
|
|
282
|
+
* (`request` = your `providerKeys`, `instance` = the deployment's), plus
|
|
283
|
+
* whether the instance still falls back to its own keys. What a settings
|
|
284
|
+
* page shows: all providers, the inactive ones disabled.
|
|
285
|
+
*/
|
|
286
|
+
async providerStatus() {
|
|
287
|
+
return this.request('GET', '/v1/providers/status');
|
|
288
|
+
}
|
|
266
289
|
/**
|
|
267
290
|
* The models this instance can route AND price — ids are full
|
|
268
|
-
* `provider/model` specs. `openrouter/*` entries mirror
|
|
269
|
-
*
|
|
291
|
+
* `provider/model` specs. `openrouter/*` and `tensorx/*` entries mirror
|
|
292
|
+
* those providers' live catalogs, so those ids exist right now; direct entries
|
|
270
293
|
* come from the deployment's curated pricing table. Offer models from this
|
|
271
294
|
* list rather than hardcoding ids that can drift.
|
|
272
295
|
*
|
|
273
|
-
* The list is "what is known now", not "everything routable":
|
|
296
|
+
* The list is "what is known now", not "everything routable": catalog
|
|
274
297
|
* entries are absent before the instance's first successful catalog
|
|
275
298
|
* refresh, and a deployment routing only `custom/*` has no priced entries
|
|
276
299
|
* at all. When it comes back empty, fall back to `providers()` plus your
|
package/dist/types.d.ts
CHANGED
|
@@ -67,6 +67,12 @@ export type SessionEvent = {
|
|
|
67
67
|
} & ({
|
|
68
68
|
status: 'connected';
|
|
69
69
|
tool_count: number;
|
|
70
|
+
/** Estimated tokens this server's kept tool definitions (names,
|
|
71
|
+
* descriptions, input schemas) add to every request of the turn,
|
|
72
|
+
* at ~4 chars/token — size connectors against each other and
|
|
73
|
+
* against the rest of the prompt. Absent on rows journaled
|
|
74
|
+
* before 0.2.5. */
|
|
75
|
+
schema_tokens?: number;
|
|
70
76
|
/** The tool names the model received from this server (its own
|
|
71
77
|
* unprefixed names, in server order) — what `tool_count` counts.
|
|
72
78
|
* Absent on rows journaled by servers before 0.2.4. */
|
|
@@ -107,8 +113,9 @@ export type SessionEvent = {
|
|
|
107
113
|
export type BuiltInTool = 'bash' | 'read_file' | 'write_file' | 'edit_file' | 'glob' | 'grep' | 'web_fetch';
|
|
108
114
|
/**
|
|
109
115
|
* Extended-thinking depth. Provider-neutral: TARS maps it to Anthropic's
|
|
110
|
-
* `effort` (with adaptive thinking)
|
|
111
|
-
* (`max` → `xhigh`)
|
|
116
|
+
* `effort` (with adaptive thinking), OpenRouter's `reasoning.effort`
|
|
117
|
+
* (`max` → `xhigh`), or TensorX's `reasoning_effort` (`xhigh`/`max` →
|
|
118
|
+
* `high`; models there may ignore it). Omit for the provider default. The reasoning text itself
|
|
112
119
|
* is never streamed or journaled — only its depth is configurable.
|
|
113
120
|
*/
|
|
114
121
|
export type ReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
@@ -185,6 +192,24 @@ export interface SkillVersion {
|
|
|
185
192
|
size_bytes: number;
|
|
186
193
|
created_at: string;
|
|
187
194
|
}
|
|
195
|
+
/** Providers a client brings its own key for (`TarsClientOptions.providerKeys`). */
|
|
196
|
+
export type KeyedProvider = 'anthropic' | 'openai' | 'openrouter' | 'tensorx';
|
|
197
|
+
/** Every routable provider; `custom` is configured per instance, never per client. */
|
|
198
|
+
export type ProviderName = KeyedProvider | 'custom';
|
|
199
|
+
export type ProviderKeys = Partial<Record<KeyedProvider, string>>;
|
|
200
|
+
export interface ProviderStatus {
|
|
201
|
+
provider: ProviderName;
|
|
202
|
+
/** Can this client route a model on it right now? */
|
|
203
|
+
active: boolean;
|
|
204
|
+
/** Whose key would route it: yours (`request`), the instance's, or none. */
|
|
205
|
+
source: 'request' | 'instance' | null;
|
|
206
|
+
}
|
|
207
|
+
export interface ProviderStatusReport {
|
|
208
|
+
providers: ProviderStatus[];
|
|
209
|
+
/** True while the instance still routes providers you sent no key for on
|
|
210
|
+
* its own keys (the cutover fallback). */
|
|
211
|
+
instance_fallback: boolean;
|
|
212
|
+
}
|
|
188
213
|
/** One routable-and-priced model from `GET /v1/models`. Prices are USD per
|
|
189
214
|
* million tokens; `id` is the full `provider/model` spec, usable as-is when
|
|
190
215
|
* creating agents/sessions. The list is "what is known now" — see
|
|
@@ -286,12 +311,34 @@ export interface ListMcpToolsInput {
|
|
|
286
311
|
/** Resolve this end user's credential first, then the tenant-level one;
|
|
287
312
|
* omit for tenant-level only. Only read when `auth` is `'required'`. */
|
|
288
313
|
endUserId?: string;
|
|
314
|
+
/** Also return each tool's `input_schema` and its FULL description — the
|
|
315
|
+
* exact definition the model is shown, for weighing a connector's prompt
|
|
316
|
+
* cost per tool. Off (default): picker shape, descriptions capped. */
|
|
317
|
+
schemas?: boolean;
|
|
289
318
|
}
|
|
290
319
|
/** One tool as the server lists it. `description` is capped at 500
|
|
291
|
-
* characters (an ellipsis marks a cut)
|
|
320
|
+
* characters (an ellipsis marks a cut) unless `schemas` was requested;
|
|
321
|
+
* `null` when the server gave none. */
|
|
322
|
+
/** The MCP spec's tool annotations, as the server sent them (these five
|
|
323
|
+
* keys only). Hints for grouping and labelling tools in a picker, never
|
|
324
|
+
* guarantees: a policy (`tools` / `blocked_tools`) must not trust them. */
|
|
325
|
+
export interface McpToolAnnotations {
|
|
326
|
+
title?: string;
|
|
327
|
+
readOnlyHint?: boolean;
|
|
328
|
+
destructiveHint?: boolean;
|
|
329
|
+
idempotentHint?: boolean;
|
|
330
|
+
openWorldHint?: boolean;
|
|
331
|
+
}
|
|
292
332
|
export interface McpToolInfo {
|
|
293
333
|
name: string;
|
|
294
334
|
description: string | null;
|
|
335
|
+
/** Human-readable name: the tool's `title`, else `annotations.title`,
|
|
336
|
+
* else null when the server gave neither. */
|
|
337
|
+
title: string | null;
|
|
338
|
+
/** The server's annotations; null when it sent none. */
|
|
339
|
+
annotations: McpToolAnnotations | null;
|
|
340
|
+
/** The input JSON Schema as listed — present only with `schemas: true`. */
|
|
341
|
+
input_schema?: Record<string, unknown>;
|
|
295
342
|
}
|
|
296
343
|
export interface McpServerTools {
|
|
297
344
|
server: string;
|
|
@@ -337,9 +384,12 @@ export interface SessionClientTool {
|
|
|
337
384
|
* given turn is in that turn's `mcp_connect` event (`tools` / `filtered_out`).
|
|
338
385
|
*/
|
|
339
386
|
export interface SessionToolSurface {
|
|
387
|
+
/** `input_schema`: the JSON Schema (draft-7) the model is shown for the
|
|
388
|
+
* tool — size it to know what the built-ins cost in context. */
|
|
340
389
|
builtin: Array<{
|
|
341
390
|
name: BuiltInTool;
|
|
342
391
|
description: string;
|
|
392
|
+
input_schema: Record<string, unknown>;
|
|
343
393
|
}>;
|
|
344
394
|
client: SessionClientTool[];
|
|
345
395
|
mcp_servers: McpServer[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wice24/tars-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Client SDK for TARS — the self-hosted managed-agents platform (sessions, streaming turns, client tools, MCP credentials, skills, files, usage, tenant administration)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -12,13 +12,6 @@
|
|
|
12
12
|
"files": [
|
|
13
13
|
"dist"
|
|
14
14
|
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsc -p tsconfig.build.json",
|
|
17
|
-
"typecheck": "tsc --noEmit",
|
|
18
|
-
"test": "vitest run",
|
|
19
|
-
"test:watch": "vitest",
|
|
20
|
-
"test:coverage": "vitest run --coverage"
|
|
21
|
-
},
|
|
22
15
|
"devDependencies": {
|
|
23
16
|
"typescript": "^6.0.3",
|
|
24
17
|
"@types/node": "^26.1.0",
|
|
@@ -40,5 +33,12 @@
|
|
|
40
33
|
"mcp",
|
|
41
34
|
"anthropic",
|
|
42
35
|
"sdk"
|
|
43
|
-
]
|
|
44
|
-
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc -p tsconfig.build.json",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"test:coverage": "vitest run --coverage"
|
|
43
|
+
}
|
|
44
|
+
}
|