@inferencesh/sdk 0.16.0 → 0.18.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,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.18.0] - 2026-10-04
11
+
12
+ ### Added
13
+
14
+ - `AgentPermissions` and `permissions` on agent configs: what an agent's new chats may do without asking (`allow_all_tools`).
15
+ - `PolicyKind` (`RemoteExec`, `Workspace`, `Harness`, `Tool`, `WebFetch`, and the usage kinds `App`, `Agent`, `Knowledge`, `Mcp`, `Flow`) with its constants. `PolicyRuleDTO.kind` is a `PolicyKind`.
16
+
17
+ ### Removed
18
+
19
+ - `ChatData.always_allowed_tools`. A chat's always-allow list became chat rules (`GET /chats/{id}/rules`); the api no longer sends it.
20
+ - `TeamDTO.usage_policy_id`. A workspace's usage policy is a policy attached to it; the org's workspace list carries it.
21
+
22
+ ## [0.17.0] - 2026-10-02
23
+
24
+ ### Changed
25
+
26
+ - `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.
27
+ - `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`.
28
+
29
+ ### Fixed
30
+
31
+ - 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.
32
+
10
33
  ## [0.16.0] - 2026-10-02
11
34
 
12
35
  ### 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
@@ -18,6 +18,22 @@ export interface InternalToolsConfig {
18
18
  remote?: boolean;
19
19
  knowledge?: boolean;
20
20
  }
21
+ /**
22
+ * AgentPermissions is what an agent's new chats in its own workspace may do
23
+ * without asking (INF-906). Each is copied into such a chat when it is
24
+ * created; the chat owns it from then on. Chats other workspaces start with
25
+ * the agent get none of it: they run on their own remotes and tools. A team
26
+ * or org policy still asks or denies over it.
27
+ */
28
+ export interface AgentPermissions {
29
+ /**
30
+ * AllowAllTools starts each new chat with "allow every tool" on: loop
31
+ * tools, harness tools and remote_exec commands run without asking. For
32
+ * agents nobody watches (webhook and cron runs), where an approval would
33
+ * stall the run.
34
+ */
35
+ allow_all_tools?: boolean;
36
+ }
21
37
  /**
22
38
  * AgentTool represents a unified tool that can be used by an agent
23
39
  */
@@ -254,6 +270,7 @@ export interface AgentVersionDTO extends BaseModelDTO, PermissionModelDTO {
254
270
  skills: SkillConfig[];
255
271
  context?: ContextField[];
256
272
  internal_tools?: InternalToolsConfig;
273
+ permissions?: AgentPermissions;
257
274
  hooks?: LifecycleHookConfig[];
258
275
  output_schema?: any;
259
276
  }
@@ -287,6 +304,7 @@ export interface AgentConfigInput {
287
304
  skills?: SkillConfig[];
288
305
  context?: ContextField[];
289
306
  internal_tools?: InternalToolsConfig;
307
+ permissions?: AgentPermissions;
290
308
  hooks?: LifecycleHookConfig[];
291
309
  output_schema?: any;
292
310
  }
@@ -1777,6 +1795,37 @@ export interface ChatSettingsRequest {
1777
1795
  */
1778
1796
  forget_memory?: string[];
1779
1797
  }
1798
+ /**
1799
+ * ChatSettingsDTO is what POST /chats/{id}/settings answers with: the chat's
1800
+ * settings after the change, every field the endpoint writes and nothing
1801
+ * else. A client merges it into the chat it holds.
1802
+ */
1803
+ export interface ChatSettingsDTO {
1804
+ chat_id: string;
1805
+ name: string;
1806
+ visibility: Visibility;
1807
+ /**
1808
+ * AllowAllTools and DisableHooks are agent_data.allow_all_tools and
1809
+ * agent_data.disable_hooks on the chat.
1810
+ */
1811
+ allow_all_tools: boolean;
1812
+ disable_hooks: boolean;
1813
+ /**
1814
+ * Memory is agent_data.memory after forget_memory removed its keys.
1815
+ */
1816
+ memory: StringEncodedMap;
1817
+ }
1818
+ /**
1819
+ * ChatAgentDTO is what POST /chats/{id}/agent answers with: the agent the
1820
+ * chat now runs on. A client merges it into the chat it holds.
1821
+ */
1822
+ export interface ChatAgentDTO {
1823
+ chat_id: string;
1824
+ agent_id: string;
1825
+ agent?: AgentDTO;
1826
+ agent_version_id: string;
1827
+ agent_version?: AgentVersionDTO;
1828
+ }
1780
1829
  /**
1781
1830
  * ChatDTO for API responses
1782
1831
  */
@@ -1800,7 +1849,12 @@ export interface ChatDTO extends BaseModelDTO, PermissionModelDTO {
1800
1849
  agent_version?: AgentVersionDTO;
1801
1850
  name: string;
1802
1851
  description: string;
1803
- chat_messages: ChatMessageDTO[];
1852
+ /**
1853
+ * ChatMessages is left out when the messages were not loaded. The chat
1854
+ * endpoints do not load them; read them from GET /chats/{id}/messages.
1855
+ * An absent field says nothing about whether the chat has messages.
1856
+ */
1857
+ chat_messages?: ChatMessageDTO[];
1804
1858
  agent_data: ChatData;
1805
1859
  active_run?: AgentRunDTO;
1806
1860
  pending_interrupts?: InterruptDTO[];
@@ -1834,13 +1888,6 @@ export interface ChatMessageDTO extends BaseModelDTO, PermissionModelDTO {
1834
1888
  tool_call_id?: string;
1835
1889
  tool_invocations?: ToolInvocationDTO[];
1836
1890
  }
1837
- /**
1838
- * PolicyEffect is a rule's outcome: allow, ask or deny.
1839
- */
1840
- export type PolicyEffect = "allow" | "ask" | "deny";
1841
- export declare const PolicyEffectAllow: PolicyEffect;
1842
- export declare const PolicyEffectAsk: PolicyEffect;
1843
- export declare const PolicyEffectDeny: PolicyEffect;
1844
1891
  /**
1845
1892
  * PolicyRuleDTO is one rule, typed form Kind[selector](specifier).
1846
1893
  */
@@ -1848,10 +1895,10 @@ export interface PolicyRuleDTO {
1848
1895
  id: string;
1849
1896
  effect: PolicyEffect;
1850
1897
  /**
1851
- * Kind: RemoteExec, Workspace, Harness, Tool (and, from phase 3, App,
1852
- * Agent, Knowledge, Mcp, Flow, WebFetch).
1898
+ * Kind: what the rule governs (RemoteExec, Workspace, Harness, Tool,
1899
+ * and the usage kinds App, Agent, Knowledge, Mcp, Flow).
1853
1900
  */
1854
- kind: string;
1901
+ kind: PolicyKind;
1855
1902
  /**
1856
1903
  * Selector narrows the rule to one remote (its id) or a tag (tag:<name>);
1857
1904
  * empty applies everywhere.
@@ -4121,11 +4168,6 @@ export interface TeamDTO extends BaseModelDTO {
4121
4168
  * org it is without belonging to the org workspace.
4122
4169
  */
4123
4170
  org_name?: string;
4124
- /**
4125
- * UsagePolicyID of the team's own usage policy ('' = inherit the org's,
4126
- * or ungoverned when standalone, INF-808).
4127
- */
4128
- usage_policy_id?: string;
4129
4171
  }
4130
4172
  /**
4131
4173
  * TeamMemberDTO is the API response for a team member.
@@ -4679,7 +4721,6 @@ export declare const ChannelTypeTelegram: ChannelType;
4679
4721
  export interface ChatData {
4680
4722
  plan_steps: PlanStep[];
4681
4723
  memory: StringEncodedMap;
4682
- always_allowed_tools: string[];
4683
4724
  /**
4684
4725
  * AllowAllTools runs every tool call in this chat without asking. The
4685
4726
  * person switches it in the chat's settings, and off again at any time.
@@ -5507,6 +5548,46 @@ export declare const NotificationStatusDelivered: NotificationStatus;
5507
5548
  export declare const NotificationStatusFailed: NotificationStatus;
5508
5549
  export declare const NotificationStatusBounced: NotificationStatus;
5509
5550
  export declare const NotificationStatusCancelled: NotificationStatus;
5551
+ /**
5552
+ * PolicyEffect is a rule's outcome and a decision's verdict.
5553
+ */
5554
+ export type PolicyEffect = "allow" | "ask" | "deny";
5555
+ export declare const PolicyEffectAllow: PolicyEffect;
5556
+ export declare const PolicyEffectAsk: PolicyEffect;
5557
+ export declare const PolicyEffectDeny: PolicyEffect;
5558
+ /**
5559
+ * PolicyKind names what a rule governs; each kind has one matcher.
5560
+ */
5561
+ export type PolicyKind = "RemoteExec" | "Workspace" | "Harness" | "Tool" | "App" | "Agent" | "Knowledge" | "Mcp" | "Flow" | "WebFetch";
5562
+ /**
5563
+ * PolicyKindRemoteExec: shell commands run on a remote.
5564
+ */
5565
+ export declare const PolicyKindRemoteExec: PolicyKind;
5566
+ /**
5567
+ * PolicyKindWorkspace: folders on a remote.
5568
+ */
5569
+ export declare const PolicyKindWorkspace: PolicyKind;
5570
+ /**
5571
+ * PolicyKindHarness: a harness's own tool approvals, e.g.
5572
+ * Harness(Bash(git status:*)).
5573
+ */
5574
+ export declare const PolicyKindHarness: PolicyKind;
5575
+ /**
5576
+ * PolicyKindTool: a tool call our own agent loop makes, by tool name.
5577
+ */
5578
+ export declare const PolicyKindTool: PolicyKind;
5579
+ /**
5580
+ * Usage kinds (UsageCategory.PolicyKind): rules name resolved ids.
5581
+ */
5582
+ export declare const PolicyKindApp: PolicyKind;
5583
+ export declare const PolicyKindAgent: PolicyKind;
5584
+ export declare const PolicyKindKnowledge: PolicyKind;
5585
+ export declare const PolicyKindMcp: PolicyKind;
5586
+ export declare const PolicyKindFlow: PolicyKind;
5587
+ /**
5588
+ * PolicyKindWebFetch: fetched domains.
5589
+ */
5590
+ export declare const PolicyKindWebFetch: PolicyKind;
5510
5591
  /**
5511
5592
  * FunctionKind is how an app function talks to its caller.
5512
5593
  */
package/dist/types.js CHANGED
@@ -302,9 +302,6 @@ export const ScopeGroupKnowledge = "knowledge";
302
302
  export const ScopeGroupArtifacts = "artifacts";
303
303
  export const ScopeGroupUser = "user";
304
304
  export const ScopeGroupSettings = "settings";
305
- export const PolicyEffectAllow = "allow";
306
- export const PolicyEffectAsk = "ask";
307
- export const PolicyEffectDeny = "deny";
308
305
  /**
309
306
  * AlwaysAllowScopeExact: this call exactly (each piece of the command,
310
307
  * the file, the domain).
@@ -1066,6 +1063,38 @@ export const NotificationStatusDelivered = "delivered";
1066
1063
  export const NotificationStatusFailed = "failed";
1067
1064
  export const NotificationStatusBounced = "bounced";
1068
1065
  export const NotificationStatusCancelled = "cancelled";
1066
+ export const PolicyEffectAllow = "allow";
1067
+ export const PolicyEffectAsk = "ask";
1068
+ export const PolicyEffectDeny = "deny";
1069
+ /**
1070
+ * PolicyKindRemoteExec: shell commands run on a remote.
1071
+ */
1072
+ export const PolicyKindRemoteExec = "RemoteExec";
1073
+ /**
1074
+ * PolicyKindWorkspace: folders on a remote.
1075
+ */
1076
+ export const PolicyKindWorkspace = "Workspace";
1077
+ /**
1078
+ * PolicyKindHarness: a harness's own tool approvals, e.g.
1079
+ * Harness(Bash(git status:*)).
1080
+ */
1081
+ export const PolicyKindHarness = "Harness";
1082
+ /**
1083
+ * PolicyKindTool: a tool call our own agent loop makes, by tool name.
1084
+ */
1085
+ export const PolicyKindTool = "Tool";
1086
+ /**
1087
+ * Usage kinds (UsageCategory.PolicyKind): rules name resolved ids.
1088
+ */
1089
+ export const PolicyKindApp = "App";
1090
+ export const PolicyKindAgent = "Agent";
1091
+ export const PolicyKindKnowledge = "Knowledge";
1092
+ export const PolicyKindMcp = "Mcp";
1093
+ export const PolicyKindFlow = "Flow";
1094
+ /**
1095
+ * PolicyKindWebFetch: fetched domains.
1096
+ */
1097
+ export const PolicyKindWebFetch = "WebFetch";
1069
1098
  /**
1070
1099
  * FunctionKindRun takes an input and returns an output (optionally
1071
1100
  * yielding progress on the way). The zero value means this.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inferencesh/sdk",
3
- "version": "0.16.0",
3
+ "version": "0.18.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",