10xgraph-client 0.6.0 → 1.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/README.md +11 -5
  3. package/dist/agent.d.ts +17 -5
  4. package/dist/agent.d.ts.map +1 -1
  5. package/dist/cjs/agent.d.ts +33 -0
  6. package/dist/cjs/client.d.ts +533 -0
  7. package/dist/cjs/compat.d.ts +27 -0
  8. package/dist/cjs/endpoints/addThreadMessages.d.ts +25 -0
  9. package/dist/cjs/endpoints/clearThreadState.d.ts +14 -0
  10. package/dist/cjs/endpoints/deleteFile.d.ts +13 -0
  11. package/dist/cjs/endpoints/deleteMemory.d.ts +18 -0
  12. package/dist/cjs/endpoints/deleteThread.d.ts +18 -0
  13. package/dist/cjs/endpoints/deleteThreadMessage.d.ts +19 -0
  14. package/dist/cjs/endpoints/files.d.ts +115 -0
  15. package/dist/cjs/endpoints/fixGraph.d.ts +33 -0
  16. package/dist/cjs/endpoints/forgetMemories.d.ts +21 -0
  17. package/dist/cjs/endpoints/getMemory.d.ts +18 -0
  18. package/dist/cjs/endpoints/graph.d.ts +50 -0
  19. package/dist/cjs/endpoints/graphTools.d.ts +31 -0
  20. package/dist/cjs/endpoints/invoke.d.ts +66 -0
  21. package/dist/cjs/endpoints/listMemories.d.ts +24 -0
  22. package/dist/cjs/endpoints/metadata.d.ts +5 -0
  23. package/dist/cjs/endpoints/observability.d.ts +111 -0
  24. package/dist/cjs/endpoints/ping.d.ts +9 -0
  25. package/dist/cjs/endpoints/realtime.d.ts +154 -0
  26. package/dist/cjs/endpoints/searchMemory.d.ts +56 -0
  27. package/dist/cjs/endpoints/stateSchema.d.ts +49 -0
  28. package/dist/cjs/endpoints/stopGraph.d.ts +35 -0
  29. package/dist/cjs/endpoints/storeMemory.d.ts +32 -0
  30. package/dist/cjs/endpoints/stream.d.ts +67 -0
  31. package/dist/cjs/endpoints/threadDetails.d.ts +18 -0
  32. package/dist/cjs/endpoints/threadMessage.d.ts +16 -0
  33. package/dist/cjs/endpoints/threadMessages.d.ts +28 -0
  34. package/dist/cjs/endpoints/threadState.d.ts +13 -0
  35. package/dist/cjs/endpoints/threads.d.ts +35 -0
  36. package/dist/cjs/endpoints/updateMemory.d.ts +20 -0
  37. package/dist/cjs/endpoints/updateThreadMessageFeedback.d.ts +19 -0
  38. package/dist/cjs/endpoints/updateThreadState.d.ts +22 -0
  39. package/dist/cjs/endpoints/wsStream.d.ts +34 -0
  40. package/dist/cjs/errors.d.ts +212 -0
  41. package/dist/cjs/index.d.ts +41 -0
  42. package/dist/cjs/interrupt.d.ts +45 -0
  43. package/dist/cjs/message.d.ts +173 -0
  44. package/dist/cjs/package.json +1 -0
  45. package/dist/cjs/request.d.ts +60 -0
  46. package/dist/cjs/tools.d.ts +80 -0
  47. package/dist/cjs/ws.d.ts +47 -0
  48. package/dist/client.d.ts +95 -40
  49. package/dist/client.d.ts.map +1 -1
  50. package/dist/endpoints/addThreadMessages.d.ts +4 -0
  51. package/dist/endpoints/addThreadMessages.d.ts.map +1 -1
  52. package/dist/endpoints/clearThreadState.d.ts.map +1 -1
  53. package/dist/endpoints/deleteFile.d.ts +14 -0
  54. package/dist/endpoints/deleteFile.d.ts.map +1 -0
  55. package/dist/endpoints/deleteMemory.d.ts.map +1 -1
  56. package/dist/endpoints/deleteThread.d.ts.map +1 -1
  57. package/dist/endpoints/deleteThreadMessage.d.ts.map +1 -1
  58. package/dist/endpoints/files.d.ts +33 -0
  59. package/dist/endpoints/files.d.ts.map +1 -1
  60. package/dist/endpoints/fixGraph.d.ts +8 -3
  61. package/dist/endpoints/fixGraph.d.ts.map +1 -1
  62. package/dist/endpoints/forgetMemories.d.ts.map +1 -1
  63. package/dist/endpoints/getMemory.d.ts.map +1 -1
  64. package/dist/endpoints/graph.d.ts +20 -8
  65. package/dist/endpoints/graph.d.ts.map +1 -1
  66. package/dist/endpoints/graphTools.d.ts.map +1 -1
  67. package/dist/endpoints/invoke.d.ts +8 -0
  68. package/dist/endpoints/invoke.d.ts.map +1 -1
  69. package/dist/endpoints/listMemories.d.ts +6 -0
  70. package/dist/endpoints/listMemories.d.ts.map +1 -1
  71. package/dist/endpoints/observability.d.ts +54 -0
  72. package/dist/endpoints/observability.d.ts.map +1 -1
  73. package/dist/endpoints/ping.d.ts.map +1 -1
  74. package/dist/endpoints/realtime.d.ts +25 -4
  75. package/dist/endpoints/realtime.d.ts.map +1 -1
  76. package/dist/endpoints/searchMemory.d.ts.map +1 -1
  77. package/dist/endpoints/stateSchema.d.ts.map +1 -1
  78. package/dist/endpoints/stopGraph.d.ts +13 -3
  79. package/dist/endpoints/stopGraph.d.ts.map +1 -1
  80. package/dist/endpoints/storeMemory.d.ts.map +1 -1
  81. package/dist/endpoints/stream.d.ts +8 -0
  82. package/dist/endpoints/stream.d.ts.map +1 -1
  83. package/dist/endpoints/threadDetails.d.ts.map +1 -1
  84. package/dist/endpoints/threadMessage.d.ts.map +1 -1
  85. package/dist/endpoints/threadMessages.d.ts +6 -0
  86. package/dist/endpoints/threadMessages.d.ts.map +1 -1
  87. package/dist/endpoints/threadState.d.ts.map +1 -1
  88. package/dist/endpoints/threads.d.ts +6 -0
  89. package/dist/endpoints/threads.d.ts.map +1 -1
  90. package/dist/endpoints/updateMemory.d.ts.map +1 -1
  91. package/dist/endpoints/updateThreadMessageFeedback.d.ts +20 -0
  92. package/dist/endpoints/updateThreadMessageFeedback.d.ts.map +1 -0
  93. package/dist/endpoints/updateThreadState.d.ts +6 -1
  94. package/dist/endpoints/updateThreadState.d.ts.map +1 -1
  95. package/dist/endpoints/wsStream.d.ts +2 -0
  96. package/dist/endpoints/wsStream.d.ts.map +1 -1
  97. package/dist/errors.d.ts +60 -2
  98. package/dist/errors.d.ts.map +1 -1
  99. package/dist/index.cjs +3 -3
  100. package/dist/index.cjs.map +1 -1
  101. package/dist/index.d.ts +3 -0
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +1742 -1217
  104. package/dist/index.js.map +1 -1
  105. package/dist/interrupt.d.ts +46 -0
  106. package/dist/interrupt.d.ts.map +1 -0
  107. package/dist/request.d.ts +28 -0
  108. package/dist/request.d.ts.map +1 -1
  109. package/dist/tools.d.ts +14 -0
  110. package/dist/tools.d.ts.map +1 -1
  111. package/package.json +11 -6
  112. package/src/agent.ts +17 -4
  113. package/src/client.ts +248 -128
  114. package/src/endpoints/addThreadMessages.ts +15 -10
  115. package/src/endpoints/clearThreadState.ts +19 -20
  116. package/src/endpoints/deleteFile.ts +65 -0
  117. package/src/endpoints/deleteMemory.ts +9 -13
  118. package/src/endpoints/deleteThread.ts +9 -13
  119. package/src/endpoints/deleteThreadMessage.ts +9 -13
  120. package/src/endpoints/files.ts +164 -131
  121. package/src/endpoints/fixGraph.ts +15 -16
  122. package/src/endpoints/forgetMemories.ts +44 -60
  123. package/src/endpoints/getMemory.ts +9 -9
  124. package/src/endpoints/graph.ts +28 -21
  125. package/src/endpoints/graphTools.ts +7 -13
  126. package/src/endpoints/invoke.ts +105 -84
  127. package/src/endpoints/listMemories.ts +18 -13
  128. package/src/endpoints/observability.ts +77 -34
  129. package/src/endpoints/ping.ts +7 -13
  130. package/src/endpoints/realtime.ts +101 -39
  131. package/src/endpoints/searchMemory.ts +19 -13
  132. package/src/endpoints/stateSchema.ts +7 -13
  133. package/src/endpoints/stopGraph.ts +20 -16
  134. package/src/endpoints/storeMemory.ts +7 -8
  135. package/src/endpoints/stream.ts +179 -61
  136. package/src/endpoints/threadDetails.ts +9 -14
  137. package/src/endpoints/threadMessage.ts +9 -9
  138. package/src/endpoints/threadMessages.ts +15 -9
  139. package/src/endpoints/threadState.ts +19 -20
  140. package/src/endpoints/threads.ts +13 -12
  141. package/src/endpoints/updateMemory.ts +9 -9
  142. package/src/endpoints/updateThreadMessageFeedback.ts +80 -0
  143. package/src/endpoints/updateThreadState.ts +28 -22
  144. package/src/endpoints/wsStream.ts +167 -42
  145. package/src/errors.ts +332 -93
  146. package/src/index.ts +9 -0
  147. package/src/interrupt.ts +60 -0
  148. package/src/request.ts +134 -0
  149. package/src/tools.ts +95 -0
@@ -3,7 +3,12 @@
3
3
  */
4
4
 
5
5
  import { createErrorFromResponse } from '../errors.js';
6
- import { buildHeaders, getRequestCredentials, RequestContext } from '../request.js';
6
+ import {
7
+ buildHeaders,
8
+ getRequestCredentials,
9
+ RequestContext,
10
+ fetchWithTimeout,
11
+ } from '../request.js';
7
12
 
8
13
  // ---------------------------------------------------------------------------
9
14
  // Types
@@ -86,46 +91,36 @@ export async function uploadFile(
86
91
  ctx: FileUploadContext,
87
92
  file: File | Blob | { data: Blob; filename: string }
88
93
  ): Promise<FileUploadResponse> {
89
- const controller = new AbortController();
90
- const timeoutId = setTimeout(() => controller.abort(), ctx.timeout);
91
-
92
- try {
93
- const formData = new FormData();
94
-
95
- // `File` only became a global in Node 20; this package supports Node 18, where a bare
96
- // `instanceof File` throws ReferenceError. Guard before touching the global.
97
- if (typeof File !== 'undefined' && file instanceof File) {
98
- formData.append('file', file, file.name);
99
- } else if ('data' in file && 'filename' in file) {
100
- formData.append('file', file.data, file.filename);
101
- } else {
102
- formData.append('file', file, 'upload');
103
- }
104
-
105
- const response = await fetch(`${ctx.baseUrl}/v1/files/upload`, {
106
- method: 'POST',
107
- headers: buildHeaders(ctx as RequestContext),
108
- body: formData,
109
- ...getRequestCredentials(ctx as RequestContext),
110
- signal: controller.signal,
111
- });
112
-
113
- clearTimeout(timeoutId);
114
-
115
- if (!response.ok) {
116
- const error = await createErrorFromResponse(
117
- response,
118
- 'File upload failed',
119
- '/v1/files/upload',
120
- 'POST'
121
- );
122
- throw error;
123
- }
94
+ const formData = new FormData();
95
+
96
+ // `File` only became a global in Node 20; this package supports Node 18, where a bare
97
+ // `instanceof File` throws ReferenceError. Guard before touching the global.
98
+ if (typeof File !== 'undefined' && file instanceof File) {
99
+ formData.append('file', file, file.name);
100
+ } else if ('data' in file && 'filename' in file) {
101
+ formData.append('file', file.data, file.filename);
102
+ } else {
103
+ formData.append('file', file, 'upload');
104
+ }
124
105
 
125
- return (await response.json()) as FileUploadResponse;
126
- } finally {
127
- clearTimeout(timeoutId);
106
+ const response = await fetchWithTimeout(ctx, `${ctx.baseUrl}/v1/files/upload`, {
107
+ method: 'POST',
108
+ headers: buildHeaders(ctx as RequestContext),
109
+ body: formData,
110
+ ...getRequestCredentials(ctx as RequestContext),
111
+ });
112
+
113
+ if (!response.ok) {
114
+ const error = await createErrorFromResponse(
115
+ response,
116
+ 'File upload failed',
117
+ '/v1/files/upload',
118
+ 'POST'
119
+ );
120
+ throw error;
128
121
  }
122
+
123
+ return (await response.json()) as FileUploadResponse;
129
124
  }
130
125
 
131
126
  // ---------------------------------------------------------------------------
@@ -135,33 +130,93 @@ export async function uploadFile(
135
130
  * Download a file by its file_id. Returns raw Blob.
136
131
  */
137
132
  export async function getFile(ctx: FileUploadContext, fileId: string): Promise<Blob> {
138
- const controller = new AbortController();
139
- const timeoutId = setTimeout(() => controller.abort(), ctx.timeout);
140
-
141
- try {
142
- const response = await fetch(`${ctx.baseUrl}/v1/files/${encodeURIComponent(fileId)}`, {
133
+ const response = await fetchWithTimeout(
134
+ ctx,
135
+ `${ctx.baseUrl}/v1/files/${encodeURIComponent(fileId)}`,
136
+ {
143
137
  method: 'GET',
144
138
  headers: buildHeaders(ctx as RequestContext),
145
139
  ...getRequestCredentials(ctx as RequestContext),
146
- signal: controller.signal,
147
- });
140
+ }
141
+ );
142
+
143
+ if (!response.ok) {
144
+ const error = await createErrorFromResponse(
145
+ response,
146
+ 'File download failed',
147
+ `/v1/files/${fileId}`,
148
+ 'GET'
149
+ );
150
+ throw error;
151
+ }
148
152
 
149
- clearTimeout(timeoutId);
153
+ return await response.blob();
154
+ }
150
155
 
151
- if (!response.ok) {
152
- const error = await createErrorFromResponse(
153
- response,
154
- 'File download failed',
155
- `/v1/files/${fileId}`,
156
- 'GET'
157
- );
158
- throw error;
159
- }
156
+ // ---------------------------------------------------------------------------
157
+ // List files (GET /v1/files)
158
+ // ---------------------------------------------------------------------------
159
+ export interface ListFilesRequest {
160
+ /** Page size (server default 50, maximum 200). */
161
+ limit?: number;
162
+ /** Number of files to skip. */
163
+ offset?: number;
164
+ }
165
+
166
+ export interface FileListItem {
167
+ file_id: string;
168
+ filename: string | null;
169
+ mime_type: string;
170
+ size_bytes: number;
171
+ url: string;
172
+ /** Unix seconds, or null when the store records no timestamp. */
173
+ created_at: number | null;
174
+ }
175
+
176
+ export interface ListFilesResponse {
177
+ data: {
178
+ files: FileListItem[];
179
+ has_more: boolean;
180
+ offset: number;
181
+ limit: number;
182
+ };
183
+ metadata?: {
184
+ request_id: string;
185
+ timestamp: string;
186
+ message: string;
187
+ };
188
+ }
160
189
 
161
- return await response.blob();
162
- } finally {
163
- clearTimeout(timeoutId);
190
+ /**
191
+ * List the caller's uploaded files. A store that cannot enumerate its files
192
+ * (for example a cloud store) answers 501, which is thrown as a TenxGraphError.
193
+ */
194
+ export async function listFiles(
195
+ ctx: FileUploadContext,
196
+ params?: ListFilesRequest
197
+ ): Promise<ListFilesResponse> {
198
+ const query = new URLSearchParams();
199
+ if (params?.limit !== undefined) query.append('limit', String(params.limit));
200
+ if (params?.offset !== undefined) query.append('offset', String(params.offset));
201
+ const qs = query.toString();
202
+
203
+ const response = await fetchWithTimeout(ctx, `${ctx.baseUrl}/v1/files${qs ? `?${qs}` : ''}`, {
204
+ method: 'GET',
205
+ headers: buildHeaders(ctx as RequestContext),
206
+ ...getRequestCredentials(ctx as RequestContext),
207
+ });
208
+
209
+ if (!response.ok) {
210
+ const error = await createErrorFromResponse(
211
+ response,
212
+ 'List files request failed',
213
+ '/v1/files',
214
+ 'GET'
215
+ );
216
+ throw error;
164
217
  }
218
+
219
+ return (await response.json()) as ListFilesResponse;
165
220
  }
166
221
 
167
222
  // ---------------------------------------------------------------------------
@@ -171,33 +226,27 @@ export async function getFileInfo(
171
226
  ctx: FileUploadContext,
172
227
  fileId: string
173
228
  ): Promise<FileInfoResponse> {
174
- const controller = new AbortController();
175
- const timeoutId = setTimeout(() => controller.abort(), ctx.timeout);
176
-
177
- try {
178
- const response = await fetch(`${ctx.baseUrl}/v1/files/${encodeURIComponent(fileId)}/info`, {
229
+ const response = await fetchWithTimeout(
230
+ ctx,
231
+ `${ctx.baseUrl}/v1/files/${encodeURIComponent(fileId)}/info`,
232
+ {
179
233
  method: 'GET',
180
234
  headers: buildHeaders(ctx as RequestContext),
181
235
  ...getRequestCredentials(ctx as RequestContext),
182
- signal: controller.signal,
183
- });
184
-
185
- clearTimeout(timeoutId);
186
-
187
- if (!response.ok) {
188
- const error = await createErrorFromResponse(
189
- response,
190
- 'File info request failed',
191
- `/v1/files/${fileId}/info`,
192
- 'GET'
193
- );
194
- throw error;
195
236
  }
196
-
197
- return (await response.json()) as FileInfoResponse;
198
- } finally {
199
- clearTimeout(timeoutId);
237
+ );
238
+
239
+ if (!response.ok) {
240
+ const error = await createErrorFromResponse(
241
+ response,
242
+ 'File info request failed',
243
+ `/v1/files/${fileId}/info`,
244
+ 'GET'
245
+ );
246
+ throw error;
200
247
  }
248
+
249
+ return (await response.json()) as FileInfoResponse;
201
250
  }
202
251
 
203
252
  // ---------------------------------------------------------------------------
@@ -207,33 +256,27 @@ export async function getFileAccessUrl(
207
256
  ctx: FileUploadContext,
208
257
  fileId: string
209
258
  ): Promise<FileAccessUrlResponse> {
210
- const controller = new AbortController();
211
- const timeoutId = setTimeout(() => controller.abort(), ctx.timeout);
212
-
213
- try {
214
- const response = await fetch(`${ctx.baseUrl}/v1/files/${encodeURIComponent(fileId)}/url`, {
259
+ const response = await fetchWithTimeout(
260
+ ctx,
261
+ `${ctx.baseUrl}/v1/files/${encodeURIComponent(fileId)}/url`,
262
+ {
215
263
  method: 'GET',
216
264
  headers: buildHeaders(ctx as RequestContext),
217
265
  ...getRequestCredentials(ctx as RequestContext),
218
- signal: controller.signal,
219
- });
220
-
221
- clearTimeout(timeoutId);
222
-
223
- if (!response.ok) {
224
- const error = await createErrorFromResponse(
225
- response,
226
- 'File access URL request failed',
227
- `/v1/files/${fileId}/url`,
228
- 'GET'
229
- );
230
- throw error;
231
266
  }
232
-
233
- return (await response.json()) as FileAccessUrlResponse;
234
- } finally {
235
- clearTimeout(timeoutId);
267
+ );
268
+
269
+ if (!response.ok) {
270
+ const error = await createErrorFromResponse(
271
+ response,
272
+ 'File access URL request failed',
273
+ `/v1/files/${fileId}/url`,
274
+ 'GET'
275
+ );
276
+ throw error;
236
277
  }
278
+
279
+ return (await response.json()) as FileAccessUrlResponse;
237
280
  }
238
281
 
239
282
  // ---------------------------------------------------------------------------
@@ -242,33 +285,23 @@ export async function getFileAccessUrl(
242
285
  export async function getMultimodalConfig(
243
286
  ctx: FileUploadContext
244
287
  ): Promise<MultimodalConfigResponse> {
245
- const controller = new AbortController();
246
- const timeoutId = setTimeout(() => controller.abort(), ctx.timeout);
247
-
248
- try {
249
- const response = await fetch(`${ctx.baseUrl}/v1/config/multimodal`, {
250
- method: 'GET',
251
- headers: buildHeaders(ctx as RequestContext, {
252
- accept: 'application/json',
253
- }),
254
- ...getRequestCredentials(ctx as RequestContext),
255
- signal: controller.signal,
256
- });
257
-
258
- clearTimeout(timeoutId);
259
-
260
- if (!response.ok) {
261
- const error = await createErrorFromResponse(
262
- response,
263
- 'Multimodal config request failed',
264
- '/v1/config/multimodal',
265
- 'GET'
266
- );
267
- throw error;
268
- }
269
-
270
- return (await response.json()) as MultimodalConfigResponse;
271
- } finally {
272
- clearTimeout(timeoutId);
288
+ const response = await fetchWithTimeout(ctx, `${ctx.baseUrl}/v1/config/multimodal`, {
289
+ method: 'GET',
290
+ headers: buildHeaders(ctx as RequestContext, {
291
+ accept: 'application/json',
292
+ }),
293
+ ...getRequestCredentials(ctx as RequestContext),
294
+ });
295
+
296
+ if (!response.ok) {
297
+ const error = await createErrorFromResponse(
298
+ response,
299
+ 'Multimodal config request failed',
300
+ '/v1/config/multimodal',
301
+ 'GET'
302
+ );
303
+ throw error;
273
304
  }
305
+
306
+ return (await response.json()) as MultimodalConfigResponse;
274
307
  }
@@ -1,6 +1,11 @@
1
1
  import { ResponseMetadata } from './metadata.js';
2
2
  import { createErrorFromResponse } from '../errors.js';
3
- import { buildHeaders, getRequestCredentials, RequestContext } from '../request.js';
3
+ import {
4
+ buildHeaders,
5
+ getRequestCredentials,
6
+ RequestContext,
7
+ fetchWithTimeout,
8
+ } from '../request.js';
4
9
 
5
10
  export interface FixGraphContext extends RequestContext {}
6
11
 
@@ -20,10 +25,15 @@ export interface FixGraphResponse {
20
25
  }
21
26
 
22
27
  /**
23
- * Fix graph state by removing messages with empty tool calls
28
+ * Repair a thread whose run stopped after the model asked for tools but before
29
+ * the results were saved.
24
30
  *
25
- * This is useful for cleaning up incomplete tool call messages that may have
26
- * failed or been interrupted during execution.
31
+ * The server removes an assistant message when any of its tool calls has no
32
+ * matching tool result (matched by tool call id), then removes tool result
33
+ * messages whose call no longer exists. If the thread is paused (interrupt,
34
+ * client tool call or human approval), the unanswered calls of the latest
35
+ * assistant message are kept. Messages without tool calls are never touched.
36
+ * When nothing needs fixing, removed_count is 0 and the state is not written.
27
37
  *
28
38
  * @param context - Request context with baseUrl, auth, timeout
29
39
  * @param request - Fix request with thread_id and optional config
@@ -38,10 +48,7 @@ export async function fixGraph(
38
48
  console.debug('TenxGraphClient: Fixing graph state for thread:', request.thread_id);
39
49
  }
40
50
 
41
- const controller = new AbortController();
42
- const timeoutId = setTimeout(() => controller.abort(), context.timeout);
43
-
44
- const response = await fetch(`${context.baseUrl}/v1/graph/fix`, {
51
+ const response = await fetchWithTimeout(context, `${context.baseUrl}/v1/graph/fix`, {
45
52
  method: 'POST',
46
53
  headers: buildHeaders(context as RequestContext, {
47
54
  'Content-Type': 'application/json',
@@ -49,11 +56,8 @@ export async function fixGraph(
49
56
  }),
50
57
  ...getRequestCredentials(context as RequestContext),
51
58
  body: JSON.stringify(request),
52
- signal: controller.signal,
53
59
  });
54
60
 
55
- clearTimeout(timeoutId);
56
-
57
61
  if (!response.ok) {
58
62
  console.warn(`TenxGraphClient: Fix graph failed with HTTP ${response.status}`);
59
63
  const error = await createErrorFromResponse(
@@ -80,11 +84,6 @@ export async function fixGraph(
80
84
  console.debug('TenxGraphClient: Fix graph failed:', error);
81
85
  }
82
86
 
83
- if ((error as Error).name === 'AbortError') {
84
- console.warn(`TenxGraphClient: Fix graph timeout after ${context.timeout}ms`);
85
- throw new Error(`Request timeout after ${context.timeout}ms`);
86
- }
87
-
88
87
  console.error('TenxGraphClient: Fix graph failed:', error);
89
88
  throw error;
90
89
  }
@@ -1,6 +1,11 @@
1
1
  import { ResponseMetadata } from './metadata.js';
2
2
  import { MemoryType } from './storeMemory.js';
3
- import { buildHeaders, getRequestCredentials, RequestContext } from '../request.js';
3
+ import {
4
+ buildHeaders,
5
+ getRequestCredentials,
6
+ RequestContext,
7
+ fetchWithTimeout,
8
+ } from '../request.js';
4
9
 
5
10
  export interface ForgetMemoriesContext extends RequestContext {}
6
11
 
@@ -26,70 +31,49 @@ export async function forgetMemories(
26
31
  context: ForgetMemoriesContext,
27
32
  request: ForgetMemoriesRequest
28
33
  ): Promise<ForgetMemoriesResponse> {
29
- try {
30
- const url = `${context.baseUrl}/v1/store/memories/forget`;
34
+ const url = `${context.baseUrl}/v1/store/memories/forget`;
31
35
 
32
- // Prepare request body - only include optional fields if provided
33
- const body: Record<string, any> = {};
36
+ // Prepare request body - only include optional fields if provided
37
+ const body: Record<string, any> = {};
34
38
 
35
- if (request.config) {
36
- body.config = request.config;
37
- }
38
- if (request.options) {
39
- body.options = request.options;
40
- }
41
- if (request.memory_type) {
42
- body.memory_type = request.memory_type;
43
- }
44
- if (request.category) {
45
- body.category = request.category;
46
- }
47
- if (request.filters) {
48
- body.filters = request.filters;
49
- }
50
-
51
- if (context.debug) {
52
- console.log('[DEBUG] Forget memories request:', body);
53
- }
54
-
55
- const controller = new AbortController();
56
- // `ReturnType<typeof setTimeout>` rather than NodeJS.Timeout: this client runs in
57
- // browsers too, and the NodeJS namespace would force consumers to install @types/node.
58
- let timeoutId: ReturnType<typeof setTimeout> | undefined;
59
-
60
- if (context.timeout > 0) {
61
- timeoutId = setTimeout(() => controller.abort(), context.timeout);
62
- }
63
-
64
- const response = await fetch(url, {
65
- method: 'POST',
66
- headers: buildHeaders(context as RequestContext, {
67
- 'Content-Type': 'application/json',
68
- }),
69
- ...getRequestCredentials(context as RequestContext),
70
- body: JSON.stringify(body),
71
- ...(context.timeout > 0 && { signal: controller.signal }),
72
- });
73
-
74
- if (timeoutId) {
75
- clearTimeout(timeoutId);
76
- }
39
+ if (request.config) {
40
+ body.config = request.config;
41
+ }
42
+ if (request.options) {
43
+ body.options = request.options;
44
+ }
45
+ if (request.memory_type) {
46
+ body.memory_type = request.memory_type;
47
+ }
48
+ if (request.category) {
49
+ body.category = request.category;
50
+ }
51
+ if (request.filters) {
52
+ body.filters = request.filters;
53
+ }
77
54
 
78
- if (!response.ok) {
79
- throw new Error(`Forget memories failed: ${response.status} ${response.statusText}`);
80
- }
55
+ if (context.debug) {
56
+ console.log('[DEBUG] Forget memories request:', body);
57
+ }
81
58
 
82
- const data: ForgetMemoriesResponse = await response.json();
59
+ const response = await fetchWithTimeout(context, url, {
60
+ method: 'POST',
61
+ headers: buildHeaders(context as RequestContext, {
62
+ 'Content-Type': 'application/json',
63
+ }),
64
+ ...getRequestCredentials(context as RequestContext),
65
+ body: JSON.stringify(body),
66
+ });
67
+
68
+ if (!response.ok) {
69
+ throw new Error(`Forget memories failed: ${response.status} ${response.statusText}`);
70
+ }
83
71
 
84
- if (context.debug) {
85
- console.log('[DEBUG] Forget memories response:', data);
86
- }
72
+ const data: ForgetMemoriesResponse = await response.json();
87
73
 
88
- return data;
89
- } catch (error) {
90
- if ((error as Error).name === 'AbortError') {
91
- throw error;
92
- }
93
- throw error;
74
+ if (context.debug) {
75
+ console.log('[DEBUG] Forget memories response:', data);
94
76
  }
77
+
78
+ return data;
95
79
  }
@@ -1,6 +1,12 @@
1
1
  import { ResponseMetadata } from './metadata.js';
2
2
  import { createErrorFromResponse } from '../errors.js';
3
- import { buildHeaders, getRequestCredentials, RequestContext } from '../request.js';
3
+ import {
4
+ buildHeaders,
5
+ getRequestCredentials,
6
+ RequestContext,
7
+ fetchWithTimeout,
8
+ encodePathSegment,
9
+ } from '../request.js';
4
10
  import { MemoryResult } from './searchMemory.js';
5
11
 
6
12
  export interface GetMemoryContext extends RequestContext {}
@@ -29,10 +35,7 @@ export async function getMemory(
29
35
  console.debug('TenxGraphClient: Fetching memory with ID:', request.memoryId);
30
36
  }
31
37
 
32
- const controller = new AbortController();
33
- const timeoutId = setTimeout(() => controller.abort(), context.timeout);
34
-
35
- const url = `${context.baseUrl}/v1/store/memories/${request.memoryId}`;
38
+ const url = `${context.baseUrl}/v1/store/memories/${encodePathSegment(request.memoryId)}`;
36
39
 
37
40
  // Prepare request body
38
41
  const body = {
@@ -40,18 +43,15 @@ export async function getMemory(
40
43
  options: request.options || {},
41
44
  };
42
45
 
43
- const response = await fetch(url, {
46
+ const response = await fetchWithTimeout(context, url, {
44
47
  method: 'POST',
45
48
  headers: buildHeaders(context as RequestContext, {
46
49
  'Content-Type': 'application/json',
47
50
  }),
48
51
  ...getRequestCredentials(context as RequestContext),
49
52
  body: JSON.stringify(body),
50
- signal: controller.signal,
51
53
  });
52
54
 
53
- clearTimeout(timeoutId);
54
-
55
55
  if (!response.ok) {
56
56
  console.warn(`TenxGraphClient: Get memory failed with HTTP ${response.status}`);
57
57
  const error = await createErrorFromResponse(
@@ -1,6 +1,11 @@
1
1
  import { ResponseMetadata } from './metadata.js';
2
2
  import { createErrorFromResponse } from '../errors.js';
3
- import { buildHeaders, getRequestCredentials, RequestContext } from '../request.js';
3
+ import {
4
+ buildHeaders,
5
+ getRequestCredentials,
6
+ RequestContext,
7
+ fetchWithTimeout,
8
+ } from '../request.js';
4
9
 
5
10
  export interface GraphContext extends RequestContext {}
6
11
 
@@ -15,20 +20,33 @@ export interface GraphEdge {
15
20
  target: string;
16
21
  }
17
22
 
23
+ /** Live (realtime) init options the server honors. */
24
+ export interface GraphRealtimeOptions {
25
+ /** Init-frame keys applied from the client (subset of voice, modalities, vad, system_prompt). */
26
+ client_overrides: string[];
27
+ /** Accepted values for the init `model`; empty means the client cannot choose. */
28
+ models: string[];
29
+ model_selectable: boolean;
30
+ /** The client may narrow (never widen) the agent's tool tags. */
31
+ tools_tags: boolean;
32
+ }
33
+
18
34
  export interface GraphInfo {
19
35
  node_count: number;
20
36
  edge_count: number;
21
37
  checkpointer: boolean;
22
- checkpointer_type: string;
38
+ checkpointer_type: string | null;
23
39
  publisher: boolean;
24
40
  store: boolean;
25
- interrupt_before: string[];
26
- interrupt_after: string[];
27
- context_type: string;
28
- id_generator: string;
29
- id_type: string;
30
- state_type: string;
31
- state_fields: string[];
41
+ interrupt_before: string[] | null;
42
+ interrupt_after: string[] | null;
43
+ context_type: string | null;
44
+ id_generator: string | null;
45
+ id_type: string | null;
46
+ state_type: string | null;
47
+ state_fields: string[] | null;
48
+ /** Live options the server honors; null when the graph is not a realtime agent. */
49
+ realtime_options?: GraphRealtimeOptions | null;
32
50
  }
33
51
 
34
52
  export interface GraphData {
@@ -48,21 +66,15 @@ export async function graph(context: GraphContext): Promise<GraphResponse> {
48
66
  console.debug('TenxGraphClient: Fetching graph from', context.baseUrl);
49
67
  }
50
68
 
51
- const controller = new AbortController();
52
- const timeoutId = setTimeout(() => controller.abort(), context.timeout);
53
-
54
- const response = await fetch(`${context.baseUrl}/v1/graph`, {
69
+ const response = await fetchWithTimeout(context, `${context.baseUrl}/v1/graph`, {
55
70
  method: 'GET',
56
71
  headers: buildHeaders(context as RequestContext, {
57
72
  'Content-Type': 'application/json',
58
73
  accept: 'application/json',
59
74
  }),
60
75
  ...getRequestCredentials(context as RequestContext),
61
- signal: controller.signal,
62
76
  });
63
77
 
64
- clearTimeout(timeoutId);
65
-
66
78
  if (!response.ok) {
67
79
  console.warn(`TenxGraphClient: Graph fetch failed with HTTP ${response.status}`);
68
80
  const error = await createErrorFromResponse(
@@ -86,11 +98,6 @@ export async function graph(context: GraphContext): Promise<GraphResponse> {
86
98
  console.debug('TenxGraphClient: Graph fetch failed:', error);
87
99
  }
88
100
 
89
- if ((error as Error).name === 'AbortError') {
90
- console.warn(`TenxGraphClient: Graph fetch timeout after ${context.timeout}ms`);
91
- throw new Error(`Request timeout after ${context.timeout}ms`);
92
- }
93
-
94
101
  console.error('TenxGraphClient: Graph fetch failed:', error);
95
102
  throw error;
96
103
  }