@hyperspell/openclaw-hyperspell 0.5.0 → 0.7.1

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/client.ts CHANGED
@@ -1,252 +1,322 @@
1
- import Hyperspell from "hyperspell"
2
- import type { HyperspellConfig, HyperspellSource } from "./config.ts"
3
- import { log } from "./logger.ts"
1
+ import Hyperspell from "hyperspell";
2
+ import type { HyperspellConfig, HyperspellSource } from "./config.ts";
3
+ import { log } from "./logger.ts";
4
+
5
+ export type Highlight = {
6
+ id: string;
7
+ score: number;
8
+ text: string;
9
+ };
4
10
 
5
11
  export type SearchResult = {
6
- resourceId: string
7
- title: string | null
8
- source: HyperspellSource
9
- score: number | null
10
- url: string | null
11
- createdAt: string | null
12
- }
12
+ resourceId: string;
13
+ title: string | null;
14
+ source: HyperspellSource;
15
+ score: number | null;
16
+ url: string | null;
17
+ createdAt: string | null;
18
+ highlights: Highlight[];
19
+ };
13
20
 
14
21
  export type SearchWithAnswerResult = {
15
- answer: string | null
16
- documents: SearchResult[]
17
- }
22
+ answer: string | null;
23
+ documents: SearchResult[];
24
+ };
18
25
 
19
26
  export type Integration = {
20
- id: string
21
- name: string
22
- provider: HyperspellSource
23
- icon: string
24
- }
27
+ id: string;
28
+ name: string;
29
+ provider: HyperspellSource;
30
+ icon: string;
31
+ };
25
32
 
26
33
  export type Connection = {
27
- id: string
28
- integrationId: string
29
- label: string | null
30
- provider: HyperspellSource
31
- }
34
+ id: string;
35
+ integrationId: string;
36
+ label: string | null;
37
+ provider: HyperspellSource;
38
+ };
32
39
 
33
40
  export class HyperspellClient {
34
- private client: Hyperspell
35
- private config: HyperspellConfig
36
-
37
- constructor(config: HyperspellConfig) {
38
- this.config = config
39
- this.client = new Hyperspell({
40
- apiKey: config.apiKey,
41
- userID: config.userId,
42
- })
43
- log.info(`client initialized${config.userId ? ` for user ${config.userId}` : ""}`)
44
- }
45
-
46
- async search(
47
- query: string,
48
- options?: { limit?: number; sources?: HyperspellSource[] },
49
- ): Promise<SearchResult[]> {
50
- const limit = options?.limit ?? this.config.maxResults
51
- const sources =
52
- options?.sources ?? (this.config.sources.length > 0 ? this.config.sources : undefined)
53
-
54
- log.debugRequest("memories.search", { query, limit, sources })
55
-
56
- const response = await this.client.memories.search({
57
- query,
58
- sources,
59
- options: {
60
- max_results: limit,
61
- },
62
- })
63
-
64
- const results: SearchResult[] = response.documents.map((doc) => ({
65
- resourceId: doc.resource_id,
66
- title: doc.title ?? null,
67
- source: doc.source as HyperspellSource,
68
- score: doc.score ?? null,
69
- url: doc.metadata?.url as string | null ?? null,
70
- createdAt: doc.metadata?.created_at as string | null ?? null,
71
- }))
72
-
73
- log.debugResponse("memories.search", { count: results.length })
74
- return results
75
- }
76
-
77
- async searchRaw(
78
- query: string,
79
- options?: { limit?: number; sources?: HyperspellSource[] },
80
- ): Promise<Record<string, unknown>> {
81
- const limit = options?.limit ?? this.config.maxResults
82
- const sources =
83
- options?.sources ?? (this.config.sources.length > 0 ? this.config.sources : undefined)
84
-
85
- log.debugRequest("memories.search (raw)", { query, limit, sources })
86
-
87
- const response = await this.client.memories.search({
88
- query,
89
- sources,
90
- options: {
91
- max_results: limit,
92
- },
93
- })
94
-
95
- log.debugResponse("memories.search (raw)", { count: response.documents.length })
96
-
97
- return response as unknown as Record<string, unknown>
98
- }
99
-
100
- async searchWithAnswer(
101
- query: string,
102
- options?: { limit?: number; sources?: HyperspellSource[] },
103
- ): Promise<SearchWithAnswerResult> {
104
- const limit = options?.limit ?? this.config.maxResults
105
- const sources =
106
- options?.sources ?? (this.config.sources.length > 0 ? this.config.sources : undefined)
107
-
108
- log.debugRequest("memories.search (with answer)", { query, limit, sources })
109
-
110
- const response = await this.client.memories.search({
111
- query,
112
- sources,
113
- answer: true,
114
- options: {
115
- max_results: limit,
116
- },
117
- })
118
-
119
- const documents: SearchResult[] = response.documents.map((doc) => ({
120
- resourceId: doc.resource_id,
121
- title: doc.title ?? null,
122
- source: doc.source as HyperspellSource,
123
- score: doc.score ?? null,
124
- url: doc.metadata?.url as string | null ?? null,
125
- createdAt: doc.metadata?.created_at as string | null ?? null,
126
- }))
127
-
128
- log.debugResponse("memories.search (with answer)", {
129
- count: documents.length,
130
- hasAnswer: !!response.answer,
131
- })
132
-
133
- return {
134
- answer: response.answer ?? null,
135
- documents,
136
- }
137
- }
138
-
139
- async addMemory(
140
- text: string,
141
- options?: {
142
- title?: string
143
- resourceId?: string
144
- collection?: string
145
- metadata?: Record<string, string | number | boolean>
146
- },
147
- ): Promise<{ resourceId: string }> {
148
- log.debugRequest("memories.add", {
149
- textLength: text.length,
150
- title: options?.title,
151
- resourceId: options?.resourceId,
152
- collection: options?.collection,
153
- })
154
-
155
- const result = await this.client.memories.add({
156
- text,
157
- title: options?.title,
158
- resource_id: options?.resourceId,
159
- collection: options?.collection,
160
- metadata: {
161
- ...options?.metadata,
162
- openclaw_source: "command",
163
- },
164
- })
165
-
166
- log.debugResponse("memories.add", { resourceId: result.resource_id })
167
- return { resourceId: result.resource_id }
168
- }
169
-
170
- async listIntegrations(): Promise<Integration[]> {
171
- log.debugRequest("integrations.list", {})
172
-
173
- const response = await this.client.integrations.list()
174
-
175
- const integrations: Integration[] = response.integrations.map((int) => ({
176
- id: int.id,
177
- name: int.name,
178
- provider: int.provider as HyperspellSource,
179
- icon: int.icon,
180
- }))
181
-
182
- log.debugResponse("integrations.list", { count: integrations.length })
183
- return integrations
184
- }
185
-
186
- async getConnectUrl(integrationId: string): Promise<{ url: string; expiresAt: string }> {
187
- log.debugRequest("integrations.connect", { integrationId })
188
-
189
- const response = await this.client.integrations.connect(integrationId)
190
-
191
- log.debugResponse("integrations.connect", { url: response.url })
192
- return {
193
- url: response.url,
194
- expiresAt: response.expires_at,
195
- }
196
- }
197
-
198
- async *listMemories(
199
- options?: { source?: HyperspellSource; collection?: string; pageSize?: number },
200
- ): AsyncGenerator<{
201
- resourceId: string
202
- source: HyperspellSource
203
- title: string | null
204
- metadata: Record<string, unknown>
205
- }> {
206
- log.debugRequest("memories.list", { source: options?.source, collection: options?.collection })
207
-
208
- const params: Record<string, unknown> = {
209
- size: options?.pageSize ?? 100,
210
- }
211
- if (options?.source) params.source = options.source
212
- if (options?.collection) params.collection = options.collection
213
-
214
- for await (const memory of this.client.memories.list(params as any)) {
215
- yield {
216
- resourceId: memory.resource_id,
217
- source: memory.source as HyperspellSource,
218
- title: memory.title ?? null,
219
- metadata: (memory.metadata ?? {}) as Record<string, unknown>,
220
- }
221
- }
222
- }
223
-
224
- async getMemory(
225
- resourceId: string,
226
- source: HyperspellSource,
227
- ): Promise<Record<string, unknown>> {
228
- log.debugRequest("memories.get", { resourceId, source })
229
-
230
- const response = await this.client.memories.get(resourceId, { source })
231
- const raw = response as unknown as Record<string, unknown>
232
-
233
- log.debugResponse("memories.get", { resourceId, hasData: "data" in raw })
234
- return raw
235
- }
236
-
237
- async listConnections(): Promise<Connection[]> {
238
- log.debugRequest("connections.list", {})
239
-
240
- const response = await this.client.connections.list()
241
-
242
- const connections: Connection[] = response.connections.map((conn) => ({
243
- id: conn.id,
244
- integrationId: conn.integration_id,
245
- label: conn.label,
246
- provider: conn.provider as HyperspellSource,
247
- }))
248
-
249
- log.debugResponse("connections.list", { count: connections.length })
250
- return connections
251
- }
41
+ private client: Hyperspell;
42
+ private config: HyperspellConfig;
43
+
44
+ constructor(config: HyperspellConfig) {
45
+ this.config = config;
46
+ this.client = new Hyperspell({
47
+ apiKey: config.apiKey,
48
+ userID: config.userId,
49
+ });
50
+ log.info(
51
+ `client initialized${config.userId ? ` for user ${config.userId}` : ""}`,
52
+ );
53
+ }
54
+
55
+ async search(
56
+ query: string,
57
+ options?: { limit?: number; sources?: HyperspellSource[]; after?: string; before?: string },
58
+ ): Promise<SearchResult[]> {
59
+ const limit = options?.limit ?? this.config.maxResults;
60
+ const sources =
61
+ options?.sources ??
62
+ (this.config.sources.length > 0 ? this.config.sources : undefined);
63
+
64
+ log.debugRequest("memories.search", { query, limit, sources, after: options?.after, before: options?.before });
65
+
66
+ const response = await this.client.memories.search({
67
+ query,
68
+ sources,
69
+ options: {
70
+ max_results: limit,
71
+ ...(options?.after ? { after: options.after } : {}),
72
+ ...(options?.before ? { before: options.before } : {}),
73
+ },
74
+ });
75
+
76
+ const results: SearchResult[] = response.documents.map((doc) => {
77
+ const raw = doc as typeof doc & { highlights?: Array<{ id: string; score: number; text: string }> };
78
+ return {
79
+ resourceId: doc.resource_id,
80
+ title: doc.title ?? null,
81
+ source: doc.source as HyperspellSource,
82
+ score: doc.score ?? null,
83
+ url: (doc.metadata?.url as string | null) ?? null,
84
+ createdAt: (doc.metadata?.created_at as string | null) ?? null,
85
+ highlights: (raw.highlights ?? []).map((h) => ({ id: h.id, score: h.score, text: h.text })),
86
+ };
87
+ });
88
+
89
+ log.debugResponse("memories.search", { count: results.length });
90
+ return results;
91
+ }
92
+
93
+ async searchRaw(
94
+ query: string,
95
+ options?: { limit?: number; sources?: HyperspellSource[]; after?: string; before?: string },
96
+ ): Promise<Record<string, unknown>> {
97
+ const limit = options?.limit ?? this.config.maxResults;
98
+ const sources =
99
+ options?.sources ??
100
+ (this.config.sources.length > 0 ? this.config.sources : undefined);
101
+
102
+ log.debugRequest("memories.search (raw)", { query, limit, sources, after: options?.after, before: options?.before });
103
+
104
+ const response = await this.client.memories.search({
105
+ query,
106
+ sources,
107
+ options: {
108
+ max_results: limit,
109
+ ...(options?.after ? { after: options.after } : {}),
110
+ ...(options?.before ? { before: options.before } : {}),
111
+ },
112
+ });
113
+
114
+ log.debugResponse("memories.search (raw)", {
115
+ count: response.documents.length,
116
+ });
117
+
118
+ return response as unknown as Record<string, unknown>;
119
+ }
120
+
121
+ async searchWithAnswer(
122
+ query: string,
123
+ options?: { limit?: number; sources?: HyperspellSource[] },
124
+ ): Promise<SearchWithAnswerResult> {
125
+ const limit = options?.limit ?? this.config.maxResults;
126
+ const sources =
127
+ options?.sources ??
128
+ (this.config.sources.length > 0 ? this.config.sources : undefined);
129
+
130
+ log.debugRequest("memories.search (with answer)", {
131
+ query,
132
+ limit,
133
+ sources,
134
+ });
135
+
136
+ const response = await this.client.memories.search({
137
+ query,
138
+ sources,
139
+ answer: true,
140
+ options: {
141
+ max_results: limit,
142
+ },
143
+ });
144
+
145
+ const documents: SearchResult[] = response.documents.map((doc) => ({
146
+ resourceId: doc.resource_id,
147
+ title: doc.title ?? null,
148
+ source: doc.source as HyperspellSource,
149
+ score: doc.score ?? null,
150
+ url: (doc.metadata?.url as string | null) ?? null,
151
+ createdAt: (doc.metadata?.created_at as string | null) ?? null,
152
+ }));
153
+
154
+ log.debugResponse("memories.search (with answer)", {
155
+ count: documents.length,
156
+ hasAnswer: !!response.answer,
157
+ });
158
+
159
+ return {
160
+ answer: response.answer ?? null,
161
+ documents,
162
+ };
163
+ }
164
+
165
+ async addMemory(
166
+ text: string,
167
+ options?: {
168
+ title?: string;
169
+ resourceId?: string;
170
+ collection?: string;
171
+ date?: string;
172
+ metadata?: Record<string, string | number | boolean>;
173
+ },
174
+ ): Promise<{ resourceId: string }> {
175
+ log.debugRequest("memories.add", {
176
+ textLength: text.length,
177
+ title: options?.title,
178
+ resourceId: options?.resourceId,
179
+ collection: options?.collection,
180
+ date: options?.date,
181
+ });
182
+
183
+ const result = await this.client.memories.add({
184
+ text,
185
+ title: options?.title,
186
+ resource_id: options?.resourceId,
187
+ collection: options?.collection,
188
+ date: options?.date,
189
+ metadata: {
190
+ ...options?.metadata,
191
+ openclaw_source: "command",
192
+ },
193
+ });
194
+
195
+ log.debugResponse("memories.add", { resourceId: result.resource_id });
196
+ return { resourceId: result.resource_id };
197
+ }
198
+
199
+ async listIntegrations(): Promise<Integration[]> {
200
+ log.debugRequest("integrations.list", {});
201
+
202
+ const response = await this.client.integrations.list();
203
+
204
+ const integrations: Integration[] = response.integrations.map((int) => ({
205
+ id: int.id,
206
+ name: int.name,
207
+ provider: int.provider as HyperspellSource,
208
+ icon: int.icon,
209
+ }));
210
+
211
+ log.debugResponse("integrations.list", { count: integrations.length });
212
+ return integrations;
213
+ }
214
+
215
+ async getConnectUrl(
216
+ integrationId: string,
217
+ ): Promise<{ url: string; expiresAt: string }> {
218
+ log.debugRequest("integrations.connect", { integrationId });
219
+
220
+ const response = await this.client.integrations.connect(integrationId);
221
+
222
+ log.debugResponse("integrations.connect", { url: response.url });
223
+ return {
224
+ url: response.url,
225
+ expiresAt: response.expires_at,
226
+ };
227
+ }
228
+
229
+ async *listMemories(options?: {
230
+ source?: HyperspellSource;
231
+ collection?: string;
232
+ pageSize?: number;
233
+ }): AsyncGenerator<{
234
+ resourceId: string;
235
+ source: HyperspellSource;
236
+ title: string | null;
237
+ metadata: Record<string, unknown>;
238
+ }> {
239
+ log.debugRequest("memories.list", {
240
+ source: options?.source,
241
+ collection: options?.collection,
242
+ });
243
+
244
+ const params: Record<string, unknown> = {
245
+ size: options?.pageSize ?? 100,
246
+ };
247
+ if (options?.source) params.source = options.source;
248
+ if (options?.collection) params.collection = options.collection;
249
+
250
+ for await (const memory of this.client.memories.list(params as any)) {
251
+ yield {
252
+ resourceId: memory.resource_id,
253
+ source: memory.source as HyperspellSource,
254
+ title: memory.title ?? null,
255
+ metadata: (memory.metadata ?? {}) as Record<string, unknown>,
256
+ };
257
+ }
258
+ }
259
+
260
+ async getMemory(
261
+ resourceId: string,
262
+ source: HyperspellSource,
263
+ ): Promise<Record<string, unknown>> {
264
+ log.debugRequest("memories.get", { resourceId, source });
265
+
266
+ const response = await this.client.memories.get(resourceId, { source });
267
+ const raw = response as unknown as Record<string, unknown>;
268
+
269
+ log.debugResponse("memories.get", { resourceId, hasData: "data" in raw });
270
+ return raw;
271
+ }
272
+
273
+ async sendTrace(
274
+ history: string,
275
+ options?: {
276
+ sessionId?: string;
277
+ title?: string;
278
+ extract?: Array<"procedure" | "memory" | "mood">;
279
+ metadata?: Record<string, string | number | boolean>;
280
+ },
281
+ ): Promise<{ resourceId: string; status: string }> {
282
+ log.debugRequest("sessions.add", {
283
+ historyLength: history.length,
284
+ sessionId: options?.sessionId,
285
+ extract: options?.extract,
286
+ });
287
+
288
+ const result = await this.client.sessions.add({
289
+ history,
290
+ session_id: options?.sessionId,
291
+ title: options?.title,
292
+ format: "openclaw",
293
+ extract: options?.extract ?? ["procedure"],
294
+ metadata: {
295
+ ...options?.metadata,
296
+ openclaw_source: "agent_end",
297
+ },
298
+ });
299
+
300
+ log.debugResponse("sessions.add", {
301
+ resourceId: result.resource_id,
302
+ status: result.status,
303
+ });
304
+ return { resourceId: result.resource_id, status: result.status };
305
+ }
306
+
307
+ async listConnections(): Promise<Connection[]> {
308
+ log.debugRequest("connections.list", {});
309
+
310
+ const response = await this.client.connections.list();
311
+
312
+ const connections: Connection[] = response.connections.map((conn) => ({
313
+ id: conn.id,
314
+ integrationId: conn.integration_id,
315
+ label: conn.label,
316
+ provider: conn.provider as HyperspellSource,
317
+ }));
318
+
319
+ log.debugResponse("connections.list", { count: connections.length });
320
+ return connections;
321
+ }
252
322
  }