@wice24/tars-sdk 0.1.8 → 0.2.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 CHANGED
@@ -1,4 +1,4 @@
1
- import type { Agent, AgentVersion, ClientTool, CreateAgentInput, FileMeta, McpCredentialInput, McpCredentialStatus, 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, McpCredentialInput, McpCredentialStatus, ReasoningConfig, SessionEvent, ModelInfo, 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
4
  export declare class TarsApiError extends Error {
@@ -11,12 +11,28 @@ export interface TarsClientOptions {
11
11
  baseUrl?: string;
12
12
  /** Injectable fetch (tests, custom agents/proxies). Defaults to global fetch. */
13
13
  fetchImpl?: typeof globalThis.fetch;
14
+ /**
15
+ * Admin keys only: scope every request to this tenant id (sent as the
16
+ * `X-Tars-Tenant` header). Act-as is READ-ONLY — GETs return the target
17
+ * tenant's data; any write is refused with 403 `act_as_read_only`, and so
18
+ * is live SSE (`sessions.stream` / `resumeStream` — sandbox reattachment is
19
+ * a side effect): read the journal via `sessions.get` / `sessions.events`
20
+ * instead. Non-admin keys get 403 `admin_required`; an unknown tenant id
21
+ * 404s on every call; an empty value 400s. The effective role is always
22
+ * `tenant`, so `admin.*` calls under act-as also get 403 `admin_required`
23
+ * — use a client WITHOUT this option to administrate.
24
+ */
25
+ actAsTenant?: string;
14
26
  }
15
27
  export declare class TarsClient {
16
28
  private readonly baseUrl;
17
29
  private readonly apiKey;
18
30
  private readonly fetchImpl;
31
+ private readonly actAsTenant?;
19
32
  constructor(options: TarsClientOptions);
33
+ /** Every request path — JSON, uploads, SSE — sends these, so act-as scoping
34
+ * can never silently miss a surface. */
35
+ private authHeaders;
20
36
  private request;
21
37
  readonly agents: {
22
38
  create: (input: CreateAgentInput) => Promise<Agent>;
@@ -47,6 +63,8 @@ export declare class TarsClient {
47
63
  /** Appended to the agent's system prompt for this session only. */
48
64
  systemSuffix?: string;
49
65
  tools?: ClientTool[];
66
+ /** Per-session thinking-depth override (mirrors `model`). */
67
+ reasoning?: ReasoningConfig;
50
68
  }) => Promise<TarsSession>;
51
69
  list: (opts?: {
52
70
  limit?: number;
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ export class TarsClient {
13
13
  baseUrl;
14
14
  apiKey;
15
15
  fetchImpl;
16
+ actAsTenant;
16
17
  constructor(options) {
17
18
  if (!options.apiKey)
18
19
  throw new Error('TarsClient: apiKey is required');
@@ -20,13 +21,22 @@ export class TarsClient {
20
21
  this.baseUrl = (options.baseUrl ?? 'http://localhost:3001').replace(/\/$/, '');
21
22
  // Bind: an unbound global fetch throws "Illegal invocation" in browsers.
22
23
  this.fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
24
+ this.actAsTenant = options.actAsTenant;
23
25
  }
24
26
  // ── low-level HTTP ───────────────────────────────────────────
27
+ /** Every request path — JSON, uploads, SSE — sends these, so act-as scoping
28
+ * can never silently miss a surface. */
29
+ authHeaders() {
30
+ return {
31
+ authorization: `Bearer ${this.apiKey}`,
32
+ ...(this.actAsTenant ? { 'x-tars-tenant': this.actAsTenant } : {}),
33
+ };
34
+ }
25
35
  async request(method, path, body) {
26
36
  const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
27
37
  method,
28
38
  headers: {
29
- authorization: `Bearer ${this.apiKey}`,
39
+ ...this.authHeaders(),
30
40
  ...(body !== undefined ? { 'content-type': 'application/json' } : {}),
31
41
  },
32
42
  ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
@@ -64,6 +74,7 @@ export class TarsClient {
64
74
  ...(input.metadata ? { metadata: input.metadata } : {}),
65
75
  ...(input.mcpServers?.length ? { mcp_servers: input.mcpServers } : {}),
66
76
  ...(input.systemSuffix ? { system_suffix: input.systemSuffix } : {}),
77
+ ...(input.reasoning ? { reasoning: input.reasoning } : {}),
67
78
  ...(input.tools?.length
68
79
  ? {
69
80
  custom_tools: input.tools.map((t) => ({
@@ -155,7 +166,7 @@ export class TarsClient {
155
166
  pushVersion: async (id, zipBytes) => {
156
167
  const res = await this.fetchImpl(`${this.baseUrl}/v1/skills/${id}/versions`, {
157
168
  method: 'POST',
158
- headers: { authorization: `Bearer ${this.apiKey}`, 'content-type': 'application/zip' },
169
+ headers: { ...this.authHeaders(), 'content-type': 'application/zip' },
159
170
  body: zipBytes,
160
171
  });
161
172
  if (!res.ok)
@@ -168,7 +179,7 @@ export class TarsClient {
168
179
  */
169
180
  downloadVersion: async (id, version) => {
170
181
  const res = await this.fetchImpl(`${this.baseUrl}/v1/skills/${id}/versions/${version}/content`, {
171
- headers: { authorization: `Bearer ${this.apiKey}` },
182
+ headers: this.authHeaders(),
172
183
  });
173
184
  if (!res.ok)
174
185
  throw new TarsApiError(res.status, await res.json().catch(() => undefined));
@@ -289,7 +300,7 @@ export class TarsClient {
289
300
  const res = await this.fetchImpl(`${this.baseUrl}/v1/files?name=${encodeURIComponent(input.name)}`, {
290
301
  method: 'POST',
291
302
  headers: {
292
- authorization: `Bearer ${this.apiKey}`,
303
+ ...this.authHeaders(),
293
304
  'content-type': input.mime ?? 'application/octet-stream',
294
305
  },
295
306
  body: bytes,
@@ -315,7 +326,7 @@ export class TarsClient {
315
326
  get: (id) => this.request('GET', `/v1/files/${id}`),
316
327
  download: async (id) => {
317
328
  const res = await this.fetchImpl(`${this.baseUrl}/v1/files/${id}/content`, {
318
- headers: { authorization: `Bearer ${this.apiKey}` },
329
+ headers: this.authHeaders(),
319
330
  });
320
331
  if (!res.ok || !res.body) {
321
332
  throw new TarsApiError(res.status, await res.json().catch(() => undefined));
@@ -356,7 +367,7 @@ export class TarsClient {
356
367
  const res = await this.fetchImpl(`${this.baseUrl}/v1/sessions/${sessionId}/messages`, {
357
368
  method: 'POST',
358
369
  headers: {
359
- authorization: `Bearer ${this.apiKey}`,
370
+ ...this.authHeaders(),
360
371
  'content-type': 'application/json',
361
372
  },
362
373
  body: JSON.stringify({ text }),
@@ -373,7 +384,7 @@ export class TarsClient {
373
384
  async streamEvents(sessionId, after, opts) {
374
385
  const qs = `after=${after}` + (opts?.mode ? `&mode=${opts.mode}` : '');
375
386
  const res = await this.fetchImpl(`${this.baseUrl}/v1/sessions/${sessionId}/stream?${qs}`, {
376
- headers: { authorization: `Bearer ${this.apiKey}` },
387
+ headers: this.authHeaders(),
377
388
  });
378
389
  if (!res.ok || !res.body) {
379
390
  const payload = await res.json().catch(() => undefined);
package/dist/types.d.ts CHANGED
@@ -57,7 +57,23 @@ export type SessionEvent = {
57
57
  } | {
58
58
  type: 'connect_required';
59
59
  server: string;
60
+ }
61
+ /** Every MCP dial's OUTCOME, successes included (one per server per turn):
62
+ * `connect_required`/`error` cover only the failure paths — this is the
63
+ * diagnostic twin that makes a healthy connector visible. */
64
+ | ({
65
+ type: 'mcp_connect';
66
+ server: string;
67
+ } & ({
68
+ status: 'connected';
69
+ tool_count: number;
60
70
  } | {
71
+ status: 'failed';
72
+ code: AgentErrorCode;
73
+ message: string;
74
+ } | {
75
+ status: 'missing_credential';
76
+ })) | {
61
77
  type: 'error';
62
78
  code: AgentErrorCode;
63
79
  message: string;
@@ -73,7 +89,17 @@ export type SessionEvent = {
73
89
  cacheWriteTokens?: number;
74
90
  };
75
91
  });
76
- export type BuiltInTool = 'bash' | 'read_file' | 'write_file';
92
+ export type BuiltInTool = 'bash' | 'read_file' | 'write_file' | 'edit_file' | 'glob' | 'grep' | 'web_fetch';
93
+ /**
94
+ * Extended-thinking depth. Provider-neutral: TARS maps it to Anthropic's
95
+ * `effort` (with adaptive thinking) or OpenRouter's `reasoning.effort`
96
+ * (`max` → `xhigh`). Omit for the provider default. The reasoning text itself
97
+ * is never streamed or journaled — only its depth is configurable.
98
+ */
99
+ export type ReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
100
+ export interface ReasoningConfig {
101
+ effort: ReasoningEffort;
102
+ }
77
103
  export interface McpServer {
78
104
  name: string;
79
105
  url: string;
@@ -112,6 +138,7 @@ export interface Agent {
112
138
  mcp_servers: McpServer[] | null;
113
139
  skills: SkillPin[] | null;
114
140
  environment: AgentEnvironment | null;
141
+ reasoning: ReasoningConfig | null;
115
142
  created_at: string;
116
143
  updated_at: string;
117
144
  }
@@ -232,6 +259,7 @@ export interface AgentVersion {
232
259
  export interface CreateAgentInput {
233
260
  skills?: SkillPin[];
234
261
  environment?: AgentEnvironment;
262
+ reasoning?: ReasoningConfig | null;
235
263
  name: string;
236
264
  system: string;
237
265
  model?: string;
@@ -260,6 +288,25 @@ export interface SessionInfo {
260
288
  input_schema: Record<string, unknown>;
261
289
  timeout_sec?: number;
262
290
  }> | null;
291
+ /**
292
+ * The EFFECTIVE system prompt the session's turns run with — agent base
293
+ * prompt + session system_suffix + skills appendix, fused at creation.
294
+ * Optional: absent from servers predating this field.
295
+ */
296
+ system_prompt?: string;
297
+ /**
298
+ * The EFFECTIVE thinking depth the session's turns run with (the agent's,
299
+ * or the per-session override). null = provider default; absent from
300
+ * servers predating this field.
301
+ */
302
+ reasoning?: ReasoningConfig | null;
303
+ /**
304
+ * The un-merged per-session suffix, when a non-empty one was passed at
305
+ * creation. Also null on sessions created before this release: the audit
306
+ * column went unwritten historically (the suffix is still fused into
307
+ * system_prompt there), and old rows cannot be backfilled.
308
+ */
309
+ system_suffix?: string | null;
263
310
  archived?: boolean;
264
311
  last_seq?: number;
265
312
  events?: SessionEvent[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wice24/tars-sdk",
3
- "version": "0.1.8",
3
+ "version": "0.2.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": {