@sogni-ai/sogni-client 4.2.0-alpha.2 → 4.2.0-alpha.21

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.
Files changed (109) hide show
  1. package/CHANGELOG.md +148 -0
  2. package/CLAUDE.md +25 -3
  3. package/README.md +411 -136
  4. package/dist/Account/index.d.ts +4 -2
  5. package/dist/Account/index.js +27 -23
  6. package/dist/Account/index.js.map +1 -1
  7. package/dist/Account/types.d.ts +7 -0
  8. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.d.ts +3 -1
  9. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +26 -2
  10. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
  11. package/dist/ApiClient/WebSocketClient/eventSubscriptions.d.ts +33 -0
  12. package/dist/ApiClient/WebSocketClient/eventSubscriptions.js +39 -0
  13. package/dist/ApiClient/WebSocketClient/eventSubscriptions.js.map +1 -0
  14. package/dist/ApiClient/WebSocketClient/events.d.ts +24 -7
  15. package/dist/ApiClient/WebSocketClient/index.d.ts +5 -1
  16. package/dist/ApiClient/WebSocketClient/index.js +24 -1
  17. package/dist/ApiClient/WebSocketClient/index.js.map +1 -1
  18. package/dist/ApiClient/WebSocketClient/messages.d.ts +2 -0
  19. package/dist/ApiClient/WebSocketClient/types.d.ts +2 -0
  20. package/dist/ApiClient/index.d.ts +6 -1
  21. package/dist/ApiClient/index.js +7 -3
  22. package/dist/ApiClient/index.js.map +1 -1
  23. package/dist/Chat/ChatTools.d.ts +5 -49
  24. package/dist/Chat/ChatTools.js +311 -88
  25. package/dist/Chat/ChatTools.js.map +1 -1
  26. package/dist/Chat/index.d.ts +11 -2
  27. package/dist/Chat/index.js +78 -4
  28. package/dist/Chat/index.js.map +1 -1
  29. package/dist/Chat/modelRouting.d.ts +100 -0
  30. package/dist/Chat/modelRouting.js +441 -0
  31. package/dist/Chat/modelRouting.js.map +1 -0
  32. package/dist/Chat/sogniHostedTools.generated.json +529 -0
  33. package/dist/Chat/tools.d.ts +9 -55
  34. package/dist/Chat/tools.js +72 -228
  35. package/dist/Chat/tools.js.map +1 -1
  36. package/dist/Chat/types.d.ts +91 -2
  37. package/dist/CreativeWorkflows/index.d.ts +23 -0
  38. package/dist/CreativeWorkflows/index.js +274 -0
  39. package/dist/CreativeWorkflows/index.js.map +1 -0
  40. package/dist/CreativeWorkflows/types.d.ts +106 -0
  41. package/dist/CreativeWorkflows/types.js +3 -0
  42. package/dist/CreativeWorkflows/types.js.map +1 -0
  43. package/dist/Projects/Job.d.ts +6 -0
  44. package/dist/Projects/Job.js +60 -5
  45. package/dist/Projects/Job.js.map +1 -1
  46. package/dist/Projects/Project.js +15 -3
  47. package/dist/Projects/Project.js.map +1 -1
  48. package/dist/Projects/createJobRequestMessage.js +140 -6
  49. package/dist/Projects/createJobRequestMessage.js.map +1 -1
  50. package/dist/Projects/index.d.ts +10 -1
  51. package/dist/Projects/index.js +197 -58
  52. package/dist/Projects/index.js.map +1 -1
  53. package/dist/Projects/types/ModelOptions.d.ts +3 -3
  54. package/dist/Projects/types/ModelOptions.js +12 -5
  55. package/dist/Projects/types/ModelOptions.js.map +1 -1
  56. package/dist/Projects/types/ModelTiersRaw.d.ts +7 -7
  57. package/dist/Projects/types/RawProject.d.ts +2 -0
  58. package/dist/Projects/types/events.d.ts +5 -4
  59. package/dist/Projects/types/index.d.ts +77 -7
  60. package/dist/Projects/types/index.js.map +1 -1
  61. package/dist/Projects/utils/index.d.ts +8 -1
  62. package/dist/Projects/utils/index.js +22 -8
  63. package/dist/Projects/utils/index.js.map +1 -1
  64. package/dist/index.d.ts +28 -3
  65. package/dist/index.js +19 -1
  66. package/dist/index.js.map +1 -1
  67. package/dist/lib/RestClient.d.ts +4 -1
  68. package/dist/lib/RestClient.js +17 -9
  69. package/dist/lib/RestClient.js.map +1 -1
  70. package/dist/lib/mediaValidation.d.ts +16 -0
  71. package/dist/lib/mediaValidation.js +280 -0
  72. package/dist/lib/mediaValidation.js.map +1 -0
  73. package/dist/lib/validation.d.ts +6 -1
  74. package/dist/lib/validation.js +28 -2
  75. package/dist/lib/validation.js.map +1 -1
  76. package/llms-full.txt +372 -133
  77. package/llms.txt +197 -86
  78. package/package.json +13 -4
  79. package/src/Account/index.ts +22 -2
  80. package/src/Account/types.ts +7 -0
  81. package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/index.ts +47 -3
  82. package/src/ApiClient/WebSocketClient/eventSubscriptions.ts +92 -0
  83. package/src/ApiClient/WebSocketClient/events.ts +25 -7
  84. package/src/ApiClient/WebSocketClient/index.ts +33 -1
  85. package/src/ApiClient/WebSocketClient/messages.ts +2 -0
  86. package/src/ApiClient/WebSocketClient/types.ts +2 -0
  87. package/src/ApiClient/index.ts +32 -2
  88. package/src/Chat/ChatTools.ts +395 -95
  89. package/src/Chat/index.ts +149 -5
  90. package/src/Chat/modelRouting.ts +602 -0
  91. package/src/Chat/sogniHostedTools.generated.json +529 -0
  92. package/src/Chat/tools.ts +98 -245
  93. package/src/Chat/types.ts +100 -2
  94. package/src/CreativeWorkflows/index.ts +290 -0
  95. package/src/CreativeWorkflows/types.ts +134 -0
  96. package/src/Projects/Job.ts +76 -5
  97. package/src/Projects/Project.ts +13 -3
  98. package/src/Projects/createJobRequestMessage.ts +152 -13
  99. package/src/Projects/index.ts +230 -52
  100. package/src/Projects/types/ModelOptions.ts +15 -8
  101. package/src/Projects/types/ModelTiersRaw.ts +7 -7
  102. package/src/Projects/types/RawProject.ts +2 -0
  103. package/src/Projects/types/events.ts +5 -4
  104. package/src/Projects/types/index.ts +86 -6
  105. package/src/Projects/utils/index.ts +24 -8
  106. package/src/index.ts +93 -0
  107. package/src/lib/RestClient.ts +15 -5
  108. package/src/lib/mediaValidation.ts +367 -0
  109. package/src/lib/validation.ts +38 -2
package/src/Chat/index.ts CHANGED
@@ -14,6 +14,8 @@ import {
14
14
  ChatJobStateEvent,
15
15
  ChatRequestMessage,
16
16
  ChatMessage,
17
+ HostedChatCompletionParams,
18
+ HostedChatCompletionResult,
17
19
  LLMCostEstimation,
18
20
  LLMEstimateResponse,
19
21
  LLMModelInfo,
@@ -22,6 +24,52 @@ import {
22
24
  } from './types';
23
25
  import getUUID from '../lib/getUUID';
24
26
  import type ProjectsApi from '../Projects';
27
+ import { parseInlineMediaDataUri } from '../lib/mediaValidation';
28
+
29
+ const MAX_VISION_IMAGE_COUNT = 20;
30
+ const MAX_VISION_IMAGE_BYTES = 10 * 1024 * 1024;
31
+ const MAX_VISION_IMAGE_LONGEST_SIDE = 1024;
32
+
33
+ function normalizeVisionImageDataUri(input: string): string {
34
+ parseInlineMediaDataUri(input, 'image', {
35
+ maxBytes: MAX_VISION_IMAGE_BYTES,
36
+ maxImageLongestSide: MAX_VISION_IMAGE_LONGEST_SIDE
37
+ });
38
+ return input.trim();
39
+ }
40
+
41
+ function normalizeVisionMessages(messages: ChatMessage[]): ChatMessage[] {
42
+ let imageCount = 0;
43
+ return messages.map((msg) => {
44
+ if (!Array.isArray(msg.content)) {
45
+ return msg;
46
+ }
47
+
48
+ return {
49
+ ...msg,
50
+ content: msg.content.map((part) => {
51
+ if (part.type !== 'image_url') {
52
+ return part;
53
+ }
54
+
55
+ imageCount += 1;
56
+ if (imageCount > MAX_VISION_IMAGE_COUNT) {
57
+ throw new Error(
58
+ `A maximum of ${MAX_VISION_IMAGE_COUNT} vision images is allowed per request`
59
+ );
60
+ }
61
+
62
+ return {
63
+ type: 'image_url' as const,
64
+ image_url: {
65
+ url: normalizeVisionImageDataUri(part.image_url.url),
66
+ ...(part.image_url.detail && { detail: part.image_url.detail })
67
+ }
68
+ };
69
+ })
70
+ };
71
+ });
72
+ }
25
73
 
26
74
  export interface ChatApiEvents {
27
75
  /** Emitted for each token chunk received during streaming */
@@ -88,6 +136,10 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
88
136
  ((params: ChatCompletionParams) => Promise<ChatStream | ChatCompletionResult>);
89
137
  };
90
138
 
139
+ hosted: {
140
+ create: (params: HostedChatCompletionParams) => Promise<HostedChatCompletionResult>;
141
+ };
142
+
91
143
  constructor(config: ApiConfig, projects?: ProjectsApi) {
92
144
  super(config);
93
145
 
@@ -102,6 +154,9 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
102
154
  this.completions = {
103
155
  create: this.createCompletion.bind(this) as any
104
156
  };
157
+ this.hosted = {
158
+ create: this.createHostedCompletion.bind(this)
159
+ };
105
160
 
106
161
  // Set up the tools API (requires ProjectsApi for media generation).
107
162
  // When ProjectsApi is not provided, tool execution methods will throw at runtime.
@@ -156,7 +211,8 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
156
211
  * const estimate = await sogni.chat.estimateCost({
157
212
  * model: 'qwen3.6-35b-a3b-gguf-iq4xs',
158
213
  * messages: [{ role: 'user', content: 'Hello!' }],
159
- * max_tokens: 1024,
214
+ * think: true,
215
+ * taskProfile: 'reasoning',
160
216
  * });
161
217
  * console.log(`Estimated cost: ${estimate.costInToken.toFixed(6)}`);
162
218
  * ```
@@ -166,12 +222,15 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
166
222
  messages: ChatMessage[];
167
223
  max_tokens?: number;
168
224
  tokenType?: 'sogni' | 'spark';
225
+ think?: boolean;
226
+ taskProfile?: 'general' | 'coding' | 'reasoning';
169
227
  }): Promise<LLMCostEstimation> {
228
+ const normalizedMessages = normalizeVisionMessages(params.messages);
170
229
  const tokenType = params.tokenType || 'sogni';
171
230
  const inputTokens = Math.ceil(
172
- JSON.stringify(this.stripImageDataForEstimation(params.messages)).length / 4
231
+ JSON.stringify(this.stripImageDataForEstimation(normalizedMessages)).length / 4
173
232
  );
174
- const maxOutputTokens = params.max_tokens || 4096;
233
+ const maxOutputTokens = this.resolveEstimatedMaxOutputTokens(params);
175
234
  const pathParams = [tokenType, params.model, inputTokens, maxOutputTokens];
176
235
  const path = pathParams.map((p) => encodeURIComponent(p)).join('/');
177
236
  const r = await this.client.socket.get<LLMEstimateResponse>(`/api/v1/job-llm/estimate/${path}`);
@@ -185,6 +244,38 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
185
244
  };
186
245
  }
187
246
 
247
+ private resolveEstimatedMaxOutputTokens(params: {
248
+ model: string;
249
+ max_tokens?: number;
250
+ think?: boolean;
251
+ taskProfile?: 'general' | 'coding' | 'reasoning';
252
+ }): number {
253
+ if (typeof params.max_tokens === 'number' && Number.isFinite(params.max_tokens)) {
254
+ return params.max_tokens;
255
+ }
256
+
257
+ const modelInfo = this.availableLLMModels[params.model];
258
+ const defaultFromModel = modelInfo?.maxOutputTokens?.default;
259
+ const thinkingComplexDefault = modelInfo?.maxOutputTokens?.thinkingComplexDefault;
260
+ const isComplexThinking =
261
+ params.think === true &&
262
+ (params.taskProfile === 'coding' || params.taskProfile === 'reasoning');
263
+
264
+ if (
265
+ isComplexThinking &&
266
+ typeof thinkingComplexDefault === 'number' &&
267
+ Number.isFinite(thinkingComplexDefault)
268
+ ) {
269
+ return thinkingComplexDefault;
270
+ }
271
+
272
+ if (typeof defaultFromModel === 'number' && Number.isFinite(defaultFromModel)) {
273
+ return defaultFromModel;
274
+ }
275
+
276
+ return 4096;
277
+ }
278
+
188
279
  private handleSwarmLLMModels(data: Record<string, number | LLMModelInfo>): void {
189
280
  const models: Record<string, LLMModelInfo> = {};
190
281
  for (const [modelId, value] of Object.entries(data)) {
@@ -233,6 +324,14 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
233
324
  return { enable_thinking: think };
234
325
  }
235
326
 
327
+ private normalizeSogniToolsMode(
328
+ value: ChatCompletionParams['sogni_tools'] | string | undefined
329
+ ): ChatRequestMessage['sogni_tools'] | undefined {
330
+ return typeof value === 'string' && value.trim().toLowerCase() === 'rich'
331
+ ? 'creative-tools'
332
+ : (value as ChatRequestMessage['sogni_tools']);
333
+ }
334
+
236
335
  private async createCompletion(
237
336
  params: ChatCompletionParams
238
337
  ): Promise<ChatStream | ChatCompletionResult> {
@@ -250,6 +349,46 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
250
349
  return this.createSingleCompletion(params);
251
350
  }
252
351
 
352
+ private async createHostedCompletion(
353
+ params: HostedChatCompletionParams
354
+ ): Promise<HostedChatCompletionResult> {
355
+ if (params.stream) {
356
+ throw new Error('chat.hosted.create currently supports non-streaming requests only.');
357
+ }
358
+
359
+ const normalizedMessages = normalizeVisionMessages(params.messages);
360
+ const chatTemplateKwargs =
361
+ params.chat_template_kwargs ?? this.buildChatTemplateKwargs(params.think);
362
+ return this.client.rest.post<HostedChatCompletionResult>(
363
+ '/v1/chat/completions',
364
+ {
365
+ model: params.model,
366
+ messages: normalizedMessages,
367
+ app_source: params.app_source || params.appSource || this.client.appSource,
368
+ max_tokens: params.max_tokens,
369
+ temperature: params.temperature,
370
+ top_p: params.top_p,
371
+ top_k: params.top_k,
372
+ min_p: params.min_p,
373
+ repetition_penalty: params.repetition_penalty,
374
+ frequency_penalty: params.frequency_penalty,
375
+ presence_penalty: params.presence_penalty,
376
+ stop: params.stop,
377
+ token_type: params.token_type || params.tokenType,
378
+ tools: params.tools,
379
+ tool_choice: params.tool_choice,
380
+ sogni_tools: this.normalizeSogniToolsMode(params.sogni_tools),
381
+ sogni_tool_execution: params.sogni_tool_execution,
382
+ task_profile: params.taskProfile,
383
+ media_references: params.media_references ?? params.mediaReferences,
384
+ api_media_references: params.api_media_references ?? params.apiMediaReferences,
385
+ ...(chatTemplateKwargs && { chat_template_kwargs: chatTemplateKwargs }),
386
+ ...(params.response_format && { response_format: params.response_format })
387
+ },
388
+ { timeoutMs: 300000 }
389
+ );
390
+ }
391
+
253
392
  /**
254
393
  * Send a single chat completion request (no auto tool execution).
255
394
  */
@@ -257,6 +396,7 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
257
396
  params: ChatCompletionParams
258
397
  ): Promise<ChatStream | ChatCompletionResult> {
259
398
  const jobID = getUUID();
399
+ const normalizedMessages = normalizeVisionMessages(params.messages);
260
400
 
261
401
  // Build chat_template_kwargs from think parameter
262
402
  const chatTemplateKwargs = this.buildChatTemplateKwargs(params.think);
@@ -265,7 +405,8 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
265
405
  jobID,
266
406
  type: 'llm',
267
407
  model: params.model,
268
- messages: params.messages,
408
+ messages: normalizedMessages,
409
+ appSource: params.appSource || this.client.appSource,
269
410
  max_tokens: params.max_tokens,
270
411
  temperature: params.temperature,
271
412
  top_p: params.top_p,
@@ -279,8 +420,11 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
279
420
  tokenType: params.tokenType,
280
421
  tools: params.tools,
281
422
  tool_choice: params.tool_choice,
423
+ sogni_tools: this.normalizeSogniToolsMode(params.sogni_tools),
424
+ sogni_tool_execution: params.sogni_tool_execution,
282
425
  taskProfile: params.taskProfile,
283
- ...(chatTemplateKwargs && { chat_template_kwargs: chatTemplateKwargs })
426
+ ...(chatTemplateKwargs && { chat_template_kwargs: chatTemplateKwargs }),
427
+ ...(params.response_format && { response_format: params.response_format })
284
428
  };
285
429
 
286
430
  const stream = new ChatStream(jobID);