@inferencesh/sdk 0.6.7 → 0.6.8

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
+ ### Added
11
+
12
+ - Typed SDK constants for integrations: `IntegrationProvider*`, `IntegrationAuthType*`, `IntegrationStatus*`
13
+ - `IntegrationDTO` fields (`provider`, `type`, `auth`, `status`) now use those typed aliases
14
+ - Additional `InstanceStatus*` constants (`creating`, `pending_provider`, `error`, `deleting`)
15
+ - `ToolParamType*` constants for JSON Schema tool parameter types (distinct from `ToolCallType`)
16
+
17
+ ## [0.6.7] - 2026-05-19
18
+
19
+ ### Added
20
+
21
+ - `client.sessions` API: `get`, `list`, `keepalive`, and `end` for session lifecycle management
22
+ - Session error types: `SessionNotFoundError`, `SessionExpiredError`, `SessionEndedError`
23
+ - Agent chat: `sendMessage` file attachments (upload `Blob` or reuse uploaded file `uri`)
24
+ - Agent lifecycle: `stopChat()`, `reset()`, and `agent.run()` for structured output via polling
25
+ - Task streaming: `onPartialUpdate` callback for partial NDJSON stream payloads
26
+ - Client config: `stream` and `pollIntervalMs` for global streaming vs status polling
27
+
28
+ ### Changed
29
+
30
+ - README documents ad-hoc agent field names (`core_app`, `system_prompt`) and tool builder API
31
+ - Polling mode: `run()` rejects if full task fetch fails after a status transition
32
+
10
33
  ## [0.1.1] - 2024-11-30
11
34
 
12
35
  ### Added
@@ -42,6 +65,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
42
65
  - Configurable reconnection behavior
43
66
  - Comprehensive error handling
44
67
 
45
- [Unreleased]: https://github.com/inference-sh/sdk-js/compare/v0.1.0...HEAD
68
+ [Unreleased]: https://github.com/inference-sh/sdk-js/compare/v0.6.7...HEAD
69
+ [0.6.7]: https://github.com/inference-sh/sdk-js/compare/v0.6.6...v0.6.7
70
+ [0.1.1]: https://github.com/inference-sh/sdk-js/compare/v0.1.0...v0.1.1
46
71
  [0.1.0]: https://github.com/inference-sh/sdk-js/releases/tag/v0.1.0
47
72
 
package/README.md CHANGED
@@ -90,18 +90,43 @@ console.log('Status:', task.status);
90
90
 
91
91
  ### Real-time Status Updates
92
92
 
93
+ By default, the client streams task progress over NDJSON (`/tasks/{id}/stream`) and invokes `onUpdate` as the task changes. Use `onPartialUpdate` when you only need specific fields from a partial stream payload:
94
+
93
95
  ```typescript
94
- const result = await client.tasks.run(
96
+ const result = await client.run(
95
97
  { app: 'my-app', input: { prompt: 'hello' } },
96
98
  {
97
99
  onUpdate: (update) => {
98
100
  console.log('Status:', update.status);
99
101
  console.log('Progress:', update.logs);
100
- }
102
+ },
103
+ onPartialUpdate: (update, fields) => {
104
+ console.log('Changed fields:', fields, update.status);
105
+ },
101
106
  }
102
107
  );
103
108
  ```
104
109
 
110
+ ### Streaming vs Polling
111
+
112
+ SSE/NDJSON streaming is the default. For edge runtimes that cannot keep long-lived connections open (Convex actions, Cloudflare Workers, etc.), disable streaming and use lightweight status polling instead:
113
+
114
+ ```typescript
115
+ const client = inference({
116
+ apiKey: 'your-api-key',
117
+ stream: false, // poll /tasks/{id}/status instead of streaming
118
+ pollIntervalMs: 2000, // default: 2000
119
+ });
120
+
121
+ // Per-call override
122
+ const result = await client.run(
123
+ { app: 'my-app', input: { prompt: 'hello' } },
124
+ { stream: false, onUpdate: (u) => console.log(u.status) }
125
+ );
126
+ ```
127
+
128
+ In polling mode, the SDK checks `/tasks/{id}/status` and fetches the full task when the status changes. If that fetch fails after a status transition, `run()` rejects with the underlying error.
129
+
105
130
  ### Batch Processing
106
131
 
107
132
  ```typescript
@@ -196,6 +221,58 @@ const result = await client.tasks.run({
196
221
  - Maximum timeout: 3600 seconds (1 hour)
197
222
  - Each successful call resets the idle timer
198
223
 
224
+ #### Session management API
225
+
226
+ Manage sessions directly without running a task:
227
+
228
+ ```typescript
229
+ // Inspect a session
230
+ const info = await client.sessions.get(sessionId);
231
+ console.log(info.status, info.expires_at, info.call_count);
232
+
233
+ // List active sessions
234
+ const sessions = await client.sessions.list();
235
+
236
+ // Extend idle timeout without a task call (sliding window)
237
+ await client.sessions.keepalive(sessionId);
238
+
239
+ // Release the worker immediately
240
+ await client.sessions.end(sessionId);
241
+ ```
242
+
243
+ #### Session errors
244
+
245
+ ```typescript
246
+ import {
247
+ SessionNotFoundError,
248
+ SessionExpiredError,
249
+ SessionEndedError,
250
+ } from '@inferencesh/sdk';
251
+
252
+ try {
253
+ await client.tasks.run({
254
+ app: 'my-stateful-app',
255
+ input: { prompt: 'hello' },
256
+ session: sessionId,
257
+ });
258
+ } catch (error) {
259
+ if (
260
+ error instanceof SessionNotFoundError ||
261
+ error instanceof SessionExpiredError ||
262
+ error instanceof SessionEndedError
263
+ ) {
264
+ // Start a new session and retry
265
+ const result = await client.tasks.run({
266
+ app: 'my-stateful-app',
267
+ input: { prompt: 'hello' },
268
+ session: 'new',
269
+ });
270
+ } else {
271
+ throw error;
272
+ }
273
+ }
274
+ ```
275
+
199
276
  For complete session documentation including error handling, best practices, and advanced patterns, see the [Sessions Developer Guide](https://inference.sh/docs/extend/sessions).
200
277
 
201
278
  ## Agent Chat
@@ -240,27 +317,42 @@ import { inference, tool, string } from '@inferencesh/sdk';
240
317
 
241
318
  const client = inference({ apiKey: 'your-api-key' });
242
319
 
243
- // Create ad-hoc agent
320
+ // Create ad-hoc agent (config uses API field names: core_app, system_prompt)
321
+ const weatherTool = tool('get_weather')
322
+ .describe('Get current weather')
323
+ .param('city', string('City name'))
324
+ .build();
325
+
244
326
  const agent = client.agents.create({
245
- coreApp: 'infsh/claude-sonnet-4@abc123', // LLM to use
246
- systemPrompt: 'You are a helpful assistant.',
247
- tools: [
248
- tool('get_weather')
249
- .description('Get current weather')
250
- .params({ city: string('City name') })
251
- .handler(async (args) => {
252
- // Your tool logic here
253
- return JSON.stringify({ temp: 72, conditions: 'sunny' });
254
- })
255
- .build()
256
- ]
327
+ core_app: { ref: 'infsh/claude-sonnet-4@abc123' },
328
+ system_prompt: 'You are a helpful assistant.',
329
+ tools: [weatherTool], // only schemas are sent to the API; handlers stay client-side
257
330
  });
258
331
 
259
332
  await agent.sendMessage('What is the weather in Paris?', {
260
333
  onMessage: (msg) => console.log(msg),
261
334
  onToolCall: async (call) => {
262
- // Tool handlers are auto-executed if defined
263
- }
335
+ const result = await runMyClientTool(call.name, call.args);
336
+ await agent.submitToolResult(call.id, result);
337
+ },
338
+ });
339
+ ```
340
+
341
+ For multi-turn chats, the SDK opens the chat stream before sending the next message so updates are not missed. Use `stopChat()` to cancel in-flight generation (`POST /chats/{id}/stop`), and `reset()` to clear the current chat and start fresh.
342
+
343
+ ### File attachments
344
+
345
+ Pass files in `sendMessage` options. `Blob` values are uploaded first; objects with a `uri` (already uploaded via `client.files.upload`) are attached as-is:
346
+
347
+ ```typescript
348
+ const uploaded = await client.files.upload(imageBlob, {
349
+ filename: 'photo.png',
350
+ contentType: 'image/png',
351
+ });
352
+
353
+ await agent.sendMessage('Describe this image', {
354
+ files: [imageBlob, uploaded], // Blob uploads; FileDTO reuses uri
355
+ onMessage: (msg) => console.log(msg),
264
356
  });
265
357
  ```
266
358
 
@@ -283,21 +375,23 @@ const agent = client.agents.create({
283
375
  internal_tools: { finish: true },
284
376
  });
285
377
 
286
- const response = await agent.sendMessage('Analyze: Great product!');
378
+ const output = await agent.run('Analyze: Great product!');
287
379
  ```
288
380
 
381
+ `agent.run()` sends a message with polling (no SSE), waits until the chat is idle, and returns `chat.output` (parsed finish-tool result, or `null` if none).
382
+
289
383
  ### Agent Methods
290
384
 
291
385
  | Method | Description |
292
386
  |--------|-------------|
293
- | `sendMessage(text, options?)` | Send a message to the agent |
294
- | `getChat(chatId?)` | Get chat history |
295
- | `stopChat(chatId?)` | Stop current generation |
296
- | `submitToolResult(toolId, resultOrAction)` | Submit result for a client tool (string or {action, form_data}) |
297
- | `streamMessages(chatId?, options?)` | Stream message updates |
298
- | `streamChat(chatId?, options?)` | Stream chat updates |
299
- | `disconnect()` | Clean up streams |
300
- | `reset()` | Start a new conversation |
387
+ | `sendMessage(text, options?)` | Send a message; streams or polls until idle when callbacks or `stream: false` |
388
+ | `run(text, options?)` | Send and return structured `chat.output` (always uses polling) |
389
+ | `getChat(chatId?)` | Get the current or specified chat (`chat_messages` on the returned chat) |
390
+ | `stopChat()` | Stop generation for the current chat (no-op if no active chat) |
391
+ | `submitToolResult(toolId, resultOrAction)` | Submit result for a client tool (string or `{action, form_data}`) |
392
+ | `startStreaming(options?)` | Manually attach to `/chats/{id}/stream` for the current chat |
393
+ | `disconnect()` | Stop active stream/poll connections |
394
+ | `reset()` | Disconnect and clear chat state so the next message starts a new chat |
301
395
 
302
396
  ## API Reference
303
397
 
@@ -309,6 +403,9 @@ Creates a new inference client.
309
403
  |-----------|------|----------|-------------|
310
404
  | `config.apiKey` | `string` | Yes | Your inference.sh API key |
311
405
  | `config.baseUrl` | `string` | No | Custom API URL (default: `https://api.inference.sh`) |
406
+ | `config.stream` | `boolean` | No | Use NDJSON streaming (`true`, default) or status polling (`false`) |
407
+ | `config.pollIntervalMs` | `number` | No | Poll interval when `stream: false` (default: `2000`) |
408
+ | `config.proxyUrl` | `string` | No | Proxy base URL for frontend apps (keeps API keys server-side) |
312
409
 
313
410
  ### `client.tasks.run(params, options?)`
314
411
 
@@ -331,10 +428,11 @@ Runs a task on inference.sh.
331
428
  | Option | Type | Default | Description |
332
429
  |--------|------|---------|-------------|
333
430
  | `wait` | `boolean` | `true` | Wait for task completion |
334
- | `onUpdate` | `function` | - | Callback for status updates |
335
- | `autoReconnect` | `boolean` | `true` | Auto-reconnect on connection loss |
336
- | `maxReconnects` | `number` | `5` | Max reconnection attempts |
337
- | `reconnectDelayMs` | `number` | `1000` | Delay between reconnects (ms) |
431
+ | `stream` | `boolean` | client default | Use NDJSON streaming or status polling |
432
+ | `pollIntervalMs` | `number` | client default | Poll interval when `stream: false` |
433
+ | `onUpdate` | `function` | - | Callback for task updates (full fetch on status change when polling) |
434
+ | `onPartialUpdate` | `function` | - | Callback for partial NDJSON stream updates `(task, fields)` |
435
+ | `maxReconnects` | `number` | `5` | Max poll retries when `stream: false` |
338
436
 
339
437
  ### `client.tasks.get(taskId)`
340
438
 
@@ -357,9 +455,11 @@ Uploads a file to inference.sh.
357
455
  | `options.contentType` | `string` | MIME type |
358
456
  | `options.public` | `boolean` | Make file publicly accessible |
359
457
 
360
- ### `client.agents.create(templateOrConfig)`
458
+ ### `client.agents.create(templateOrConfig)` / `client.agent(...)`
459
+
460
+ Creates an agent instance from a template or ad-hoc configuration. `client.agent(...)` is an alias for `client.agents.create(...)`.
361
461
 
362
- Creates an agent instance from a template or ad-hoc configuration.
462
+ **`sendMessage` options:** `onMessage`, `onChat`, `onToolCall`, `files`, `stream`, `pollIntervalMs`. Client tools with status `awaiting_input` are dispatched once per invocation ID via `onToolCall`.
363
463
 
364
464
  **Template mode:**
365
465
  ```typescript
@@ -369,12 +469,21 @@ const agent = client.agents.create('namespace/name@version');
369
469
  **Ad-hoc mode:**
370
470
  ```typescript
371
471
  const agent = client.agents.create({
372
- coreApp: 'infsh/claude-sonnet-4@abc123',
373
- systemPrompt: 'You are helpful.',
374
- tools: [...]
472
+ core_app: { ref: 'infsh/claude-sonnet-4@abc123' },
473
+ system_prompt: 'You are helpful.',
474
+ tools: [...],
375
475
  });
376
476
  ```
377
477
 
478
+ ### `client.sessions`
479
+
480
+ | Method | HTTP | Description |
481
+ |--------|------|-------------|
482
+ | `get(sessionId)` | `GET /sessions/{id}` | Session metadata (`status`, `expires_at`, `call_count`, …) |
483
+ | `list()` | `GET /sessions` | All sessions (empty array if none) |
484
+ | `keepalive(sessionId)` | `POST /sessions/{id}/keepalive` | Reset idle expiration |
485
+ | `end(sessionId)` | `DELETE /sessions/{id}` | End session and release worker |
486
+
378
487
  ## Task Status Constants
379
488
 
380
489
  ```typescript
@@ -391,12 +500,103 @@ if (task.status === TaskStatusCompleted) {
391
500
  }
392
501
  ```
393
502
 
503
+ ## Integration Constants
504
+
505
+ `IntegrationDTO` fields (`provider`, `type`, `auth`, `status`) use typed string unions exported as constants:
506
+
507
+ ```typescript
508
+ import type { IntegrationDTO } from '@inferencesh/sdk';
509
+ import {
510
+ IntegrationProviderGoogle,
511
+ IntegrationAuthTypeOAuth,
512
+ IntegrationStatusConnected,
513
+ IntegrationStatusDisconnected,
514
+ IntegrationStatusExpired,
515
+ IntegrationStatusError,
516
+ isRequirementsNotMetException,
517
+ } from '@inferencesh/sdk';
518
+
519
+ function isGoogleConnected(integration: IntegrationDTO): boolean {
520
+ return (
521
+ integration.provider === IntegrationProviderGoogle &&
522
+ integration.status === IntegrationStatusConnected
523
+ );
524
+ }
525
+
526
+ // HTTP 412 when an app requires a missing secret, integration, or scope
527
+ try {
528
+ await client.run({ app: 'my-app', input: {} });
529
+ } catch (error) {
530
+ if (isRequirementsNotMetException(error)) {
531
+ for (const req of error.errors) {
532
+ if (req.type === 'integration' && req.action?.provider === IntegrationProviderGoogle) {
533
+ // User must connect Google — see https://inference.sh/docs/extend/integrations
534
+ }
535
+ }
536
+ }
537
+ }
538
+ ```
539
+
540
+ | Constant group | Values |
541
+ |----------------|--------|
542
+ | `IntegrationProvider*` | `google`, `slack`, `notion`, `github`, `x`, `microsoft`, `salesforce`, `discord`, `gcp`, `mcp`, `reddit` |
543
+ | `IntegrationAuthType*` | `service_account`, `oauth`, `api_key`, `wif`, `mcp` |
544
+ | `IntegrationStatus*` | `connected`, `disconnected`, `expired`, `error` |
545
+
546
+ ## Instance Status Constants
547
+
548
+ Use when working with engine instance APIs (`InstanceDTO.status`):
549
+
550
+ ```typescript
551
+ import {
552
+ InstanceStatusCreating,
553
+ InstanceStatusPendingProvider,
554
+ InstanceStatusPending,
555
+ InstanceStatusActive,
556
+ InstanceStatusError,
557
+ InstanceStatusDeleting,
558
+ InstanceStatusDeleted,
559
+ } from '@inferencesh/sdk';
560
+ ```
561
+
562
+ ## Tool Parameter Types
563
+
564
+ When building `AgentTool` schemas manually (outside the tool builder), use `ToolParamType*` for JSON Schema `type` fields:
565
+
566
+ ```typescript
567
+ import {
568
+ ToolParamTypeObject,
569
+ ToolParamTypeString,
570
+ ToolParamTypeInteger,
571
+ ToolParamTypeNumber,
572
+ ToolParamTypeBoolean,
573
+ ToolParamTypeArray,
574
+ ToolParamTypeNull,
575
+ } from '@inferencesh/sdk';
576
+
577
+ const schema = {
578
+ type: ToolParamTypeObject,
579
+ properties: {
580
+ city: { type: ToolParamTypeString, description: 'City name' },
581
+ },
582
+ required: ['city'],
583
+ };
584
+ ```
585
+
586
+ The fluent tool builder (`string()`, `number()`, `object()`, …) infers these types automatically.
587
+
394
588
  ## TypeScript Support
395
589
 
396
590
  This SDK is written in TypeScript and includes full type definitions. All types are exported:
397
591
 
398
592
  ```typescript
399
- import type { Task, ApiTaskRequest, RunOptions } from '@inferencesh/sdk';
593
+ import type {
594
+ Task,
595
+ ApiAppRunRequest,
596
+ RunOptions,
597
+ IntegrationDTO,
598
+ AgentTool,
599
+ } from '@inferencesh/sdk';
400
600
  ```
401
601
 
402
602
  ## Requirements
@@ -0,0 +1 @@
1
+ export {};