@inferencesh/sdk 0.16.0 → 0.17.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,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.17.0] - 2026-10-02
11
+
12
+ ### Changed
13
+
14
+ - `updateChatSettings` and `switchAgent` merge what the api now answers with into the chat they hold: `ChatSettingsDTO` (`chat_id`, `name`, `visibility`, `allow_all_tools`, `disable_hooks`, `memory`) from `POST /chats/{id}/settings` and `ChatAgentDTO` (`chat_id`, `agent_id`, `agent`, `agent_version_id`, `agent_version`) from `POST /chats/{id}/agent`. The reducer has `MERGE_CHAT_SETTINGS` and `MERGE_CHAT_AGENT` for them; a response for a chat other than the one on screen is ignored. The low-level `updateChatSettings` and `setAgent` in the agent api return those types. Needs an api that answers with them.
15
+ - `ChatDTO.chat_messages` is optional: the api leaves it out when it did not load the messages, which it never does on the chat endpoints. Read messages from `GET /chats/{id}/messages`.
16
+
17
+ ### Fixed
18
+
19
+ - Polling `sendMessage` handled a fetched chat with an unchanged status only when it carried `chat_messages`. It now skips only the poll's own "nothing changed" answer.
20
+
10
21
  ## [0.16.0] - 2026-10-02
11
22
 
12
23
  ### Added
@@ -414,9 +414,7 @@ export function createActions(ctx) {
414
414
  return;
415
415
  }
416
416
  try {
417
- // The response carries the chat without its messages: update the
418
- // chat and keep the conversation on screen.
419
- dispatch({ type: 'UPDATE_CHAT', payload: await api.updateChatSettings(client, chatId, settings) });
417
+ dispatch({ type: 'MERGE_CHAT_SETTINGS', payload: await api.updateChatSettings(client, chatId, settings) });
420
418
  }
421
419
  catch (error) {
422
420
  console.error('[AgentSDK] Failed to change chat settings:', error);
@@ -433,7 +431,7 @@ export function createActions(ctx) {
433
431
  return;
434
432
  }
435
433
  try {
436
- dispatch({ type: 'UPDATE_CHAT', payload: await api.setAgent(client, chatId, agentRef) });
434
+ dispatch({ type: 'MERGE_CHAT_AGENT', payload: await api.setAgent(client, chatId, agentRef) });
437
435
  }
438
436
  catch (error) {
439
437
  console.error('[AgentSDK] Failed to switch the agent:', error);
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * /agents/run stays for A2A/programmatic use.
9
9
  */
10
- import type { AlwaysAllowOptionsDTO, AlwaysAllowResultDTO, ChatDTO, ChatMessageDTO, ChatSettingsRequest, InterruptDTO, ToolExplanationDTO } from '../types';
10
+ import type { AlwaysAllowOptionsDTO, AlwaysAllowResultDTO, ChatAgentDTO, ChatDTO, ChatMessageDTO, ChatSettingsDTO, ChatSettingsRequest, InterruptDTO, ToolExplanationDTO } from '../types';
11
11
  import type { AgentOptions, AgentClient, AgentInfo, FileRef } from './types';
12
12
  export interface SendResult {
13
13
  chatId: string;
@@ -36,7 +36,8 @@ export declare function fetchMessagesPage(client: AgentClient, chatId: string, o
36
36
  export declare function fetchChat(client: AgentClient, chatId: string): Promise<ChatDTO | null>;
37
37
  export declare function stopChat(client: AgentClient, chatId: string): Promise<void>;
38
38
  export declare function cancelMessage(client: AgentClient, messageId: string): Promise<void>;
39
- export declare function setAgent(client: AgentClient, chatId: string, agentRef: string): Promise<ChatDTO>;
39
+ /** Hand the chat to another agent. Answers with the agent the chat now runs on. */
40
+ export declare function setAgent(client: AgentClient, chatId: string, agentRef: string): Promise<ChatAgentDTO>;
40
41
  export declare function submitToolResult(client: AgentClient, toolInvocationId: string, resultOrAction: string | {
41
42
  action: {
42
43
  type: string;
@@ -63,7 +64,8 @@ export declare function alwaysAllowTool(client: AgentClient, chatId: string, too
63
64
  * for the call, so asking again is free.
64
65
  */
65
66
  export declare function explainTool(client: AgentClient, chatId: string, toolInvocationId: string): Promise<ToolExplanationDTO>;
66
- export declare function updateChatSettings(client: AgentClient, chatId: string, settings: ChatSettingsRequest): Promise<ChatDTO>;
67
+ /** Change the chat's settings. Answers with the settings as they now are. */
68
+ export declare function updateChatSettings(client: AgentClient, chatId: string, settings: ChatSettingsRequest): Promise<ChatSettingsDTO>;
67
69
  export declare function resolveInterrupt(client: AgentClient, interruptId: string, decision: 'allow' | 'deny'): Promise<InterruptDTO>;
68
70
  export declare function listRunInterrupts(client: AgentClient, runId: string): Promise<InterruptDTO[]>;
69
71
  export declare function uploadFile(client: AgentClient, file: globalThis.File): Promise<FileRef>;
package/dist/agent/api.js CHANGED
@@ -132,6 +132,7 @@ export async function stopChat(client, chatId) {
132
132
  export async function cancelMessage(client, messageId) {
133
133
  await client.http.request('post', `/chats/messages/${messageId}/cancel`);
134
134
  }
135
+ /** Hand the chat to another agent. Answers with the agent the chat now runs on. */
135
136
  export async function setAgent(client, chatId, agentRef) {
136
137
  const resp = await client.http.request('post', `/chats/${chatId}/agent`, {
137
138
  data: { agent: agentRef },
@@ -178,6 +179,7 @@ export async function explainTool(client, chatId, toolInvocationId) {
178
179
  const resp = await client.http.request('post', `/chats/${chatId}/tools/${toolInvocationId}/explain`);
179
180
  return resp.data;
180
181
  }
182
+ /** Change the chat's settings. Answers with the settings as they now are. */
181
183
  export async function updateChatSettings(client, chatId, settings) {
182
184
  const resp = await client.http.request('post', `/chats/${chatId}/settings`, { data: settings });
183
185
  return resp.data;
@@ -50,6 +50,43 @@ export function chatReducer(state, action) {
50
50
  return state;
51
51
  return { ...state, chat };
52
52
  }
53
+ // The settings and set-agent endpoints answer with only what they wrote.
54
+ // Merge it into the chat it belongs to; a chat switched away from in the
55
+ // meantime is left alone.
56
+ case 'MERGE_CHAT_SETTINGS': {
57
+ const settings = action.payload;
58
+ if (!state.chat || state.chat.id !== settings.chat_id)
59
+ return state;
60
+ return {
61
+ ...state,
62
+ chat: {
63
+ ...state.chat,
64
+ name: settings.name,
65
+ visibility: settings.visibility,
66
+ agent_data: {
67
+ ...state.chat.agent_data,
68
+ allow_all_tools: settings.allow_all_tools,
69
+ disable_hooks: settings.disable_hooks,
70
+ memory: settings.memory,
71
+ },
72
+ },
73
+ };
74
+ }
75
+ case 'MERGE_CHAT_AGENT': {
76
+ const agent = action.payload;
77
+ if (!state.chat || state.chat.id !== agent.chat_id)
78
+ return state;
79
+ return {
80
+ ...state,
81
+ chat: {
82
+ ...state.chat,
83
+ agent_id: agent.agent_id,
84
+ agent: agent.agent,
85
+ agent_version_id: agent.agent_version_id,
86
+ agent_version: agent.agent_version,
87
+ },
88
+ };
89
+ }
53
90
  case 'UPDATE_ACTIVE_RUN': {
54
91
  if (!state.chat)
55
92
  return state;
@@ -4,7 +4,7 @@
4
4
  * Public types for the Agent chat module.
5
5
  */
6
6
  import type { Dispatch } from 'react';
7
- import type { AgentRunDTO, AgentVersionDTO, AlwaysAllowOptionsDTO, AlwaysAllowResultDTO, ToolExplanationDTO, ChatDTO, ChatMessageDTO, ChatSettingsRequest, AgentTool, AgentConfigInput as GeneratedAgentConfig, CoreAppConfigInput as CoreAppConfig, FileRef, ElicitResult } from '../types';
7
+ import type { AgentRunDTO, AgentVersionDTO, AlwaysAllowOptionsDTO, AlwaysAllowResultDTO, ToolExplanationDTO, ChatAgentDTO, ChatDTO, ChatMessageDTO, ChatSettingsDTO, ChatSettingsRequest, AgentTool, AgentConfigInput as GeneratedAgentConfig, CoreAppConfigInput as CoreAppConfig, FileRef, ElicitResult } from '../types';
8
8
  import type { HttpClient } from '../http/client';
9
9
  import type { StreamableManager } from '../http/streamable';
10
10
  import type { PollManager } from '../http/poll';
@@ -233,6 +233,12 @@ export type ChatAction = {
233
233
  } | {
234
234
  type: 'UPDATE_CHAT';
235
235
  payload: ChatDTO | null;
236
+ } | {
237
+ type: 'MERGE_CHAT_SETTINGS';
238
+ payload: ChatSettingsDTO;
239
+ } | {
240
+ type: 'MERGE_CHAT_AGENT';
241
+ payload: ChatAgentDTO;
236
242
  } | {
237
243
  type: 'UPDATE_ACTIVE_RUN';
238
244
  payload: AgentRunDTO;
@@ -296,6 +296,10 @@ export class Agent {
296
296
  const intervalMs = options.pollIntervalMs ?? this.http.getPollIntervalMs();
297
297
  let prevStatus = null;
298
298
  let knownMessageIds = new Set();
299
+ // Returned by the poll when nothing changed. Compared by identity: a
300
+ // fetched chat never carries chat_messages, so their absence cannot tell
301
+ // the two apart.
302
+ const unchanged = {};
299
303
  return new Promise((resolve) => {
300
304
  this.poller?.stop();
301
305
  this.poller = new PollManager({
@@ -305,17 +309,15 @@ export class Agent {
305
309
  const status = statusResp.data;
306
310
  // Unchanged status is skipped — unless the turn is still ungated: a run
307
311
  // that started and finished between two polls only shows in the messages.
308
- if (status.status === prevStatus && gate.settled) {
309
- // No change — return a stub to skip processing
310
- return { status: status.status };
311
- }
312
+ if (status.status === prevStatus && gate.settled)
313
+ return unchanged;
312
314
  // Status changed — fetch full chat
313
315
  const chatResp = await this.http.request('get', `/chats/${this.chatId}`);
314
316
  return chatResp.data;
315
317
  },
316
318
  intervalMs,
317
319
  onData: (chat) => {
318
- if (chat.status === prevStatus && !chat.chat_messages)
320
+ if (chat === unchanged)
319
321
  return;
320
322
  prevStatus = chat.status;
321
323
  options.onChat?.(chat);
package/dist/types.d.ts CHANGED
@@ -1777,6 +1777,37 @@ export interface ChatSettingsRequest {
1777
1777
  */
1778
1778
  forget_memory?: string[];
1779
1779
  }
1780
+ /**
1781
+ * ChatSettingsDTO is what POST /chats/{id}/settings answers with: the chat's
1782
+ * settings after the change, every field the endpoint writes and nothing
1783
+ * else. A client merges it into the chat it holds.
1784
+ */
1785
+ export interface ChatSettingsDTO {
1786
+ chat_id: string;
1787
+ name: string;
1788
+ visibility: Visibility;
1789
+ /**
1790
+ * AllowAllTools and DisableHooks are agent_data.allow_all_tools and
1791
+ * agent_data.disable_hooks on the chat.
1792
+ */
1793
+ allow_all_tools: boolean;
1794
+ disable_hooks: boolean;
1795
+ /**
1796
+ * Memory is agent_data.memory after forget_memory removed its keys.
1797
+ */
1798
+ memory: StringEncodedMap;
1799
+ }
1800
+ /**
1801
+ * ChatAgentDTO is what POST /chats/{id}/agent answers with: the agent the
1802
+ * chat now runs on. A client merges it into the chat it holds.
1803
+ */
1804
+ export interface ChatAgentDTO {
1805
+ chat_id: string;
1806
+ agent_id: string;
1807
+ agent?: AgentDTO;
1808
+ agent_version_id: string;
1809
+ agent_version?: AgentVersionDTO;
1810
+ }
1780
1811
  /**
1781
1812
  * ChatDTO for API responses
1782
1813
  */
@@ -1800,7 +1831,12 @@ export interface ChatDTO extends BaseModelDTO, PermissionModelDTO {
1800
1831
  agent_version?: AgentVersionDTO;
1801
1832
  name: string;
1802
1833
  description: string;
1803
- chat_messages: ChatMessageDTO[];
1834
+ /**
1835
+ * ChatMessages is left out when the messages were not loaded. The chat
1836
+ * endpoints do not load them; read them from GET /chats/{id}/messages.
1837
+ * An absent field says nothing about whether the chat has messages.
1838
+ */
1839
+ chat_messages?: ChatMessageDTO[];
1804
1840
  agent_data: ChatData;
1805
1841
  active_run?: AgentRunDTO;
1806
1842
  pending_interrupts?: InterruptDTO[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inferencesh/sdk",
3
- "version": "0.16.0",
3
+ "version": "0.17.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",