@realtimex/sdk 1.1.1 → 1.1.2

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 CHANGED
@@ -25,6 +25,9 @@ Before using this SDK, ensure your Supabase database is set up:
25
25
  import { RealtimeXSDK } from '@realtimex/sdk';
26
26
 
27
27
  const sdk = new RealtimeXSDK({
28
+ // Development Mode: Use API key for full access
29
+ realtimex: { apiKey: 'sk-abc123...' },
30
+ // OR Production Mode: Declare permissions
28
31
  permissions: ['activities.read', 'activities.write', 'webhook.trigger']
29
32
  });
30
33
 
@@ -59,8 +62,9 @@ When you start your Local App from the RealtimeX Main App:
59
62
  const sdk = new RealtimeXSDK({
60
63
  realtimex: {
61
64
  url: 'http://custom-host:3001', // Default: localhost:3001
62
- appId: 'custom-id', // Override auto-detected
63
- appName: 'My App', // Override auto-detected
65
+ apiKey: 'sk-abc123...', // Development mode
66
+ appId: 'custom-id', // Production mode (override)
67
+ appName: 'My App', // Optional
64
68
  }
65
69
  });
66
70
  ```
@@ -133,11 +137,18 @@ const sdk = new RealtimeXSDK({
133
137
  #### List Providers & Models
134
138
 
135
139
  ```typescript
136
- const { llm, embedding } = await sdk.llm.getProviders();
137
- // llm[]: Array of LLM providers with models
138
- // embedding[]: Array of embedding providers with models
140
+
141
+
142
+ // Get only configured Chat providers (recommended)
143
+ const chatRes = await sdk.llm.chatProviders();
144
+ // chatRes.providers: Array of chat providers with models
145
+
146
+ // Get only configured Embedding providers (recommended)
147
+ const embedRes = await sdk.llm.embedProviders();
148
+ // embedRes.providers: Array of embedding providers with models
139
149
  ```
140
150
 
151
+
141
152
  #### Chat Completion
142
153
 
143
154
  ```typescript
package/dist/index.d.mts CHANGED
@@ -6,6 +6,7 @@ interface SDKConfig {
6
6
  url?: string;
7
7
  appId?: string;
8
8
  appName?: string;
9
+ apiKey?: string;
9
10
  };
10
11
  defaultPort?: number;
11
12
  permissions?: string[];
@@ -88,7 +89,8 @@ declare class ActivitiesModule {
88
89
  private baseUrl;
89
90
  private appId;
90
91
  private appName;
91
- constructor(realtimexUrl: string, appId: string, appName?: string);
92
+ private apiKey?;
93
+ constructor(realtimexUrl: string, appId: string, appName?: string, apiKey?: string);
92
94
  /**
93
95
  * Request a single permission from Electron via internal API
94
96
  */
@@ -124,7 +126,8 @@ declare class WebhookModule {
124
126
  private realtimexUrl;
125
127
  private appName?;
126
128
  private appId?;
127
- constructor(realtimexUrl: string, appName?: string, appId?: string);
129
+ private apiKey?;
130
+ constructor(realtimexUrl: string, appName?: string, appId?: string, apiKey?: string);
128
131
  /**
129
132
  * Request a single permission from Electron via internal API
130
133
  */
@@ -160,7 +163,8 @@ declare class ApiModule {
160
163
  private realtimexUrl;
161
164
  private appId;
162
165
  private appName;
163
- constructor(realtimexUrl: string, appId: string, appName?: string);
166
+ private apiKey?;
167
+ constructor(realtimexUrl: string, appId: string, appName?: string, apiKey?: string);
164
168
  private getHeaders;
165
169
  /**
166
170
  * Request a single permission from Electron via internal API
@@ -190,7 +194,8 @@ declare class TaskModule {
190
194
  private realtimexUrl;
191
195
  private appName?;
192
196
  private appId?;
193
- constructor(realtimexUrl: string, appName?: string, appId?: string);
197
+ private apiKey?;
198
+ constructor(realtimexUrl: string, appName?: string, appId?: string, apiKey?: string);
194
199
  /**
195
200
  * Mark task as processing
196
201
  */
@@ -317,6 +322,7 @@ interface ProvidersResponse {
317
322
  success: boolean;
318
323
  llm?: Provider[];
319
324
  embedding?: Provider[];
325
+ providers?: Provider[];
320
326
  error?: string;
321
327
  code?: string;
322
328
  }
@@ -397,7 +403,8 @@ declare class LLMProviderError extends Error {
397
403
  declare class VectorStore {
398
404
  private baseUrl;
399
405
  private appId;
400
- constructor(baseUrl: string, appId: string);
406
+ private apiKey?;
407
+ constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
401
408
  private get headers();
402
409
  /**
403
410
  * Upsert (insert or update) vectors into storage
@@ -449,19 +456,30 @@ declare class VectorStore {
449
456
  declare class LLMModule {
450
457
  private baseUrl;
451
458
  private appId;
459
+ private apiKey?;
452
460
  vectors: VectorStore;
453
- constructor(baseUrl: string, appId: string);
461
+ constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
454
462
  private get headers();
455
463
  /**
456
- * Get available LLM and embedding providers/models
464
+ * Get only configured chat (LLM) providers
457
465
  *
458
466
  * @example
459
467
  * ```ts
460
- * const { llm, embedding } = await sdk.llm.getProviders();
461
- * console.log('Available LLM models:', llm[0].models);
468
+ * const { providers } = await sdk.llm.chatProviders();
469
+ * console.log('Available chat models:', providers[0].models);
462
470
  * ```
463
471
  */
464
- getProviders(): Promise<ProvidersResponse>;
472
+ chatProviders(): Promise<ProvidersResponse>;
473
+ /**
474
+ * Get only configured embedding providers
475
+ *
476
+ * @example
477
+ * ```ts
478
+ * const { providers } = await sdk.llm.embedProviders();
479
+ * console.log('Available embedding models:', providers[0].models);
480
+ * ```
481
+ */
482
+ embedProviders(): Promise<ProvidersResponse>;
465
483
  /**
466
484
  * Send a chat completion request (synchronous)
467
485
  *
@@ -556,6 +574,7 @@ declare class RealtimeXSDK {
556
574
  llm: LLMModule;
557
575
  readonly appId: string;
558
576
  readonly appName: string | undefined;
577
+ readonly apiKey: string | undefined;
559
578
  private readonly realtimexUrl;
560
579
  private readonly permissions;
561
580
  private static DEFAULT_REALTIMEX_URL;
@@ -569,6 +588,16 @@ declare class RealtimeXSDK {
569
588
  * Get environment variable (works in Node.js and browser)
570
589
  */
571
590
  private getEnvVar;
591
+ /**
592
+ * Ping RealtimeX server to verify connection and authentication.
593
+ * Works in both development (API Key) and production (App ID) modes.
594
+ */
595
+ ping(): Promise<{
596
+ success: boolean;
597
+ mode: 'development' | 'production';
598
+ appId?: string;
599
+ timestamp: string;
600
+ }>;
572
601
  }
573
602
 
574
603
  export { ActivitiesModule, type Activity, type Agent, ApiModule, type ChatMessage, type ChatOptions, type ChatResponse, type EmbedOptions, type EmbedResponse, LLMModule, LLMPermissionError, LLMProviderError, PermissionDeniedError, PermissionRequiredError, PortModule, type Provider, type ProvidersResponse, RealtimeXSDK, type SDKConfig, type StreamChunk, type Task, TaskModule, type TaskRun, type Thread, type TriggerAgentPayload, type TriggerAgentResponse, type VectorDeleteOptions, type VectorDeleteResponse, type VectorQueryOptions, type VectorQueryResponse, type VectorQueryResult, type VectorRecord, VectorStore, type VectorUpsertOptions, type VectorUpsertResponse, WebhookModule, type Workspace };
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ interface SDKConfig {
6
6
  url?: string;
7
7
  appId?: string;
8
8
  appName?: string;
9
+ apiKey?: string;
9
10
  };
10
11
  defaultPort?: number;
11
12
  permissions?: string[];
@@ -88,7 +89,8 @@ declare class ActivitiesModule {
88
89
  private baseUrl;
89
90
  private appId;
90
91
  private appName;
91
- constructor(realtimexUrl: string, appId: string, appName?: string);
92
+ private apiKey?;
93
+ constructor(realtimexUrl: string, appId: string, appName?: string, apiKey?: string);
92
94
  /**
93
95
  * Request a single permission from Electron via internal API
94
96
  */
@@ -124,7 +126,8 @@ declare class WebhookModule {
124
126
  private realtimexUrl;
125
127
  private appName?;
126
128
  private appId?;
127
- constructor(realtimexUrl: string, appName?: string, appId?: string);
129
+ private apiKey?;
130
+ constructor(realtimexUrl: string, appName?: string, appId?: string, apiKey?: string);
128
131
  /**
129
132
  * Request a single permission from Electron via internal API
130
133
  */
@@ -160,7 +163,8 @@ declare class ApiModule {
160
163
  private realtimexUrl;
161
164
  private appId;
162
165
  private appName;
163
- constructor(realtimexUrl: string, appId: string, appName?: string);
166
+ private apiKey?;
167
+ constructor(realtimexUrl: string, appId: string, appName?: string, apiKey?: string);
164
168
  private getHeaders;
165
169
  /**
166
170
  * Request a single permission from Electron via internal API
@@ -190,7 +194,8 @@ declare class TaskModule {
190
194
  private realtimexUrl;
191
195
  private appName?;
192
196
  private appId?;
193
- constructor(realtimexUrl: string, appName?: string, appId?: string);
197
+ private apiKey?;
198
+ constructor(realtimexUrl: string, appName?: string, appId?: string, apiKey?: string);
194
199
  /**
195
200
  * Mark task as processing
196
201
  */
@@ -317,6 +322,7 @@ interface ProvidersResponse {
317
322
  success: boolean;
318
323
  llm?: Provider[];
319
324
  embedding?: Provider[];
325
+ providers?: Provider[];
320
326
  error?: string;
321
327
  code?: string;
322
328
  }
@@ -397,7 +403,8 @@ declare class LLMProviderError extends Error {
397
403
  declare class VectorStore {
398
404
  private baseUrl;
399
405
  private appId;
400
- constructor(baseUrl: string, appId: string);
406
+ private apiKey?;
407
+ constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
401
408
  private get headers();
402
409
  /**
403
410
  * Upsert (insert or update) vectors into storage
@@ -449,19 +456,30 @@ declare class VectorStore {
449
456
  declare class LLMModule {
450
457
  private baseUrl;
451
458
  private appId;
459
+ private apiKey?;
452
460
  vectors: VectorStore;
453
- constructor(baseUrl: string, appId: string);
461
+ constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
454
462
  private get headers();
455
463
  /**
456
- * Get available LLM and embedding providers/models
464
+ * Get only configured chat (LLM) providers
457
465
  *
458
466
  * @example
459
467
  * ```ts
460
- * const { llm, embedding } = await sdk.llm.getProviders();
461
- * console.log('Available LLM models:', llm[0].models);
468
+ * const { providers } = await sdk.llm.chatProviders();
469
+ * console.log('Available chat models:', providers[0].models);
462
470
  * ```
463
471
  */
464
- getProviders(): Promise<ProvidersResponse>;
472
+ chatProviders(): Promise<ProvidersResponse>;
473
+ /**
474
+ * Get only configured embedding providers
475
+ *
476
+ * @example
477
+ * ```ts
478
+ * const { providers } = await sdk.llm.embedProviders();
479
+ * console.log('Available embedding models:', providers[0].models);
480
+ * ```
481
+ */
482
+ embedProviders(): Promise<ProvidersResponse>;
465
483
  /**
466
484
  * Send a chat completion request (synchronous)
467
485
  *
@@ -556,6 +574,7 @@ declare class RealtimeXSDK {
556
574
  llm: LLMModule;
557
575
  readonly appId: string;
558
576
  readonly appName: string | undefined;
577
+ readonly apiKey: string | undefined;
559
578
  private readonly realtimexUrl;
560
579
  private readonly permissions;
561
580
  private static DEFAULT_REALTIMEX_URL;
@@ -569,6 +588,16 @@ declare class RealtimeXSDK {
569
588
  * Get environment variable (works in Node.js and browser)
570
589
  */
571
590
  private getEnvVar;
591
+ /**
592
+ * Ping RealtimeX server to verify connection and authentication.
593
+ * Works in both development (API Key) and production (App ID) modes.
594
+ */
595
+ ping(): Promise<{
596
+ success: boolean;
597
+ mode: 'development' | 'production';
598
+ appId?: string;
599
+ timestamp: string;
600
+ }>;
572
601
  }
573
602
 
574
603
  export { ActivitiesModule, type Activity, type Agent, ApiModule, type ChatMessage, type ChatOptions, type ChatResponse, type EmbedOptions, type EmbedResponse, LLMModule, LLMPermissionError, LLMProviderError, PermissionDeniedError, PermissionRequiredError, PortModule, type Provider, type ProvidersResponse, RealtimeXSDK, type SDKConfig, type StreamChunk, type Task, TaskModule, type TaskRun, type Thread, type TriggerAgentPayload, type TriggerAgentResponse, type VectorDeleteOptions, type VectorDeleteResponse, type VectorQueryOptions, type VectorQueryResponse, type VectorQueryResult, type VectorRecord, VectorStore, type VectorUpsertOptions, type VectorUpsertResponse, WebhookModule, type Workspace };
package/dist/index.js CHANGED
@@ -61,12 +61,19 @@ var PermissionRequiredError = class extends Error {
61
61
  }
62
62
  };
63
63
  var ApiModule = class {
64
- constructor(realtimexUrl, appId, appName) {
64
+ constructor(realtimexUrl, appId, appName, apiKey) {
65
65
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
66
66
  this.appId = appId;
67
67
  this.appName = appName || process.env.RTX_APP_NAME || "Local App";
68
+ this.apiKey = apiKey;
68
69
  }
69
70
  getHeaders() {
71
+ if (this.apiKey) {
72
+ return {
73
+ "Content-Type": "application/json",
74
+ "Authorization": `Bearer ${this.apiKey}`
75
+ };
76
+ }
70
77
  return {
71
78
  "Content-Type": "application/json",
72
79
  "x-app-id": this.appId
@@ -145,10 +152,11 @@ var ApiModule = class {
145
152
 
146
153
  // src/modules/activities.ts
147
154
  var ActivitiesModule = class {
148
- constructor(realtimexUrl, appId, appName) {
155
+ constructor(realtimexUrl, appId, appName, apiKey) {
149
156
  this.baseUrl = realtimexUrl.replace(/\/$/, "");
150
157
  this.appId = appId;
151
158
  this.appName = appName || process.env.RTX_APP_NAME || "Local App";
159
+ this.apiKey = apiKey;
152
160
  }
153
161
  /**
154
162
  * Request a single permission from Electron via internal API
@@ -176,8 +184,10 @@ var ActivitiesModule = class {
176
184
  const headers = {
177
185
  "Content-Type": "application/json"
178
186
  };
179
- if (this.appId) {
180
- headers["X-App-Id"] = this.appId;
187
+ if (this.apiKey) {
188
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
189
+ } else if (this.appId) {
190
+ headers["x-app-id"] = this.appId;
181
191
  }
182
192
  const response = await fetch(url, {
183
193
  ...options,
@@ -264,10 +274,11 @@ var ActivitiesModule = class {
264
274
 
265
275
  // src/modules/webhook.ts
266
276
  var WebhookModule = class {
267
- constructor(realtimexUrl, appName, appId) {
277
+ constructor(realtimexUrl, appName, appId, apiKey) {
268
278
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
269
279
  this.appName = appName;
270
280
  this.appId = appId;
281
+ this.apiKey = apiKey;
271
282
  }
272
283
  /**
273
284
  * Request a single permission from Electron via internal API
@@ -292,12 +303,18 @@ var WebhookModule = class {
292
303
  }
293
304
  async request(path, options = {}) {
294
305
  const url = `${this.realtimexUrl}${path}`;
306
+ const headers = {
307
+ "Content-Type": "application/json",
308
+ ...options.headers
309
+ };
310
+ if (this.apiKey) {
311
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
312
+ } else if (this.appId) {
313
+ headers["x-app-id"] = this.appId;
314
+ }
295
315
  const response = await fetch(url, {
296
316
  ...options,
297
- headers: {
298
- "Content-Type": "application/json",
299
- ...options.headers
300
- }
317
+ headers
301
318
  });
302
319
  const data = await response.json();
303
320
  if (response.status === 403) {
@@ -356,10 +373,11 @@ var WebhookModule = class {
356
373
 
357
374
  // src/modules/task.ts
358
375
  var TaskModule = class {
359
- constructor(realtimexUrl, appName, appId) {
376
+ constructor(realtimexUrl, appName, appId, apiKey) {
360
377
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
361
378
  this.appName = appName;
362
379
  this.appId = appId;
380
+ this.apiKey = apiKey;
363
381
  }
364
382
  /**
365
383
  * Mark task as processing
@@ -380,9 +398,15 @@ var TaskModule = class {
380
398
  return this._sendEvent("task-fail", taskUuid, { error, machine_id: machineId });
381
399
  }
382
400
  async _sendEvent(event, taskUuid, extra) {
401
+ const headers = { "Content-Type": "application/json" };
402
+ if (this.apiKey) {
403
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
404
+ } else if (this.appId) {
405
+ headers["x-app-id"] = this.appId;
406
+ }
383
407
  const response = await fetch(`${this.realtimexUrl}/webhooks/realtimex`, {
384
408
  method: "POST",
385
- headers: { "Content-Type": "application/json" },
409
+ headers,
386
410
  body: JSON.stringify({
387
411
  app_name: this.appName,
388
412
  app_id: this.appId,
@@ -493,11 +517,18 @@ var LLMProviderError = class extends Error {
493
517
  }
494
518
  };
495
519
  var VectorStore = class {
496
- constructor(baseUrl, appId) {
520
+ constructor(baseUrl, appId, apiKey) {
497
521
  this.baseUrl = baseUrl;
498
522
  this.appId = appId;
523
+ this.apiKey = apiKey;
499
524
  }
500
525
  get headers() {
526
+ if (this.apiKey) {
527
+ return {
528
+ "Content-Type": "application/json",
529
+ "Authorization": `Bearer ${this.apiKey}`
530
+ };
531
+ }
501
532
  return {
502
533
  "Content-Type": "application/json",
503
534
  "x-app-id": this.appId
@@ -602,28 +633,55 @@ var VectorStore = class {
602
633
  }
603
634
  };
604
635
  var LLMModule = class {
605
- constructor(baseUrl, appId) {
636
+ constructor(baseUrl, appId, apiKey) {
606
637
  this.baseUrl = baseUrl;
607
638
  this.appId = appId;
608
- this.vectors = new VectorStore(baseUrl, appId);
639
+ this.apiKey = apiKey;
640
+ this.vectors = new VectorStore(baseUrl, appId, apiKey);
609
641
  }
610
642
  get headers() {
643
+ if (this.apiKey) {
644
+ return {
645
+ "Content-Type": "application/json",
646
+ "Authorization": `Bearer ${this.apiKey}`
647
+ };
648
+ }
611
649
  return {
612
650
  "Content-Type": "application/json",
613
651
  "x-app-id": this.appId
614
652
  };
615
653
  }
616
654
  /**
617
- * Get available LLM and embedding providers/models
655
+ * Get only configured chat (LLM) providers
618
656
  *
619
657
  * @example
620
658
  * ```ts
621
- * const { llm, embedding } = await sdk.llm.getProviders();
622
- * console.log('Available LLM models:', llm[0].models);
659
+ * const { providers } = await sdk.llm.chatProviders();
660
+ * console.log('Available chat models:', providers[0].models);
623
661
  * ```
624
662
  */
625
- async getProviders() {
626
- const response = await fetch(`${this.baseUrl}/sdk/llm/providers`, {
663
+ async chatProviders() {
664
+ const response = await fetch(`${this.baseUrl}/sdk/llm/providers/chat`, {
665
+ method: "GET",
666
+ headers: this.headers
667
+ });
668
+ const data = await response.json();
669
+ if (data.code === "PERMISSION_REQUIRED") {
670
+ throw new LLMPermissionError(data.permission || "llm.providers");
671
+ }
672
+ return data;
673
+ }
674
+ /**
675
+ * Get only configured embedding providers
676
+ *
677
+ * @example
678
+ * ```ts
679
+ * const { providers } = await sdk.llm.embedProviders();
680
+ * console.log('Available embedding models:', providers[0].models);
681
+ * ```
682
+ */
683
+ async embedProviders() {
684
+ const response = await fetch(`${this.baseUrl}/sdk/llm/providers/embed`, {
627
685
  method: "GET",
628
686
  headers: this.headers
629
687
  });
@@ -812,13 +870,19 @@ var LLMModule = class {
812
870
  code: embedResult.code
813
871
  };
814
872
  }
873
+ let uniquePrefix = idPrefix;
874
+ if (idPrefix === "chunk") {
875
+ const randomSuffix = Math.random().toString(36).substring(2, 6);
876
+ uniquePrefix = `chunk_${randomSuffix}`;
877
+ }
815
878
  const vectors = texts.map((text, i) => ({
816
- id: `${idPrefix}_${i}`,
879
+ id: `${uniquePrefix}_${i}`,
817
880
  vector: embedResult.embeddings[i],
818
881
  metadata: {
819
882
  text,
820
883
  documentId,
821
- workspaceId
884
+ workspaceId,
885
+ embeddingModel: embedResult.model || model || "unknown"
822
886
  }
823
887
  }));
824
888
  return this.vectors.upsert(vectors, { workspaceId });
@@ -846,7 +910,10 @@ var LLMModule = class {
846
910
  if (!embedResult.success || !embedResult.embeddings?.[0]) {
847
911
  throw new LLMProviderError("Failed to embed query");
848
912
  }
849
- const queryResult = await this.vectors.query(embedResult.embeddings[0], options);
913
+ const queryResult = await this.vectors.query(embedResult.embeddings[0], {
914
+ ...options,
915
+ model: options.model || embedResult.model
916
+ });
850
917
  if (!queryResult.success) {
851
918
  throw new LLMProviderError(queryResult.error || "Vector search failed");
852
919
  }
@@ -859,17 +926,19 @@ var _RealtimeXSDK = class _RealtimeXSDK {
859
926
  constructor(config = {}) {
860
927
  const envAppId = this.getEnvVar("RTX_APP_ID");
861
928
  const envAppName = this.getEnvVar("RTX_APP_NAME");
929
+ const envApiKey = this.getEnvVar("RTX_API_KEY");
862
930
  this.appId = config.realtimex?.appId || envAppId || "";
863
931
  this.appName = config.realtimex?.appName || envAppName;
932
+ this.apiKey = config.realtimex?.apiKey || envApiKey;
864
933
  this.permissions = config.permissions || [];
865
934
  this.realtimexUrl = config.realtimex?.url || _RealtimeXSDK.DEFAULT_REALTIMEX_URL;
866
- this.activities = new ActivitiesModule(this.realtimexUrl, this.appId, this.appName);
867
- this.webhook = new WebhookModule(this.realtimexUrl, this.appName, this.appId);
868
- this.api = new ApiModule(this.realtimexUrl, this.appId, this.appName);
869
- this.task = new TaskModule(this.realtimexUrl, this.appName, this.appId);
935
+ this.activities = new ActivitiesModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
936
+ this.webhook = new WebhookModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
937
+ this.api = new ApiModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
938
+ this.task = new TaskModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
870
939
  this.port = new PortModule(config.defaultPort);
871
- this.llm = new LLMModule(this.realtimexUrl, this.appId);
872
- if (this.permissions.length > 0) {
940
+ this.llm = new LLMModule(this.realtimexUrl, this.appId, this.apiKey);
941
+ if (this.permissions.length > 0 && this.appId && !this.apiKey) {
873
942
  this.register().catch((err) => {
874
943
  console.error("[RealtimeX SDK] Auto-registration failed:", err.message);
875
944
  });
@@ -913,6 +982,31 @@ var _RealtimeXSDK = class _RealtimeXSDK {
913
982
  }
914
983
  return void 0;
915
984
  }
985
+ /**
986
+ * Ping RealtimeX server to verify connection and authentication.
987
+ * Works in both development (API Key) and production (App ID) modes.
988
+ */
989
+ async ping() {
990
+ try {
991
+ const headers = { "Content-Type": "application/json" };
992
+ if (this.apiKey) {
993
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
994
+ } else if (this.appId) {
995
+ headers["x-app-id"] = this.appId;
996
+ }
997
+ const response = await fetch(`${this.realtimexUrl.replace(/\/$/, "")}/sdk/ping`, {
998
+ method: "GET",
999
+ headers
1000
+ });
1001
+ const data = await response.json();
1002
+ if (!response.ok) {
1003
+ throw new Error(data.error || "Ping failed");
1004
+ }
1005
+ return data;
1006
+ } catch (error) {
1007
+ throw new Error(`Connection failed: ${error.message}`);
1008
+ }
1009
+ }
916
1010
  };
917
1011
  _RealtimeXSDK.DEFAULT_REALTIMEX_URL = "http://localhost:3001";
918
1012
  var RealtimeXSDK = _RealtimeXSDK;
package/dist/index.mjs CHANGED
@@ -14,12 +14,19 @@ var PermissionRequiredError = class extends Error {
14
14
  }
15
15
  };
16
16
  var ApiModule = class {
17
- constructor(realtimexUrl, appId, appName) {
17
+ constructor(realtimexUrl, appId, appName, apiKey) {
18
18
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
19
19
  this.appId = appId;
20
20
  this.appName = appName || process.env.RTX_APP_NAME || "Local App";
21
+ this.apiKey = apiKey;
21
22
  }
22
23
  getHeaders() {
24
+ if (this.apiKey) {
25
+ return {
26
+ "Content-Type": "application/json",
27
+ "Authorization": `Bearer ${this.apiKey}`
28
+ };
29
+ }
23
30
  return {
24
31
  "Content-Type": "application/json",
25
32
  "x-app-id": this.appId
@@ -98,10 +105,11 @@ var ApiModule = class {
98
105
 
99
106
  // src/modules/activities.ts
100
107
  var ActivitiesModule = class {
101
- constructor(realtimexUrl, appId, appName) {
108
+ constructor(realtimexUrl, appId, appName, apiKey) {
102
109
  this.baseUrl = realtimexUrl.replace(/\/$/, "");
103
110
  this.appId = appId;
104
111
  this.appName = appName || process.env.RTX_APP_NAME || "Local App";
112
+ this.apiKey = apiKey;
105
113
  }
106
114
  /**
107
115
  * Request a single permission from Electron via internal API
@@ -129,8 +137,10 @@ var ActivitiesModule = class {
129
137
  const headers = {
130
138
  "Content-Type": "application/json"
131
139
  };
132
- if (this.appId) {
133
- headers["X-App-Id"] = this.appId;
140
+ if (this.apiKey) {
141
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
142
+ } else if (this.appId) {
143
+ headers["x-app-id"] = this.appId;
134
144
  }
135
145
  const response = await fetch(url, {
136
146
  ...options,
@@ -217,10 +227,11 @@ var ActivitiesModule = class {
217
227
 
218
228
  // src/modules/webhook.ts
219
229
  var WebhookModule = class {
220
- constructor(realtimexUrl, appName, appId) {
230
+ constructor(realtimexUrl, appName, appId, apiKey) {
221
231
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
222
232
  this.appName = appName;
223
233
  this.appId = appId;
234
+ this.apiKey = apiKey;
224
235
  }
225
236
  /**
226
237
  * Request a single permission from Electron via internal API
@@ -245,12 +256,18 @@ var WebhookModule = class {
245
256
  }
246
257
  async request(path, options = {}) {
247
258
  const url = `${this.realtimexUrl}${path}`;
259
+ const headers = {
260
+ "Content-Type": "application/json",
261
+ ...options.headers
262
+ };
263
+ if (this.apiKey) {
264
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
265
+ } else if (this.appId) {
266
+ headers["x-app-id"] = this.appId;
267
+ }
248
268
  const response = await fetch(url, {
249
269
  ...options,
250
- headers: {
251
- "Content-Type": "application/json",
252
- ...options.headers
253
- }
270
+ headers
254
271
  });
255
272
  const data = await response.json();
256
273
  if (response.status === 403) {
@@ -309,10 +326,11 @@ var WebhookModule = class {
309
326
 
310
327
  // src/modules/task.ts
311
328
  var TaskModule = class {
312
- constructor(realtimexUrl, appName, appId) {
329
+ constructor(realtimexUrl, appName, appId, apiKey) {
313
330
  this.realtimexUrl = realtimexUrl.replace(/\/$/, "");
314
331
  this.appName = appName;
315
332
  this.appId = appId;
333
+ this.apiKey = apiKey;
316
334
  }
317
335
  /**
318
336
  * Mark task as processing
@@ -333,9 +351,15 @@ var TaskModule = class {
333
351
  return this._sendEvent("task-fail", taskUuid, { error, machine_id: machineId });
334
352
  }
335
353
  async _sendEvent(event, taskUuid, extra) {
354
+ const headers = { "Content-Type": "application/json" };
355
+ if (this.apiKey) {
356
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
357
+ } else if (this.appId) {
358
+ headers["x-app-id"] = this.appId;
359
+ }
336
360
  const response = await fetch(`${this.realtimexUrl}/webhooks/realtimex`, {
337
361
  method: "POST",
338
- headers: { "Content-Type": "application/json" },
362
+ headers,
339
363
  body: JSON.stringify({
340
364
  app_name: this.appName,
341
365
  app_id: this.appId,
@@ -446,11 +470,18 @@ var LLMProviderError = class extends Error {
446
470
  }
447
471
  };
448
472
  var VectorStore = class {
449
- constructor(baseUrl, appId) {
473
+ constructor(baseUrl, appId, apiKey) {
450
474
  this.baseUrl = baseUrl;
451
475
  this.appId = appId;
476
+ this.apiKey = apiKey;
452
477
  }
453
478
  get headers() {
479
+ if (this.apiKey) {
480
+ return {
481
+ "Content-Type": "application/json",
482
+ "Authorization": `Bearer ${this.apiKey}`
483
+ };
484
+ }
454
485
  return {
455
486
  "Content-Type": "application/json",
456
487
  "x-app-id": this.appId
@@ -555,28 +586,55 @@ var VectorStore = class {
555
586
  }
556
587
  };
557
588
  var LLMModule = class {
558
- constructor(baseUrl, appId) {
589
+ constructor(baseUrl, appId, apiKey) {
559
590
  this.baseUrl = baseUrl;
560
591
  this.appId = appId;
561
- this.vectors = new VectorStore(baseUrl, appId);
592
+ this.apiKey = apiKey;
593
+ this.vectors = new VectorStore(baseUrl, appId, apiKey);
562
594
  }
563
595
  get headers() {
596
+ if (this.apiKey) {
597
+ return {
598
+ "Content-Type": "application/json",
599
+ "Authorization": `Bearer ${this.apiKey}`
600
+ };
601
+ }
564
602
  return {
565
603
  "Content-Type": "application/json",
566
604
  "x-app-id": this.appId
567
605
  };
568
606
  }
569
607
  /**
570
- * Get available LLM and embedding providers/models
608
+ * Get only configured chat (LLM) providers
571
609
  *
572
610
  * @example
573
611
  * ```ts
574
- * const { llm, embedding } = await sdk.llm.getProviders();
575
- * console.log('Available LLM models:', llm[0].models);
612
+ * const { providers } = await sdk.llm.chatProviders();
613
+ * console.log('Available chat models:', providers[0].models);
576
614
  * ```
577
615
  */
578
- async getProviders() {
579
- const response = await fetch(`${this.baseUrl}/sdk/llm/providers`, {
616
+ async chatProviders() {
617
+ const response = await fetch(`${this.baseUrl}/sdk/llm/providers/chat`, {
618
+ method: "GET",
619
+ headers: this.headers
620
+ });
621
+ const data = await response.json();
622
+ if (data.code === "PERMISSION_REQUIRED") {
623
+ throw new LLMPermissionError(data.permission || "llm.providers");
624
+ }
625
+ return data;
626
+ }
627
+ /**
628
+ * Get only configured embedding providers
629
+ *
630
+ * @example
631
+ * ```ts
632
+ * const { providers } = await sdk.llm.embedProviders();
633
+ * console.log('Available embedding models:', providers[0].models);
634
+ * ```
635
+ */
636
+ async embedProviders() {
637
+ const response = await fetch(`${this.baseUrl}/sdk/llm/providers/embed`, {
580
638
  method: "GET",
581
639
  headers: this.headers
582
640
  });
@@ -765,13 +823,19 @@ var LLMModule = class {
765
823
  code: embedResult.code
766
824
  };
767
825
  }
826
+ let uniquePrefix = idPrefix;
827
+ if (idPrefix === "chunk") {
828
+ const randomSuffix = Math.random().toString(36).substring(2, 6);
829
+ uniquePrefix = `chunk_${randomSuffix}`;
830
+ }
768
831
  const vectors = texts.map((text, i) => ({
769
- id: `${idPrefix}_${i}`,
832
+ id: `${uniquePrefix}_${i}`,
770
833
  vector: embedResult.embeddings[i],
771
834
  metadata: {
772
835
  text,
773
836
  documentId,
774
- workspaceId
837
+ workspaceId,
838
+ embeddingModel: embedResult.model || model || "unknown"
775
839
  }
776
840
  }));
777
841
  return this.vectors.upsert(vectors, { workspaceId });
@@ -799,7 +863,10 @@ var LLMModule = class {
799
863
  if (!embedResult.success || !embedResult.embeddings?.[0]) {
800
864
  throw new LLMProviderError("Failed to embed query");
801
865
  }
802
- const queryResult = await this.vectors.query(embedResult.embeddings[0], options);
866
+ const queryResult = await this.vectors.query(embedResult.embeddings[0], {
867
+ ...options,
868
+ model: options.model || embedResult.model
869
+ });
803
870
  if (!queryResult.success) {
804
871
  throw new LLMProviderError(queryResult.error || "Vector search failed");
805
872
  }
@@ -812,17 +879,19 @@ var _RealtimeXSDK = class _RealtimeXSDK {
812
879
  constructor(config = {}) {
813
880
  const envAppId = this.getEnvVar("RTX_APP_ID");
814
881
  const envAppName = this.getEnvVar("RTX_APP_NAME");
882
+ const envApiKey = this.getEnvVar("RTX_API_KEY");
815
883
  this.appId = config.realtimex?.appId || envAppId || "";
816
884
  this.appName = config.realtimex?.appName || envAppName;
885
+ this.apiKey = config.realtimex?.apiKey || envApiKey;
817
886
  this.permissions = config.permissions || [];
818
887
  this.realtimexUrl = config.realtimex?.url || _RealtimeXSDK.DEFAULT_REALTIMEX_URL;
819
- this.activities = new ActivitiesModule(this.realtimexUrl, this.appId, this.appName);
820
- this.webhook = new WebhookModule(this.realtimexUrl, this.appName, this.appId);
821
- this.api = new ApiModule(this.realtimexUrl, this.appId, this.appName);
822
- this.task = new TaskModule(this.realtimexUrl, this.appName, this.appId);
888
+ this.activities = new ActivitiesModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
889
+ this.webhook = new WebhookModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
890
+ this.api = new ApiModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
891
+ this.task = new TaskModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
823
892
  this.port = new PortModule(config.defaultPort);
824
- this.llm = new LLMModule(this.realtimexUrl, this.appId);
825
- if (this.permissions.length > 0) {
893
+ this.llm = new LLMModule(this.realtimexUrl, this.appId, this.apiKey);
894
+ if (this.permissions.length > 0 && this.appId && !this.apiKey) {
826
895
  this.register().catch((err) => {
827
896
  console.error("[RealtimeX SDK] Auto-registration failed:", err.message);
828
897
  });
@@ -866,6 +935,31 @@ var _RealtimeXSDK = class _RealtimeXSDK {
866
935
  }
867
936
  return void 0;
868
937
  }
938
+ /**
939
+ * Ping RealtimeX server to verify connection and authentication.
940
+ * Works in both development (API Key) and production (App ID) modes.
941
+ */
942
+ async ping() {
943
+ try {
944
+ const headers = { "Content-Type": "application/json" };
945
+ if (this.apiKey) {
946
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
947
+ } else if (this.appId) {
948
+ headers["x-app-id"] = this.appId;
949
+ }
950
+ const response = await fetch(`${this.realtimexUrl.replace(/\/$/, "")}/sdk/ping`, {
951
+ method: "GET",
952
+ headers
953
+ });
954
+ const data = await response.json();
955
+ if (!response.ok) {
956
+ throw new Error(data.error || "Ping failed");
957
+ }
958
+ return data;
959
+ } catch (error) {
960
+ throw new Error(`Connection failed: ${error.message}`);
961
+ }
962
+ }
869
963
  };
870
964
  _RealtimeXSDK.DEFAULT_REALTIMEX_URL = "http://localhost:3001";
871
965
  var RealtimeXSDK = _RealtimeXSDK;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realtimex/sdk",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "SDK for building Local Apps that integrate with RealtimeX",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",