@inferencesh/sdk 0.28.0 → 0.29.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/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.29.0] - 2026-10-17
11
+
12
+ ### Removed
13
+ - `CredentialConfigDTO.provider_info` is gone: read `company` (INF-1079). The API stopped sending it in api-v1313.
14
+
15
+ ### Changed
16
+ - `CredentialConfigDTO.auth_scheme_id` is `auth_provider_id`, matching the API (INF-1079).
17
+ - Generated types follow the API: engine release targets (`client.engines.updateBinary` takes a release target, `releases()` lists channel heads), `EngineDTO.capabilities` (`EngineCapability`, `EngineCapabilities`), `ChatMessageDTO.compaction_meta`.
18
+
19
+ ### Fixed
20
+ - Partial chat and run stream updates merge instead of replacing, and streamed text never blinks back to an older copy.
21
+ - A read that got no response is sent again, twice.
22
+
10
23
  ## [0.28.0] - 2026-10-15
11
24
 
12
25
  ### Changed
@@ -12,6 +12,7 @@ import { createLLMDeltaAccumulator } from '../delta.js';
12
12
  import { isAdHocConfig, extractClientToolHandlers } from './types.js';
13
13
  import * as api from './api.js';
14
14
  import { buildMCPInputResult } from './mcp-input.js';
15
+ import { applyChatUpdate } from './reducer.js';
15
16
  import { isInferenceError } from '../http/errors.js';
16
17
  // =============================================================================
17
18
  // Action Creators
@@ -226,11 +227,16 @@ export function createActions(ctx) {
226
227
  },
227
228
  });
228
229
  // Listen for Chat object updates (status changes only — don't replace messages)
229
- manager.addEventListener('chats', (chatData) => {
230
- dispatch({ type: 'UPDATE_CHAT', payload: chatData });
231
- if (chatData) {
232
- callbacks.onStatusChange?.(isChatBusy(chatData) ? 'streaming' : 'idle');
233
- checkTurnEnd(chatData);
230
+ manager.addEventListener('chats', (chatData, fields) => {
231
+ if (!chatData)
232
+ return;
233
+ dispatch({ type: 'UPDATE_CHAT', payload: chatData, fields });
234
+ // A partial update (a plan step writing agent_data) says nothing about
235
+ // the turn on its own: judge the chat it merges into.
236
+ const chat = applyChatUpdate(getState().chat, chatData, fields);
237
+ if (chat) {
238
+ callbacks.onStatusChange?.(isChatBusy(chat) ? 'streaming' : 'idle');
239
+ checkTurnEnd(chat);
234
240
  }
235
241
  });
236
242
  // Listen for ChatMessage updates
@@ -244,8 +250,11 @@ export function createActions(ctx) {
244
250
  updateMessage(message, fields);
245
251
  });
246
252
  // Listen for AgentRun updates (state transitions, output)
247
- manager.addEventListener('agent_runs', (run) => {
248
- dispatch({ type: 'UPDATE_ACTIVE_RUN', payload: run });
253
+ manager.addEventListener('agent_runs', (run, fields) => {
254
+ dispatch({ type: 'UPDATE_ACTIVE_RUN', payload: run, fields });
255
+ // A partial update (the run's output) carries no state.
256
+ if (fields)
257
+ return;
249
258
  callbacks.onStatusChange?.(isRunWorking(run.state) || isRunInterrupted(run.state) ? 'streaming' : 'idle');
250
259
  const currentChat = getState().chat;
251
260
  if (currentChat)
@@ -3,6 +3,12 @@
3
3
  *
4
4
  * Pure reducer for managing agent chat state.
5
5
  */
6
+ import type { ChatDTO } from '../types.js';
6
7
  import type { AgentChatState, ChatAction } from './types.js';
8
+ /**
9
+ * The chat after a chats event: replaced by a full one, merged with a partial
10
+ * one. A partial update to another chat (or before any chat) is dropped.
11
+ */
12
+ export declare function applyChatUpdate(existing: ChatDTO | null, update: ChatDTO, fields?: string[]): ChatDTO | null;
7
13
  export declare const initialState: AgentChatState;
8
14
  export declare function chatReducer(state: AgentChatState, action: ChatAction): AgentChatState;
@@ -4,7 +4,7 @@
4
4
  * Pure reducer for managing agent chat state.
5
5
  */
6
6
  import { ChatStatusBusy, ChatStatusAwaitingInput, ChatStatusIdle } from '../types.js';
7
- import { isRunInterrupted, isRunWorking } from '../utils.js';
7
+ import { isMessageTerminal, isRunInterrupted, isRunWorking } from '../utils.js';
8
8
  function deriveChatStatus(run) {
9
9
  if (!run)
10
10
  return ChatStatusIdle;
@@ -14,6 +14,38 @@ function deriveChatStatus(run) {
14
14
  return ChatStatusAwaitingInput;
15
15
  return ChatStatusIdle;
16
16
  }
17
+ /**
18
+ * A partial stream update (`fields` set) carries only the fields it names, so
19
+ * it merges into the object it updates instead of replacing it: a chat update
20
+ * naming only agent_data (a plan step) keeps the chat's status and active run.
21
+ * A named field missing from the payload was cleared (omitempty).
22
+ */
23
+ function mergeFields(existing, update, fields) {
24
+ const merged = { ...existing };
25
+ for (const field of fields)
26
+ merged[field] = update[field];
27
+ return merged;
28
+ }
29
+ /**
30
+ * The chat after a chats event: replaced by a full one, merged with a partial
31
+ * one. A partial update to another chat (or before any chat) is dropped.
32
+ */
33
+ export function applyChatUpdate(existing, update, fields) {
34
+ if (!fields)
35
+ return update;
36
+ if (!existing || existing.id !== update.id)
37
+ return existing;
38
+ const merged = mergeFields(existing, update, fields);
39
+ // The projector's update names active_run_id, which ChatDTO does not
40
+ // declare. The run object belongs to that id: a new or cleared active run
41
+ // drops it until the run's own event arrives.
42
+ if (fields.includes('active_run_id')) {
43
+ const runId = update.active_run_id;
44
+ if (merged.active_run && merged.active_run.id !== runId)
45
+ merged.active_run = undefined;
46
+ }
47
+ return merged;
48
+ }
17
49
  /**
18
50
  * Every message enters state through here. The API serializes a message with
19
51
  * no content as `content: null` (a nil Go slice), and a partial stream update
@@ -27,6 +59,28 @@ function normalizeMessage(message, existing) {
27
59
  return message;
28
60
  return { ...message, content: existing?.content ?? [] };
29
61
  }
62
+ /**
63
+ * Streamed text only grows until the message is done. Deltas build the text
64
+ * locally, while a message update carries the server's saved copy, which can
65
+ * lag behind them (often still empty). Taking that copy as-is blanks the text
66
+ * until the next delta, so while the message is still generating, a text
67
+ * that is an earlier version of what is shown keeps what is shown. Once the
68
+ * message is terminal the server's copy is final and wins.
69
+ */
70
+ function keepStreamedText(updated, existing) {
71
+ if (isMessageTerminal(updated.status))
72
+ return updated;
73
+ const shown = existing.content.find((c) => c.type === 'text')?.text;
74
+ if (!shown)
75
+ return updated;
76
+ const incoming = updated.content.find((c) => c.type === 'text');
77
+ if (incoming?.text && !shown.startsWith(incoming.text))
78
+ return updated;
79
+ const content = incoming
80
+ ? updated.content.map((c) => (c === incoming ? { ...c, text: shown } : c))
81
+ : [{ type: 'text', text: shown }, ...updated.content];
82
+ return { ...updated, content };
83
+ }
30
84
  const normalizeMessages = (messages) => messages.map((m) => normalizeMessage(m));
31
85
  // =============================================================================
32
86
  // Initial State
@@ -59,10 +113,10 @@ export function chatReducer(state, action) {
59
113
  }
60
114
  case 'UPDATE_CHAT': {
61
115
  // Update chat metadata without replacing messages
62
- const chat = action.payload;
63
- if (!chat)
116
+ if (!action.payload)
64
117
  return state;
65
- return { ...state, chat };
118
+ const chat = applyChatUpdate(state.chat, action.payload, action.fields);
119
+ return chat === state.chat ? state : { ...state, chat };
66
120
  }
67
121
  // The settings and set-agent endpoints answer with only what they wrote.
68
122
  // Merge it into the chat it belongs to; a chat switched away from in the
@@ -104,7 +158,15 @@ export function chatReducer(state, action) {
104
158
  case 'UPDATE_ACTIVE_RUN': {
105
159
  if (!state.chat)
106
160
  return state;
107
- return { ...state, chat: { ...state.chat, active_run: action.payload, status: deriveChatStatus(action.payload) } };
161
+ let run = action.payload;
162
+ if (action.fields) {
163
+ // A partial update (the run's output) needs the run it belongs to.
164
+ const existing = state.chat.active_run;
165
+ if (!existing || existing.id !== run.id)
166
+ return state;
167
+ run = mergeFields(existing, run, action.fields);
168
+ }
169
+ return { ...state, chat: { ...state.chat, active_run: run, status: deriveChatStatus(run) } };
108
170
  }
109
171
  case 'SET_MESSAGES':
110
172
  return { ...state, messages: normalizeMessages(action.payload) };
@@ -120,9 +182,7 @@ export function chatReducer(state, action) {
120
182
  const existingIndex = state.messages.findIndex((m) => m.id === message.id);
121
183
  if (existingIndex !== -1) {
122
184
  const existing = state.messages[existingIndex];
123
- const updated = action.partial
124
- ? normalizeMessage({ ...existing, ...message }, existing)
125
- : normalizeMessage(message);
185
+ const updated = keepStreamedText(action.partial ? normalizeMessage({ ...existing, ...message }, existing) : normalizeMessage(message), existing);
126
186
  if (existing === updated)
127
187
  return state;
128
188
  const newMessages = [...state.messages];
@@ -148,6 +208,10 @@ export function chatReducer(state, action) {
148
208
  if (!target)
149
209
  return state;
150
210
  const textBlock = target.content.find(c => c.type === 'text');
211
+ // Deltas from a stream joined mid-message start partway; the message
212
+ // update already showed more, so keep it until they catch up.
213
+ if (textBlock?.text && textBlock.text.startsWith(output.response ?? ''))
214
+ return state;
151
215
  const newContent = textBlock
152
216
  ? target.content.map(c => c.type === 'text' ? { ...c, text: output.response } : c)
153
217
  : [{ type: 'text', text: output.response }, ...target.content];
@@ -261,6 +261,7 @@ export type ChatAction = {
261
261
  } | {
262
262
  type: 'UPDATE_CHAT';
263
263
  payload: ChatDTO | null;
264
+ fields?: string[];
264
265
  } | {
265
266
  type: 'MERGE_CHAT_SETTINGS';
266
267
  payload: ChatSettingsDTO;
@@ -270,6 +271,7 @@ export type ChatAction = {
270
271
  } | {
271
272
  type: 'UPDATE_ACTIVE_RUN';
272
273
  payload: AgentRunDTO;
274
+ fields?: string[];
273
275
  } | {
274
276
  type: 'SET_MESSAGES';
275
277
  payload: ChatMessageDTO[];
@@ -1,7 +1,7 @@
1
1
  import { HttpClient } from '../http/client.js';
2
2
  import type { Response } from '../http/response.js';
3
3
  import type { EngineUpdateBody } from './write-bodies.js';
4
- import { EngineDTO as Engine, CursorListRequest, CursorListResponse } from '../types.js';
4
+ import { EngineDTO as Engine, EngineReleasesResponse, CursorListRequest, CursorListResponse } from '../types.js';
5
5
  /**
6
6
  * Engines API
7
7
  */
@@ -65,8 +65,16 @@ export declare class EnginesAPI {
65
65
  */
66
66
  drain(engineId: string): Promise<Response<void>>;
67
67
  /**
68
- * Update an engine binary (drain + restart with new version)
68
+ * Update an engine binary: it drains, installs the release and restarts.
69
+ * `version` is "stable" (the default: newest stable, lifting any pin),
70
+ * "canary" (the current canary build, pinned), or a version such as
71
+ * v1.9.3 (pinned). A pinned engine stays on its version until sent
72
+ * "stable" again.
69
73
  */
70
- updateBinary(engineId: string): Promise<Response<void>>;
74
+ updateBinary(engineId: string, version?: string): Promise<Response<void>>;
75
+ /**
76
+ * The head of each engine release channel (stable, canary) on dist.inference.sh.
77
+ */
78
+ releases(): Promise<Response<EngineReleasesResponse>>;
71
79
  }
72
80
  export declare function createEnginesAPI(http: HttpClient): EnginesAPI;
@@ -85,10 +85,21 @@ export class EnginesAPI {
85
85
  return this.http.request('post', `/engines/${engineId}/drain`);
86
86
  }
87
87
  /**
88
- * Update an engine binary (drain + restart with new version)
88
+ * Update an engine binary: it drains, installs the release and restarts.
89
+ * `version` is "stable" (the default: newest stable, lifting any pin),
90
+ * "canary" (the current canary build, pinned), or a version such as
91
+ * v1.9.3 (pinned). A pinned engine stays on its version until sent
92
+ * "stable" again.
89
93
  */
90
- async updateBinary(engineId) {
91
- return this.http.request('post', `/engines/${engineId}/update`);
94
+ async updateBinary(engineId, version) {
95
+ const body = version ? { version } : {};
96
+ return this.http.request('post', `/engines/${engineId}/update`, { data: body });
97
+ }
98
+ /**
99
+ * The head of each engine release channel (stable, canary) on dist.inference.sh.
100
+ */
101
+ async releases() {
102
+ return this.http.request('get', '/engines/releases');
92
103
  }
93
104
  }
94
105
  export function createEnginesAPI(http) {
@@ -1,6 +1,40 @@
1
1
  import { InferenceError, RequirementsNotMetException } from './errors.js';
2
2
  import { EventSource } from 'eventsource';
3
3
  import { SDK_VERSION } from '../version.js';
4
+ /** How long to wait before each new try of a read that got no response. */
5
+ const NETWORK_RETRY_DELAYS_MS = [300, 1000];
6
+ /**
7
+ * fetch, sending a GET or HEAD that got no response again after each of
8
+ * NETWORK_RETRY_DELAYS_MS: a dropped connection or a network change fails a
9
+ * read that would succeed a moment later, and a read changes nothing on the
10
+ * server, so sending it again is safe. fetch rejects with a TypeError only
11
+ * when no response came; a response of any status, an abort, or a request
12
+ * of another method is the caller's at once.
13
+ */
14
+ function fetchRetryingReads(input, init, attempt = 0) {
15
+ const method = (init.method ?? 'GET').toUpperCase();
16
+ const read = method === 'GET' || method === 'HEAD';
17
+ const sent = fetch(input, init);
18
+ if (!read)
19
+ return sent;
20
+ return sent.catch(async (error) => {
21
+ const delay = NETWORK_RETRY_DELAYS_MS[attempt];
22
+ if (delay === undefined || !(error instanceof TypeError) || init.signal?.aborted)
23
+ throw error;
24
+ await wait(delay, init.signal);
25
+ return fetchRetryingReads(input, init, attempt + 1);
26
+ });
27
+ }
28
+ /** Resolves after ms, or rejects with the abort when signal aborts first. */
29
+ function wait(ms, signal) {
30
+ return new Promise((resolve, reject) => {
31
+ const timer = setTimeout(resolve, ms);
32
+ signal?.addEventListener('abort', () => {
33
+ clearTimeout(timer);
34
+ reject(signal.reason);
35
+ }, { once: true });
36
+ });
37
+ }
4
38
  /**
5
39
  * Low-level HTTP client for inference.sh API
6
40
  *
@@ -127,7 +161,7 @@ export class HttpClient {
127
161
  * (`refused: 'return'`), handed back with its body unread.
128
162
  */
129
163
  async fetchHandled(url, targetUrl, init, refused) {
130
- const send = (token) => fetch(url, {
164
+ const send = (token) => fetchRetryingReads(url, {
131
165
  ...init,
132
166
  headers: { ...init.headers, ...this.requestHeaders(targetUrl, token) },
133
167
  credentials: this.credentials,
@@ -213,7 +247,7 @@ export class HttpClient {
213
247
  if (options.data) {
214
248
  fetchOptions.body = JSON.stringify(options.data);
215
249
  }
216
- const response = await fetch(fetchUrl, fetchOptions);
250
+ const response = await fetchRetryingReads(fetchUrl, fetchOptions);
217
251
  const responseText = await response.text();
218
252
  let data = null;
219
253
  try {
package/dist/types.d.ts CHANGED
@@ -1629,7 +1629,7 @@ export interface AppVersionDTO extends BaseModelDTO {
1629
1629
  export interface DeployWarning {
1630
1630
  /**
1631
1631
  * Code identifies the check: readonly_broad_credential,
1632
- * unused_credential, missing_annotations.
1632
+ * unused_credential, missing_annotations, unapproved_platform_scope.
1633
1633
  */
1634
1634
  code: string;
1635
1635
  /**
@@ -1791,6 +1791,32 @@ export interface ArtifactVersionDTO extends BaseModelDTO {
1791
1791
  [key: string]: any;
1792
1792
  };
1793
1793
  created_by_user_id?: string;
1794
+ /**
1795
+ * Files are the pages and data served beside the index page.
1796
+ */
1797
+ files?: ArtifactVersionFileDTO[];
1798
+ }
1799
+ /**
1800
+ * ArtifactVersionFileDTO is one file published beside a version's index.
1801
+ */
1802
+ export interface ArtifactVersionFileDTO {
1803
+ path: string;
1804
+ size_bytes: number;
1805
+ content_type: string;
1806
+ }
1807
+ /**
1808
+ * ArtifactFileInput is one extra file in a publish, served at Path relative
1809
+ * to the index page: another page (.html, .md), or css, js, json, svg, txt,
1810
+ * xml, csv.
1811
+ */
1812
+ export interface ArtifactFileInput {
1813
+ path: string;
1814
+ content: string;
1815
+ /**
1816
+ * ContentEncoding is "base64" when Content is base64-encoded, as for the
1817
+ * main content.
1818
+ */
1819
+ content_encoding?: string;
1794
1820
  }
1795
1821
  /**
1796
1822
  * ArtifactCreateRequest is the body for POST /artifacts. Creates the entry
@@ -1816,6 +1842,11 @@ export interface ArtifactCreateRequest {
1816
1842
  * from browsers and CLIs: edge firewalls reject raw <script> in JSON bodies.
1817
1843
  */
1818
1844
  content_encoding?: string;
1845
+ /**
1846
+ * Files are published beside the index page. A publish is the whole
1847
+ * site: files of the previous version are not carried over.
1848
+ */
1849
+ files?: ArtifactFileInput[];
1819
1850
  label?: string;
1820
1851
  notes?: string;
1821
1852
  origin?: string;
@@ -1862,6 +1893,11 @@ export interface ArtifactPublishRequest {
1862
1893
  * ContentEncoding is "base64" when Content is base64-encoded UTF-8.
1863
1894
  */
1864
1895
  content_encoding?: string;
1896
+ /**
1897
+ * Files are published beside the index page. A publish is the whole
1898
+ * site: files of the previous version are not carried over.
1899
+ */
1900
+ files?: ArtifactFileInput[];
1865
1901
  label?: string;
1866
1902
  notes?: string;
1867
1903
  origin?: string;
@@ -1932,9 +1968,25 @@ export interface ArtifactDataRequest {
1932
1968
  [key: string]: any;
1933
1969
  };
1934
1970
  /**
1935
- * Limit caps a list; the server clamps it.
1971
+ * Limit caps a list; the server clamps it to 200.
1936
1972
  */
1937
1973
  limit?: number;
1974
+ /**
1975
+ * Cursor continues a list from the next_cursor of the page before.
1976
+ */
1977
+ cursor?: string;
1978
+ /**
1979
+ * Order is the list order: -updated_at (the default), updated_at,
1980
+ * -created_at or created_at.
1981
+ */
1982
+ order?: string;
1983
+ /**
1984
+ * Where keeps only documents whose top-level fields equal these values
1985
+ * (string, number, boolean, or null for a missing field).
1986
+ */
1987
+ where?: {
1988
+ [key: string]: any;
1989
+ };
1938
1990
  }
1939
1991
  /**
1940
1992
  * ArtifactDataListResponse is a page of documents from one collection.
@@ -1943,6 +1995,10 @@ export interface ArtifactDataListResponse {
1943
1995
  collection: string;
1944
1996
  documents: ArtifactDataDTO[];
1945
1997
  count: number;
1998
+ /**
1999
+ * NextCursor fetches the page after this one; empty on the last page.
2000
+ */
2001
+ next_cursor?: string;
1946
2002
  }
1947
2003
  /**
1948
2004
  * ArtifactViewerDTO is what the user capability tells a page about whoever
@@ -2277,6 +2333,10 @@ export interface ChatMessageDTO extends BaseModelDTO, PermissionModelDTO {
2277
2333
  tools?: Tool[];
2278
2334
  tool_call_id?: string;
2279
2335
  tool_invocations?: ToolInvocationDTO[];
2336
+ /**
2337
+ * CompactionMeta is what a compaction (role compaction) retired.
2338
+ */
2339
+ compaction_meta?: CompactionMeta;
2280
2340
  }
2281
2341
  /**
2282
2342
  * PolicyRuleDTO is one rule, typed form Kind[selector](specifier).
@@ -2529,6 +2589,12 @@ export interface CredentialDTO extends BaseModelDTO, PermissionModelDTO {
2529
2589
  account_identifier?: string;
2530
2590
  account_name?: string;
2531
2591
  scopes: StringSlice;
2592
+ /**
2593
+ * AllowedScopes, on an OAuth app row (grant credentials), is every
2594
+ * scope a login through it may request; absent when any scope may be
2595
+ * (a team's own client by default). Never set on a login.
2596
+ */
2597
+ allowed_scopes?: StringSlice;
2532
2598
  expires_at?: string;
2533
2599
  vault_id?: string;
2534
2600
  metadata?: {
@@ -2572,17 +2638,12 @@ export interface CredentialConfigDTO {
2572
2638
  slug: string;
2573
2639
  /**
2574
2640
  * Provider is the credential slug (what Credential.Provider stores):
2575
- * one way to authenticate. The company it belongs to is ProviderInfo.
2641
+ * one way to authenticate. The company it belongs to is Company.
2576
2642
  */
2577
2643
  provider: string;
2578
2644
  /**
2579
- * ProviderInfo is the company this slug belongs to, for grouping: the
2580
- * providers row its auth provider names, else the slug's own identity.
2581
- */
2582
- provider_info?: CompanySummary;
2583
- /**
2584
- * Company is ProviderInfo under its settled name (INF-1079); provider_info
2585
- * stays one release.
2645
+ * Company is the company this slug belongs to, for grouping: the
2646
+ * companies row its auth provider names, else the slug's own identity.
2586
2647
  */
2587
2648
  company?: CompanySummary;
2588
2649
  type: string;
@@ -2613,7 +2674,7 @@ export interface CredentialConfigDTO {
2613
2674
  * AuthProviderID is set when the provider is one the team defined
2614
2675
  * itself (models.AuthProvider), so the UI can offer edit and remove.
2615
2676
  */
2616
- auth_scheme_id?: string;
2677
+ auth_provider_id?: string;
2617
2678
  /**
2618
2679
  * Credential is the login used where no account is named: the caller's
2619
2680
  * own, else the workspace's default account.
@@ -2750,9 +2811,38 @@ export interface EngineDTO extends BaseModelDTO, PermissionModelDTO {
2750
2811
  api_url: string;
2751
2812
  status: EngineStatus;
2752
2813
  engine_version: string;
2814
+ /**
2815
+ * EnginePin is the version the engine is held on; empty follows stable.
2816
+ */
2817
+ engine_pin?: string;
2818
+ /**
2819
+ * Capabilities are what the engine last reported it can do.
2820
+ */
2821
+ capabilities?: EngineCapabilities;
2753
2822
  system_info?: SystemInfo;
2754
2823
  workers: (WorkerDTO | undefined)[];
2755
2824
  }
2825
+ /**
2826
+ * EngineUpdateRequest names the release an engine should install: "stable",
2827
+ * "canary", or a version such as v1.9.3. Empty is stable.
2828
+ */
2829
+ export interface EngineUpdateRequest {
2830
+ version?: string;
2831
+ }
2832
+ /**
2833
+ * EngineRelease is one published engine build.
2834
+ */
2835
+ export interface EngineRelease {
2836
+ version: string;
2837
+ release_date?: string;
2838
+ }
2839
+ /**
2840
+ * EngineReleasesResponse is the head of each engine release channel.
2841
+ */
2842
+ export interface EngineReleasesResponse {
2843
+ stable?: EngineRelease;
2844
+ canary?: EngineRelease;
2845
+ }
2756
2846
  /**
2757
2847
  * EngineSummary is a lightweight engine response embedded in tasks.
2758
2848
  */
@@ -2831,6 +2921,19 @@ export interface WorkerRAM {
2831
2921
  worker_id: string;
2832
2922
  total: number;
2833
2923
  }
2924
+ /**
2925
+ * EngineCapability is something an engine can do beyond the base contract
2926
+ * every engine meets. An engine reports the ones it has (EngineTelemetry);
2927
+ * a task lists the ones it needs (Task.Requires); the scheduler only sends
2928
+ * a task to an engine that has every one it needs.
2929
+ */
2930
+ export type EngineCapability = "egress_gateway";
2931
+ export declare const EngineCapabilityEgressGateway: EngineCapability;
2932
+ /**
2933
+ * EngineCapabilities is a set of capabilities, kept as a list. Nil and
2934
+ * empty are the same: nothing beyond the base contract.
2935
+ */
2936
+ export type EngineCapabilities = EngineCapability[];
2834
2937
  /**
2835
2938
  * EntitlementDTO for API responses
2836
2939
  */
@@ -7835,6 +7938,16 @@ export interface ContextInjection {
7835
7938
  */
7836
7939
  items?: string[];
7837
7940
  }
7941
+ /**
7942
+ * CompactionMeta is stored on ChatMessage for context compaction markers.
7943
+ */
7944
+ export interface CompactionMeta {
7945
+ compacted_up_to_order: number;
7946
+ compacted_count: number;
7947
+ estimated_tokens: number;
7948
+ method?: string;
7949
+ analysis?: string;
7950
+ }
7838
7951
  /**
7839
7952
  * ToolCallEventData is the typed payload for agent.tool_call events.
7840
7953
  */
package/dist/types.js CHANGED
@@ -376,6 +376,7 @@ export const ToolRiskMedium = "medium";
376
376
  * ToolRiskHigh: dangerous or irreversible changes.
377
377
  */
378
378
  export const ToolRiskHigh = "high";
379
+ export const EngineCapabilityEgressGateway = "egress_gateway";
379
380
  export const ErrorCodeInvalidRequest = "invalid_request";
380
381
  export const ErrorCodeValidationError = "validation_error";
381
382
  export const ErrorCodeUnauthorized = "unauthorized";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inferencesh/sdk",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for inference.sh - Run AI models with a simple API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",