@wice24/tars-sdk 0.2.3 → 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 +94 -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,23 @@ 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;
|
|
76
|
+
/** The tool names the model received from this server (its own
|
|
77
|
+
* unprefixed names, in server order) — what `tool_count` counts.
|
|
78
|
+
* Absent on rows journaled by servers before 0.2.4. */
|
|
79
|
+
tools?: string[];
|
|
80
|
+
/** Offered by the server but removed by the declaration's policy:
|
|
81
|
+
* the `blocked_tools` it offered (deny), or everything not in
|
|
82
|
+
* `tools` (allow). Empty with no policy. Absent before 0.2.4. */
|
|
83
|
+
filtered_out?: string[];
|
|
84
|
+
/** Either list was cut — at 256 names, a 200-character name, or
|
|
85
|
+
* the row's character budget; `tool_count` stays exact. */
|
|
86
|
+
truncated?: true;
|
|
70
87
|
} | {
|
|
71
88
|
status: 'failed';
|
|
72
89
|
code: AgentErrorCode;
|
|
@@ -96,8 +113,9 @@ export type SessionEvent = {
|
|
|
96
113
|
export type BuiltInTool = 'bash' | 'read_file' | 'write_file' | 'edit_file' | 'glob' | 'grep' | 'web_fetch';
|
|
97
114
|
/**
|
|
98
115
|
* Extended-thinking depth. Provider-neutral: TARS maps it to Anthropic's
|
|
99
|
-
* `effort` (with adaptive thinking)
|
|
100
|
-
* (`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
|
|
101
119
|
* is never streamed or journaled — only its depth is configurable.
|
|
102
120
|
*/
|
|
103
121
|
export type ReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
@@ -174,6 +192,24 @@ export interface SkillVersion {
|
|
|
174
192
|
size_bytes: number;
|
|
175
193
|
created_at: string;
|
|
176
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
|
+
}
|
|
177
213
|
/** One routable-and-priced model from `GET /v1/models`. Prices are USD per
|
|
178
214
|
* million tokens; `id` is the full `provider/model` spec, usable as-is when
|
|
179
215
|
* creating agents/sessions. The list is "what is known now" — see
|
|
@@ -275,12 +311,34 @@ export interface ListMcpToolsInput {
|
|
|
275
311
|
/** Resolve this end user's credential first, then the tenant-level one;
|
|
276
312
|
* omit for tenant-level only. Only read when `auth` is `'required'`. */
|
|
277
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;
|
|
278
318
|
}
|
|
279
319
|
/** One tool as the server lists it. `description` is capped at 500
|
|
280
|
-
* 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
|
+
}
|
|
281
332
|
export interface McpToolInfo {
|
|
282
333
|
name: string;
|
|
283
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>;
|
|
284
342
|
}
|
|
285
343
|
export interface McpServerTools {
|
|
286
344
|
server: string;
|
|
@@ -309,6 +367,33 @@ export interface CreateAgentInput {
|
|
|
309
367
|
mcp_servers?: McpServer[] | null;
|
|
310
368
|
}
|
|
311
369
|
export type UpdateAgentInput = Partial<CreateAgentInput>;
|
|
370
|
+
/** A client-executed tool as a session stores it: the wire declaration,
|
|
371
|
+
* without `execute` (that runs in your app) — the same shape as a
|
|
372
|
+
* `SessionInfo.custom_tools` element. */
|
|
373
|
+
export interface SessionClientTool {
|
|
374
|
+
name: string;
|
|
375
|
+
description: string;
|
|
376
|
+
input_schema: Record<string, unknown>;
|
|
377
|
+
timeout_sec?: number;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* The complete tool surface a session's turns are built with, as declared:
|
|
381
|
+
* the enabled built-ins with the descriptions the model is shown, the
|
|
382
|
+
* client-executed tools, and the MCP servers with their `tools` /
|
|
383
|
+
* `blocked_tools` policy. What each MCP server actually contributed on a
|
|
384
|
+
* given turn is in that turn's `mcp_connect` event (`tools` / `filtered_out`).
|
|
385
|
+
*/
|
|
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. */
|
|
389
|
+
builtin: Array<{
|
|
390
|
+
name: BuiltInTool;
|
|
391
|
+
description: string;
|
|
392
|
+
input_schema: Record<string, unknown>;
|
|
393
|
+
}>;
|
|
394
|
+
client: SessionClientTool[];
|
|
395
|
+
mcp_servers: McpServer[];
|
|
396
|
+
}
|
|
312
397
|
export interface SessionInfo {
|
|
313
398
|
id: string;
|
|
314
399
|
status: SessionStatus;
|
|
@@ -328,6 +413,12 @@ export interface SessionInfo {
|
|
|
328
413
|
input_schema: Record<string, unknown>;
|
|
329
414
|
timeout_sec?: number;
|
|
330
415
|
}> | null;
|
|
416
|
+
/**
|
|
417
|
+
* The declared tool surface (built-ins, client tools, MCP servers with
|
|
418
|
+
* policy) the session's turns run with. Optional: absent from servers
|
|
419
|
+
* predating this field.
|
|
420
|
+
*/
|
|
421
|
+
tools?: SessionToolSurface;
|
|
331
422
|
/**
|
|
332
423
|
* The EFFECTIVE system prompt the session's turns run with — agent base
|
|
333
424
|
* prompt + session system_suffix + skills appendix, fused at creation.
|
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
|
+
}
|