@inferencesh/sdk 0.6.30 → 0.6.47
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/README.md +35 -0
- package/dist/agent/actions.js +72 -13
- package/dist/agent/api.d.ts +30 -51
- package/dist/agent/api.js +129 -154
- package/dist/agent/provider.js +18 -1
- package/dist/agent/reducer.js +50 -11
- package/dist/agent/types.d.ts +34 -1
- package/dist/api/agents.d.ts +23 -14
- package/dist/api/agents.js +22 -4
- package/dist/api/api-keys.d.ts +4 -3
- package/dist/api/apps.d.ts +16 -15
- package/dist/api/chats.d.ts +14 -9
- package/dist/api/chats.js +6 -0
- package/dist/api/engines.d.ts +14 -13
- package/dist/api/files.d.ts +4 -3
- package/dist/api/files.js +2 -2
- package/dist/api/flow-runs.d.ts +8 -7
- package/dist/api/flows.d.ts +11 -10
- package/dist/api/integrations.d.ts +9 -8
- package/dist/api/integrations.js +8 -8
- package/dist/api/knowledge.d.ts +25 -24
- package/dist/api/mcp-servers.d.ts +10 -9
- package/dist/api/projects.d.ts +6 -5
- package/dist/api/search.d.ts +3 -2
- package/dist/api/secrets.d.ts +6 -5
- package/dist/api/sessions.d.ts +5 -4
- package/dist/api/sessions.js +2 -3
- package/dist/api/tasks.d.ts +14 -11
- package/dist/api/tasks.js +10 -4
- package/dist/api/teams.d.ts +16 -17
- package/dist/delta.d.ts +15 -0
- package/dist/delta.js +84 -0
- package/dist/hook-builder.d.ts +23 -0
- package/dist/hook-builder.js +50 -0
- package/dist/http/client.d.ts +9 -1
- package/dist/http/client.js +12 -3
- package/dist/http/response.d.ts +9 -0
- package/dist/http/response.js +1 -0
- package/dist/http/stream.d.ts +1 -0
- package/dist/http/stream.js +8 -3
- package/dist/http/streamable.d.ts +3 -1
- package/dist/http/streamable.js +10 -1
- package/dist/index.d.ts +11 -5
- package/dist/index.js +6 -1
- package/dist/proxy/index.d.ts +2 -0
- package/dist/proxy/index.js +9 -0
- package/dist/tool-builder.d.ts +2 -0
- package/dist/tool-builder.js +5 -0
- package/dist/types.d.ts +1041 -157
- package/dist/types.js +230 -30
- package/dist/utils.d.ts +13 -0
- package/dist/utils.js +43 -3
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -409,6 +409,41 @@ const agent = client.agents.create({
|
|
|
409
409
|
|
|
410
410
|
`callTool` is an alias for `httpTool`. Run `npx tsx examples/tool-builder.ts` for more schema examples (no API key required).
|
|
411
411
|
|
|
412
|
+
### Lifecycle hooks
|
|
413
|
+
|
|
414
|
+
Use `lifecycleHook()` to attach hooks to agent events. Hooks can call a webhook or delegate to another agent as a task:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { inference, lifecycleHook, HookEventTurnStart, HookEventToolCall } from '@inferencesh/sdk';
|
|
418
|
+
|
|
419
|
+
const client = inference({ apiKey: 'your-api-key' });
|
|
420
|
+
|
|
421
|
+
const agent = client.agents.create({
|
|
422
|
+
core_app: { ref: 'openrouter/claude-sonnet-4@abc' },
|
|
423
|
+
hooks: [
|
|
424
|
+
lifecycleHook(HookEventTurnStart)
|
|
425
|
+
.webhook('https://example.com/on-turn')
|
|
426
|
+
.timeout(10)
|
|
427
|
+
.build(),
|
|
428
|
+
lifecycleHook(HookEventToolCall)
|
|
429
|
+
.task('my-org/approval-agent')
|
|
430
|
+
.async(true)
|
|
431
|
+
.build(),
|
|
432
|
+
],
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Queued messages
|
|
437
|
+
|
|
438
|
+
`sendMessage` automatically queues when the agent is busy processing a previous message. Queued messages appear with a `queued` status until the agent picks them up.
|
|
439
|
+
|
|
440
|
+
To cancel a queued message before it is processed, use `cancelMessage` on the React provider or `chats.cancelMessage` on the API client:
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
// Via the API client
|
|
444
|
+
await client.chats.cancelMessage(messageId);
|
|
445
|
+
```
|
|
446
|
+
|
|
412
447
|
### File attachments
|
|
413
448
|
|
|
414
449
|
Pass files in `sendMessage` options. `Blob` values are uploaded first; objects with a `uri` (already uploaded via `client.files.upload`) are attached as-is:
|
package/dist/agent/actions.js
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* Action creators that handle side effects (API calls, streaming).
|
|
5
5
|
* These are created once per provider instance with access to dispatch.
|
|
6
6
|
*/
|
|
7
|
-
import { ToolInvocationStatusAwaitingInput, ToolInvocationStatusInProgress, ToolTypeClient, } from '../types';
|
|
7
|
+
import { AgentRunStateWorking, AgentRunStateSubmitted, AgentRunStateInputRequired, ToolInvocationStatusAwaitingInput, ToolInvocationStatusInProgress, ToolTypeClient, } from '../types';
|
|
8
8
|
import { isChatBusy } from '../utils';
|
|
9
9
|
import { StreamableManager } from '../http/streamable';
|
|
10
10
|
import { PollManager } from '../http/poll';
|
|
11
|
+
import { createLLMDeltaAccumulator } from '../delta';
|
|
11
12
|
import { isAdHocConfig, extractClientToolHandlers } from './types';
|
|
12
13
|
import * as api from './api';
|
|
13
14
|
// =============================================================================
|
|
@@ -15,7 +16,7 @@ import * as api from './api';
|
|
|
15
16
|
// =============================================================================
|
|
16
17
|
export function createActions(ctx) {
|
|
17
18
|
const dispatchedToolInvocations = new Set();
|
|
18
|
-
const { client, dispatch, getConfig, getChatId, getClientToolHandlers, getStreamManager, setStreamManager, getStreamEnabled, getPollIntervalMs, callbacks } = ctx;
|
|
19
|
+
const { client, dispatch, getState, getConfig, getChatId, getClientToolHandlers, getStreamManager, setStreamManager, getStreamEnabled, getPollIntervalMs, callbacks } = ctx;
|
|
19
20
|
let prevChatWasBusy = false;
|
|
20
21
|
const checkTurnEnd = (chat) => {
|
|
21
22
|
const busy = isChatBusy(chat);
|
|
@@ -34,13 +35,13 @@ export function createActions(ctx) {
|
|
|
34
35
|
checkTurnEnd(chat);
|
|
35
36
|
}
|
|
36
37
|
};
|
|
37
|
-
const updateMessage = (message) => {
|
|
38
|
+
const updateMessage = (message, fields) => {
|
|
38
39
|
const chatId = getChatId();
|
|
39
40
|
// TODO: remove startsWith once the provider normalizes chatId to full ID after first fetchChat
|
|
40
41
|
// Support short ID matching (URL short IDs are prefixes of full IDs)
|
|
41
42
|
if (chatId && message.chat_id && message.chat_id !== chatId && !message.chat_id.startsWith(chatId))
|
|
42
43
|
return;
|
|
43
|
-
dispatch({ type: 'UPDATE_MESSAGE', payload: message });
|
|
44
|
+
dispatch({ type: 'UPDATE_MESSAGE', payload: message, partial: fields ? true : undefined });
|
|
44
45
|
// Dispatch client tool handlers when ready (in_progress or awaiting_input for backwards compat)
|
|
45
46
|
const clientToolHandlers = getClientToolHandlers();
|
|
46
47
|
if (message.tool_invocations && chatId && clientToolHandlers.size > 0) {
|
|
@@ -88,7 +89,7 @@ export function createActions(ctx) {
|
|
|
88
89
|
dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'connecting' });
|
|
89
90
|
callbacks.onStatusChange?.('connecting');
|
|
90
91
|
try {
|
|
91
|
-
// Fetch initial chat
|
|
92
|
+
// Fetch initial chat (fetchChat loads messages separately since Chat.Get no longer preloads them)
|
|
92
93
|
const chat = await api.fetchChat(client, id);
|
|
93
94
|
if (chat) {
|
|
94
95
|
setChat(chat);
|
|
@@ -139,15 +140,25 @@ export function createActions(ctx) {
|
|
|
139
140
|
}
|
|
140
141
|
});
|
|
141
142
|
// Listen for ChatMessage updates
|
|
142
|
-
manager.addEventListener('chat_messages', (message) => {
|
|
143
|
-
updateMessage(message);
|
|
143
|
+
manager.addEventListener('chat_messages', (message, fields) => {
|
|
144
|
+
updateMessage(message, fields);
|
|
144
145
|
});
|
|
145
146
|
// Listen for AgentRun updates (state transitions, output)
|
|
146
147
|
manager.addEventListener('agent_runs', (run) => {
|
|
147
148
|
dispatch({ type: 'UPDATE_ACTIVE_RUN', payload: run });
|
|
148
|
-
const
|
|
149
|
-
callbacks.onStatusChange?.(
|
|
150
|
-
|
|
149
|
+
const isRunActive = run.state === AgentRunStateWorking || run.state === AgentRunStateSubmitted || run.state === AgentRunStateInputRequired;
|
|
150
|
+
callbacks.onStatusChange?.(isRunActive ? 'streaming' : 'idle');
|
|
151
|
+
const currentChat = getState().chat;
|
|
152
|
+
if (currentChat)
|
|
153
|
+
checkTurnEnd({ ...currentChat, active_run: run });
|
|
154
|
+
});
|
|
155
|
+
// Listen for LLM delta events (token-by-token streaming)
|
|
156
|
+
const deltaAccum = createLLMDeltaAccumulator();
|
|
157
|
+
manager.addEventListener('delta', (evt) => {
|
|
158
|
+
if (evt && evt.delta) {
|
|
159
|
+
deltaAccum.apply(evt.delta);
|
|
160
|
+
dispatch({ type: 'DELTA_TOKEN', payload: deltaAccum.toOutput() });
|
|
161
|
+
}
|
|
151
162
|
});
|
|
152
163
|
setStreamManager(manager);
|
|
153
164
|
manager.start();
|
|
@@ -156,13 +167,16 @@ export function createActions(ctx) {
|
|
|
156
167
|
const pollChat = (id) => {
|
|
157
168
|
let prevStatus = null;
|
|
158
169
|
const manager = new PollManager({
|
|
159
|
-
pollFunction: () =>
|
|
170
|
+
pollFunction: async () => {
|
|
171
|
+
const resp = await client.http.request('get', `/chats/${id}/status`);
|
|
172
|
+
return resp.data;
|
|
173
|
+
},
|
|
160
174
|
intervalMs: getPollIntervalMs(),
|
|
161
175
|
onData: async (statusData) => {
|
|
162
176
|
if (statusData.status === prevStatus)
|
|
163
177
|
return;
|
|
164
178
|
prevStatus = statusData.status;
|
|
165
|
-
// Status changed — fetch
|
|
179
|
+
// Status changed — fetch chat (fetchChat loads messages)
|
|
166
180
|
try {
|
|
167
181
|
const chat = await api.fetchChat(client, id);
|
|
168
182
|
if (chat) {
|
|
@@ -229,7 +243,10 @@ export function createActions(ctx) {
|
|
|
229
243
|
try {
|
|
230
244
|
const result = await api.sendMessage(client, agentConfig, chatId, trimmedText, files);
|
|
231
245
|
if (result) {
|
|
232
|
-
const { chatId: newChatId } = result;
|
|
246
|
+
const { chatId: newChatId, userMessage } = result;
|
|
247
|
+
// Add user message from POST response immediately
|
|
248
|
+
if (userMessage)
|
|
249
|
+
dispatch({ type: 'UPDATE_MESSAGE', payload: userMessage });
|
|
233
250
|
// Start streaming if not already connected
|
|
234
251
|
const streamManager = getStreamManager();
|
|
235
252
|
if (newChatId && !streamManager) {
|
|
@@ -330,6 +347,48 @@ export function createActions(ctx) {
|
|
|
330
347
|
throw error;
|
|
331
348
|
}
|
|
332
349
|
},
|
|
350
|
+
cancelMessage: async (messageId) => {
|
|
351
|
+
try {
|
|
352
|
+
await api.cancelMessage(client, messageId);
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
console.error('[AgentSDK] Failed to cancel message:', error);
|
|
356
|
+
const err = error instanceof Error ? error : new Error('Failed to cancel message');
|
|
357
|
+
dispatch({ type: 'SET_ERROR', payload: err.message });
|
|
358
|
+
callbacks.onError?.(err);
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
resolveInterrupt: async (interruptId, decision) => {
|
|
363
|
+
try {
|
|
364
|
+
await api.resolveInterrupt(client, interruptId, decision);
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
console.error('[AgentSDK] Failed to resolve interrupt:', error);
|
|
368
|
+
const err = error instanceof Error ? error : new Error('Failed to resolve interrupt');
|
|
369
|
+
dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'error' });
|
|
370
|
+
dispatch({ type: 'SET_ERROR', payload: err.message });
|
|
371
|
+
callbacks.onError?.(err);
|
|
372
|
+
throw error;
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
loadOlderMessages: async () => {
|
|
376
|
+
const chatId = getChatId();
|
|
377
|
+
const cursor = getState().messageCursor;
|
|
378
|
+
if (!chatId || !cursor)
|
|
379
|
+
return false;
|
|
380
|
+
const page = await api.fetchMessagesPage(client, chatId, { cursor });
|
|
381
|
+
if (page.items.length > 0) {
|
|
382
|
+
dispatch({
|
|
383
|
+
type: 'PREPEND_MESSAGES',
|
|
384
|
+
payload: { messages: page.items, cursor: page.next_cursor, hasMore: page.has_next },
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
return page.has_next;
|
|
388
|
+
},
|
|
389
|
+
get hasOlderMessages() {
|
|
390
|
+
return getState().hasOlderMessages ?? false;
|
|
391
|
+
},
|
|
333
392
|
};
|
|
334
393
|
const internalActions = {
|
|
335
394
|
streamChat,
|
package/dist/agent/api.d.ts
CHANGED
|
@@ -1,50 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent Chat API
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* File input that can be either a File to upload or an already-uploaded file
|
|
11
|
-
*/
|
|
12
|
-
export type FileInput = globalThis.File | FileRef;
|
|
13
|
-
/**
|
|
14
|
-
* Send a message using ad-hoc agent config
|
|
15
|
-
*/
|
|
16
|
-
export declare function sendAdHocMessage(client: AgentClient, config: AdHocAgentConfig, chatId: string | null, text: string, attachments?: FileRef[]): Promise<{
|
|
17
|
-
chatId: string;
|
|
18
|
-
userMessage: ChatMessageDTO;
|
|
19
|
-
assistantMessage: ChatMessageDTO;
|
|
20
|
-
} | null>;
|
|
21
|
-
/**
|
|
22
|
-
* Send a message using template agent config
|
|
4
|
+
* Two paths by user intent:
|
|
5
|
+
* - New conversation: POST /chats (create chat with agent) → POST /chats/{id}/messages
|
|
6
|
+
* - Existing chat: POST /chats/{id}/messages
|
|
7
|
+
*
|
|
8
|
+
* /agents/run stays for A2A/programmatic use.
|
|
23
9
|
*/
|
|
24
|
-
|
|
10
|
+
import type { ChatDTO, ChatMessageDTO, InterruptDTO } from '../types';
|
|
11
|
+
import type { AgentOptions, AgentClient, AgentInfo, FileRef } from './types';
|
|
12
|
+
export interface SendResult {
|
|
25
13
|
chatId: string;
|
|
26
14
|
userMessage: ChatMessageDTO;
|
|
27
|
-
|
|
28
|
-
} | null>;
|
|
15
|
+
}
|
|
29
16
|
/**
|
|
30
|
-
*
|
|
17
|
+
* File input that can be either a File to upload or an already-uploaded file
|
|
31
18
|
*/
|
|
32
|
-
export
|
|
33
|
-
chatId: string;
|
|
34
|
-
userMessage: ChatMessageDTO;
|
|
35
|
-
assistantMessage: ChatMessageDTO;
|
|
36
|
-
} | null>;
|
|
19
|
+
export type FileInput = globalThis.File | FileRef;
|
|
37
20
|
/**
|
|
38
|
-
*
|
|
39
|
-
*/
|
|
21
|
+
* Send a message — creates chat if needed, then sends message
|
|
22
|
+
*/
|
|
23
|
+
export declare function sendMessage(client: AgentClient, config: AgentOptions, chatId: string | null, text: string, files?: FileInput[]): Promise<SendResult | null>;
|
|
24
|
+
export declare function fetchAgentInfo(client: AgentClient, agentRef: string): Promise<AgentInfo | null>;
|
|
25
|
+
export interface FetchMessagesOptions {
|
|
26
|
+
limit?: number;
|
|
27
|
+
cursor?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface FetchMessagesResult {
|
|
30
|
+
items: ChatMessageDTO[];
|
|
31
|
+
next_cursor: string;
|
|
32
|
+
has_next: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function fetchMessages(client: AgentClient, chatId: string, options?: FetchMessagesOptions): Promise<ChatMessageDTO[]>;
|
|
35
|
+
export declare function fetchMessagesPage(client: AgentClient, chatId: string, options?: FetchMessagesOptions): Promise<FetchMessagesResult>;
|
|
40
36
|
export declare function fetchChat(client: AgentClient, chatId: string): Promise<ChatDTO | null>;
|
|
41
|
-
/**
|
|
42
|
-
* Stop a chat
|
|
43
|
-
*/
|
|
44
37
|
export declare function stopChat(client: AgentClient, chatId: string): Promise<void>;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
*/
|
|
38
|
+
export declare function cancelMessage(client: AgentClient, messageId: string): Promise<void>;
|
|
39
|
+
export declare function setAgent(client: AgentClient, chatId: string, agentRef: string): Promise<ChatDTO>;
|
|
48
40
|
export declare function submitToolResult(client: AgentClient, toolInvocationId: string, resultOrAction: string | {
|
|
49
41
|
action: {
|
|
50
42
|
type: string;
|
|
@@ -52,25 +44,12 @@ export declare function submitToolResult(client: AgentClient, toolInvocationId:
|
|
|
52
44
|
};
|
|
53
45
|
form_data?: Record<string, unknown>;
|
|
54
46
|
}): Promise<void>;
|
|
55
|
-
/**
|
|
56
|
-
* Approve a tool (for HIL approval)
|
|
57
|
-
*/
|
|
58
47
|
export declare function approveTool(client: AgentClient, toolInvocationId: string): Promise<void>;
|
|
59
|
-
/**
|
|
60
|
-
* Reject a tool (for HIL approval)
|
|
61
|
-
*/
|
|
62
48
|
export declare function rejectTool(client: AgentClient, toolInvocationId: string, reason?: string): Promise<void>;
|
|
63
|
-
/**
|
|
64
|
-
* Always allow a tool for this chat
|
|
65
|
-
*/
|
|
66
49
|
export declare function alwaysAllowTool(client: AgentClient, chatId: string, toolInvocationId: string, toolName: string): Promise<void>;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
*/
|
|
50
|
+
export declare function resolveInterrupt(client: AgentClient, interruptId: string, decision: 'allow' | 'deny'): Promise<InterruptDTO>;
|
|
51
|
+
export declare function listRunInterrupts(client: AgentClient, runId: string): Promise<InterruptDTO[]>;
|
|
70
52
|
export declare function uploadFile(client: AgentClient, file: globalThis.File): Promise<FileRef>;
|
|
71
|
-
/**
|
|
72
|
-
* Get streamable config for chat streaming (NDJSON)
|
|
73
|
-
*/
|
|
74
53
|
export declare function getChatStreamConfig(client: AgentClient, chatId: string): {
|
|
75
54
|
url: string;
|
|
76
55
|
headers: Record<string, string>;
|
package/dist/agent/api.js
CHANGED
|
@@ -1,136 +1,126 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Agent Chat API
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* Check if input is an already-uploaded file
|
|
4
|
+
* Two paths by user intent:
|
|
5
|
+
* - New conversation: POST /chats (create chat with agent) → POST /chats/{id}/messages
|
|
6
|
+
* - Existing chat: POST /chats/{id}/messages
|
|
7
|
+
*
|
|
8
|
+
* /agents/run stays for A2A/programmatic use.
|
|
10
9
|
*/
|
|
10
|
+
import { isAdHocConfig } from './types';
|
|
11
11
|
function isFileRef(input) {
|
|
12
12
|
return 'uri' in input && typeof input.uri === 'string';
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Process file inputs — upload raw files, pass through already-uploaded FileRefs
|
|
16
16
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
tools: toolSchemas
|
|
26
|
-
},
|
|
27
|
-
agent_name: config.name,
|
|
28
|
-
input: {
|
|
29
|
-
text,
|
|
30
|
-
attachments,
|
|
31
|
-
context_size: 0,
|
|
32
|
-
system_prompt: '',
|
|
33
|
-
context: [],
|
|
34
|
-
role: 'user',
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
const response = await client.http.request('post', '/agents/run', { data: request });
|
|
38
|
-
if (response) {
|
|
39
|
-
const { user_message, assistant_message } = response;
|
|
40
|
-
if (user_message && assistant_message) {
|
|
41
|
-
return {
|
|
42
|
-
chatId: assistant_message.chat_id,
|
|
43
|
-
userMessage: user_message,
|
|
44
|
-
assistantMessage: assistant_message,
|
|
45
|
-
};
|
|
17
|
+
async function processFiles(client, files) {
|
|
18
|
+
if (!files || files.length === 0)
|
|
19
|
+
return undefined;
|
|
20
|
+
const results = await Promise.all(files.map(async (file) => {
|
|
21
|
+
if (isFileRef(file))
|
|
22
|
+
return file;
|
|
23
|
+
try {
|
|
24
|
+
return await client.files.upload(file);
|
|
46
25
|
}
|
|
47
|
-
|
|
48
|
-
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error('[AgentSDK] Failed to upload file:', error);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
const refs = results.filter((r) => r !== null);
|
|
32
|
+
return refs.length > 0 ? refs : undefined;
|
|
49
33
|
}
|
|
50
34
|
/**
|
|
51
|
-
*
|
|
35
|
+
* Create a new chat with an agent — POST /chats
|
|
52
36
|
*/
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
37
|
+
async function createChat(client, config) {
|
|
38
|
+
const agentRef = isAdHocConfig(config) ? config.core_app.ref : config.agent;
|
|
39
|
+
const context = !isAdHocConfig(config) ? config.context : undefined;
|
|
40
|
+
const resp = await client.http.request('post', '/chats', {
|
|
41
|
+
data: { agent: agentRef, context },
|
|
42
|
+
});
|
|
43
|
+
return resp.data;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Send a message in a chat — POST /chats/{id}/messages
|
|
47
|
+
*/
|
|
48
|
+
async function sendChatMessage(client, chatId, text) {
|
|
49
|
+
const resp = await client.http.request('post', `/chats/${chatId}/messages`, {
|
|
50
|
+
data: { message: text },
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
chatId,
|
|
54
|
+
userMessage: resp.data,
|
|
69
55
|
};
|
|
70
|
-
const response = await client.http.request('post', '/agents/run', { data: request });
|
|
71
|
-
if (response) {
|
|
72
|
-
const { user_message, assistant_message } = response;
|
|
73
|
-
if (user_message && assistant_message) {
|
|
74
|
-
return {
|
|
75
|
-
chatId: assistant_message.chat_id,
|
|
76
|
-
userMessage: user_message,
|
|
77
|
-
assistantMessage: assistant_message,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return null;
|
|
82
56
|
}
|
|
83
57
|
/**
|
|
84
|
-
* Send a message
|
|
58
|
+
* Send a message — creates chat if needed, then sends message
|
|
85
59
|
*/
|
|
86
60
|
export async function sendMessage(client, config, chatId, text, files) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
if (attachments.length === 0) {
|
|
109
|
-
attachments = undefined;
|
|
110
|
-
}
|
|
61
|
+
await processFiles(client, files);
|
|
62
|
+
// Existing chat — just send the message
|
|
63
|
+
if (chatId) {
|
|
64
|
+
return sendChatMessage(client, chatId, text);
|
|
65
|
+
}
|
|
66
|
+
// New chat — create it, then send the first message
|
|
67
|
+
const chat = await createChat(client, config);
|
|
68
|
+
return sendChatMessage(client, chat.id, text);
|
|
69
|
+
}
|
|
70
|
+
// =========================================================================
|
|
71
|
+
// Agent info
|
|
72
|
+
// =========================================================================
|
|
73
|
+
export async function fetchAgentInfo(client, agentRef) {
|
|
74
|
+
try {
|
|
75
|
+
const resp = await client.http.request('get', `/agents/${agentRef}`);
|
|
76
|
+
const version = resp.data?.version;
|
|
77
|
+
return {
|
|
78
|
+
description: version?.description,
|
|
79
|
+
example_prompts: version?.example_prompts,
|
|
80
|
+
};
|
|
111
81
|
}
|
|
112
|
-
|
|
113
|
-
return
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export async function fetchMessages(client, chatId, options) {
|
|
87
|
+
const result = await fetchMessagesPage(client, chatId, options);
|
|
88
|
+
return result.items;
|
|
89
|
+
}
|
|
90
|
+
export async function fetchMessagesPage(client, chatId, options) {
|
|
91
|
+
try {
|
|
92
|
+
const params = {};
|
|
93
|
+
if (options?.limit !== undefined)
|
|
94
|
+
params.limit = options.limit;
|
|
95
|
+
if (options?.cursor)
|
|
96
|
+
params.cursor = options.cursor;
|
|
97
|
+
const resp = await client.http.request('get', `/chats/${chatId}/messages`, { params });
|
|
98
|
+
return resp.data || { items: [], next_cursor: '', has_next: false };
|
|
114
99
|
}
|
|
115
|
-
|
|
116
|
-
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error('[AgentSDK] Failed to fetch messages:', error);
|
|
102
|
+
return { items: [], next_cursor: '', has_next: false };
|
|
117
103
|
}
|
|
118
104
|
}
|
|
119
|
-
/**
|
|
120
|
-
* Fetch a chat by ID
|
|
121
|
-
*/
|
|
122
105
|
export async function fetchChat(client, chatId) {
|
|
123
106
|
try {
|
|
124
|
-
|
|
107
|
+
const resp = await client.http.request('get', `/chats/${chatId}`);
|
|
108
|
+
const chat = resp.data;
|
|
109
|
+
// Chat.Get no longer preloads messages — fetch them separately and attach
|
|
110
|
+
if (chat && (!chat.chat_messages || chat.chat_messages.length === 0)) {
|
|
111
|
+
const page = await fetchMessagesPage(client, chatId);
|
|
112
|
+
chat.chat_messages = page.items;
|
|
113
|
+
// Store pagination info on the chat for the reducer to pick up
|
|
114
|
+
chat._messageCursor = page.next_cursor;
|
|
115
|
+
chat._hasOlderMessages = page.has_next;
|
|
116
|
+
}
|
|
117
|
+
return chat;
|
|
125
118
|
}
|
|
126
119
|
catch (error) {
|
|
127
120
|
console.error('[AgentSDK] Failed to fetch chat:', error);
|
|
128
121
|
}
|
|
129
122
|
return null;
|
|
130
123
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Stop a chat
|
|
133
|
-
*/
|
|
134
124
|
export async function stopChat(client, chatId) {
|
|
135
125
|
try {
|
|
136
126
|
await client.http.request('post', `/chats/${chatId}/stop`);
|
|
@@ -139,67 +129,52 @@ export async function stopChat(client, chatId) {
|
|
|
139
129
|
console.error('[AgentSDK] Failed to stop chat:', error);
|
|
140
130
|
}
|
|
141
131
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
132
|
+
export async function cancelMessage(client, messageId) {
|
|
133
|
+
await client.http.request('post', `/chats/messages/${messageId}/cancel`);
|
|
134
|
+
}
|
|
135
|
+
export async function setAgent(client, chatId, agentRef) {
|
|
136
|
+
const resp = await client.http.request('post', `/chats/${chatId}/agent`, {
|
|
137
|
+
data: { agent: agentRef },
|
|
138
|
+
});
|
|
139
|
+
return resp.data;
|
|
140
|
+
}
|
|
141
|
+
// =========================================================================
|
|
142
|
+
// Tool operations
|
|
143
|
+
// =========================================================================
|
|
145
144
|
export async function submitToolResult(client, toolInvocationId, resultOrAction) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
await client.http.request('post', `/tools/${toolInvocationId}`, { data });
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
console.error('[AgentSDK] Failed to submit tool result:', error);
|
|
152
|
-
throw error;
|
|
153
|
-
}
|
|
145
|
+
const data = typeof resultOrAction === 'string' ? { result: resultOrAction } : resultOrAction;
|
|
146
|
+
await client.http.request('post', `/tools/${toolInvocationId}`, { data });
|
|
154
147
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Approve a tool (for HIL approval)
|
|
157
|
-
*/
|
|
158
148
|
export async function approveTool(client, toolInvocationId) {
|
|
159
|
-
|
|
160
|
-
await client.http.request('post', `/tools/${toolInvocationId}/invoke`);
|
|
161
|
-
}
|
|
162
|
-
catch (error) {
|
|
163
|
-
console.error('[AgentSDK] Failed to approve tool:', error);
|
|
164
|
-
throw error;
|
|
165
|
-
}
|
|
149
|
+
await client.http.request('post', `/tools/${toolInvocationId}/invoke`);
|
|
166
150
|
}
|
|
167
|
-
/**
|
|
168
|
-
* Reject a tool (for HIL approval)
|
|
169
|
-
*/
|
|
170
151
|
export async function rejectTool(client, toolInvocationId, reason) {
|
|
171
|
-
|
|
172
|
-
await client.http.request('post', `/tools/${toolInvocationId}/reject`, { data: { reason } });
|
|
173
|
-
}
|
|
174
|
-
catch (error) {
|
|
175
|
-
console.error('[AgentSDK] Failed to reject tool:', error);
|
|
176
|
-
throw error;
|
|
177
|
-
}
|
|
152
|
+
await client.http.request('post', `/tools/${toolInvocationId}/reject`, { data: { reason } });
|
|
178
153
|
}
|
|
179
|
-
/**
|
|
180
|
-
* Always allow a tool for this chat
|
|
181
|
-
*/
|
|
182
154
|
export async function alwaysAllowTool(client, chatId, toolInvocationId, toolName) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
console.error('[AgentSDK] Failed to always-allow tool:', error);
|
|
190
|
-
throw error;
|
|
191
|
-
}
|
|
155
|
+
await client.http.request('post', `/chats/${chatId}/tools/${toolInvocationId}/always-allow`, {
|
|
156
|
+
data: { tool_name: toolName }
|
|
157
|
+
});
|
|
192
158
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
159
|
+
// =========================================================================
|
|
160
|
+
// Interrupt operations
|
|
161
|
+
// =========================================================================
|
|
162
|
+
export async function resolveInterrupt(client, interruptId, decision) {
|
|
163
|
+
const resp = await client.http.request('post', `/interrupts/${interruptId}/resolve`, {
|
|
164
|
+
data: { decision }
|
|
165
|
+
});
|
|
166
|
+
return resp.data;
|
|
167
|
+
}
|
|
168
|
+
export async function listRunInterrupts(client, runId) {
|
|
169
|
+
const resp = await client.http.request('get', `/agent-runs/${runId}/interrupts`);
|
|
170
|
+
return resp.data;
|
|
171
|
+
}
|
|
172
|
+
// =========================================================================
|
|
173
|
+
// File & stream operations
|
|
174
|
+
// =========================================================================
|
|
196
175
|
export async function uploadFile(client, file) {
|
|
197
|
-
|
|
198
|
-
return result;
|
|
176
|
+
return client.files.upload(file);
|
|
199
177
|
}
|
|
200
|
-
/**
|
|
201
|
-
* Get streamable config for chat streaming (NDJSON)
|
|
202
|
-
*/
|
|
203
178
|
export function getChatStreamConfig(client, chatId) {
|
|
204
179
|
return client.http.getStreamableConfig(`/chats/${chatId}/stream`);
|
|
205
180
|
}
|