@mnexium/sdk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -258,6 +258,15 @@ interface MnxOptions {
258
258
  metadata?: Record<string, unknown>;
259
259
  /** Force regenerate trial key (for key recovery) */
260
260
  regenerateKey?: boolean;
261
+ /** Records configuration */
262
+ records?: {
263
+ /** Enable record recall (inject existing records as context) */
264
+ recall?: boolean;
265
+ /** Enable record extraction: true = async, "sync" = await and return results (non-streaming only) */
266
+ learn?: boolean | 'sync';
267
+ /** Limit extraction to specific record types */
268
+ types?: string[];
269
+ };
261
270
  }
262
271
  interface ChatCompletionOptions extends MnxOptions {
263
272
  /** Model to use (e.g., 'gpt-4o-mini', 'claude-3-sonnet', 'gemini-1.5-pro') */
@@ -419,6 +428,74 @@ interface SystemPromptCreateOptions {
419
428
  /** Set as default prompt for the project */
420
429
  isDefault?: boolean;
421
430
  }
431
+ /** A record schema definition */
432
+ interface RecordSchema {
433
+ project_id: string;
434
+ type_name: string;
435
+ fields: Record<string, RecordFieldDef>;
436
+ display_name?: string;
437
+ description?: string;
438
+ created_at: string;
439
+ updated_at: string;
440
+ }
441
+ /** A field definition within a record schema */
442
+ interface RecordFieldDef {
443
+ type: string;
444
+ required?: boolean;
445
+ description?: string;
446
+ display_name?: string;
447
+ }
448
+ /** Options for defining a record schema */
449
+ interface RecordSchemaDefineOptions {
450
+ /** Record type name (e.g. 'deal', 'contact') */
451
+ typeName: string;
452
+ /** Field definitions */
453
+ fields: Record<string, RecordFieldDef>;
454
+ /** Human-readable display name */
455
+ displayName?: string;
456
+ /** Description of this record type */
457
+ description?: string;
458
+ }
459
+ /** A record instance */
460
+ interface MnxRecord {
461
+ record_id: string;
462
+ project_id: string;
463
+ type_name: string;
464
+ owner_id?: string;
465
+ visibility: 'public' | 'private';
466
+ collaborators?: string[];
467
+ data: globalThis.Record<string, unknown>;
468
+ summary_text?: string;
469
+ is_deleted?: boolean;
470
+ created_at: string;
471
+ updated_at: string;
472
+ }
473
+ /** Options for inserting a record */
474
+ interface RecordInsertOptions {
475
+ /** Record data */
476
+ data: globalThis.Record<string, unknown>;
477
+ /** Owner subject ID */
478
+ ownerId?: string;
479
+ /** Visibility: 'public' (default) or 'private' */
480
+ visibility?: 'public' | 'private';
481
+ /** Subject IDs with write access (in addition to the owner) */
482
+ collaborators?: string[];
483
+ }
484
+ /** Options for querying records */
485
+ interface RecordQueryOptions {
486
+ /** JSONB field filters */
487
+ where?: globalThis.Record<string, unknown>;
488
+ /** Order by field (prefix with - for DESC) */
489
+ orderBy?: string;
490
+ /** Maximum results */
491
+ limit?: number;
492
+ /** Offset for pagination */
493
+ offset?: number;
494
+ }
495
+ /** A record search result with similarity score */
496
+ interface RecordSearchResult extends MnxRecord {
497
+ similarity: number;
498
+ }
422
499
 
423
500
  /**
424
501
  * Streaming support for Mnexium SDK
@@ -597,6 +674,7 @@ declare class SubjectMemoriesResource {
597
674
  source?: string;
598
675
  visibility?: 'private' | 'shared';
599
676
  metadata?: Record<string, unknown>;
677
+ no_supersede?: boolean;
600
678
  }): Promise<any>;
601
679
  list(options?: {
602
680
  limit?: number;
@@ -731,7 +809,13 @@ declare class ChatResource {
731
809
  declare class ChatCompletionsResource {
732
810
  private readonly client;
733
811
  constructor(client: Mnexium);
734
- create(options: ChatCompletionOptions): Promise<ChatCompletionResponse>;
812
+ create(options: ChatCompletionOptions & {
813
+ stream: true;
814
+ }): Promise<StreamResponse>;
815
+ create(options: ChatCompletionOptions & {
816
+ stream?: false;
817
+ }): Promise<ChatCompletionResponse>;
818
+ create(options: ChatCompletionOptions): Promise<ChatCompletionResponse | StreamResponse>;
735
819
  }
736
820
 
737
821
  /**
@@ -806,6 +890,84 @@ declare class PromptsResource {
806
890
  }): Promise<any>;
807
891
  }
808
892
 
893
+ /**
894
+ * Records Resource - Structured data management API
895
+ */
896
+
897
+ declare class RecordsResource {
898
+ private readonly client;
899
+ constructor(client: Mnexium);
900
+ /**
901
+ * Define or update a record schema
902
+ *
903
+ * @example
904
+ * await mnx.records.defineSchema('deal', {
905
+ * title: { type: 'string', required: true },
906
+ * value: { type: 'number' },
907
+ * stage: { type: 'string' },
908
+ * account_id: { type: 'ref:account' },
909
+ * }, { displayName: 'Deal', description: 'Sales deals' });
910
+ */
911
+ defineSchema(typeName: string, fields: RecordSchemaDefineOptions['fields'], opts?: {
912
+ displayName?: string;
913
+ description?: string;
914
+ }): Promise<RecordSchema>;
915
+ /**
916
+ * Get a schema by type name
917
+ */
918
+ getSchema(typeName: string): Promise<RecordSchema | null>;
919
+ /**
920
+ * List all schemas for the project
921
+ */
922
+ listSchemas(): Promise<RecordSchema[]>;
923
+ /**
924
+ * Insert a new record
925
+ *
926
+ * @example
927
+ * const deal = await mnx.records.insert('deal', {
928
+ * title: 'Acme Renewal',
929
+ * value: 500000,
930
+ * stage: 'negotiation',
931
+ * });
932
+ */
933
+ insert(typeName: string, data: Record<string, unknown>, opts?: Omit<RecordInsertOptions, 'data'>): Promise<MnxRecord>;
934
+ /**
935
+ * Get a record by ID
936
+ */
937
+ get(typeName: string, recordId: string): Promise<MnxRecord | null>;
938
+ /**
939
+ * Update a record (partial merge)
940
+ *
941
+ * @example
942
+ * await mnx.records.update('deal', 'rec_abc', { stage: 'closed_won', value: 550000 });
943
+ */
944
+ update(typeName: string, recordId: string, data: Record<string, unknown>): Promise<MnxRecord>;
945
+ /**
946
+ * Soft-delete a record
947
+ */
948
+ delete(typeName: string, recordId: string): Promise<void>;
949
+ /**
950
+ * Query records with JSONB filters
951
+ *
952
+ * @example
953
+ * const deals = await mnx.records.query('deal', {
954
+ * where: { stage: 'closed_won' },
955
+ * orderBy: '-value',
956
+ * limit: 10,
957
+ * });
958
+ */
959
+ query(typeName: string, opts?: RecordQueryOptions): Promise<MnxRecord[]>;
960
+ /**
961
+ * Semantic search across records
962
+ *
963
+ * @example
964
+ * const results = await mnx.records.search('deal', 'large enterprise renewal');
965
+ */
966
+ search(typeName: string, query: string, opts?: {
967
+ limit?: number;
968
+ }): Promise<RecordSearchResult[]>;
969
+ }
970
+
809
971
  /**
810
972
  * Mnexium SDK Client
811
973
  */
@@ -826,6 +988,7 @@ declare class Mnexium {
826
988
  readonly profiles: ProfilesResource;
827
989
  readonly state: StateResource;
828
990
  readonly prompts: PromptsResource;
991
+ readonly records: RecordsResource;
829
992
  constructor(config?: MnexiumConfig);
830
993
  /**
831
994
  * Process a message with Mnexium's memory-enhanced AI
@@ -903,6 +1066,7 @@ declare class Mnexium {
903
1066
  body?: unknown;
904
1067
  headers?: Record<string, string>;
905
1068
  query?: Record<string, string | number | boolean | undefined>;
1069
+ signal?: AbortSignal;
906
1070
  }): Promise<Response>;
907
1071
  /**
908
1072
  * Internal: Make an API request
package/dist/index.d.ts CHANGED
@@ -258,6 +258,15 @@ interface MnxOptions {
258
258
  metadata?: Record<string, unknown>;
259
259
  /** Force regenerate trial key (for key recovery) */
260
260
  regenerateKey?: boolean;
261
+ /** Records configuration */
262
+ records?: {
263
+ /** Enable record recall (inject existing records as context) */
264
+ recall?: boolean;
265
+ /** Enable record extraction: true = async, "sync" = await and return results (non-streaming only) */
266
+ learn?: boolean | 'sync';
267
+ /** Limit extraction to specific record types */
268
+ types?: string[];
269
+ };
261
270
  }
262
271
  interface ChatCompletionOptions extends MnxOptions {
263
272
  /** Model to use (e.g., 'gpt-4o-mini', 'claude-3-sonnet', 'gemini-1.5-pro') */
@@ -419,6 +428,74 @@ interface SystemPromptCreateOptions {
419
428
  /** Set as default prompt for the project */
420
429
  isDefault?: boolean;
421
430
  }
431
+ /** A record schema definition */
432
+ interface RecordSchema {
433
+ project_id: string;
434
+ type_name: string;
435
+ fields: Record<string, RecordFieldDef>;
436
+ display_name?: string;
437
+ description?: string;
438
+ created_at: string;
439
+ updated_at: string;
440
+ }
441
+ /** A field definition within a record schema */
442
+ interface RecordFieldDef {
443
+ type: string;
444
+ required?: boolean;
445
+ description?: string;
446
+ display_name?: string;
447
+ }
448
+ /** Options for defining a record schema */
449
+ interface RecordSchemaDefineOptions {
450
+ /** Record type name (e.g. 'deal', 'contact') */
451
+ typeName: string;
452
+ /** Field definitions */
453
+ fields: Record<string, RecordFieldDef>;
454
+ /** Human-readable display name */
455
+ displayName?: string;
456
+ /** Description of this record type */
457
+ description?: string;
458
+ }
459
+ /** A record instance */
460
+ interface MnxRecord {
461
+ record_id: string;
462
+ project_id: string;
463
+ type_name: string;
464
+ owner_id?: string;
465
+ visibility: 'public' | 'private';
466
+ collaborators?: string[];
467
+ data: globalThis.Record<string, unknown>;
468
+ summary_text?: string;
469
+ is_deleted?: boolean;
470
+ created_at: string;
471
+ updated_at: string;
472
+ }
473
+ /** Options for inserting a record */
474
+ interface RecordInsertOptions {
475
+ /** Record data */
476
+ data: globalThis.Record<string, unknown>;
477
+ /** Owner subject ID */
478
+ ownerId?: string;
479
+ /** Visibility: 'public' (default) or 'private' */
480
+ visibility?: 'public' | 'private';
481
+ /** Subject IDs with write access (in addition to the owner) */
482
+ collaborators?: string[];
483
+ }
484
+ /** Options for querying records */
485
+ interface RecordQueryOptions {
486
+ /** JSONB field filters */
487
+ where?: globalThis.Record<string, unknown>;
488
+ /** Order by field (prefix with - for DESC) */
489
+ orderBy?: string;
490
+ /** Maximum results */
491
+ limit?: number;
492
+ /** Offset for pagination */
493
+ offset?: number;
494
+ }
495
+ /** A record search result with similarity score */
496
+ interface RecordSearchResult extends MnxRecord {
497
+ similarity: number;
498
+ }
422
499
 
423
500
  /**
424
501
  * Streaming support for Mnexium SDK
@@ -597,6 +674,7 @@ declare class SubjectMemoriesResource {
597
674
  source?: string;
598
675
  visibility?: 'private' | 'shared';
599
676
  metadata?: Record<string, unknown>;
677
+ no_supersede?: boolean;
600
678
  }): Promise<any>;
601
679
  list(options?: {
602
680
  limit?: number;
@@ -731,7 +809,13 @@ declare class ChatResource {
731
809
  declare class ChatCompletionsResource {
732
810
  private readonly client;
733
811
  constructor(client: Mnexium);
734
- create(options: ChatCompletionOptions): Promise<ChatCompletionResponse>;
812
+ create(options: ChatCompletionOptions & {
813
+ stream: true;
814
+ }): Promise<StreamResponse>;
815
+ create(options: ChatCompletionOptions & {
816
+ stream?: false;
817
+ }): Promise<ChatCompletionResponse>;
818
+ create(options: ChatCompletionOptions): Promise<ChatCompletionResponse | StreamResponse>;
735
819
  }
736
820
 
737
821
  /**
@@ -806,6 +890,84 @@ declare class PromptsResource {
806
890
  }): Promise<any>;
807
891
  }
808
892
 
893
+ /**
894
+ * Records Resource - Structured data management API
895
+ */
896
+
897
+ declare class RecordsResource {
898
+ private readonly client;
899
+ constructor(client: Mnexium);
900
+ /**
901
+ * Define or update a record schema
902
+ *
903
+ * @example
904
+ * await mnx.records.defineSchema('deal', {
905
+ * title: { type: 'string', required: true },
906
+ * value: { type: 'number' },
907
+ * stage: { type: 'string' },
908
+ * account_id: { type: 'ref:account' },
909
+ * }, { displayName: 'Deal', description: 'Sales deals' });
910
+ */
911
+ defineSchema(typeName: string, fields: RecordSchemaDefineOptions['fields'], opts?: {
912
+ displayName?: string;
913
+ description?: string;
914
+ }): Promise<RecordSchema>;
915
+ /**
916
+ * Get a schema by type name
917
+ */
918
+ getSchema(typeName: string): Promise<RecordSchema | null>;
919
+ /**
920
+ * List all schemas for the project
921
+ */
922
+ listSchemas(): Promise<RecordSchema[]>;
923
+ /**
924
+ * Insert a new record
925
+ *
926
+ * @example
927
+ * const deal = await mnx.records.insert('deal', {
928
+ * title: 'Acme Renewal',
929
+ * value: 500000,
930
+ * stage: 'negotiation',
931
+ * });
932
+ */
933
+ insert(typeName: string, data: Record<string, unknown>, opts?: Omit<RecordInsertOptions, 'data'>): Promise<MnxRecord>;
934
+ /**
935
+ * Get a record by ID
936
+ */
937
+ get(typeName: string, recordId: string): Promise<MnxRecord | null>;
938
+ /**
939
+ * Update a record (partial merge)
940
+ *
941
+ * @example
942
+ * await mnx.records.update('deal', 'rec_abc', { stage: 'closed_won', value: 550000 });
943
+ */
944
+ update(typeName: string, recordId: string, data: Record<string, unknown>): Promise<MnxRecord>;
945
+ /**
946
+ * Soft-delete a record
947
+ */
948
+ delete(typeName: string, recordId: string): Promise<void>;
949
+ /**
950
+ * Query records with JSONB filters
951
+ *
952
+ * @example
953
+ * const deals = await mnx.records.query('deal', {
954
+ * where: { stage: 'closed_won' },
955
+ * orderBy: '-value',
956
+ * limit: 10,
957
+ * });
958
+ */
959
+ query(typeName: string, opts?: RecordQueryOptions): Promise<MnxRecord[]>;
960
+ /**
961
+ * Semantic search across records
962
+ *
963
+ * @example
964
+ * const results = await mnx.records.search('deal', 'large enterprise renewal');
965
+ */
966
+ search(typeName: string, query: string, opts?: {
967
+ limit?: number;
968
+ }): Promise<RecordSearchResult[]>;
969
+ }
970
+
809
971
  /**
810
972
  * Mnexium SDK Client
811
973
  */
@@ -826,6 +988,7 @@ declare class Mnexium {
826
988
  readonly profiles: ProfilesResource;
827
989
  readonly state: StateResource;
828
990
  readonly prompts: PromptsResource;
991
+ readonly records: RecordsResource;
829
992
  constructor(config?: MnexiumConfig);
830
993
  /**
831
994
  * Process a message with Mnexium's memory-enhanced AI
@@ -903,6 +1066,7 @@ declare class Mnexium {
903
1066
  body?: unknown;
904
1067
  headers?: Record<string, string>;
905
1068
  query?: Record<string, string | number | boolean | undefined>;
1069
+ signal?: AbortSignal;
906
1070
  }): Promise<Response>;
907
1071
  /**
908
1072
  * Internal: Make an API request
package/dist/index.js CHANGED
@@ -116,7 +116,8 @@ var EventStream = class {
116
116
  }
117
117
  async *[Symbol.asyncIterator]() {
118
118
  const response = await this.client._requestRaw("GET", "/events/memories", {
119
- query: { subject_id: this.subjectId }
119
+ query: { subject_id: this.subjectId },
120
+ signal: this.abortController.signal
120
121
  });
121
122
  if (!response.body) {
122
123
  throw new Error("Response body is null \u2014 SSE not supported");
@@ -205,7 +206,8 @@ var SubjectMemoriesResource = class {
205
206
  text,
206
207
  source: options?.source,
207
208
  visibility: options?.visibility,
208
- metadata: options?.metadata
209
+ metadata: options?.metadata,
210
+ no_supersede: options?.no_supersede
209
211
  }
210
212
  });
211
213
  }
@@ -619,9 +621,23 @@ var ChatCompletionsResource = class {
619
621
  state: options.state,
620
622
  system_prompt: options.systemPrompt,
621
623
  metadata: options.metadata,
622
- regenerate_key: options.regenerateKey
624
+ regenerate_key: options.regenerateKey,
625
+ records: options.records
623
626
  }
624
627
  };
628
+ if (options.stream) {
629
+ const response = await this.client._requestRaw("POST", "/chat/completions", {
630
+ body,
631
+ headers
632
+ });
633
+ return new StreamResponse(response, {
634
+ chatId: response.headers.get("X-Mnx-Chat-Id") || options.chatId || "",
635
+ subjectId: response.headers.get("X-Mnx-Subject-Id") || options.subjectId || "",
636
+ model: options.model,
637
+ provisionedKey: response.headers.get("X-Mnx-Key-Provisioned") || void 0,
638
+ claimUrl: response.headers.get("X-Mnx-Claim-Url") || void 0
639
+ });
640
+ }
625
641
  return this.client._request("POST", "/chat/completions", {
626
642
  body,
627
643
  headers
@@ -656,20 +672,18 @@ var MemoriesResource = class {
656
672
  offset: options?.offset
657
673
  }
658
674
  });
659
- return response.memories;
675
+ return response.data || [];
660
676
  }
661
677
  async search(options) {
662
- const response = await this.client._request("POST", "/memories/search", {
663
- body: {
678
+ const response = await this.client._request("GET", "/memories/search", {
679
+ query: {
664
680
  subject_id: options.subjectId,
665
- query: options.query,
681
+ q: options.query,
666
682
  limit: options.limit,
667
- min_score: options.minScore,
668
- include_deleted: options.includeDeleted,
669
- include_superseded: options.includeSuperseded
683
+ min_score: options.minScore
670
684
  }
671
685
  });
672
- return response.results;
686
+ return response.data || [];
673
687
  }
674
688
  async delete(id) {
675
689
  await this.client._request("DELETE", `/memories/${id}`);
@@ -734,7 +748,7 @@ var StateResource = class {
734
748
  async get(key, subjectId) {
735
749
  try {
736
750
  return await this.client._request("GET", `/state/${key}`, {
737
- query: subjectId ? { subject_id: subjectId } : void 0
751
+ headers: subjectId ? { "x-subject-id": subjectId } : void 0
738
752
  });
739
753
  } catch (error) {
740
754
  if (error instanceof NotFoundError) {
@@ -744,17 +758,21 @@ var StateResource = class {
744
758
  }
745
759
  }
746
760
  async set(options) {
747
- return this.client._request("POST", `/state/${options.key}`, {
761
+ const headers = {};
762
+ if (options.subjectId) {
763
+ headers["x-subject-id"] = options.subjectId;
764
+ }
765
+ return this.client._request("PUT", `/state/${options.key}`, {
766
+ headers,
748
767
  body: {
749
768
  value: options.value,
750
- subject_id: options.subjectId,
751
769
  ttl_seconds: options.ttlSeconds
752
770
  }
753
771
  });
754
772
  }
755
773
  async delete(key, subjectId) {
756
774
  await this.client._request("DELETE", `/state/${key}`, {
757
- query: subjectId ? { subject_id: subjectId } : void 0
775
+ headers: subjectId ? { "x-subject-id": subjectId } : void 0
758
776
  });
759
777
  }
760
778
  };
@@ -804,6 +822,136 @@ var PromptsResource = class {
804
822
  }
805
823
  };
806
824
 
825
+ // src/resources/records.ts
826
+ var RecordsResource = class {
827
+ constructor(client) {
828
+ this.client = client;
829
+ }
830
+ /**
831
+ * Define or update a record schema
832
+ *
833
+ * @example
834
+ * await mnx.records.defineSchema('deal', {
835
+ * title: { type: 'string', required: true },
836
+ * value: { type: 'number' },
837
+ * stage: { type: 'string' },
838
+ * account_id: { type: 'ref:account' },
839
+ * }, { displayName: 'Deal', description: 'Sales deals' });
840
+ */
841
+ async defineSchema(typeName, fields, opts) {
842
+ return this.client._request("POST", "/records/schemas", {
843
+ body: {
844
+ type_name: typeName,
845
+ fields,
846
+ display_name: opts?.displayName,
847
+ description: opts?.description
848
+ }
849
+ });
850
+ }
851
+ /**
852
+ * Get a schema by type name
853
+ */
854
+ async getSchema(typeName) {
855
+ try {
856
+ return await this.client._request("GET", `/records/schemas/${typeName}`);
857
+ } catch (error) {
858
+ if (error instanceof NotFoundError) return null;
859
+ throw error;
860
+ }
861
+ }
862
+ /**
863
+ * List all schemas for the project
864
+ */
865
+ async listSchemas() {
866
+ const response = await this.client._request("GET", "/records/schemas");
867
+ return response.schemas;
868
+ }
869
+ /**
870
+ * Insert a new record
871
+ *
872
+ * @example
873
+ * const deal = await mnx.records.insert('deal', {
874
+ * title: 'Acme Renewal',
875
+ * value: 500000,
876
+ * stage: 'negotiation',
877
+ * });
878
+ */
879
+ async insert(typeName, data, opts) {
880
+ return this.client._request("POST", `/records/${typeName}`, {
881
+ body: {
882
+ data,
883
+ owner_id: opts?.ownerId,
884
+ visibility: opts?.visibility,
885
+ collaborators: opts?.collaborators
886
+ }
887
+ });
888
+ }
889
+ /**
890
+ * Get a record by ID
891
+ */
892
+ async get(typeName, recordId) {
893
+ try {
894
+ return await this.client._request("GET", `/records/${typeName}/${recordId}`);
895
+ } catch (error) {
896
+ if (error instanceof NotFoundError) return null;
897
+ throw error;
898
+ }
899
+ }
900
+ /**
901
+ * Update a record (partial merge)
902
+ *
903
+ * @example
904
+ * await mnx.records.update('deal', 'rec_abc', { stage: 'closed_won', value: 550000 });
905
+ */
906
+ async update(typeName, recordId, data) {
907
+ return this.client._request("PUT", `/records/${typeName}/${recordId}`, {
908
+ body: { data }
909
+ });
910
+ }
911
+ /**
912
+ * Soft-delete a record
913
+ */
914
+ async delete(typeName, recordId) {
915
+ await this.client._request("DELETE", `/records/${typeName}/${recordId}`);
916
+ }
917
+ /**
918
+ * Query records with JSONB filters
919
+ *
920
+ * @example
921
+ * const deals = await mnx.records.query('deal', {
922
+ * where: { stage: 'closed_won' },
923
+ * orderBy: '-value',
924
+ * limit: 10,
925
+ * });
926
+ */
927
+ async query(typeName, opts) {
928
+ const response = await this.client._request("POST", `/records/${typeName}/query`, {
929
+ body: {
930
+ where: opts?.where,
931
+ order_by: opts?.orderBy,
932
+ limit: opts?.limit,
933
+ offset: opts?.offset
934
+ }
935
+ });
936
+ return response.records;
937
+ }
938
+ /**
939
+ * Semantic search across records
940
+ *
941
+ * @example
942
+ * const results = await mnx.records.search('deal', 'large enterprise renewal');
943
+ */
944
+ async search(typeName, query, opts) {
945
+ const response = await this.client._request("POST", `/records/${typeName}/search`, {
946
+ body: {
947
+ query,
948
+ limit: opts?.limit
949
+ }
950
+ });
951
+ return response.records;
952
+ }
953
+ };
954
+
807
955
  // src/client.ts
808
956
  var DEFAULT_BASE_URL = "https://mnexium.com/api/v1";
809
957
  var DEFAULT_TIMEOUT = 3e4;
@@ -833,6 +981,7 @@ var Mnexium = class {
833
981
  this.profiles = new ProfilesResource(this);
834
982
  this.state = new StateResource(this);
835
983
  this.prompts = new PromptsResource(this);
984
+ this.records = new RecordsResource(this);
836
985
  }
837
986
  async process(input) {
838
987
  const options = typeof input === "string" ? { content: input } : input;
@@ -1003,13 +1152,20 @@ var Mnexium = class {
1003
1152
  }
1004
1153
  const controller = new AbortController();
1005
1154
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1006
- const response = await fetch(url.toString(), {
1007
- method,
1008
- headers,
1009
- body: options.body ? JSON.stringify(options.body) : void 0,
1010
- signal: controller.signal
1011
- });
1012
- clearTimeout(timeoutId);
1155
+ if (options.signal) {
1156
+ options.signal.addEventListener("abort", () => controller.abort(), { once: true });
1157
+ }
1158
+ let response;
1159
+ try {
1160
+ response = await fetch(url.toString(), {
1161
+ method,
1162
+ headers,
1163
+ body: options.body ? JSON.stringify(options.body) : void 0,
1164
+ signal: controller.signal
1165
+ });
1166
+ } finally {
1167
+ clearTimeout(timeoutId);
1168
+ }
1013
1169
  const provisionedKey = response.headers.get("x-mnx-key-provisioned");
1014
1170
  if (provisionedKey) {
1015
1171
  this._setProvisionedKey(provisionedKey);
@@ -1042,16 +1198,15 @@ var Mnexium = class {
1042
1198
  }
1043
1199
  let lastError;
1044
1200
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
1201
+ const controller = new AbortController();
1202
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1045
1203
  try {
1046
- const controller = new AbortController();
1047
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1048
1204
  const response = await fetch(url.toString(), {
1049
1205
  method,
1050
1206
  headers,
1051
1207
  body: options.body ? JSON.stringify(options.body) : void 0,
1052
1208
  signal: controller.signal
1053
1209
  });
1054
- clearTimeout(timeoutId);
1055
1210
  const provisionedKey = response.headers.get("x-mnx-key-provisioned");
1056
1211
  if (provisionedKey) {
1057
1212
  this._setProvisionedKey(provisionedKey);
@@ -1060,7 +1215,14 @@ var Mnexium = class {
1060
1215
  const errorBody = await response.json().catch(() => ({}));
1061
1216
  throw this._handleErrorResponse(response.status, errorBody);
1062
1217
  }
1063
- return await response.json();
1218
+ if (response.status === 204) {
1219
+ return void 0;
1220
+ }
1221
+ const text = await response.text();
1222
+ if (!text) {
1223
+ return void 0;
1224
+ }
1225
+ return JSON.parse(text);
1064
1226
  } catch (error) {
1065
1227
  lastError = error;
1066
1228
  if (error instanceof APIError && error.status < 500 && !(error instanceof RateLimitError)) {
@@ -1070,6 +1232,8 @@ var Mnexium = class {
1070
1232
  throw error;
1071
1233
  }
1072
1234
  await this._sleep(Math.pow(2, attempt) * 1e3);
1235
+ } finally {
1236
+ clearTimeout(timeoutId);
1073
1237
  }
1074
1238
  }
1075
1239
  throw lastError || new MnexiumError("Request failed");
package/dist/index.mjs CHANGED
@@ -81,7 +81,8 @@ var EventStream = class {
81
81
  }
82
82
  async *[Symbol.asyncIterator]() {
83
83
  const response = await this.client._requestRaw("GET", "/events/memories", {
84
- query: { subject_id: this.subjectId }
84
+ query: { subject_id: this.subjectId },
85
+ signal: this.abortController.signal
85
86
  });
86
87
  if (!response.body) {
87
88
  throw new Error("Response body is null \u2014 SSE not supported");
@@ -170,7 +171,8 @@ var SubjectMemoriesResource = class {
170
171
  text,
171
172
  source: options?.source,
172
173
  visibility: options?.visibility,
173
- metadata: options?.metadata
174
+ metadata: options?.metadata,
175
+ no_supersede: options?.no_supersede
174
176
  }
175
177
  });
176
178
  }
@@ -584,9 +586,23 @@ var ChatCompletionsResource = class {
584
586
  state: options.state,
585
587
  system_prompt: options.systemPrompt,
586
588
  metadata: options.metadata,
587
- regenerate_key: options.regenerateKey
589
+ regenerate_key: options.regenerateKey,
590
+ records: options.records
588
591
  }
589
592
  };
593
+ if (options.stream) {
594
+ const response = await this.client._requestRaw("POST", "/chat/completions", {
595
+ body,
596
+ headers
597
+ });
598
+ return new StreamResponse(response, {
599
+ chatId: response.headers.get("X-Mnx-Chat-Id") || options.chatId || "",
600
+ subjectId: response.headers.get("X-Mnx-Subject-Id") || options.subjectId || "",
601
+ model: options.model,
602
+ provisionedKey: response.headers.get("X-Mnx-Key-Provisioned") || void 0,
603
+ claimUrl: response.headers.get("X-Mnx-Claim-Url") || void 0
604
+ });
605
+ }
590
606
  return this.client._request("POST", "/chat/completions", {
591
607
  body,
592
608
  headers
@@ -621,20 +637,18 @@ var MemoriesResource = class {
621
637
  offset: options?.offset
622
638
  }
623
639
  });
624
- return response.memories;
640
+ return response.data || [];
625
641
  }
626
642
  async search(options) {
627
- const response = await this.client._request("POST", "/memories/search", {
628
- body: {
643
+ const response = await this.client._request("GET", "/memories/search", {
644
+ query: {
629
645
  subject_id: options.subjectId,
630
- query: options.query,
646
+ q: options.query,
631
647
  limit: options.limit,
632
- min_score: options.minScore,
633
- include_deleted: options.includeDeleted,
634
- include_superseded: options.includeSuperseded
648
+ min_score: options.minScore
635
649
  }
636
650
  });
637
- return response.results;
651
+ return response.data || [];
638
652
  }
639
653
  async delete(id) {
640
654
  await this.client._request("DELETE", `/memories/${id}`);
@@ -699,7 +713,7 @@ var StateResource = class {
699
713
  async get(key, subjectId) {
700
714
  try {
701
715
  return await this.client._request("GET", `/state/${key}`, {
702
- query: subjectId ? { subject_id: subjectId } : void 0
716
+ headers: subjectId ? { "x-subject-id": subjectId } : void 0
703
717
  });
704
718
  } catch (error) {
705
719
  if (error instanceof NotFoundError) {
@@ -709,17 +723,21 @@ var StateResource = class {
709
723
  }
710
724
  }
711
725
  async set(options) {
712
- return this.client._request("POST", `/state/${options.key}`, {
726
+ const headers = {};
727
+ if (options.subjectId) {
728
+ headers["x-subject-id"] = options.subjectId;
729
+ }
730
+ return this.client._request("PUT", `/state/${options.key}`, {
731
+ headers,
713
732
  body: {
714
733
  value: options.value,
715
- subject_id: options.subjectId,
716
734
  ttl_seconds: options.ttlSeconds
717
735
  }
718
736
  });
719
737
  }
720
738
  async delete(key, subjectId) {
721
739
  await this.client._request("DELETE", `/state/${key}`, {
722
- query: subjectId ? { subject_id: subjectId } : void 0
740
+ headers: subjectId ? { "x-subject-id": subjectId } : void 0
723
741
  });
724
742
  }
725
743
  };
@@ -769,6 +787,136 @@ var PromptsResource = class {
769
787
  }
770
788
  };
771
789
 
790
+ // src/resources/records.ts
791
+ var RecordsResource = class {
792
+ constructor(client) {
793
+ this.client = client;
794
+ }
795
+ /**
796
+ * Define or update a record schema
797
+ *
798
+ * @example
799
+ * await mnx.records.defineSchema('deal', {
800
+ * title: { type: 'string', required: true },
801
+ * value: { type: 'number' },
802
+ * stage: { type: 'string' },
803
+ * account_id: { type: 'ref:account' },
804
+ * }, { displayName: 'Deal', description: 'Sales deals' });
805
+ */
806
+ async defineSchema(typeName, fields, opts) {
807
+ return this.client._request("POST", "/records/schemas", {
808
+ body: {
809
+ type_name: typeName,
810
+ fields,
811
+ display_name: opts?.displayName,
812
+ description: opts?.description
813
+ }
814
+ });
815
+ }
816
+ /**
817
+ * Get a schema by type name
818
+ */
819
+ async getSchema(typeName) {
820
+ try {
821
+ return await this.client._request("GET", `/records/schemas/${typeName}`);
822
+ } catch (error) {
823
+ if (error instanceof NotFoundError) return null;
824
+ throw error;
825
+ }
826
+ }
827
+ /**
828
+ * List all schemas for the project
829
+ */
830
+ async listSchemas() {
831
+ const response = await this.client._request("GET", "/records/schemas");
832
+ return response.schemas;
833
+ }
834
+ /**
835
+ * Insert a new record
836
+ *
837
+ * @example
838
+ * const deal = await mnx.records.insert('deal', {
839
+ * title: 'Acme Renewal',
840
+ * value: 500000,
841
+ * stage: 'negotiation',
842
+ * });
843
+ */
844
+ async insert(typeName, data, opts) {
845
+ return this.client._request("POST", `/records/${typeName}`, {
846
+ body: {
847
+ data,
848
+ owner_id: opts?.ownerId,
849
+ visibility: opts?.visibility,
850
+ collaborators: opts?.collaborators
851
+ }
852
+ });
853
+ }
854
+ /**
855
+ * Get a record by ID
856
+ */
857
+ async get(typeName, recordId) {
858
+ try {
859
+ return await this.client._request("GET", `/records/${typeName}/${recordId}`);
860
+ } catch (error) {
861
+ if (error instanceof NotFoundError) return null;
862
+ throw error;
863
+ }
864
+ }
865
+ /**
866
+ * Update a record (partial merge)
867
+ *
868
+ * @example
869
+ * await mnx.records.update('deal', 'rec_abc', { stage: 'closed_won', value: 550000 });
870
+ */
871
+ async update(typeName, recordId, data) {
872
+ return this.client._request("PUT", `/records/${typeName}/${recordId}`, {
873
+ body: { data }
874
+ });
875
+ }
876
+ /**
877
+ * Soft-delete a record
878
+ */
879
+ async delete(typeName, recordId) {
880
+ await this.client._request("DELETE", `/records/${typeName}/${recordId}`);
881
+ }
882
+ /**
883
+ * Query records with JSONB filters
884
+ *
885
+ * @example
886
+ * const deals = await mnx.records.query('deal', {
887
+ * where: { stage: 'closed_won' },
888
+ * orderBy: '-value',
889
+ * limit: 10,
890
+ * });
891
+ */
892
+ async query(typeName, opts) {
893
+ const response = await this.client._request("POST", `/records/${typeName}/query`, {
894
+ body: {
895
+ where: opts?.where,
896
+ order_by: opts?.orderBy,
897
+ limit: opts?.limit,
898
+ offset: opts?.offset
899
+ }
900
+ });
901
+ return response.records;
902
+ }
903
+ /**
904
+ * Semantic search across records
905
+ *
906
+ * @example
907
+ * const results = await mnx.records.search('deal', 'large enterprise renewal');
908
+ */
909
+ async search(typeName, query, opts) {
910
+ const response = await this.client._request("POST", `/records/${typeName}/search`, {
911
+ body: {
912
+ query,
913
+ limit: opts?.limit
914
+ }
915
+ });
916
+ return response.records;
917
+ }
918
+ };
919
+
772
920
  // src/client.ts
773
921
  var DEFAULT_BASE_URL = "https://mnexium.com/api/v1";
774
922
  var DEFAULT_TIMEOUT = 3e4;
@@ -798,6 +946,7 @@ var Mnexium = class {
798
946
  this.profiles = new ProfilesResource(this);
799
947
  this.state = new StateResource(this);
800
948
  this.prompts = new PromptsResource(this);
949
+ this.records = new RecordsResource(this);
801
950
  }
802
951
  async process(input) {
803
952
  const options = typeof input === "string" ? { content: input } : input;
@@ -968,13 +1117,20 @@ var Mnexium = class {
968
1117
  }
969
1118
  const controller = new AbortController();
970
1119
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
971
- const response = await fetch(url.toString(), {
972
- method,
973
- headers,
974
- body: options.body ? JSON.stringify(options.body) : void 0,
975
- signal: controller.signal
976
- });
977
- clearTimeout(timeoutId);
1120
+ if (options.signal) {
1121
+ options.signal.addEventListener("abort", () => controller.abort(), { once: true });
1122
+ }
1123
+ let response;
1124
+ try {
1125
+ response = await fetch(url.toString(), {
1126
+ method,
1127
+ headers,
1128
+ body: options.body ? JSON.stringify(options.body) : void 0,
1129
+ signal: controller.signal
1130
+ });
1131
+ } finally {
1132
+ clearTimeout(timeoutId);
1133
+ }
978
1134
  const provisionedKey = response.headers.get("x-mnx-key-provisioned");
979
1135
  if (provisionedKey) {
980
1136
  this._setProvisionedKey(provisionedKey);
@@ -1007,16 +1163,15 @@ var Mnexium = class {
1007
1163
  }
1008
1164
  let lastError;
1009
1165
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
1166
+ const controller = new AbortController();
1167
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1010
1168
  try {
1011
- const controller = new AbortController();
1012
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1013
1169
  const response = await fetch(url.toString(), {
1014
1170
  method,
1015
1171
  headers,
1016
1172
  body: options.body ? JSON.stringify(options.body) : void 0,
1017
1173
  signal: controller.signal
1018
1174
  });
1019
- clearTimeout(timeoutId);
1020
1175
  const provisionedKey = response.headers.get("x-mnx-key-provisioned");
1021
1176
  if (provisionedKey) {
1022
1177
  this._setProvisionedKey(provisionedKey);
@@ -1025,7 +1180,14 @@ var Mnexium = class {
1025
1180
  const errorBody = await response.json().catch(() => ({}));
1026
1181
  throw this._handleErrorResponse(response.status, errorBody);
1027
1182
  }
1028
- return await response.json();
1183
+ if (response.status === 204) {
1184
+ return void 0;
1185
+ }
1186
+ const text = await response.text();
1187
+ if (!text) {
1188
+ return void 0;
1189
+ }
1190
+ return JSON.parse(text);
1029
1191
  } catch (error) {
1030
1192
  lastError = error;
1031
1193
  if (error instanceof APIError && error.status < 500 && !(error instanceof RateLimitError)) {
@@ -1035,6 +1197,8 @@ var Mnexium = class {
1035
1197
  throw error;
1036
1198
  }
1037
1199
  await this._sleep(Math.pow(2, attempt) * 1e3);
1200
+ } finally {
1201
+ clearTimeout(timeoutId);
1038
1202
  }
1039
1203
  }
1040
1204
  throw lastError || new MnexiumError("Request failed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnexium/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Official Mnexium SDK for JavaScript/TypeScript - Add memory to your AI applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -19,7 +19,7 @@
19
19
  "build": "tsup src/index.ts --format cjs,esm --dts --clean",
20
20
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
21
21
  "test": "vitest",
22
- "lint": "eslint src/",
22
+ "lint": "eslint --ext .ts src/",
23
23
  "prepublishOnly": "npm run build",
24
24
  "examples:install": "npm run build && cd examples && npm pkg set dependencies.@mnexium/sdk=file:.. && npm install",
25
25
  "example:hello": "cd examples && npm run hello",
@@ -56,6 +56,7 @@
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/node": "^20.0.0",
59
+ "@typescript-eslint/parser": "^6.0.0",
59
60
  "eslint": "^8.0.0",
60
61
  "tsup": "^8.0.0",
61
62
  "typescript": "^5.0.0",