@sogni-ai/sogni-client 5.2.0 → 5.3.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +37 -0
  3. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.d.ts +2 -1
  4. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +2 -2
  5. package/dist/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
  6. package/dist/ApiClient/WebSocketClient/index.d.ts +3 -1
  7. package/dist/ApiClient/WebSocketClient/index.js +4 -1
  8. package/dist/ApiClient/WebSocketClient/index.js.map +1 -1
  9. package/dist/ApiClient/index.d.ts +10 -1
  10. package/dist/ApiClient/index.js +16 -3
  11. package/dist/ApiClient/index.js.map +1 -1
  12. package/dist/ApiGroup.d.ts +3 -0
  13. package/dist/ApiGroup.js +13 -0
  14. package/dist/ApiGroup.js.map +1 -1
  15. package/dist/Chat/ChatTools.js +2 -1
  16. package/dist/Chat/ChatTools.js.map +1 -1
  17. package/dist/Chat/index.d.ts +6 -0
  18. package/dist/Chat/index.js +35 -8
  19. package/dist/Chat/index.js.map +1 -1
  20. package/dist/Chat/types.d.ts +10 -1
  21. package/dist/CreativeWorkflows/index.js +4 -5
  22. package/dist/CreativeWorkflows/index.js.map +1 -1
  23. package/dist/CreativeWorkflows/types.d.ts +7 -0
  24. package/dist/Projects/createJobRequestMessage.js +3 -1
  25. package/dist/Projects/createJobRequestMessage.js.map +1 -1
  26. package/dist/Projects/index.js +1 -1
  27. package/dist/Projects/index.js.map +1 -1
  28. package/dist/Projects/types/index.d.ts +6 -0
  29. package/dist/Projects/types/index.js.map +1 -1
  30. package/dist/index.d.ts +9 -1
  31. package/dist/index.js +1 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/lib/RestClient.d.ts +3 -2
  34. package/dist/lib/RestClient.js +2 -3
  35. package/dist/lib/RestClient.js.map +1 -1
  36. package/dist/lib/attribution.d.ts +24 -0
  37. package/dist/lib/attribution.js +264 -0
  38. package/dist/lib/attribution.js.map +1 -0
  39. package/dist/types/attribution.d.ts +67 -0
  40. package/dist/types/attribution.js +3 -0
  41. package/dist/types/attribution.js.map +1 -0
  42. package/dist/version.d.ts +1 -1
  43. package/dist/version.js +1 -1
  44. package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js +2 -2
  45. package/dist-esm/ApiClient/WebSocketClient/BrowserWebSocketClient/index.js.map +1 -1
  46. package/dist-esm/ApiClient/WebSocketClient/index.js +4 -1
  47. package/dist-esm/ApiClient/WebSocketClient/index.js.map +1 -1
  48. package/dist-esm/ApiClient/index.js +16 -3
  49. package/dist-esm/ApiClient/index.js.map +1 -1
  50. package/dist-esm/ApiGroup.js +13 -0
  51. package/dist-esm/ApiGroup.js.map +1 -1
  52. package/dist-esm/Chat/ChatTools.js +2 -1
  53. package/dist-esm/Chat/ChatTools.js.map +1 -1
  54. package/dist-esm/Chat/index.js +35 -8
  55. package/dist-esm/Chat/index.js.map +1 -1
  56. package/dist-esm/CreativeWorkflows/index.js +4 -5
  57. package/dist-esm/CreativeWorkflows/index.js.map +1 -1
  58. package/dist-esm/Projects/createJobRequestMessage.js +3 -1
  59. package/dist-esm/Projects/createJobRequestMessage.js.map +1 -1
  60. package/dist-esm/Projects/index.js +1 -1
  61. package/dist-esm/Projects/index.js.map +1 -1
  62. package/dist-esm/Projects/types/index.js.map +1 -1
  63. package/dist-esm/index.js +1 -0
  64. package/dist-esm/index.js.map +1 -1
  65. package/dist-esm/lib/RestClient.js +2 -3
  66. package/dist-esm/lib/RestClient.js.map +1 -1
  67. package/dist-esm/lib/attribution.js +257 -0
  68. package/dist-esm/lib/attribution.js.map +1 -0
  69. package/dist-esm/types/attribution.js +2 -0
  70. package/dist-esm/types/attribution.js.map +1 -0
  71. package/dist-esm/version.js +1 -1
  72. package/llms-full.txt +27 -0
  73. package/llms.txt +4 -0
  74. package/package.json +2 -1
  75. package/src/ApiClient/WebSocketClient/BrowserWebSocketClient/index.ts +5 -2
  76. package/src/ApiClient/WebSocketClient/index.ts +10 -1
  77. package/src/ApiClient/index.ts +42 -2
  78. package/src/ApiGroup.ts +25 -0
  79. package/src/Chat/ChatTools.ts +5 -1
  80. package/src/Chat/index.ts +46 -7
  81. package/src/Chat/types.ts +10 -1
  82. package/src/CreativeWorkflows/index.ts +11 -3
  83. package/src/CreativeWorkflows/types.ts +7 -0
  84. package/src/Projects/createJobRequestMessage.ts +4 -1
  85. package/src/Projects/index.ts +2 -1
  86. package/src/Projects/types/index.ts +6 -0
  87. package/src/index.ts +35 -1
  88. package/src/lib/RestClient.ts +10 -3
  89. package/src/lib/attribution.ts +304 -0
  90. package/src/types/attribution.ts +89 -0
  91. package/src/version.ts +1 -1
package/src/Chat/index.ts CHANGED
@@ -34,6 +34,8 @@ import {
34
34
  import getUUID from '../lib/getUUID.js';
35
35
  import type ProjectsApi from '../Projects/index.js';
36
36
  import { mediaInputToInlineDataUri } from '../lib/mediaValidation.js';
37
+ import { workloadAttributionToWireFields } from '../lib/attribution.js';
38
+ import type { WorkloadAttributionInput } from '../types/attribution.js';
37
39
 
38
40
  const MAX_VISION_IMAGE_COUNT = 20;
39
41
  const MAX_VISION_IMAGE_BYTES = 10 * 1024 * 1024;
@@ -510,13 +512,15 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
510
512
  const normalizedMessages = await normalizeVisionMessages(params.messages);
511
513
  const chatTemplateKwargs =
512
514
  params.chat_template_kwargs ?? this.buildChatTemplateKwargs(params.think);
515
+ const appSource = params.app_source ?? params.appSource ?? this.client.appSource;
516
+ const attributionHeaders = this.attributionHeaders(appSource, params.attribution, getUUID());
513
517
  try {
514
518
  return await this.client.rest.post<HostedChatCompletionResult>(
515
519
  '/v1/chat/completions',
516
520
  {
517
521
  model: params.model,
518
522
  messages: normalizedMessages,
519
- app_source: params.app_source ?? params.appSource ?? this.client.appSource,
523
+ app_source: appSource,
520
524
  max_tokens: params.max_tokens,
521
525
  temperature: params.temperature,
522
526
  top_p: params.top_p,
@@ -541,7 +545,7 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
541
545
  ...(chatTemplateKwargs && { chat_template_kwargs: chatTemplateKwargs }),
542
546
  ...(params.response_format && { response_format: params.response_format })
543
547
  },
544
- { timeoutMs: 300000 }
548
+ { timeoutMs: 300000, headers: attributionHeaders }
545
549
  );
546
550
  } catch (error) {
547
551
  // Re-throw recognized chat-job error bodies (e.g. subscription
@@ -569,18 +573,22 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
569
573
  private async executeHostedTool(
570
574
  params: HostedToolExecutionParams
571
575
  ): Promise<HostedToolExecutionResult> {
576
+ const appSource = params.app_source ?? params.appSource ?? this.client.appSource;
572
577
  return this.client.rest.post<HostedToolExecutionResult>(
573
578
  '/v1/creative-agent/tools/execute',
574
579
  {
575
580
  tool: params.tool,
576
581
  arguments: params.arguments,
577
- app_source: params.app_source ?? params.appSource ?? this.client.appSource,
582
+ app_source: appSource,
578
583
  token_type: params.token_type ?? params.tokenType,
579
584
  ...(params.safe_content_filter !== undefined || params.safeContentFilter !== undefined
580
585
  ? { safe_content_filter: params.safe_content_filter ?? params.safeContentFilter }
581
586
  : {})
582
587
  },
583
- { timeoutMs: 300000 }
588
+ {
589
+ timeoutMs: 300000,
590
+ headers: this.attributionHeaders(appSource, params.attribution, getUUID())
591
+ }
584
592
  );
585
593
  }
586
594
 
@@ -633,6 +641,7 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
633
641
  private async createChatRun(params: StartChatRunParams): Promise<ChatRunRecord> {
634
642
  assertChatRunUsesExternalMedia(params);
635
643
  const appSource = params.appSource ?? this.client.appSource;
644
+ const operationId = getUUID();
636
645
  const body: Record<string, unknown> = {
637
646
  messages: params.messages,
638
647
  ...(params.tools ? { tools: params.tools } : {}),
@@ -652,7 +661,10 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
652
661
  ...(appSource ? { app_source: appSource } : {}),
653
662
  ...(params.runtimeConfig ? { runtime_config: params.runtimeConfig } : {})
654
663
  };
655
- const headers: Record<string, string> = { 'Content-Type': 'application/json' };
664
+ const headers: Record<string, string> = {
665
+ 'Content-Type': 'application/json',
666
+ ...this.attributionHeaders(appSource, params.attribution, operationId)
667
+ };
656
668
  if (params.idempotencyKey) headers['Idempotency-Key'] = params.idempotencyKey;
657
669
  const response = await this.chatRunJson<{
658
670
  status: string;
@@ -828,7 +840,8 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
828
840
  sogni_tool_execution: params.sogni_tool_execution,
829
841
  taskProfile: params.taskProfile,
830
842
  ...(chatTemplateKwargs && { chat_template_kwargs: chatTemplateKwargs }),
831
- ...(params.response_format && { response_format: params.response_format })
843
+ ...(params.response_format && { response_format: params.response_format }),
844
+ ...workloadAttributionToWireFields(this.resolveWorkloadAttribution(params.attribution, jobID))
832
845
  };
833
846
 
834
847
  const stream = new ChatStream(jobID);
@@ -891,13 +904,18 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
891
904
  const maxRounds = params.maxToolRounds || 5;
892
905
  const toolHistory: ToolHistoryEntry[] = [];
893
906
  let messages = [...params.messages];
907
+ const logicalOperation = this.resolveWorkloadAttribution(params.attribution, getUUID());
908
+ const autoToolChildAttribution = this.createAutoToolChildAttribution(logicalOperation);
894
909
 
895
910
  for (let round = 0; round < maxRounds; round++) {
896
911
  const result = (await this.createSingleCompletion({
897
912
  ...params,
898
913
  messages,
899
914
  stream: false,
900
- autoExecuteTools: false
915
+ autoExecuteTools: false,
916
+ // The first LLM admission represents the logical auto-tool request.
917
+ // Later rounds and tool/media work are compute children of that root.
918
+ attribution: round === 0 ? logicalOperation : autoToolChildAttribution
901
919
  })) as ChatCompletionResult;
902
920
 
903
921
  // If model didn't request tools, return final result
@@ -911,6 +929,7 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
911
929
  // Execute tool calls
912
930
  const toolResults = await this.tools.executeAll(result.tool_calls, {
913
931
  tokenType: params.tokenType,
932
+ attribution: autoToolChildAttribution,
914
933
  onToolCall: params.onToolCall,
915
934
  onToolProgress: params.onToolProgress
916
935
  });
@@ -942,6 +961,26 @@ class ChatApi extends ApiGroup<ChatApiEvents> {
942
961
  throw new Error(`Max tool calling rounds (${maxRounds}) exceeded`);
943
962
  }
944
963
 
964
+ /**
965
+ * Build attribution for compute spawned by one logical auto-tool operation.
966
+ * Each child receives its own transport operation ID while retaining the
967
+ * logical operation as its immediate parent.
968
+ */
969
+ private createAutoToolChildAttribution(
970
+ attribution: WorkloadAttributionInput | undefined
971
+ ): WorkloadAttributionInput | undefined {
972
+ const logicalOperation = this.resolveWorkloadAttribution(attribution, getUUID());
973
+ if (!logicalOperation?.operationId) return undefined;
974
+ const rootOperationId = logicalOperation.rootOperationId ?? logicalOperation.operationId;
975
+ return {
976
+ ...logicalOperation,
977
+ operationScope: 'child',
978
+ operationId: undefined,
979
+ rootOperationId,
980
+ parentOperationId: logicalOperation.operationId
981
+ };
982
+ }
983
+
945
984
  private handleJobTokens(data: JobTokensData): void {
946
985
  const stream = this.activeStreams.get(data.jobID);
947
986
  if (!stream) return;
package/src/Chat/types.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { BillingMode } from '../Projects/types/index.js';
2
+ import type { WorkloadAttributionInput } from '../types/attribution.js';
2
3
 
3
4
  export interface ToolFunction {
4
5
  name: string;
@@ -96,6 +97,8 @@ export interface ChatCompletionParams {
96
97
  messages: ChatMessage[];
97
98
  /** Optional source label for this request. Defaults to the client appSource when configured. */
98
99
  appSource?: string;
100
+ /** Optional workload attribution overriding this client's defaults. */
101
+ attribution?: WorkloadAttributionInput;
99
102
  max_tokens?: number;
100
103
  temperature?: number;
101
104
  top_p?: number;
@@ -181,7 +184,7 @@ export interface ChatCompletionParams {
181
184
  maxToolRounds?: number;
182
185
  }
183
186
 
184
- export interface ChatRequestMessage {
187
+ export interface ChatRequestMessage extends WorkloadAttributionInput {
185
188
  jobID: string;
186
189
  type: 'llm';
187
190
  model: string;
@@ -295,6 +298,8 @@ export interface HostedToolExecutionParams {
295
298
  app_source?: string;
296
299
  /** camelCase alias for {@link HostedToolExecutionParams.app_source}. */
297
300
  appSource?: string;
301
+ /** Optional workload attribution overriding this client's defaults. */
302
+ attribution?: WorkloadAttributionInput;
298
303
  /** Token type to use for hosted REST billing. */
299
304
  token_type?: 'sogni' | 'spark' | 'auto';
300
305
  /** camelCase alias for {@link HostedToolExecutionParams.token_type}. */
@@ -457,6 +462,8 @@ export interface StartChatRunParams {
457
462
  billingMode?: BillingMode;
458
463
  /** Optional source label for attribution. Defaults to the client appSource when configured. */
459
464
  appSource?: string;
465
+ /** Optional workload attribution overriding this client's defaults. */
466
+ attribution?: WorkloadAttributionInput;
460
467
  /** Idempotency key (also accepted via `Idempotency-Key` header). */
461
468
  idempotencyKey?: string;
462
469
  /**
@@ -647,6 +654,8 @@ export interface ToolExecutionOptions {
647
654
  network?: 'fast' | 'relaxed';
648
655
  /** Number of media items to generate per tool call. Default: 1. */
649
656
  numberOfMedia?: number;
657
+ /** Optional workload attribution for media projects executed by the tool. */
658
+ attribution?: WorkloadAttributionInput;
650
659
  /** Progress callback fired during media generation. */
651
660
  onProgress?: (progress: ToolExecutionProgress) => void;
652
661
  /**
@@ -16,6 +16,7 @@ import {
16
16
  StartCreativeWorkflowParams,
17
17
  StreamCreativeWorkflowEventsOptions
18
18
  } from './types.js';
19
+ import getUUID from '../lib/getUUID.js';
19
20
 
20
21
  interface CreativeWorkflowEnvelope {
21
22
  workflow?: CreativeWorkflowRecord;
@@ -187,7 +188,8 @@ class CreativeWorkflowsApi extends ApiGroup {
187
188
  if (mediaReferences !== undefined) body.media_references = mediaReferences;
188
189
 
189
190
  const headers: Record<string, string> = {
190
- 'Content-Type': 'application/json'
191
+ 'Content-Type': 'application/json',
192
+ ...this.attributionHeaders(appSource, params.attribution, getUUID())
191
193
  };
192
194
  if (idempotencyKey) {
193
195
  headers['Idempotency-Key'] = idempotencyKey;
@@ -226,7 +228,10 @@ class CreativeWorkflowsApi extends ApiGroup {
226
228
  `/v1/creative-agent/workflows/${encodeURIComponent(workflowId)}/resume`,
227
229
  {
228
230
  method: 'POST',
229
- headers: { 'Content-Type': 'application/json' },
231
+ headers: {
232
+ 'Content-Type': 'application/json',
233
+ ...this.attributionHeaders(appSource, params.attribution, getUUID())
234
+ },
230
235
  body: JSON.stringify(body),
231
236
  signal: options.signal
232
237
  }
@@ -261,7 +266,10 @@ class CreativeWorkflowsApi extends ApiGroup {
261
266
  `/v1/creative-agent/workflows/${encodeURIComponent(workflowId)}/reseed`,
262
267
  {
263
268
  method: 'POST',
264
- headers: { 'Content-Type': 'application/json' },
269
+ headers: {
270
+ 'Content-Type': 'application/json',
271
+ ...this.attributionHeaders(appSource, params.attribution, getUUID())
272
+ },
265
273
  body: JSON.stringify(body),
266
274
  signal: options.signal
267
275
  }
@@ -1,5 +1,6 @@
1
1
  import { TokenType } from '../types/token.js';
2
2
  import type { BillingMode } from '../Projects/types/index.js';
3
+ import type { WorkloadAttributionInput } from '../types/attribution.js';
3
4
 
4
5
  export type CreativeWorkflowStatus =
5
6
  | 'queued'
@@ -144,6 +145,8 @@ export interface StartCreativeWorkflowParams {
144
145
  billingMode?: BillingMode;
145
146
  /** Optional source label for attribution. Defaults to the client appSource when configured. */
146
147
  appSource?: string;
148
+ /** Optional workload attribution overriding this client's defaults. */
149
+ attribution?: WorkloadAttributionInput;
147
150
  idempotencyKey?: string;
148
151
  /** Durable workflows require uploaded HTTP(S) URLs, not inline data URIs. */
149
152
  mediaReferences?: unknown[];
@@ -174,6 +177,8 @@ export interface ResumeCreativeWorkflowParams {
174
177
  billingMode?: BillingMode;
175
178
  /** Optional source label for attribution. Defaults to the client appSource when configured. */
176
179
  appSource?: string;
180
+ /** Optional workload attribution overriding this client's defaults. */
181
+ attribution?: WorkloadAttributionInput;
177
182
  /** @internal Undocumented compatibility alias. Use tokenType. */
178
183
  token_type?: TokenType;
179
184
  /** @internal Undocumented compatibility alias. Use billingMode. */
@@ -203,6 +208,8 @@ export interface ReseedCreativeWorkflowParams {
203
208
  billingMode?: BillingMode;
204
209
  /** Optional source label for attribution. Defaults to the client appSource when configured. */
205
210
  appSource?: string;
211
+ /** Optional workload attribution overriding this client's defaults. */
212
+ attribution?: WorkloadAttributionInput;
206
213
  /** @internal Undocumented compatibility alias. Use seedOverrides. */
207
214
  seed_overrides?: Record<string, number>;
208
215
  /** @internal Undocumented compatibility alias. Use tokenType. */
@@ -43,6 +43,7 @@ import {
43
43
  ModelOptions,
44
44
  VideoModelOptions
45
45
  } from './types/ModelOptions.js';
46
+ import { workloadAttributionToWireFields } from '../lib/attribution.js';
46
47
 
47
48
  /**
48
49
  * Validate that the provided assets match the workflow requirements.
@@ -735,7 +736,9 @@ function createJobRequestMessage(id: string, params: ProjectParams, options: Mod
735
736
  tokenType: params.tokenType,
736
737
  billingMode: params.billingMode,
737
738
  outputFormat:
738
- params.outputFormat || (isAudioParams(params) ? 'mp3' : isVideoParams(params) ? 'mp4' : 'png')
739
+ params.outputFormat ||
740
+ (isAudioParams(params) ? 'mp3' : isVideoParams(params) ? 'mp4' : 'png'),
741
+ ...workloadAttributionToWireFields(params.attribution)
739
742
  };
740
743
 
741
744
  if (params.network) {
@@ -667,7 +667,8 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
667
667
  const modelOptions = await this.getModelOptions(data.modelId);
668
668
  const requestParams = {
669
669
  ...data,
670
- appSource: data.appSource || this.client.appSource
670
+ appSource: data.appSource || this.client.appSource,
671
+ attribution: this.resolveWorkloadAttribution(data.attribution, project.id)
671
672
  } as ProjectParams;
672
673
  const request = createJobRequestMessage(project.id, requestParams, modelOptions);
673
674
 
@@ -1,6 +1,7 @@
1
1
  import { SupernetType } from '../../ApiClient/WebSocketClient/types.js';
2
2
  import { ControlNetParams, VideoControlNetParams } from './ControlNetParams.js';
3
3
  import { TokenType } from '../../types/token.js';
4
+ import type { WorkloadAttributionInput } from '../../types/attribution.js';
4
5
 
5
6
  export interface SupportedModel {
6
7
  id: string;
@@ -99,6 +100,11 @@ export interface BaseProjectParams {
99
100
  * Optional client app/source label to attach to the project request for server-side attribution.
100
101
  */
101
102
  appSource?: string;
103
+ /**
104
+ * Optional workload attribution for this project. Fields override the
105
+ * immutable defaults configured on SogniClient.
106
+ */
107
+ attribution?: WorkloadAttributionInput;
102
108
  /**
103
109
  * LoRA IDs to apply, in the order they should be chained.
104
110
  *
package/src/index.ts CHANGED
@@ -176,6 +176,20 @@ import {
176
176
  TokenAuthManager
177
177
  } from './lib/AuthManager/index.js';
178
178
  import { MeData } from './Account/types.js';
179
+ import type {
180
+ AgentAttributionMetadata,
181
+ AgentSurface,
182
+ ConnectionAttribution,
183
+ ExecutionMode,
184
+ InteractionKind,
185
+ OperationLineage,
186
+ OperationScope,
187
+ SogniAttributionConfig,
188
+ WorkloadAttribution,
189
+ WorkloadAttributionDefaults,
190
+ WorkloadAttributionInput,
191
+ WorkloadKind
192
+ } from './types/attribution.js';
179
193
 
180
194
  export type {
181
195
  AudioFormat,
@@ -313,7 +327,19 @@ export type {
313
327
  RawProject,
314
328
  ToastMessage,
315
329
  DataEntity,
316
- InputMedia
330
+ InputMedia,
331
+ AgentAttributionMetadata,
332
+ AgentSurface,
333
+ ConnectionAttribution,
334
+ ExecutionMode,
335
+ InteractionKind,
336
+ OperationLineage,
337
+ OperationScope,
338
+ SogniAttributionConfig,
339
+ WorkloadAttribution,
340
+ WorkloadAttributionDefaults,
341
+ WorkloadAttributionInput,
342
+ WorkloadKind
317
343
  };
318
344
 
319
345
  export {
@@ -346,6 +372,13 @@ export interface SogniClientConfig {
346
372
  * The socket server uses this as the default source for project and chat requests from this client.
347
373
  */
348
374
  appSource?: string;
375
+ /**
376
+ * Optional immutable connection and per-workload attribution defaults.
377
+ *
378
+ * Individual project, chat, tool, and workflow calls can override workload
379
+ * fields without mutating other concurrent requests.
380
+ */
381
+ attribution?: SogniAttributionConfig;
349
382
  /**
350
383
  * Initial WebSocket event subscriptions for this connection.
351
384
  *
@@ -538,6 +571,7 @@ export class SogniClient {
538
571
  socketUrl: socketEndpoint,
539
572
  appId: config.appId,
540
573
  appSource: config.appSource,
574
+ attribution: config.attribution,
541
575
  socketEventSubscriptions: config.socketEventSubscriptions,
542
576
  networkType: network,
543
577
  logger,
@@ -8,6 +8,11 @@ interface RestRequestInit extends RequestInit {
8
8
  timeoutMs?: number;
9
9
  }
10
10
 
11
+ interface RestPostOptions {
12
+ timeoutMs?: number;
13
+ headers?: Record<string, string>;
14
+ }
15
+
11
16
  class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
12
17
  readonly baseUrl: string;
13
18
  protected _auth: AuthManager;
@@ -120,15 +125,17 @@ class RestClient<E extends EventMap = never> extends TypedEventEmitter<E> {
120
125
  post<T = JSONValue>(
121
126
  path: string,
122
127
  body: Record<string, unknown> = {},
123
- options: Pick<RestRequestInit, 'timeoutMs'> = {}
128
+ options: RestPostOptions = {}
124
129
  ): Promise<T> {
130
+ const { headers = {}, ...requestOptions } = options;
125
131
  return this.request<T>(this.formatUrl(path), {
126
132
  method: 'POST',
127
133
  headers: {
128
- 'Content-Type': 'application/json'
134
+ 'Content-Type': 'application/json',
135
+ ...headers
129
136
  },
130
137
  body: JSON.stringify(body),
131
- ...options
138
+ ...requestOptions
132
139
  });
133
140
  }
134
141
  }