@inferencesh/sdk 0.1.3 → 0.2.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/dist/client.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.inference = exports.Inference = void 0;
3
+ exports.Agent = exports.Inference = void 0;
4
+ exports.inference = inference;
4
5
  const types_1 = require("./types");
5
6
  const stream_1 = require("./stream");
6
7
  const eventsource_1 = require("eventsource");
@@ -22,7 +23,8 @@ class Inference {
22
23
  this.apiKey = config.apiKey;
23
24
  this.baseUrl = config.baseUrl || "https://api.inference.sh";
24
25
  }
25
- async request(method, endpoint, options = {}) {
26
+ /** @internal */
27
+ async _request(method, endpoint, options = {}) {
26
28
  const url = new URL(`${this.baseUrl}${endpoint}`);
27
29
  if (options.params) {
28
30
  Object.entries(options.params).forEach(([key, value]) => {
@@ -84,7 +86,8 @@ class Inference {
84
86
  }
85
87
  return apiResponse.data;
86
88
  }
87
- createEventSource(endpoint) {
89
+ /** @internal */
90
+ _createEventSource(endpoint) {
88
91
  const url = new URL(`${this.baseUrl}${endpoint}`);
89
92
  return new eventsource_1.EventSource(url.toString(), {
90
93
  fetch: (input, init) => fetch(input, {
@@ -147,26 +150,37 @@ class Inference {
147
150
  * @param options - Run options for waiting, updates, and reconnection
148
151
  * @returns The completed task result
149
152
  *
153
+ * App reference format: `namespace/name@shortid` (version is required)
154
+ *
155
+ * The short ID ensures your code always runs the same version,
156
+ * protecting against breaking changes from app updates.
157
+ *
150
158
  * @example
151
159
  * ```typescript
152
- * // Simple usage - wait for result
153
- * const result = await client.run({ app: 'my-app', input: { prompt: 'hello' } });
160
+ * // Run a specific version (required)
161
+ * const result = await client.run({
162
+ * app: 'okaris/flux@abc1', // version @abc1 is pinned
163
+ * input: { prompt: 'hello' }
164
+ * });
154
165
  *
155
166
  * // With status updates
156
167
  * const result = await client.run(
157
- * { app: 'my-app', input: { prompt: 'hello' } },
168
+ * { app: 'okaris/flux@abc1', input: { prompt: 'hello' } },
158
169
  * { onUpdate: (update) => console.log(update.status) }
159
170
  * );
160
171
  *
161
172
  * // Fire and forget
162
- * const task = await client.run({ app: 'my-app', input: {} }, { wait: false });
173
+ * const task = await client.run(
174
+ * { app: 'okaris/flux@abc1', input: {} },
175
+ * { wait: false }
176
+ * );
163
177
  * ```
164
178
  */
165
179
  async run(params, options = {}) {
166
180
  const { onUpdate, onPartialUpdate, wait = true, autoReconnect = true, maxReconnects = 5, reconnectDelayMs = 1000, } = options;
167
181
  // Process input data and upload any files
168
182
  const processedInput = await this.processInputData(params.input);
169
- const task = await this.request("post", "/run", {
183
+ const task = await this._request("post", "/apps/run", {
170
184
  data: {
171
185
  ...params,
172
186
  input: processedInput
@@ -179,7 +193,7 @@ class Inference {
179
193
  // Wait for completion with optional updates
180
194
  return new Promise((resolve, reject) => {
181
195
  const streamManager = new stream_1.StreamManager({
182
- createEventSource: async () => this.createEventSource(`/tasks/${task.id}/stream`),
196
+ createEventSource: async () => this._createEventSource(`/tasks/${task.id}/stream`),
183
197
  autoReconnect,
184
198
  maxReconnects,
185
199
  reconnectDelayMs,
@@ -224,7 +238,7 @@ class Inference {
224
238
  path: options.path,
225
239
  size: data instanceof Blob ? data.size : undefined,
226
240
  };
227
- const response = await this.request("post", "/files", {
241
+ const response = await this._request("post", "/files", {
228
242
  data: {
229
243
  files: [fileRequest]
230
244
  }
@@ -281,11 +295,159 @@ class Inference {
281
295
  * @param taskId - The ID of the task to cancel
282
296
  */
283
297
  async cancel(taskId) {
284
- return this.request("post", `/tasks/${taskId}/cancel`);
298
+ return this._request("post", `/tasks/${taskId}/cancel`);
299
+ }
300
+ /**
301
+ * Create an agent for chat interactions
302
+ *
303
+ * @param config - Either a template reference string (namespace/name@version) or ad-hoc config
304
+ * @returns An Agent instance for chat operations
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * // Template agent
309
+ * const agent = client.agent('okaris/assistant@abc123')
310
+ *
311
+ * // Ad-hoc agent
312
+ * const agent = client.agent({
313
+ * coreApp: 'infsh/claude-sonnet-4@xyz789',
314
+ * systemPrompt: 'You are a helpful assistant',
315
+ * tools: [...]
316
+ * })
317
+ *
318
+ * // Send messages
319
+ * const response = await agent.sendMessage('Hello!')
320
+ * ```
321
+ */
322
+ agent(config) {
323
+ return new Agent(this, config);
285
324
  }
286
325
  }
287
326
  exports.Inference = Inference;
327
+ // =============================================================================
328
+ // Agent Class
329
+ // =============================================================================
330
+ /**
331
+ * Agent for chat interactions
332
+ *
333
+ * Created via `client.agent()` - do not instantiate directly.
334
+ */
335
+ class Agent {
336
+ /** @internal */
337
+ constructor(client, config) {
338
+ this.chatId = null;
339
+ this.stream = null;
340
+ this.client = client;
341
+ this.config = config;
342
+ }
343
+ /** Get current chat ID */
344
+ get currentChatId() {
345
+ return this.chatId;
346
+ }
347
+ /** Send a message to the agent */
348
+ async sendMessage(text, options = {}) {
349
+ const isTemplate = typeof this.config === 'string';
350
+ // Upload files if provided
351
+ let imageUri;
352
+ let fileUris;
353
+ if (options.files && options.files.length > 0) {
354
+ const uploadedFiles = await Promise.all(options.files.map(f => this.client.uploadFile(f)));
355
+ const images = uploadedFiles.filter(f => f.content_type?.startsWith('image/'));
356
+ const others = uploadedFiles.filter(f => !f.content_type?.startsWith('image/'));
357
+ if (images.length > 0)
358
+ imageUri = images[0].uri;
359
+ if (others.length > 0)
360
+ fileUris = others.map(f => f.uri);
361
+ }
362
+ const body = isTemplate
363
+ ? {
364
+ chat_id: this.chatId,
365
+ agent: this.config,
366
+ input: { text, image: imageUri, files: fileUris, role: 'user', context: [], system_prompt: '', context_size: 0 },
367
+ }
368
+ : {
369
+ chat_id: this.chatId,
370
+ core_app: this.config.coreApp,
371
+ core_app_input: this.config.coreAppInput,
372
+ name: this.config.name,
373
+ system_prompt: this.config.systemPrompt,
374
+ tools: this.config.tools,
375
+ internal_tools: this.config.internalTools,
376
+ input: { text, image: imageUri, files: fileUris, role: 'user', context: [], system_prompt: '', context_size: 0 },
377
+ };
378
+ const response = await this.client._request('post', '/agents/run', { data: body });
379
+ if (!this.chatId && response.assistant_message.chat_id) {
380
+ this.chatId = response.assistant_message.chat_id;
381
+ this.startStreaming(options);
382
+ }
383
+ return response.assistant_message;
384
+ }
385
+ /** Get chat by ID */
386
+ async getChat(chatId) {
387
+ const id = chatId || this.chatId;
388
+ if (!id)
389
+ return null;
390
+ return this.client._request('get', `/chats/${id}`);
391
+ }
392
+ /** Stop the current chat generation */
393
+ async stopChat() {
394
+ if (!this.chatId)
395
+ return;
396
+ await this.client._request('post', `/chats/${this.chatId}/stop`);
397
+ }
398
+ /** Submit a tool result */
399
+ async submitToolResult(toolInvocationId, result) {
400
+ if (!this.chatId)
401
+ throw new Error('No active chat');
402
+ await this.client._request('post', `/chats/${this.chatId}/tool-result`, {
403
+ data: { tool_invocation_id: toolInvocationId, result },
404
+ });
405
+ }
406
+ /** Stop streaming and cleanup */
407
+ disconnect() {
408
+ this.stream?.stop();
409
+ this.stream = null;
410
+ }
411
+ /** Reset the agent (start fresh chat) */
412
+ reset() {
413
+ this.disconnect();
414
+ this.chatId = null;
415
+ }
416
+ startStreaming(options) {
417
+ if (!this.chatId)
418
+ return;
419
+ this.stream = new stream_1.StreamManager({
420
+ createEventSource: async () => this.client._createEventSource(`/chats/${this.chatId}/stream`),
421
+ autoReconnect: true,
422
+ });
423
+ this.stream.addEventListener('chats', (chat) => {
424
+ options.onChat?.(chat);
425
+ });
426
+ this.stream.addEventListener('chat_messages', (message) => {
427
+ options.onMessage?.(message);
428
+ if (message.tool_invocations && options.onToolCall) {
429
+ for (const inv of message.tool_invocations) {
430
+ if (inv.type === types_1.ToolTypeClient && inv.status === types_1.ToolInvocationStatusAwaitingInput) {
431
+ options.onToolCall({
432
+ id: inv.id,
433
+ name: inv.function?.name || '',
434
+ args: inv.function?.arguments || {},
435
+ });
436
+ }
437
+ }
438
+ }
439
+ });
440
+ this.stream.connect();
441
+ }
442
+ }
443
+ exports.Agent = Agent;
288
444
  /**
289
- * @deprecated Use `Inference` instead. Will be removed in v1.0.0
445
+ * Factory function for creating an Inference client (lowercase for branding)
446
+ * @example
447
+ * ```typescript
448
+ * const client = inference({ apiKey: 'your-api-key' });
449
+ * ```
290
450
  */
291
- exports.inference = Inference;
451
+ function inference(config) {
452
+ return new Inference(config);
453
+ }
@@ -155,12 +155,12 @@ describe('Inference', () => {
155
155
  expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('/tasks/task-123/cancel'), expect.objectContaining({ method: 'POST' }));
156
156
  });
157
157
  });
158
- describe('backward compatibility', () => {
159
- it('should export lowercase inference as alias', () => {
160
- expect(client_1.inference).toBe(client_1.Inference);
158
+ describe('lowercase factory', () => {
159
+ it('should export lowercase inference factory', () => {
160
+ expect(typeof client_1.inference).toBe('function');
161
161
  });
162
- it('should work with lowercase inference', () => {
163
- const client = new client_1.inference({ apiKey: 'test-api-key' });
162
+ it('should work with lowercase inference factory', () => {
163
+ const client = (0, client_1.inference)({ apiKey: 'test-api-key' });
164
164
  expect(client).toBeInstanceOf(client_1.Inference);
165
165
  });
166
166
  });
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- export { Inference, inference, InferenceConfig, RunOptions, UploadFileOptions } from './client';
1
+ export { Inference, inference, InferenceConfig, RunOptions, UploadFileOptions, Agent, AdHocAgentConfig, SendMessageOptions, } from './client';
2
+ export { AgentConfig, AdHocAgentOptions, TemplateAgentOptions, AgentOptions, } from './agent';
3
+ export { tool, appTool, agentTool, webhookTool, internalTools, string, number, integer, boolean, enumOf, object, array, optional } from './tool-builder';
2
4
  export { StreamManager, PartialDataWrapper } from './stream';
3
5
  export { InferenceError, RequirementsNotMetException } from './errors';
4
6
  export * from './types';
package/dist/index.js CHANGED
@@ -14,11 +14,27 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.RequirementsNotMetException = exports.InferenceError = exports.StreamManager = exports.inference = exports.Inference = void 0;
18
- // Main client export
17
+ exports.RequirementsNotMetException = exports.InferenceError = exports.StreamManager = exports.optional = exports.array = exports.object = exports.enumOf = exports.boolean = exports.integer = exports.number = exports.string = exports.internalTools = exports.webhookTool = exports.agentTool = exports.appTool = exports.tool = exports.Agent = exports.inference = exports.Inference = void 0;
18
+ // Main client export (includes Agent)
19
19
  var client_1 = require("./client");
20
20
  Object.defineProperty(exports, "Inference", { enumerable: true, get: function () { return client_1.Inference; } });
21
21
  Object.defineProperty(exports, "inference", { enumerable: true, get: function () { return client_1.inference; } });
22
+ Object.defineProperty(exports, "Agent", { enumerable: true, get: function () { return client_1.Agent; } });
23
+ // Tool Builder (fluent API)
24
+ var tool_builder_1 = require("./tool-builder");
25
+ Object.defineProperty(exports, "tool", { enumerable: true, get: function () { return tool_builder_1.tool; } });
26
+ Object.defineProperty(exports, "appTool", { enumerable: true, get: function () { return tool_builder_1.appTool; } });
27
+ Object.defineProperty(exports, "agentTool", { enumerable: true, get: function () { return tool_builder_1.agentTool; } });
28
+ Object.defineProperty(exports, "webhookTool", { enumerable: true, get: function () { return tool_builder_1.webhookTool; } });
29
+ Object.defineProperty(exports, "internalTools", { enumerable: true, get: function () { return tool_builder_1.internalTools; } });
30
+ Object.defineProperty(exports, "string", { enumerable: true, get: function () { return tool_builder_1.string; } });
31
+ Object.defineProperty(exports, "number", { enumerable: true, get: function () { return tool_builder_1.number; } });
32
+ Object.defineProperty(exports, "integer", { enumerable: true, get: function () { return tool_builder_1.integer; } });
33
+ Object.defineProperty(exports, "boolean", { enumerable: true, get: function () { return tool_builder_1.boolean; } });
34
+ Object.defineProperty(exports, "enumOf", { enumerable: true, get: function () { return tool_builder_1.enumOf; } });
35
+ Object.defineProperty(exports, "object", { enumerable: true, get: function () { return tool_builder_1.object; } });
36
+ Object.defineProperty(exports, "array", { enumerable: true, get: function () { return tool_builder_1.array; } });
37
+ Object.defineProperty(exports, "optional", { enumerable: true, get: function () { return tool_builder_1.optional; } });
22
38
  // Stream utilities
23
39
  var stream_1 = require("./stream");
24
40
  Object.defineProperty(exports, "StreamManager", { enumerable: true, get: function () { return stream_1.StreamManager; } });
package/dist/stream.d.ts CHANGED
@@ -24,7 +24,15 @@ export declare class StreamManager<T> {
24
24
  private initialConnectionAttempts;
25
25
  private isConnected;
26
26
  private isStopped;
27
+ private eventListeners;
27
28
  constructor(options: StreamManagerOptions<T>);
29
+ /**
30
+ * Add a listener for typed SSE events (e.g., 'chats', 'chat_messages')
31
+ * Used when server sends events with `event: eventName` header
32
+ */
33
+ addEventListener<E = unknown>(eventName: string, callback: (data: E) => void): () => void;
34
+ private setupEventListener;
35
+ private setupAllEventListeners;
28
36
  private clearTimeouts;
29
37
  private closeEventSource;
30
38
  private cleanup;
package/dist/stream.js CHANGED
@@ -20,6 +20,7 @@ class StreamManager {
20
20
  this.initialConnectionAttempts = 0;
21
21
  this.isConnected = false;
22
22
  this.isStopped = false;
23
+ this.eventListeners = new Map();
23
24
  this.options = {
24
25
  autoReconnect: true,
25
26
  maxReconnects: 5,
@@ -27,6 +28,51 @@ class StreamManager {
27
28
  ...options,
28
29
  };
29
30
  }
31
+ /**
32
+ * Add a listener for typed SSE events (e.g., 'chats', 'chat_messages')
33
+ * Used when server sends events with `event: eventName` header
34
+ */
35
+ addEventListener(eventName, callback) {
36
+ const listeners = this.eventListeners.get(eventName) || new Set();
37
+ listeners.add(callback);
38
+ this.eventListeners.set(eventName, listeners);
39
+ // If already connected, set up the listener on the existing EventSource
40
+ if (this.eventSource) {
41
+ this.setupEventListener(this.eventSource, eventName);
42
+ }
43
+ // Return cleanup function
44
+ return () => {
45
+ const listeners = this.eventListeners.get(eventName);
46
+ if (listeners) {
47
+ listeners.delete(callback);
48
+ if (listeners.size === 0) {
49
+ this.eventListeners.delete(eventName);
50
+ }
51
+ }
52
+ };
53
+ }
54
+ setupEventListener(source, eventName) {
55
+ source.addEventListener(eventName, (e) => {
56
+ if (this.isStopped)
57
+ return;
58
+ try {
59
+ const data = JSON.parse(e.data);
60
+ const listeners = this.eventListeners.get(eventName);
61
+ if (listeners?.size) {
62
+ listeners.forEach(callback => callback(data));
63
+ }
64
+ }
65
+ catch (err) {
66
+ const error = err instanceof Error ? err : new Error('Invalid JSON');
67
+ this.options.onError?.(error);
68
+ }
69
+ });
70
+ }
71
+ setupAllEventListeners(source) {
72
+ this.eventListeners.forEach((_, eventName) => {
73
+ this.setupEventListener(source, eventName);
74
+ });
75
+ }
30
76
  clearTimeouts() {
31
77
  if (this.reconnectTimeout) {
32
78
  clearTimeout(this.reconnectTimeout);
@@ -93,6 +139,8 @@ class StreamManager {
93
139
  this.eventSource = source;
94
140
  this.isConnected = true;
95
141
  this.options.onStart?.();
142
+ // Set up typed event listeners (for events with `event: eventName` header)
143
+ this.setupAllEventListeners(source);
96
144
  source.onmessage = (e) => {
97
145
  if (this.isStopped)
98
146
  return;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Tool Builder - Fluent API for defining agent tools
3
+ */
4
+ import { AgentTool, InternalToolsConfig } from './types';
5
+ type JsonSchemaType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
6
+ interface ParamSchema {
7
+ type: JsonSchemaType;
8
+ description?: string;
9
+ optional?: boolean;
10
+ enum?: string[];
11
+ properties?: Record<string, ParamSchema>;
12
+ items?: ParamSchema;
13
+ }
14
+ export declare const string: (description?: string) => ParamSchema;
15
+ export declare const number: (description?: string) => ParamSchema;
16
+ export declare const integer: (description?: string) => ParamSchema;
17
+ export declare const boolean: (description?: string) => ParamSchema;
18
+ export declare const enumOf: (values: string[], description?: string) => ParamSchema;
19
+ export declare const object: (properties: Record<string, ParamSchema>, description?: string) => ParamSchema;
20
+ export declare const array: (items: ParamSchema, description?: string) => ParamSchema;
21
+ export declare const optional: <T extends ParamSchema>(schema: T) => T & {
22
+ optional: true;
23
+ };
24
+ declare class ToolBuilder {
25
+ protected name: string;
26
+ protected desc: string;
27
+ protected displayName?: string;
28
+ protected params: Record<string, ParamSchema>;
29
+ protected approval: boolean;
30
+ constructor(name: string);
31
+ describe(description: string): this;
32
+ display(name: string): this;
33
+ param(name: string, schema: ParamSchema): this;
34
+ requireApproval(): this;
35
+ }
36
+ declare class ClientToolBuilder extends ToolBuilder {
37
+ build(): AgentTool;
38
+ }
39
+ declare class AppToolBuilder extends ToolBuilder {
40
+ private appRef;
41
+ constructor(name: string, appRef: string);
42
+ build(): AgentTool;
43
+ }
44
+ declare class AgentToolBuilder extends ToolBuilder {
45
+ private agentRef;
46
+ constructor(name: string, agentRef: string);
47
+ build(): AgentTool;
48
+ }
49
+ declare class WebhookToolBuilder extends ToolBuilder {
50
+ private url;
51
+ private secretKey?;
52
+ constructor(name: string, url: string);
53
+ secret(key: string): this;
54
+ build(): AgentTool;
55
+ }
56
+ /** Create a client tool (executed by SDK consumer) */
57
+ export declare const tool: (name: string) => ClientToolBuilder;
58
+ /** Create an app tool (runs another inference app) */
59
+ export declare const appTool: (name: string, appRef: string) => AppToolBuilder;
60
+ /** Create an agent tool (delegates to sub-agent) */
61
+ export declare const agentTool: (name: string, agentRef: string) => AgentToolBuilder;
62
+ /** Create a webhook tool (calls external URL) */
63
+ export declare const webhookTool: (name: string, url: string) => WebhookToolBuilder;
64
+ declare class InternalToolsBuilder {
65
+ private config;
66
+ /** Enable plan tools (Create, Update, Load) */
67
+ plan(enabled?: boolean): this;
68
+ /** Enable memory tools (Set, Get, GetAll) */
69
+ memory(enabled?: boolean): this;
70
+ /** Enable widget tools (UI, HTML) - top-level only */
71
+ widget(enabled?: boolean): this;
72
+ /** Enable finish tool - sub-agents only */
73
+ finish(enabled?: boolean): this;
74
+ /** Enable all internal tools */
75
+ all(): this;
76
+ /** Disable all internal tools */
77
+ none(): this;
78
+ build(): InternalToolsConfig;
79
+ }
80
+ /** Create internal tools configuration */
81
+ export declare const internalTools: () => InternalToolsBuilder;
82
+ export {};