@realtimex/sdk 1.1.2 → 1.1.4

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/index.d.mts CHANGED
@@ -150,14 +150,16 @@ declare class WebhookModule {
150
150
  */
151
151
  declare class PermissionDeniedError extends Error {
152
152
  readonly permission: string;
153
- constructor(permission: string, message?: string);
153
+ readonly code: string;
154
+ constructor(permission: string, message?: string, code?: string);
154
155
  }
155
156
  /**
156
157
  * Error thrown when a permission needs to be granted
157
158
  */
158
159
  declare class PermissionRequiredError extends Error {
159
160
  readonly permission: string;
160
- constructor(permission: string, message?: string);
161
+ readonly code: string;
162
+ constructor(permission: string, message?: string, code?: string);
161
163
  }
162
164
  declare class ApiModule {
163
165
  private realtimexUrl;
@@ -263,6 +265,7 @@ declare class PortModule {
263
265
  * - Provider/model listing
264
266
  * - Vector storage (upsert, query, delete)
265
267
  */
268
+
266
269
  interface ChatMessage {
267
270
  role: 'system' | 'user' | 'assistant';
268
271
  content: string;
@@ -272,6 +275,9 @@ interface ChatOptions {
272
275
  provider?: string;
273
276
  temperature?: number;
274
277
  max_tokens?: number;
278
+ response_format?: {
279
+ type: string;
280
+ };
275
281
  }
276
282
  interface ChatResponse {
277
283
  success: boolean;
@@ -390,10 +396,41 @@ interface VectorListWorkspacesResponse {
390
396
  workspaces?: string[];
391
397
  error?: string;
392
398
  code?: string;
399
+ error_message?: string;
393
400
  }
394
- declare class LLMPermissionError extends Error {
395
- permission: string;
396
- code: string;
401
+ interface VectorRegisterResponse {
402
+ success: boolean;
403
+ message?: string;
404
+ error?: string;
405
+ code?: string;
406
+ }
407
+ interface VectorConfigResponse {
408
+ success: boolean;
409
+ provider?: string;
410
+ config?: Record<string, any>;
411
+ error?: string;
412
+ code?: string;
413
+ }
414
+ interface VectorProviderField {
415
+ name: string;
416
+ label: string;
417
+ type: 'string' | 'password';
418
+ placeholder?: string;
419
+ }
420
+ interface VectorProviderMetadata {
421
+ name: string;
422
+ label: string;
423
+ description?: string;
424
+ fields: VectorProviderField[];
425
+ }
426
+ interface VectorProvidersResponse {
427
+ success: boolean;
428
+ providers: VectorProviderMetadata[];
429
+ }
430
+ /**
431
+ * @deprecated Use PermissionRequiredError from api module instead
432
+ */
433
+ declare class LLMPermissionError extends PermissionRequiredError {
397
434
  constructor(permission: string, code?: string);
398
435
  }
399
436
  declare class LLMProviderError extends Error {
@@ -403,9 +440,18 @@ declare class LLMProviderError extends Error {
403
440
  declare class VectorStore {
404
441
  private baseUrl;
405
442
  private appId;
443
+ private appName;
406
444
  private apiKey?;
407
- constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
445
+ constructor(baseUrl: string, appId: string, appName?: string, apiKey?: string | undefined);
408
446
  private get headers();
447
+ /**
448
+ * Request a single permission from Electron via internal API
449
+ */
450
+ private requestPermission;
451
+ /**
452
+ * Internal request wrapper that handles automatic permission prompts
453
+ */
454
+ private request;
409
455
  /**
410
456
  * Upsert (insert or update) vectors into storage
411
457
  *
@@ -452,14 +498,46 @@ declare class VectorStore {
452
498
  * ```
453
499
  */
454
500
  listWorkspaces(): Promise<VectorListWorkspacesResponse>;
501
+ /**
502
+ * Register a custom vector database configuration for this app
503
+ *
504
+ * @example
505
+ * ```ts
506
+ * await sdk.llm.vectors.registerConfig('lancedb', { });
507
+ * ```
508
+ */
509
+ registerConfig(provider: string, config: Record<string, any>): Promise<VectorRegisterResponse>;
510
+ /**
511
+ * List all supported vector database providers and their configuration requirements
512
+ */
513
+ listProviders(): Promise<VectorProvidersResponse>;
514
+ /**
515
+ * Get the current vector database configuration for this app
516
+ *
517
+ * @example
518
+ * ```ts
519
+ * const { provider, config } = await sdk.llm.vectors.getConfig();
520
+ * console.log(`App is using ${provider}`);
521
+ * ```
522
+ */
523
+ getConfig(): Promise<VectorConfigResponse>;
455
524
  }
456
525
  declare class LLMModule {
457
526
  private baseUrl;
458
527
  private appId;
528
+ private appName;
459
529
  private apiKey?;
460
530
  vectors: VectorStore;
461
- constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
531
+ constructor(baseUrl: string, appId: string, appName?: string, apiKey?: string | undefined);
462
532
  private get headers();
533
+ /**
534
+ * Request a single permission from Electron via internal API
535
+ */
536
+ private requestPermission;
537
+ /**
538
+ * Internal request wrapper that handles automatic permission prompts
539
+ */
540
+ private request;
463
541
  /**
464
542
  * Get only configured chat (LLM) providers
465
543
  *
@@ -598,6 +676,11 @@ declare class RealtimeXSDK {
598
676
  appId?: string;
599
677
  timestamp: string;
600
678
  }>;
679
+ /**
680
+ * Get the absolute path to the data directory for this app.
681
+ * Path: ~/.realtimex.ai/Resources/local-apps/{appId}
682
+ */
683
+ getAppDataDir(): Promise<string>;
601
684
  }
602
685
 
603
686
  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
@@ -150,14 +150,16 @@ declare class WebhookModule {
150
150
  */
151
151
  declare class PermissionDeniedError extends Error {
152
152
  readonly permission: string;
153
- constructor(permission: string, message?: string);
153
+ readonly code: string;
154
+ constructor(permission: string, message?: string, code?: string);
154
155
  }
155
156
  /**
156
157
  * Error thrown when a permission needs to be granted
157
158
  */
158
159
  declare class PermissionRequiredError extends Error {
159
160
  readonly permission: string;
160
- constructor(permission: string, message?: string);
161
+ readonly code: string;
162
+ constructor(permission: string, message?: string, code?: string);
161
163
  }
162
164
  declare class ApiModule {
163
165
  private realtimexUrl;
@@ -263,6 +265,7 @@ declare class PortModule {
263
265
  * - Provider/model listing
264
266
  * - Vector storage (upsert, query, delete)
265
267
  */
268
+
266
269
  interface ChatMessage {
267
270
  role: 'system' | 'user' | 'assistant';
268
271
  content: string;
@@ -272,6 +275,9 @@ interface ChatOptions {
272
275
  provider?: string;
273
276
  temperature?: number;
274
277
  max_tokens?: number;
278
+ response_format?: {
279
+ type: string;
280
+ };
275
281
  }
276
282
  interface ChatResponse {
277
283
  success: boolean;
@@ -390,10 +396,41 @@ interface VectorListWorkspacesResponse {
390
396
  workspaces?: string[];
391
397
  error?: string;
392
398
  code?: string;
399
+ error_message?: string;
393
400
  }
394
- declare class LLMPermissionError extends Error {
395
- permission: string;
396
- code: string;
401
+ interface VectorRegisterResponse {
402
+ success: boolean;
403
+ message?: string;
404
+ error?: string;
405
+ code?: string;
406
+ }
407
+ interface VectorConfigResponse {
408
+ success: boolean;
409
+ provider?: string;
410
+ config?: Record<string, any>;
411
+ error?: string;
412
+ code?: string;
413
+ }
414
+ interface VectorProviderField {
415
+ name: string;
416
+ label: string;
417
+ type: 'string' | 'password';
418
+ placeholder?: string;
419
+ }
420
+ interface VectorProviderMetadata {
421
+ name: string;
422
+ label: string;
423
+ description?: string;
424
+ fields: VectorProviderField[];
425
+ }
426
+ interface VectorProvidersResponse {
427
+ success: boolean;
428
+ providers: VectorProviderMetadata[];
429
+ }
430
+ /**
431
+ * @deprecated Use PermissionRequiredError from api module instead
432
+ */
433
+ declare class LLMPermissionError extends PermissionRequiredError {
397
434
  constructor(permission: string, code?: string);
398
435
  }
399
436
  declare class LLMProviderError extends Error {
@@ -403,9 +440,18 @@ declare class LLMProviderError extends Error {
403
440
  declare class VectorStore {
404
441
  private baseUrl;
405
442
  private appId;
443
+ private appName;
406
444
  private apiKey?;
407
- constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
445
+ constructor(baseUrl: string, appId: string, appName?: string, apiKey?: string | undefined);
408
446
  private get headers();
447
+ /**
448
+ * Request a single permission from Electron via internal API
449
+ */
450
+ private requestPermission;
451
+ /**
452
+ * Internal request wrapper that handles automatic permission prompts
453
+ */
454
+ private request;
409
455
  /**
410
456
  * Upsert (insert or update) vectors into storage
411
457
  *
@@ -452,14 +498,46 @@ declare class VectorStore {
452
498
  * ```
453
499
  */
454
500
  listWorkspaces(): Promise<VectorListWorkspacesResponse>;
501
+ /**
502
+ * Register a custom vector database configuration for this app
503
+ *
504
+ * @example
505
+ * ```ts
506
+ * await sdk.llm.vectors.registerConfig('lancedb', { });
507
+ * ```
508
+ */
509
+ registerConfig(provider: string, config: Record<string, any>): Promise<VectorRegisterResponse>;
510
+ /**
511
+ * List all supported vector database providers and their configuration requirements
512
+ */
513
+ listProviders(): Promise<VectorProvidersResponse>;
514
+ /**
515
+ * Get the current vector database configuration for this app
516
+ *
517
+ * @example
518
+ * ```ts
519
+ * const { provider, config } = await sdk.llm.vectors.getConfig();
520
+ * console.log(`App is using ${provider}`);
521
+ * ```
522
+ */
523
+ getConfig(): Promise<VectorConfigResponse>;
455
524
  }
456
525
  declare class LLMModule {
457
526
  private baseUrl;
458
527
  private appId;
528
+ private appName;
459
529
  private apiKey?;
460
530
  vectors: VectorStore;
461
- constructor(baseUrl: string, appId: string, apiKey?: string | undefined);
531
+ constructor(baseUrl: string, appId: string, appName?: string, apiKey?: string | undefined);
462
532
  private get headers();
533
+ /**
534
+ * Request a single permission from Electron via internal API
535
+ */
536
+ private requestPermission;
537
+ /**
538
+ * Internal request wrapper that handles automatic permission prompts
539
+ */
540
+ private request;
463
541
  /**
464
542
  * Get only configured chat (LLM) providers
465
543
  *
@@ -598,6 +676,11 @@ declare class RealtimeXSDK {
598
676
  appId?: string;
599
677
  timestamp: string;
600
678
  }>;
679
+ /**
680
+ * Get the absolute path to the data directory for this app.
681
+ * Path: ~/.realtimex.ai/Resources/local-apps/{appId}
682
+ */
683
+ getAppDataDir(): Promise<string>;
601
684
  }
602
685
 
603
686
  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
@@ -47,17 +47,19 @@ module.exports = __toCommonJS(index_exports);
47
47
 
48
48
  // src/modules/api.ts
49
49
  var PermissionDeniedError = class extends Error {
50
- constructor(permission, message) {
50
+ constructor(permission, message, code = "PERMISSION_DENIED") {
51
51
  super(message || `Permission '${permission}' was denied`);
52
52
  this.name = "PermissionDeniedError";
53
53
  this.permission = permission;
54
+ this.code = code;
54
55
  }
55
56
  };
56
57
  var PermissionRequiredError = class extends Error {
57
- constructor(permission, message) {
58
+ constructor(permission, message, code = "PERMISSION_REQUIRED") {
58
59
  super(message || `Permission '${permission}' is required`);
59
60
  this.name = "PermissionRequiredError";
60
61
  this.permission = permission;
62
+ this.code = code;
61
63
  }
62
64
  };
63
65
  var ApiModule = class {
@@ -501,11 +503,9 @@ var PortModule = class {
501
503
  };
502
504
 
503
505
  // src/modules/llm.ts
504
- var LLMPermissionError = class extends Error {
506
+ var LLMPermissionError = class extends PermissionRequiredError {
505
507
  constructor(permission, code = "PERMISSION_REQUIRED") {
506
- super(`Permission required: ${permission}`);
507
- this.permission = permission;
508
- this.code = code;
508
+ super(permission, void 0, code);
509
509
  this.name = "LLMPermissionError";
510
510
  }
511
511
  };
@@ -517,9 +517,10 @@ var LLMProviderError = class extends Error {
517
517
  }
518
518
  };
519
519
  var VectorStore = class {
520
- constructor(baseUrl, appId, apiKey) {
520
+ constructor(baseUrl, appId, appName = "Local App", apiKey) {
521
521
  this.baseUrl = baseUrl;
522
522
  this.appId = appId;
523
+ this.appName = appName;
523
524
  this.apiKey = apiKey;
524
525
  }
525
526
  get headers() {
@@ -534,6 +535,52 @@ var VectorStore = class {
534
535
  "x-app-id": this.appId
535
536
  };
536
537
  }
538
+ /**
539
+ * Request a single permission from Electron via internal API
540
+ */
541
+ async requestPermission(permission) {
542
+ try {
543
+ const response = await fetch(`${this.baseUrl}/api/local-apps/request-permission`, {
544
+ method: "POST",
545
+ headers: { "Content-Type": "application/json" },
546
+ body: JSON.stringify({
547
+ app_id: this.appId,
548
+ app_name: this.appName,
549
+ permission
550
+ })
551
+ });
552
+ const data = await response.json();
553
+ return data.granted === true;
554
+ } catch (error) {
555
+ return false;
556
+ }
557
+ }
558
+ /**
559
+ * Internal request wrapper that handles automatic permission prompts
560
+ */
561
+ async request(method, endpoint, body) {
562
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
563
+ method,
564
+ headers: this.headers,
565
+ body: body ? JSON.stringify(body) : void 0
566
+ });
567
+ const data = await response.json();
568
+ if (data.code === "PERMISSION_REQUIRED") {
569
+ const permission = data.permission || "vectors.read";
570
+ const granted = await this.requestPermission(permission);
571
+ if (granted) {
572
+ return this.request(method, endpoint, body);
573
+ }
574
+ throw new PermissionDeniedError(permission);
575
+ }
576
+ if (!data.success && data.error) {
577
+ if (data.code === "LLM_ERROR") {
578
+ throw new LLMProviderError(data.error);
579
+ }
580
+ throw new Error(data.error);
581
+ }
582
+ return data;
583
+ }
537
584
  /**
538
585
  * Upsert (insert or update) vectors into storage
539
586
  *
@@ -545,19 +592,10 @@ var VectorStore = class {
545
592
  * ```
546
593
  */
547
594
  async upsert(vectors, options = {}) {
548
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/upsert`, {
549
- method: "POST",
550
- headers: this.headers,
551
- body: JSON.stringify({
552
- vectors,
553
- workspaceId: options.workspaceId
554
- })
595
+ return this.request("POST", "/sdk/llm/vectors/upsert", {
596
+ vectors,
597
+ workspaceId: options.workspaceId
555
598
  });
556
- const data = await response.json();
557
- if (data.code === "PERMISSION_REQUIRED") {
558
- throw new LLMPermissionError(data.permission || "vectors.write");
559
- }
560
- return data;
561
599
  }
562
600
  /**
563
601
  * Query similar vectors by embedding
@@ -572,21 +610,12 @@ var VectorStore = class {
572
610
  * ```
573
611
  */
574
612
  async query(vector, options = {}) {
575
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/query`, {
576
- method: "POST",
577
- headers: this.headers,
578
- body: JSON.stringify({
579
- vector,
580
- topK: options.topK ?? 5,
581
- filter: options.filter,
582
- workspaceId: options.workspaceId
583
- })
613
+ return this.request("POST", "/sdk/llm/vectors/query", {
614
+ vector,
615
+ topK: options.topK ?? 5,
616
+ filter: options.filter,
617
+ workspaceId: options.workspaceId
584
618
  });
585
- const data = await response.json();
586
- if (data.code === "PERMISSION_REQUIRED") {
587
- throw new LLMPermissionError(data.permission || "vectors.read");
588
- }
589
- return data;
590
619
  }
591
620
  /**
592
621
  * Delete vectors from storage
@@ -600,16 +629,7 @@ var VectorStore = class {
600
629
  * ```
601
630
  */
602
631
  async delete(options) {
603
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/delete`, {
604
- method: "POST",
605
- headers: this.headers,
606
- body: JSON.stringify(options)
607
- });
608
- const data = await response.json();
609
- if (data.code === "PERMISSION_REQUIRED") {
610
- throw new LLMPermissionError(data.permission || "vectors.write");
611
- }
612
- return data;
632
+ return this.request("POST", "/sdk/llm/vectors/delete", options);
613
633
  }
614
634
  /**
615
635
  * List all available workspaces (namespaces) for this app
@@ -621,23 +641,48 @@ var VectorStore = class {
621
641
  * ```
622
642
  */
623
643
  async listWorkspaces() {
624
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/workspaces`, {
625
- method: "GET",
626
- headers: this.headers
644
+ return this.request("GET", "/sdk/llm/vectors/workspaces");
645
+ }
646
+ /**
647
+ * Register a custom vector database configuration for this app
648
+ *
649
+ * @example
650
+ * ```ts
651
+ * await sdk.llm.vectors.registerConfig('lancedb', { });
652
+ * ```
653
+ */
654
+ async registerConfig(provider, config) {
655
+ return this.request("POST", "/sdk/llm/vectors/register", {
656
+ provider,
657
+ config
627
658
  });
628
- const data = await response.json();
629
- if (data.code === "PERMISSION_REQUIRED") {
630
- throw new LLMPermissionError(data.permission || "vectors.read");
631
- }
632
- return data;
659
+ }
660
+ /**
661
+ * List all supported vector database providers and their configuration requirements
662
+ */
663
+ async listProviders() {
664
+ return this.request("GET", "/sdk/llm/vectors/providers");
665
+ }
666
+ /**
667
+ * Get the current vector database configuration for this app
668
+ *
669
+ * @example
670
+ * ```ts
671
+ * const { provider, config } = await sdk.llm.vectors.getConfig();
672
+ * console.log(`App is using ${provider}`);
673
+ * ```
674
+ */
675
+ async getConfig() {
676
+ return this.request("GET", "/sdk/llm/vectors/config");
633
677
  }
634
678
  };
635
679
  var LLMModule = class {
636
- constructor(baseUrl, appId, apiKey) {
680
+ constructor(baseUrl, appId, appName = "Local App", apiKey) {
637
681
  this.baseUrl = baseUrl;
638
682
  this.appId = appId;
683
+ this.appName = appName;
639
684
  this.apiKey = apiKey;
640
- this.vectors = new VectorStore(baseUrl, appId, apiKey);
685
+ this.vectors = new VectorStore(baseUrl, appId, appName, apiKey);
641
686
  }
642
687
  get headers() {
643
688
  if (this.apiKey) {
@@ -651,6 +696,52 @@ var LLMModule = class {
651
696
  "x-app-id": this.appId
652
697
  };
653
698
  }
699
+ /**
700
+ * Request a single permission from Electron via internal API
701
+ */
702
+ async requestPermission(permission) {
703
+ try {
704
+ const response = await fetch(`${this.baseUrl}/api/local-apps/request-permission`, {
705
+ method: "POST",
706
+ headers: { "Content-Type": "application/json" },
707
+ body: JSON.stringify({
708
+ app_id: this.appId,
709
+ app_name: this.appName,
710
+ permission
711
+ })
712
+ });
713
+ const data = await response.json();
714
+ return data.granted === true;
715
+ } catch (error) {
716
+ return false;
717
+ }
718
+ }
719
+ /**
720
+ * Internal request wrapper that handles automatic permission prompts
721
+ */
722
+ async request(method, endpoint, body) {
723
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
724
+ method,
725
+ headers: this.headers,
726
+ body: body ? JSON.stringify(body) : void 0
727
+ });
728
+ const data = await response.json();
729
+ if (data.code === "PERMISSION_REQUIRED") {
730
+ const permission = data.permission || "llm.chat";
731
+ const granted = await this.requestPermission(permission);
732
+ if (granted) {
733
+ return this.request(method, endpoint, body);
734
+ }
735
+ throw new PermissionDeniedError(permission);
736
+ }
737
+ if (!data.success && data.error) {
738
+ if (data.code === "LLM_ERROR") {
739
+ throw new LLMProviderError(data.error);
740
+ }
741
+ throw new Error(data.error);
742
+ }
743
+ return data;
744
+ }
654
745
  /**
655
746
  * Get only configured chat (LLM) providers
656
747
  *
@@ -661,15 +752,7 @@ var LLMModule = class {
661
752
  * ```
662
753
  */
663
754
  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;
755
+ return this.request("GET", "/sdk/llm/providers/chat");
673
756
  }
674
757
  /**
675
758
  * Get only configured embedding providers
@@ -681,15 +764,7 @@ var LLMModule = class {
681
764
  * ```
682
765
  */
683
766
  async embedProviders() {
684
- const response = await fetch(`${this.baseUrl}/sdk/llm/providers/embed`, {
685
- method: "GET",
686
- headers: this.headers
687
- });
688
- const data = await response.json();
689
- if (data.code === "PERMISSION_REQUIRED") {
690
- throw new LLMPermissionError(data.permission || "llm.providers");
691
- }
692
- return data;
767
+ return this.request("GET", "/sdk/llm/providers/embed");
693
768
  }
694
769
  /**
695
770
  * Send a chat completion request (synchronous)
@@ -705,25 +780,14 @@ var LLMModule = class {
705
780
  * ```
706
781
  */
707
782
  async chat(messages, options = {}) {
708
- const response = await fetch(`${this.baseUrl}/sdk/llm/chat`, {
709
- method: "POST",
710
- headers: this.headers,
711
- body: JSON.stringify({
712
- messages,
713
- model: options.model,
714
- provider: options.provider,
715
- temperature: options.temperature ?? 0.7,
716
- max_tokens: options.max_tokens ?? 1e3
717
- })
783
+ return this.request("POST", "/sdk/llm/chat", {
784
+ messages,
785
+ model: options.model,
786
+ provider: options.provider,
787
+ temperature: options.temperature ?? 0.7,
788
+ max_tokens: options.max_tokens ?? 1e3,
789
+ response_format: options.response_format
718
790
  });
719
- const data = await response.json();
720
- if (data.code === "PERMISSION_REQUIRED") {
721
- throw new LLMPermissionError(data.permission || "llm.chat");
722
- }
723
- if (data.code === "LLM_ERROR") {
724
- throw new LLMProviderError(data.error || "LLM request failed");
725
- }
726
- return data;
727
791
  }
728
792
  /**
729
793
  * Send a streaming chat completion request (SSE)
@@ -749,13 +813,20 @@ var LLMModule = class {
749
813
  model: options.model,
750
814
  provider: options.provider,
751
815
  temperature: options.temperature ?? 0.7,
752
- max_tokens: options.max_tokens ?? 1e3
816
+ max_tokens: options.max_tokens ?? 1e3,
817
+ response_format: options.response_format
753
818
  })
754
819
  });
755
820
  if (!response.ok) {
756
821
  const errorData = await response.json();
757
822
  if (errorData.code === "PERMISSION_REQUIRED") {
758
- throw new LLMPermissionError(errorData.permission || "llm.chat");
823
+ const permission = errorData.permission || "llm.chat";
824
+ const granted = await this.requestPermission(permission);
825
+ if (granted) {
826
+ yield* this.chatStream(messages, options);
827
+ return;
828
+ }
829
+ throw new PermissionDeniedError(permission);
759
830
  }
760
831
  throw new LLMProviderError(errorData.error || "Stream request failed");
761
832
  }
@@ -830,23 +901,11 @@ var LLMModule = class {
830
901
  */
831
902
  async embed(input, options = {}) {
832
903
  const inputArray = Array.isArray(input) ? input : [input];
833
- const response = await fetch(`${this.baseUrl}/sdk/llm/embed`, {
834
- method: "POST",
835
- headers: this.headers,
836
- body: JSON.stringify({
837
- input: inputArray,
838
- provider: options.provider,
839
- model: options.model
840
- })
904
+ return this.request("POST", "/sdk/llm/embed", {
905
+ input: inputArray,
906
+ provider: options.provider,
907
+ model: options.model
841
908
  });
842
- const data = await response.json();
843
- if (data.code === "PERMISSION_REQUIRED") {
844
- throw new LLMPermissionError(data.permission || "llm.embed");
845
- }
846
- if (data.code === "PROVIDER_UNAVAILABLE") {
847
- throw new LLMProviderError(data.error || "Embedding provider not available");
848
- }
849
- return data;
850
909
  }
851
910
  /**
852
911
  * Helper: Embed text and store as vectors in one call
@@ -937,7 +996,7 @@ var _RealtimeXSDK = class _RealtimeXSDK {
937
996
  this.api = new ApiModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
938
997
  this.task = new TaskModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
939
998
  this.port = new PortModule(config.defaultPort);
940
- this.llm = new LLMModule(this.realtimexUrl, this.appId, this.apiKey);
999
+ this.llm = new LLMModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
941
1000
  if (this.permissions.length > 0 && this.appId && !this.apiKey) {
942
1001
  this.register().catch((err) => {
943
1002
  console.error("[RealtimeX SDK] Auto-registration failed:", err.message);
@@ -1007,6 +1066,31 @@ var _RealtimeXSDK = class _RealtimeXSDK {
1007
1066
  throw new Error(`Connection failed: ${error.message}`);
1008
1067
  }
1009
1068
  }
1069
+ /**
1070
+ * Get the absolute path to the data directory for this app.
1071
+ * Path: ~/.realtimex.ai/Resources/local-apps/{appId}
1072
+ */
1073
+ async getAppDataDir() {
1074
+ try {
1075
+ const headers = { "Content-Type": "application/json" };
1076
+ if (this.apiKey) {
1077
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
1078
+ } else if (this.appId) {
1079
+ headers["x-app-id"] = this.appId;
1080
+ }
1081
+ const response = await fetch(`${this.realtimexUrl.replace(/\/$/, "")}/sdk/local-apps/data-dir`, {
1082
+ method: "GET",
1083
+ headers
1084
+ });
1085
+ const data = await response.json();
1086
+ if (!response.ok) {
1087
+ throw new Error(data.error || "Failed to get data directory");
1088
+ }
1089
+ return data.dataDir;
1090
+ } catch (error) {
1091
+ throw new Error(`Failed to get app data directory: ${error.message}`);
1092
+ }
1093
+ }
1010
1094
  };
1011
1095
  _RealtimeXSDK.DEFAULT_REALTIMEX_URL = "http://localhost:3001";
1012
1096
  var RealtimeXSDK = _RealtimeXSDK;
package/dist/index.mjs CHANGED
@@ -1,16 +1,18 @@
1
1
  // src/modules/api.ts
2
2
  var PermissionDeniedError = class extends Error {
3
- constructor(permission, message) {
3
+ constructor(permission, message, code = "PERMISSION_DENIED") {
4
4
  super(message || `Permission '${permission}' was denied`);
5
5
  this.name = "PermissionDeniedError";
6
6
  this.permission = permission;
7
+ this.code = code;
7
8
  }
8
9
  };
9
10
  var PermissionRequiredError = class extends Error {
10
- constructor(permission, message) {
11
+ constructor(permission, message, code = "PERMISSION_REQUIRED") {
11
12
  super(message || `Permission '${permission}' is required`);
12
13
  this.name = "PermissionRequiredError";
13
14
  this.permission = permission;
15
+ this.code = code;
14
16
  }
15
17
  };
16
18
  var ApiModule = class {
@@ -454,11 +456,9 @@ var PortModule = class {
454
456
  };
455
457
 
456
458
  // src/modules/llm.ts
457
- var LLMPermissionError = class extends Error {
459
+ var LLMPermissionError = class extends PermissionRequiredError {
458
460
  constructor(permission, code = "PERMISSION_REQUIRED") {
459
- super(`Permission required: ${permission}`);
460
- this.permission = permission;
461
- this.code = code;
461
+ super(permission, void 0, code);
462
462
  this.name = "LLMPermissionError";
463
463
  }
464
464
  };
@@ -470,9 +470,10 @@ var LLMProviderError = class extends Error {
470
470
  }
471
471
  };
472
472
  var VectorStore = class {
473
- constructor(baseUrl, appId, apiKey) {
473
+ constructor(baseUrl, appId, appName = "Local App", apiKey) {
474
474
  this.baseUrl = baseUrl;
475
475
  this.appId = appId;
476
+ this.appName = appName;
476
477
  this.apiKey = apiKey;
477
478
  }
478
479
  get headers() {
@@ -487,6 +488,52 @@ var VectorStore = class {
487
488
  "x-app-id": this.appId
488
489
  };
489
490
  }
491
+ /**
492
+ * Request a single permission from Electron via internal API
493
+ */
494
+ async requestPermission(permission) {
495
+ try {
496
+ const response = await fetch(`${this.baseUrl}/api/local-apps/request-permission`, {
497
+ method: "POST",
498
+ headers: { "Content-Type": "application/json" },
499
+ body: JSON.stringify({
500
+ app_id: this.appId,
501
+ app_name: this.appName,
502
+ permission
503
+ })
504
+ });
505
+ const data = await response.json();
506
+ return data.granted === true;
507
+ } catch (error) {
508
+ return false;
509
+ }
510
+ }
511
+ /**
512
+ * Internal request wrapper that handles automatic permission prompts
513
+ */
514
+ async request(method, endpoint, body) {
515
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
516
+ method,
517
+ headers: this.headers,
518
+ body: body ? JSON.stringify(body) : void 0
519
+ });
520
+ const data = await response.json();
521
+ if (data.code === "PERMISSION_REQUIRED") {
522
+ const permission = data.permission || "vectors.read";
523
+ const granted = await this.requestPermission(permission);
524
+ if (granted) {
525
+ return this.request(method, endpoint, body);
526
+ }
527
+ throw new PermissionDeniedError(permission);
528
+ }
529
+ if (!data.success && data.error) {
530
+ if (data.code === "LLM_ERROR") {
531
+ throw new LLMProviderError(data.error);
532
+ }
533
+ throw new Error(data.error);
534
+ }
535
+ return data;
536
+ }
490
537
  /**
491
538
  * Upsert (insert or update) vectors into storage
492
539
  *
@@ -498,19 +545,10 @@ var VectorStore = class {
498
545
  * ```
499
546
  */
500
547
  async upsert(vectors, options = {}) {
501
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/upsert`, {
502
- method: "POST",
503
- headers: this.headers,
504
- body: JSON.stringify({
505
- vectors,
506
- workspaceId: options.workspaceId
507
- })
548
+ return this.request("POST", "/sdk/llm/vectors/upsert", {
549
+ vectors,
550
+ workspaceId: options.workspaceId
508
551
  });
509
- const data = await response.json();
510
- if (data.code === "PERMISSION_REQUIRED") {
511
- throw new LLMPermissionError(data.permission || "vectors.write");
512
- }
513
- return data;
514
552
  }
515
553
  /**
516
554
  * Query similar vectors by embedding
@@ -525,21 +563,12 @@ var VectorStore = class {
525
563
  * ```
526
564
  */
527
565
  async query(vector, options = {}) {
528
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/query`, {
529
- method: "POST",
530
- headers: this.headers,
531
- body: JSON.stringify({
532
- vector,
533
- topK: options.topK ?? 5,
534
- filter: options.filter,
535
- workspaceId: options.workspaceId
536
- })
566
+ return this.request("POST", "/sdk/llm/vectors/query", {
567
+ vector,
568
+ topK: options.topK ?? 5,
569
+ filter: options.filter,
570
+ workspaceId: options.workspaceId
537
571
  });
538
- const data = await response.json();
539
- if (data.code === "PERMISSION_REQUIRED") {
540
- throw new LLMPermissionError(data.permission || "vectors.read");
541
- }
542
- return data;
543
572
  }
544
573
  /**
545
574
  * Delete vectors from storage
@@ -553,16 +582,7 @@ var VectorStore = class {
553
582
  * ```
554
583
  */
555
584
  async delete(options) {
556
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/delete`, {
557
- method: "POST",
558
- headers: this.headers,
559
- body: JSON.stringify(options)
560
- });
561
- const data = await response.json();
562
- if (data.code === "PERMISSION_REQUIRED") {
563
- throw new LLMPermissionError(data.permission || "vectors.write");
564
- }
565
- return data;
585
+ return this.request("POST", "/sdk/llm/vectors/delete", options);
566
586
  }
567
587
  /**
568
588
  * List all available workspaces (namespaces) for this app
@@ -574,23 +594,48 @@ var VectorStore = class {
574
594
  * ```
575
595
  */
576
596
  async listWorkspaces() {
577
- const response = await fetch(`${this.baseUrl}/sdk/llm/vectors/workspaces`, {
578
- method: "GET",
579
- headers: this.headers
597
+ return this.request("GET", "/sdk/llm/vectors/workspaces");
598
+ }
599
+ /**
600
+ * Register a custom vector database configuration for this app
601
+ *
602
+ * @example
603
+ * ```ts
604
+ * await sdk.llm.vectors.registerConfig('lancedb', { });
605
+ * ```
606
+ */
607
+ async registerConfig(provider, config) {
608
+ return this.request("POST", "/sdk/llm/vectors/register", {
609
+ provider,
610
+ config
580
611
  });
581
- const data = await response.json();
582
- if (data.code === "PERMISSION_REQUIRED") {
583
- throw new LLMPermissionError(data.permission || "vectors.read");
584
- }
585
- return data;
612
+ }
613
+ /**
614
+ * List all supported vector database providers and their configuration requirements
615
+ */
616
+ async listProviders() {
617
+ return this.request("GET", "/sdk/llm/vectors/providers");
618
+ }
619
+ /**
620
+ * Get the current vector database configuration for this app
621
+ *
622
+ * @example
623
+ * ```ts
624
+ * const { provider, config } = await sdk.llm.vectors.getConfig();
625
+ * console.log(`App is using ${provider}`);
626
+ * ```
627
+ */
628
+ async getConfig() {
629
+ return this.request("GET", "/sdk/llm/vectors/config");
586
630
  }
587
631
  };
588
632
  var LLMModule = class {
589
- constructor(baseUrl, appId, apiKey) {
633
+ constructor(baseUrl, appId, appName = "Local App", apiKey) {
590
634
  this.baseUrl = baseUrl;
591
635
  this.appId = appId;
636
+ this.appName = appName;
592
637
  this.apiKey = apiKey;
593
- this.vectors = new VectorStore(baseUrl, appId, apiKey);
638
+ this.vectors = new VectorStore(baseUrl, appId, appName, apiKey);
594
639
  }
595
640
  get headers() {
596
641
  if (this.apiKey) {
@@ -604,6 +649,52 @@ var LLMModule = class {
604
649
  "x-app-id": this.appId
605
650
  };
606
651
  }
652
+ /**
653
+ * Request a single permission from Electron via internal API
654
+ */
655
+ async requestPermission(permission) {
656
+ try {
657
+ const response = await fetch(`${this.baseUrl}/api/local-apps/request-permission`, {
658
+ method: "POST",
659
+ headers: { "Content-Type": "application/json" },
660
+ body: JSON.stringify({
661
+ app_id: this.appId,
662
+ app_name: this.appName,
663
+ permission
664
+ })
665
+ });
666
+ const data = await response.json();
667
+ return data.granted === true;
668
+ } catch (error) {
669
+ return false;
670
+ }
671
+ }
672
+ /**
673
+ * Internal request wrapper that handles automatic permission prompts
674
+ */
675
+ async request(method, endpoint, body) {
676
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
677
+ method,
678
+ headers: this.headers,
679
+ body: body ? JSON.stringify(body) : void 0
680
+ });
681
+ const data = await response.json();
682
+ if (data.code === "PERMISSION_REQUIRED") {
683
+ const permission = data.permission || "llm.chat";
684
+ const granted = await this.requestPermission(permission);
685
+ if (granted) {
686
+ return this.request(method, endpoint, body);
687
+ }
688
+ throw new PermissionDeniedError(permission);
689
+ }
690
+ if (!data.success && data.error) {
691
+ if (data.code === "LLM_ERROR") {
692
+ throw new LLMProviderError(data.error);
693
+ }
694
+ throw new Error(data.error);
695
+ }
696
+ return data;
697
+ }
607
698
  /**
608
699
  * Get only configured chat (LLM) providers
609
700
  *
@@ -614,15 +705,7 @@ var LLMModule = class {
614
705
  * ```
615
706
  */
616
707
  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;
708
+ return this.request("GET", "/sdk/llm/providers/chat");
626
709
  }
627
710
  /**
628
711
  * Get only configured embedding providers
@@ -634,15 +717,7 @@ var LLMModule = class {
634
717
  * ```
635
718
  */
636
719
  async embedProviders() {
637
- const response = await fetch(`${this.baseUrl}/sdk/llm/providers/embed`, {
638
- method: "GET",
639
- headers: this.headers
640
- });
641
- const data = await response.json();
642
- if (data.code === "PERMISSION_REQUIRED") {
643
- throw new LLMPermissionError(data.permission || "llm.providers");
644
- }
645
- return data;
720
+ return this.request("GET", "/sdk/llm/providers/embed");
646
721
  }
647
722
  /**
648
723
  * Send a chat completion request (synchronous)
@@ -658,25 +733,14 @@ var LLMModule = class {
658
733
  * ```
659
734
  */
660
735
  async chat(messages, options = {}) {
661
- const response = await fetch(`${this.baseUrl}/sdk/llm/chat`, {
662
- method: "POST",
663
- headers: this.headers,
664
- body: JSON.stringify({
665
- messages,
666
- model: options.model,
667
- provider: options.provider,
668
- temperature: options.temperature ?? 0.7,
669
- max_tokens: options.max_tokens ?? 1e3
670
- })
736
+ return this.request("POST", "/sdk/llm/chat", {
737
+ messages,
738
+ model: options.model,
739
+ provider: options.provider,
740
+ temperature: options.temperature ?? 0.7,
741
+ max_tokens: options.max_tokens ?? 1e3,
742
+ response_format: options.response_format
671
743
  });
672
- const data = await response.json();
673
- if (data.code === "PERMISSION_REQUIRED") {
674
- throw new LLMPermissionError(data.permission || "llm.chat");
675
- }
676
- if (data.code === "LLM_ERROR") {
677
- throw new LLMProviderError(data.error || "LLM request failed");
678
- }
679
- return data;
680
744
  }
681
745
  /**
682
746
  * Send a streaming chat completion request (SSE)
@@ -702,13 +766,20 @@ var LLMModule = class {
702
766
  model: options.model,
703
767
  provider: options.provider,
704
768
  temperature: options.temperature ?? 0.7,
705
- max_tokens: options.max_tokens ?? 1e3
769
+ max_tokens: options.max_tokens ?? 1e3,
770
+ response_format: options.response_format
706
771
  })
707
772
  });
708
773
  if (!response.ok) {
709
774
  const errorData = await response.json();
710
775
  if (errorData.code === "PERMISSION_REQUIRED") {
711
- throw new LLMPermissionError(errorData.permission || "llm.chat");
776
+ const permission = errorData.permission || "llm.chat";
777
+ const granted = await this.requestPermission(permission);
778
+ if (granted) {
779
+ yield* this.chatStream(messages, options);
780
+ return;
781
+ }
782
+ throw new PermissionDeniedError(permission);
712
783
  }
713
784
  throw new LLMProviderError(errorData.error || "Stream request failed");
714
785
  }
@@ -783,23 +854,11 @@ var LLMModule = class {
783
854
  */
784
855
  async embed(input, options = {}) {
785
856
  const inputArray = Array.isArray(input) ? input : [input];
786
- const response = await fetch(`${this.baseUrl}/sdk/llm/embed`, {
787
- method: "POST",
788
- headers: this.headers,
789
- body: JSON.stringify({
790
- input: inputArray,
791
- provider: options.provider,
792
- model: options.model
793
- })
857
+ return this.request("POST", "/sdk/llm/embed", {
858
+ input: inputArray,
859
+ provider: options.provider,
860
+ model: options.model
794
861
  });
795
- const data = await response.json();
796
- if (data.code === "PERMISSION_REQUIRED") {
797
- throw new LLMPermissionError(data.permission || "llm.embed");
798
- }
799
- if (data.code === "PROVIDER_UNAVAILABLE") {
800
- throw new LLMProviderError(data.error || "Embedding provider not available");
801
- }
802
- return data;
803
862
  }
804
863
  /**
805
864
  * Helper: Embed text and store as vectors in one call
@@ -890,7 +949,7 @@ var _RealtimeXSDK = class _RealtimeXSDK {
890
949
  this.api = new ApiModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
891
950
  this.task = new TaskModule(this.realtimexUrl, this.appName, this.appId, this.apiKey);
892
951
  this.port = new PortModule(config.defaultPort);
893
- this.llm = new LLMModule(this.realtimexUrl, this.appId, this.apiKey);
952
+ this.llm = new LLMModule(this.realtimexUrl, this.appId, this.appName, this.apiKey);
894
953
  if (this.permissions.length > 0 && this.appId && !this.apiKey) {
895
954
  this.register().catch((err) => {
896
955
  console.error("[RealtimeX SDK] Auto-registration failed:", err.message);
@@ -960,6 +1019,31 @@ var _RealtimeXSDK = class _RealtimeXSDK {
960
1019
  throw new Error(`Connection failed: ${error.message}`);
961
1020
  }
962
1021
  }
1022
+ /**
1023
+ * Get the absolute path to the data directory for this app.
1024
+ * Path: ~/.realtimex.ai/Resources/local-apps/{appId}
1025
+ */
1026
+ async getAppDataDir() {
1027
+ try {
1028
+ const headers = { "Content-Type": "application/json" };
1029
+ if (this.apiKey) {
1030
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
1031
+ } else if (this.appId) {
1032
+ headers["x-app-id"] = this.appId;
1033
+ }
1034
+ const response = await fetch(`${this.realtimexUrl.replace(/\/$/, "")}/sdk/local-apps/data-dir`, {
1035
+ method: "GET",
1036
+ headers
1037
+ });
1038
+ const data = await response.json();
1039
+ if (!response.ok) {
1040
+ throw new Error(data.error || "Failed to get data directory");
1041
+ }
1042
+ return data.dataDir;
1043
+ } catch (error) {
1044
+ throw new Error(`Failed to get app data directory: ${error.message}`);
1045
+ }
1046
+ }
963
1047
  };
964
1048
  _RealtimeXSDK.DEFAULT_REALTIMEX_URL = "http://localhost:3001";
965
1049
  var RealtimeXSDK = _RealtimeXSDK;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realtimex/sdk",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "SDK for building Local Apps that integrate with RealtimeX",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",