@scitrera/memorylayer-sdk 0.0.5 → 0.1.22
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/client.d.ts +175 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +497 -7
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp_servers.d.ts +81 -0
- package/dist/mcp_servers.d.ts.map +1 -0
- package/dist/mcp_servers.js +104 -0
- package/dist/mcp_servers.js.map +1 -0
- package/dist/skills.d.ts +109 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +215 -0
- package/dist/skills.js.map +1 -0
- package/dist/types.d.ts +279 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
package/dist/client.js
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
|
-
import { MemoryLayerError, AuthenticationError, AuthorizationError, NotFoundError, ValidationError } from "./errors.js";
|
|
1
|
+
import { MemoryLayerError, AuthenticationError, AuthorizationError, NotFoundError, ValidationError, EnterpriseRequiredError } from "./errors.js";
|
|
2
|
+
import { SkillsNamespace } from "./skills.js";
|
|
3
|
+
import { McpServersNamespace } from "./mcp_servers.js";
|
|
2
4
|
export class MemoryLayerClient {
|
|
3
5
|
baseUrl;
|
|
4
6
|
apiKey;
|
|
5
7
|
workspaceId;
|
|
6
8
|
sessionId;
|
|
7
9
|
timeout;
|
|
10
|
+
defaultAuthority;
|
|
11
|
+
/** Skills namespace — access via `client.skills.list(...)` etc. */
|
|
12
|
+
skills;
|
|
13
|
+
/** MCP Servers namespace — access via `client.mcpServers.list(...)` etc. */
|
|
14
|
+
mcpServers;
|
|
8
15
|
constructor(config = {}) {
|
|
9
16
|
this.baseUrl = config.baseUrl ?? "http://localhost:61001";
|
|
10
17
|
this.apiKey = config.apiKey;
|
|
11
18
|
this.workspaceId = config.workspaceId;
|
|
12
19
|
this.sessionId = config.sessionId;
|
|
13
20
|
this.timeout = config.timeout ?? 30000;
|
|
21
|
+
this.defaultAuthority = config.defaultAuthority;
|
|
22
|
+
this.skills = new SkillsNamespace(this);
|
|
23
|
+
this.mcpServers = new McpServersNamespace(this);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns a lightweight proxy that sends OBO headers for the given grant/subject
|
|
27
|
+
* on every request. The proxy is synchronous and reuses the parent client's
|
|
28
|
+
* connection settings — safe for concurrent use across multiple subjects.
|
|
29
|
+
*/
|
|
30
|
+
actingFor(opts) {
|
|
31
|
+
return new OboProxy(this, { grantId: opts.grantId, subject: opts.subject });
|
|
14
32
|
}
|
|
15
33
|
/**
|
|
16
34
|
* Set the active session ID. All subsequent requests will include
|
|
@@ -32,7 +50,19 @@ export class MemoryLayerClient {
|
|
|
32
50
|
getSessionId() {
|
|
33
51
|
return this.sessionId;
|
|
34
52
|
}
|
|
35
|
-
|
|
53
|
+
buildAuthorityHeaders(authority) {
|
|
54
|
+
const resolved = authority ?? this.defaultAuthority;
|
|
55
|
+
if (!resolved)
|
|
56
|
+
return {};
|
|
57
|
+
const h = {
|
|
58
|
+
"X-Aether-Grant-ID": resolved.grantId,
|
|
59
|
+
"X-Aether-Authority-Mode": "on_behalf_of",
|
|
60
|
+
"X-Aether-Subject-Type": resolved.subject.type,
|
|
61
|
+
"X-Aether-Subject-ID": resolved.subject.id,
|
|
62
|
+
};
|
|
63
|
+
return h;
|
|
64
|
+
}
|
|
65
|
+
async request(method, path, body, enterpriseFeature, authority) {
|
|
36
66
|
const headers = {
|
|
37
67
|
"Content-Type": "application/json",
|
|
38
68
|
};
|
|
@@ -45,6 +75,7 @@ export class MemoryLayerClient {
|
|
|
45
75
|
if (this.workspaceId) {
|
|
46
76
|
headers["X-Workspace-ID"] = this.workspaceId;
|
|
47
77
|
}
|
|
78
|
+
Object.assign(headers, this.buildAuthorityHeaders(authority));
|
|
48
79
|
const url = `${this.baseUrl}${path}`;
|
|
49
80
|
const controller = new AbortController();
|
|
50
81
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
@@ -57,7 +88,7 @@ export class MemoryLayerClient {
|
|
|
57
88
|
});
|
|
58
89
|
clearTimeout(timeoutId);
|
|
59
90
|
if (!response.ok) {
|
|
60
|
-
await this.handleError(response);
|
|
91
|
+
await this.handleError(response, enterpriseFeature);
|
|
61
92
|
}
|
|
62
93
|
if (response.status === 204) {
|
|
63
94
|
return undefined;
|
|
@@ -70,7 +101,7 @@ export class MemoryLayerClient {
|
|
|
70
101
|
throw new MemoryLayerError(`Request failed: ${error}`);
|
|
71
102
|
}
|
|
72
103
|
}
|
|
73
|
-
async handleError(response) {
|
|
104
|
+
async handleError(response, enterpriseFeature) {
|
|
74
105
|
const body = await response.json().catch(() => ({}));
|
|
75
106
|
const rawDetail = body.message ?? body.detail ?? response.statusText;
|
|
76
107
|
const message = typeof rawDetail === 'string'
|
|
@@ -86,6 +117,11 @@ export class MemoryLayerClient {
|
|
|
86
117
|
case 400:
|
|
87
118
|
case 422:
|
|
88
119
|
throw new ValidationError(message, body.details);
|
|
120
|
+
case 501:
|
|
121
|
+
if (enterpriseFeature) {
|
|
122
|
+
throw new EnterpriseRequiredError(enterpriseFeature);
|
|
123
|
+
}
|
|
124
|
+
throw new NotFoundError(message);
|
|
89
125
|
default:
|
|
90
126
|
throw new MemoryLayerError(message, response.status);
|
|
91
127
|
}
|
|
@@ -103,8 +139,9 @@ export class MemoryLayerClient {
|
|
|
103
139
|
metadata: options.metadata ?? {},
|
|
104
140
|
associations: options.associations ?? [],
|
|
105
141
|
context_id: options.contextId,
|
|
142
|
+
user_id: options.userId,
|
|
106
143
|
};
|
|
107
|
-
const response = await this.request("POST", "/v1/memories", body);
|
|
144
|
+
const response = await this.request("POST", "/v1/memories", body, undefined, options.authority);
|
|
108
145
|
return response.memory;
|
|
109
146
|
}
|
|
110
147
|
async recall(query, options = {}) {
|
|
@@ -130,8 +167,9 @@ export class MemoryLayerClient {
|
|
|
130
167
|
context: options.conversationContext ?? [],
|
|
131
168
|
rag_threshold: options.ragThreshold,
|
|
132
169
|
detail_level: options.detailLevel,
|
|
170
|
+
user_id: options.userId,
|
|
133
171
|
};
|
|
134
|
-
return this.request("POST", "/v1/memories/recall", body);
|
|
172
|
+
return this.request("POST", "/v1/memories/recall", body, undefined, options.authority);
|
|
135
173
|
}
|
|
136
174
|
async reflect(query, options = {}) {
|
|
137
175
|
const body = {
|
|
@@ -145,8 +183,9 @@ export class MemoryLayerClient {
|
|
|
145
183
|
subtypes: options.subtypes ?? [],
|
|
146
184
|
tags: options.tags ?? [],
|
|
147
185
|
context_id: options.contextId,
|
|
186
|
+
user_id: options.userId,
|
|
148
187
|
};
|
|
149
|
-
return this.request("POST", "/v1/memories/reflect", body);
|
|
188
|
+
return this.request("POST", "/v1/memories/reflect", body, undefined, options.authority);
|
|
150
189
|
}
|
|
151
190
|
async getMemory(memoryId) {
|
|
152
191
|
const response = await this.request("GET", `/v1/memories/${memoryId}`);
|
|
@@ -577,5 +616,456 @@ export class MemoryLayerClient {
|
|
|
577
616
|
async contextCheckpoint() {
|
|
578
617
|
await this.request("POST", "/v1/context/checkpoint");
|
|
579
618
|
}
|
|
619
|
+
// ------------------------------------------------------------------ //
|
|
620
|
+
// Document operations (Enterprise)
|
|
621
|
+
// ------------------------------------------------------------------ //
|
|
622
|
+
/**
|
|
623
|
+
* Upload a document for ingestion.
|
|
624
|
+
*
|
|
625
|
+
* Requires MemoryLayer Enterprise. On OSS servers this throws
|
|
626
|
+
* `EnterpriseRequiredError`.
|
|
627
|
+
*/
|
|
628
|
+
async uploadDocument(file, filename, options = {}) {
|
|
629
|
+
const formData = new FormData();
|
|
630
|
+
formData.append("file", file, filename);
|
|
631
|
+
if (options.targetContextId)
|
|
632
|
+
formData.append("target_context_id", options.targetContextId);
|
|
633
|
+
if (options.chunkingStrategy)
|
|
634
|
+
formData.append("chunking_strategy", options.chunkingStrategy);
|
|
635
|
+
if (options.chunkSize !== undefined)
|
|
636
|
+
formData.append("chunk_size", String(options.chunkSize));
|
|
637
|
+
if (options.chunkOverlap !== undefined)
|
|
638
|
+
formData.append("chunk_overlap", String(options.chunkOverlap));
|
|
639
|
+
if (options.importance !== undefined)
|
|
640
|
+
formData.append("importance", String(options.importance));
|
|
641
|
+
if (options.retainOriginal !== undefined)
|
|
642
|
+
formData.append("retain_original", String(options.retainOriginal));
|
|
643
|
+
const headers = {};
|
|
644
|
+
if (this.apiKey)
|
|
645
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
646
|
+
if (this.sessionId)
|
|
647
|
+
headers["X-Session-ID"] = this.sessionId;
|
|
648
|
+
if (this.workspaceId)
|
|
649
|
+
headers["X-Workspace-ID"] = this.workspaceId;
|
|
650
|
+
const url = `${this.baseUrl}/v1/documents`;
|
|
651
|
+
const controller = new AbortController();
|
|
652
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
653
|
+
try {
|
|
654
|
+
const response = await fetch(url, {
|
|
655
|
+
method: "POST",
|
|
656
|
+
headers,
|
|
657
|
+
body: formData,
|
|
658
|
+
signal: controller.signal,
|
|
659
|
+
});
|
|
660
|
+
clearTimeout(timeoutId);
|
|
661
|
+
if (!response.ok) {
|
|
662
|
+
await this.handleError(response, "Document ingestion");
|
|
663
|
+
}
|
|
664
|
+
return await response.json();
|
|
665
|
+
}
|
|
666
|
+
catch (error) {
|
|
667
|
+
if (error instanceof MemoryLayerError)
|
|
668
|
+
throw error;
|
|
669
|
+
throw new MemoryLayerError(`Document upload failed: ${error}`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* List documents in the workspace.
|
|
674
|
+
*/
|
|
675
|
+
async listDocuments(options) {
|
|
676
|
+
const params = new URLSearchParams();
|
|
677
|
+
if (options?.status)
|
|
678
|
+
params.set("status", options.status);
|
|
679
|
+
if (options?.limit !== undefined)
|
|
680
|
+
params.set("limit", String(options.limit));
|
|
681
|
+
if (options?.offset !== undefined)
|
|
682
|
+
params.set("offset", String(options.offset));
|
|
683
|
+
const query = params.toString();
|
|
684
|
+
return this.request("GET", `/v1/documents${query ? `?${query}` : ""}`, undefined, "Document management");
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Get document metadata and processing status.
|
|
688
|
+
*/
|
|
689
|
+
async getDocument(documentId) {
|
|
690
|
+
const response = await this.request("GET", `/v1/documents/${documentId}`, undefined, "Document management");
|
|
691
|
+
return response;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Delete a document and optionally its extracted memories.
|
|
695
|
+
*/
|
|
696
|
+
async deleteDocument(documentId, deleteMemories = false) {
|
|
697
|
+
await this.request("DELETE", `/v1/documents/${documentId}?delete_memories=${deleteMemories}`, undefined, "Document management");
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Search document pages using ColPali MaxSim visual similarity.
|
|
701
|
+
*
|
|
702
|
+
* Requires MemoryLayer Enterprise.
|
|
703
|
+
*/
|
|
704
|
+
async searchDocumentPages(query, options = {}) {
|
|
705
|
+
const body = {
|
|
706
|
+
query,
|
|
707
|
+
limit: options.limit ?? 10,
|
|
708
|
+
doc_ids: options.docIds,
|
|
709
|
+
};
|
|
710
|
+
return this.request("POST", "/v1/documents/search", body, "Document page search");
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Get all pages for a document.
|
|
714
|
+
*/
|
|
715
|
+
async getDocumentPages(documentId) {
|
|
716
|
+
return this.request("GET", `/v1/documents/${documentId}/pages`, undefined, "Document pages");
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Get a page image as a Blob.
|
|
720
|
+
*/
|
|
721
|
+
async getPageImage(documentId, pageId) {
|
|
722
|
+
const headers = {};
|
|
723
|
+
if (this.apiKey)
|
|
724
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
725
|
+
if (this.sessionId)
|
|
726
|
+
headers["X-Session-ID"] = this.sessionId;
|
|
727
|
+
if (this.workspaceId)
|
|
728
|
+
headers["X-Workspace-ID"] = this.workspaceId;
|
|
729
|
+
const url = `${this.baseUrl}/v1/documents/${documentId}/pages/${pageId}/image`;
|
|
730
|
+
const controller = new AbortController();
|
|
731
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
732
|
+
try {
|
|
733
|
+
const response = await fetch(url, { method: "GET", headers, signal: controller.signal });
|
|
734
|
+
clearTimeout(timeoutId);
|
|
735
|
+
if (!response.ok) {
|
|
736
|
+
await this.handleError(response, "Document page images");
|
|
737
|
+
}
|
|
738
|
+
return await response.blob();
|
|
739
|
+
}
|
|
740
|
+
catch (error) {
|
|
741
|
+
if (error instanceof MemoryLayerError)
|
|
742
|
+
throw error;
|
|
743
|
+
throw new MemoryLayerError(`Page image request failed: ${error}`);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Get ingestion job status.
|
|
748
|
+
*/
|
|
749
|
+
async getJob(jobId) {
|
|
750
|
+
return this.request("GET", `/v1/documents/jobs/${jobId}`, undefined, "Document ingestion jobs");
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* List ingestion jobs in the workspace.
|
|
754
|
+
*/
|
|
755
|
+
async listJobs(options) {
|
|
756
|
+
const params = new URLSearchParams();
|
|
757
|
+
if (options?.status)
|
|
758
|
+
params.set("status", options.status);
|
|
759
|
+
if (options?.limit !== undefined)
|
|
760
|
+
params.set("limit", String(options.limit));
|
|
761
|
+
const query = params.toString();
|
|
762
|
+
return this.request("GET", `/v1/documents/jobs${query ? `?${query}` : ""}`, undefined, "Document ingestion jobs");
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Cancel a running ingestion job.
|
|
766
|
+
*/
|
|
767
|
+
async cancelJob(jobId) {
|
|
768
|
+
await this.request("POST", `/v1/documents/jobs/${jobId}/cancel`, undefined, "Document ingestion jobs");
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Reprocess a document with optionally different extraction options.
|
|
772
|
+
*/
|
|
773
|
+
async reprocessDocument(documentId, options) {
|
|
774
|
+
const body = {};
|
|
775
|
+
if (options?.targetContextId)
|
|
776
|
+
body.target_context_id = options.targetContextId;
|
|
777
|
+
if (options?.chunkingStrategy)
|
|
778
|
+
body.chunking_strategy = options.chunkingStrategy;
|
|
779
|
+
if (options?.chunkSize !== undefined)
|
|
780
|
+
body.chunk_size = options.chunkSize;
|
|
781
|
+
if (options?.chunkOverlap !== undefined)
|
|
782
|
+
body.chunk_overlap = options.chunkOverlap;
|
|
783
|
+
if (options?.importance !== undefined)
|
|
784
|
+
body.importance = options.importance;
|
|
785
|
+
return this.request("POST", `/v1/documents/${documentId}/reprocess`, Object.keys(body).length ? body : undefined, "Document reprocessing");
|
|
786
|
+
}
|
|
787
|
+
// ------------------------------------------------------------------ //
|
|
788
|
+
// Chat History operations
|
|
789
|
+
// ------------------------------------------------------------------ //
|
|
790
|
+
async createThread(options = {}) {
|
|
791
|
+
const body = {
|
|
792
|
+
thread_id: options.threadId,
|
|
793
|
+
workspace_id: options.workspaceId ?? this.workspaceId,
|
|
794
|
+
user_id: options.userId,
|
|
795
|
+
context_id: options.contextId,
|
|
796
|
+
observer_id: options.observerId,
|
|
797
|
+
subject_id: options.subjectId,
|
|
798
|
+
title: options.title,
|
|
799
|
+
metadata: options.metadata,
|
|
800
|
+
expires_at: options.expiresAt,
|
|
801
|
+
};
|
|
802
|
+
const response = await this.request("POST", "/v1/threads", body);
|
|
803
|
+
return response.thread;
|
|
804
|
+
}
|
|
805
|
+
async listThreads(options = {}) {
|
|
806
|
+
const params = new URLSearchParams();
|
|
807
|
+
const wsId = options.workspaceId ?? this.workspaceId;
|
|
808
|
+
if (wsId)
|
|
809
|
+
params.set("workspace_id", wsId);
|
|
810
|
+
if (options.userId)
|
|
811
|
+
params.set("user_id", options.userId);
|
|
812
|
+
if (options.limit !== undefined)
|
|
813
|
+
params.set("limit", String(options.limit));
|
|
814
|
+
if (options.offset !== undefined)
|
|
815
|
+
params.set("offset", String(options.offset));
|
|
816
|
+
const query = params.toString();
|
|
817
|
+
const response = await this.request("GET", `/v1/threads${query ? `?${query}` : ""}`);
|
|
818
|
+
return response.threads;
|
|
819
|
+
}
|
|
820
|
+
async getThread(threadId, workspaceId) {
|
|
821
|
+
const params = new URLSearchParams();
|
|
822
|
+
const wsId = workspaceId ?? this.workspaceId;
|
|
823
|
+
if (wsId)
|
|
824
|
+
params.set("workspace_id", wsId);
|
|
825
|
+
const query = params.toString();
|
|
826
|
+
const response = await this.request("GET", `/v1/threads/${threadId}${query ? `?${query}` : ""}`);
|
|
827
|
+
return response.thread;
|
|
828
|
+
}
|
|
829
|
+
async getThreadFull(threadId, options) {
|
|
830
|
+
const params = new URLSearchParams();
|
|
831
|
+
const wsId = options?.workspaceId ?? this.workspaceId;
|
|
832
|
+
if (wsId)
|
|
833
|
+
params.set("workspace_id", wsId);
|
|
834
|
+
if (options?.limit !== undefined)
|
|
835
|
+
params.set("limit", String(options.limit));
|
|
836
|
+
if (options?.offset !== undefined)
|
|
837
|
+
params.set("offset", String(options.offset));
|
|
838
|
+
if (options?.order)
|
|
839
|
+
params.set("order", options.order);
|
|
840
|
+
const query = params.toString();
|
|
841
|
+
return this.request("GET", `/v1/threads/${threadId}/full${query ? `?${query}` : ""}`);
|
|
842
|
+
}
|
|
843
|
+
async deleteThread(threadId, workspaceId) {
|
|
844
|
+
const params = new URLSearchParams();
|
|
845
|
+
const wsId = workspaceId ?? this.workspaceId;
|
|
846
|
+
if (wsId)
|
|
847
|
+
params.set("workspace_id", wsId);
|
|
848
|
+
const query = params.toString();
|
|
849
|
+
await this.request("DELETE", `/v1/threads/${threadId}${query ? `?${query}` : ""}`);
|
|
850
|
+
}
|
|
851
|
+
async appendMessages(threadId, messages, workspaceId) {
|
|
852
|
+
const params = new URLSearchParams();
|
|
853
|
+
const wsId = workspaceId ?? this.workspaceId;
|
|
854
|
+
if (wsId)
|
|
855
|
+
params.set("workspace_id", wsId);
|
|
856
|
+
const query = params.toString();
|
|
857
|
+
return this.request("POST", `/v1/threads/${threadId}/messages${query ? `?${query}` : ""}`, { messages });
|
|
858
|
+
}
|
|
859
|
+
async getMessages(threadId, options) {
|
|
860
|
+
const params = new URLSearchParams();
|
|
861
|
+
const wsId = options?.workspaceId ?? this.workspaceId;
|
|
862
|
+
if (wsId)
|
|
863
|
+
params.set("workspace_id", wsId);
|
|
864
|
+
if (options?.limit !== undefined)
|
|
865
|
+
params.set("limit", String(options.limit));
|
|
866
|
+
if (options?.offset !== undefined)
|
|
867
|
+
params.set("offset", String(options.offset));
|
|
868
|
+
if (options?.afterIndex !== undefined)
|
|
869
|
+
params.set("after_index", String(options.afterIndex));
|
|
870
|
+
if (options?.order)
|
|
871
|
+
params.set("order", options.order);
|
|
872
|
+
const query = params.toString();
|
|
873
|
+
return this.request("GET", `/v1/threads/${threadId}/messages${query ? `?${query}` : ""}`);
|
|
874
|
+
}
|
|
875
|
+
async decomposeThread(threadId, workspaceId) {
|
|
876
|
+
const params = new URLSearchParams();
|
|
877
|
+
const wsId = workspaceId ?? this.workspaceId;
|
|
878
|
+
if (wsId)
|
|
879
|
+
params.set("workspace_id", wsId);
|
|
880
|
+
const query = params.toString();
|
|
881
|
+
return this.request("POST", `/v1/threads/${threadId}/decompose${query ? `?${query}` : ""}`);
|
|
882
|
+
}
|
|
883
|
+
// ------------------------------------------------------------------ //
|
|
884
|
+
// Dataset operations (Enterprise)
|
|
885
|
+
// ------------------------------------------------------------------ //
|
|
886
|
+
/**
|
|
887
|
+
* Upload a dataset for profiling and memory extraction.
|
|
888
|
+
*
|
|
889
|
+
* Requires MemoryLayer Enterprise. On OSS servers this throws
|
|
890
|
+
* `EnterpriseRequiredError`.
|
|
891
|
+
*/
|
|
892
|
+
async uploadDataset(file, filename, options = {}) {
|
|
893
|
+
const formData = new FormData();
|
|
894
|
+
formData.append("file", file, filename);
|
|
895
|
+
if (options.name)
|
|
896
|
+
formData.append("name", options.name);
|
|
897
|
+
if (options.targetContextId)
|
|
898
|
+
formData.append("target_context_id", options.targetContextId);
|
|
899
|
+
if (options.importance !== undefined)
|
|
900
|
+
formData.append("importance", String(options.importance));
|
|
901
|
+
if (options.sampleRows !== undefined)
|
|
902
|
+
formData.append("sample_rows", String(options.sampleRows));
|
|
903
|
+
if (options.detectTimeSeries !== undefined)
|
|
904
|
+
formData.append("detect_time_series", String(options.detectTimeSeries));
|
|
905
|
+
if (options.generateSummaries !== undefined)
|
|
906
|
+
formData.append("generate_summaries", String(options.generateSummaries));
|
|
907
|
+
const headers = {};
|
|
908
|
+
if (this.apiKey)
|
|
909
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
910
|
+
if (this.sessionId)
|
|
911
|
+
headers["X-Session-ID"] = this.sessionId;
|
|
912
|
+
if (this.workspaceId)
|
|
913
|
+
headers["X-Workspace-ID"] = this.workspaceId;
|
|
914
|
+
const url = `${this.baseUrl}/v1/datasets`;
|
|
915
|
+
const controller = new AbortController();
|
|
916
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
917
|
+
try {
|
|
918
|
+
const response = await fetch(url, {
|
|
919
|
+
method: "POST",
|
|
920
|
+
headers,
|
|
921
|
+
body: formData,
|
|
922
|
+
signal: controller.signal,
|
|
923
|
+
});
|
|
924
|
+
clearTimeout(timeoutId);
|
|
925
|
+
if (!response.ok) {
|
|
926
|
+
await this.handleError(response, "Dataset management");
|
|
927
|
+
}
|
|
928
|
+
return await response.json();
|
|
929
|
+
}
|
|
930
|
+
catch (error) {
|
|
931
|
+
if (error instanceof MemoryLayerError)
|
|
932
|
+
throw error;
|
|
933
|
+
throw new MemoryLayerError(`Dataset upload failed: ${error}`);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* List datasets in the workspace.
|
|
938
|
+
*/
|
|
939
|
+
async listDatasets(options) {
|
|
940
|
+
const params = new URLSearchParams();
|
|
941
|
+
if (options?.status)
|
|
942
|
+
params.set("status", options.status);
|
|
943
|
+
if (options?.limit !== undefined)
|
|
944
|
+
params.set("limit", String(options.limit));
|
|
945
|
+
if (options?.offset !== undefined)
|
|
946
|
+
params.set("offset", String(options.offset));
|
|
947
|
+
const query = params.toString();
|
|
948
|
+
return this.request("GET", `/v1/datasets${query ? `?${query}` : ""}`, undefined, "Dataset management");
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Get dataset metadata, schema, and profile.
|
|
952
|
+
*/
|
|
953
|
+
async getDataset(datasetId) {
|
|
954
|
+
return this.request("GET", `/v1/datasets/${datasetId}`, undefined, "Dataset management");
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Delete a dataset and optionally its extracted memories.
|
|
958
|
+
*/
|
|
959
|
+
async deleteDataset(datasetId, deleteMemories = false) {
|
|
960
|
+
await this.request("DELETE", `/v1/datasets/${datasetId}?delete_memories=${deleteMemories}`, undefined, "Dataset management");
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Get memories extracted from a dataset.
|
|
964
|
+
*/
|
|
965
|
+
async getDatasetMemories(datasetId) {
|
|
966
|
+
return this.request("GET", `/v1/datasets/${datasetId}/memories`, undefined, "Dataset management");
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Query a slice of dataset data using DuckDB.
|
|
970
|
+
*
|
|
971
|
+
* Supports both structured filters and raw SQL (SELECT only).
|
|
972
|
+
* The dataset is queried as a table named 'data'.
|
|
973
|
+
*/
|
|
974
|
+
async queryDatasetSlice(datasetId, options = {}) {
|
|
975
|
+
const body = {
|
|
976
|
+
limit: options.limit ?? 100,
|
|
977
|
+
offset: options.offset ?? 0,
|
|
978
|
+
descending: options.descending ?? false,
|
|
979
|
+
};
|
|
980
|
+
if (options.sql !== undefined)
|
|
981
|
+
body.sql = options.sql;
|
|
982
|
+
if (options.columns !== undefined)
|
|
983
|
+
body.columns = options.columns;
|
|
984
|
+
if (options.filters !== undefined)
|
|
985
|
+
body.filters = options.filters;
|
|
986
|
+
if (options.orderBy !== undefined)
|
|
987
|
+
body.order_by = options.orderBy;
|
|
988
|
+
return this.request("POST", `/v1/datasets/${datasetId}/slice`, body, "Dataset management");
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Get dataset processing job status.
|
|
992
|
+
*/
|
|
993
|
+
async getDatasetJob(jobId) {
|
|
994
|
+
return this.request("GET", `/v1/datasets/jobs/${jobId}`, undefined, "Dataset processing jobs");
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* List dataset processing jobs in the workspace.
|
|
998
|
+
*/
|
|
999
|
+
async listDatasetJobs(options) {
|
|
1000
|
+
const params = new URLSearchParams();
|
|
1001
|
+
if (options?.status)
|
|
1002
|
+
params.set("status", options.status);
|
|
1003
|
+
if (options?.limit !== undefined)
|
|
1004
|
+
params.set("limit", String(options.limit));
|
|
1005
|
+
const query = params.toString();
|
|
1006
|
+
return this.request("GET", `/v1/datasets/jobs${query ? `?${query}` : ""}`, undefined, "Dataset processing jobs");
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Cancel a running dataset processing job.
|
|
1010
|
+
*/
|
|
1011
|
+
async cancelDatasetJob(jobId) {
|
|
1012
|
+
await this.request("POST", `/v1/datasets/jobs/${jobId}/cancel`, undefined, "Dataset processing jobs");
|
|
1013
|
+
}
|
|
1014
|
+
/** Used internally by SkillsNamespace to make requests with OBO authority. */
|
|
1015
|
+
async _skillsRequest(method, path, body, authority) {
|
|
1016
|
+
return this.request(method, path, body, undefined, authority);
|
|
1017
|
+
}
|
|
1018
|
+
/** Used internally by McpServersNamespace to make requests with OBO authority. */
|
|
1019
|
+
async _mcpServersRequest(method, path, body, authority) {
|
|
1020
|
+
return this.request(method, path, body, undefined, authority);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Lightweight OBO proxy returned by `client.actingFor()`.
|
|
1025
|
+
* Delegates all calls to the parent client with a fixed AuthorityContext and
|
|
1026
|
+
* optional workspace override. Per-call authority headers are computed fresh
|
|
1027
|
+
* on each request — no shared mutable state, so concurrent calls for different
|
|
1028
|
+
* subjects on the same underlying client never interfere.
|
|
1029
|
+
*/
|
|
1030
|
+
export class OboProxy {
|
|
1031
|
+
_client;
|
|
1032
|
+
_authority;
|
|
1033
|
+
_workspaceId;
|
|
1034
|
+
/** Skills namespace scoped to this proxy's authority. */
|
|
1035
|
+
skills;
|
|
1036
|
+
/** MCP Servers namespace scoped to this proxy's authority. */
|
|
1037
|
+
mcpServers;
|
|
1038
|
+
constructor(client, authority, workspaceId) {
|
|
1039
|
+
this._client = client;
|
|
1040
|
+
this._authority = authority;
|
|
1041
|
+
this._workspaceId = workspaceId;
|
|
1042
|
+
this.skills = new SkillsNamespace(client, authority, workspaceId);
|
|
1043
|
+
this.mcpServers = new McpServersNamespace(client, authority, workspaceId);
|
|
1044
|
+
}
|
|
1045
|
+
/** Further scope this proxy to a single workspace. */
|
|
1046
|
+
forWorkspace(workspaceId) {
|
|
1047
|
+
return new OboProxy(this._client, this._authority, workspaceId);
|
|
1048
|
+
}
|
|
1049
|
+
async remember(content, options = {}) {
|
|
1050
|
+
return this._client.remember(content, {
|
|
1051
|
+
...options,
|
|
1052
|
+
workspaceId: options.workspaceId ?? this._workspaceId,
|
|
1053
|
+
authority: options.authority ?? this._authority,
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
async recall(query, options = {}) {
|
|
1057
|
+
return this._client.recall(query, {
|
|
1058
|
+
...options,
|
|
1059
|
+
workspaceId: options.workspaceId ?? this._workspaceId,
|
|
1060
|
+
authority: options.authority ?? this._authority,
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
async reflect(query, options = {}) {
|
|
1064
|
+
return this._client.reflect(query, {
|
|
1065
|
+
...options,
|
|
1066
|
+
workspaceId: options.workspaceId ?? this._workspaceId,
|
|
1067
|
+
authority: options.authority ?? this._authority,
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
580
1070
|
}
|
|
581
1071
|
//# sourceMappingURL=client.js.map
|