10xgraph-client 0.0.0-stage → 0.6.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.
Files changed (125) hide show
  1. package/CHANGELOG.md +276 -0
  2. package/LICENSE +21 -0
  3. package/README.md +400 -2
  4. package/dist/agent.d.ts +22 -0
  5. package/dist/agent.d.ts.map +1 -0
  6. package/dist/client.d.ts +479 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/compat.d.ts +28 -0
  9. package/dist/compat.d.ts.map +1 -0
  10. package/dist/endpoints/addThreadMessages.d.ts +22 -0
  11. package/dist/endpoints/addThreadMessages.d.ts.map +1 -0
  12. package/dist/endpoints/clearThreadState.d.ts +15 -0
  13. package/dist/endpoints/clearThreadState.d.ts.map +1 -0
  14. package/dist/endpoints/deleteMemory.d.ts +19 -0
  15. package/dist/endpoints/deleteMemory.d.ts.map +1 -0
  16. package/dist/endpoints/deleteThread.d.ts +19 -0
  17. package/dist/endpoints/deleteThread.d.ts.map +1 -0
  18. package/dist/endpoints/deleteThreadMessage.d.ts +20 -0
  19. package/dist/endpoints/deleteThreadMessage.d.ts.map +1 -0
  20. package/dist/endpoints/files.d.ts +83 -0
  21. package/dist/endpoints/files.d.ts.map +1 -0
  22. package/dist/endpoints/fixGraph.d.ts +29 -0
  23. package/dist/endpoints/fixGraph.d.ts.map +1 -0
  24. package/dist/endpoints/forgetMemories.d.ts +22 -0
  25. package/dist/endpoints/forgetMemories.d.ts.map +1 -0
  26. package/dist/endpoints/getMemory.d.ts +19 -0
  27. package/dist/endpoints/getMemory.d.ts.map +1 -0
  28. package/dist/endpoints/graph.d.ts +39 -0
  29. package/dist/endpoints/graph.d.ts.map +1 -0
  30. package/dist/endpoints/graphTools.d.ts +32 -0
  31. package/dist/endpoints/graphTools.d.ts.map +1 -0
  32. package/dist/endpoints/invoke.d.ts +59 -0
  33. package/dist/endpoints/invoke.d.ts.map +1 -0
  34. package/dist/endpoints/listMemories.d.ts +19 -0
  35. package/dist/endpoints/listMemories.d.ts.map +1 -0
  36. package/dist/endpoints/metadata.d.ts +6 -0
  37. package/dist/endpoints/metadata.d.ts.map +1 -0
  38. package/dist/endpoints/observability.d.ts +58 -0
  39. package/dist/endpoints/observability.d.ts.map +1 -0
  40. package/dist/endpoints/ping.d.ts +10 -0
  41. package/dist/endpoints/ping.d.ts.map +1 -0
  42. package/dist/endpoints/realtime.d.ts +134 -0
  43. package/dist/endpoints/realtime.d.ts.map +1 -0
  44. package/dist/endpoints/searchMemory.d.ts +57 -0
  45. package/dist/endpoints/searchMemory.d.ts.map +1 -0
  46. package/dist/endpoints/stateSchema.d.ts +50 -0
  47. package/dist/endpoints/stateSchema.d.ts.map +1 -0
  48. package/dist/endpoints/stopGraph.d.ts +26 -0
  49. package/dist/endpoints/stopGraph.d.ts.map +1 -0
  50. package/dist/endpoints/storeMemory.d.ts +33 -0
  51. package/dist/endpoints/storeMemory.d.ts.map +1 -0
  52. package/dist/endpoints/stream.d.ts +60 -0
  53. package/dist/endpoints/stream.d.ts.map +1 -0
  54. package/dist/endpoints/threadDetails.d.ts +19 -0
  55. package/dist/endpoints/threadDetails.d.ts.map +1 -0
  56. package/dist/endpoints/threadMessage.d.ts +17 -0
  57. package/dist/endpoints/threadMessage.d.ts.map +1 -0
  58. package/dist/endpoints/threadMessages.d.ts +23 -0
  59. package/dist/endpoints/threadMessages.d.ts.map +1 -0
  60. package/dist/endpoints/threadState.d.ts +14 -0
  61. package/dist/endpoints/threadState.d.ts.map +1 -0
  62. package/dist/endpoints/threads.d.ts +30 -0
  63. package/dist/endpoints/threads.d.ts.map +1 -0
  64. package/dist/endpoints/updateMemory.d.ts +21 -0
  65. package/dist/endpoints/updateMemory.d.ts.map +1 -0
  66. package/dist/endpoints/updateThreadState.d.ts +18 -0
  67. package/dist/endpoints/updateThreadState.d.ts.map +1 -0
  68. package/dist/endpoints/wsStream.d.ts +33 -0
  69. package/dist/endpoints/wsStream.d.ts.map +1 -0
  70. package/dist/errors.d.ts +155 -0
  71. package/dist/errors.d.ts.map +1 -0
  72. package/dist/index.cjs +6 -0
  73. package/dist/index.cjs.map +1 -0
  74. package/dist/index.d.ts +39 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +2664 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/message.d.ts +174 -0
  79. package/dist/message.d.ts.map +1 -0
  80. package/dist/request.d.ts +33 -0
  81. package/dist/request.d.ts.map +1 -0
  82. package/dist/tools.d.ts +67 -0
  83. package/dist/tools.d.ts.map +1 -0
  84. package/dist/ws.d.ts +48 -0
  85. package/dist/ws.d.ts.map +1 -0
  86. package/package.json +99 -4
  87. package/src/agent.ts +43 -0
  88. package/src/client.ts +1044 -0
  89. package/src/compat.ts +35 -0
  90. package/src/endpoints/addThreadMessages.ts +83 -0
  91. package/src/endpoints/clearThreadState.ts +75 -0
  92. package/src/endpoints/deleteMemory.ts +91 -0
  93. package/src/endpoints/deleteThread.ts +78 -0
  94. package/src/endpoints/deleteThreadMessage.ts +83 -0
  95. package/src/endpoints/files.ts +274 -0
  96. package/src/endpoints/fixGraph.ts +91 -0
  97. package/src/endpoints/forgetMemories.ts +95 -0
  98. package/src/endpoints/getMemory.ts +82 -0
  99. package/src/endpoints/graph.ts +97 -0
  100. package/src/endpoints/graphTools.ts +90 -0
  101. package/src/endpoints/invoke.ts +318 -0
  102. package/src/endpoints/listMemories.ts +97 -0
  103. package/src/endpoints/metadata.ts +6 -0
  104. package/src/endpoints/observability.ts +107 -0
  105. package/src/endpoints/ping.ts +58 -0
  106. package/src/endpoints/realtime.ts +326 -0
  107. package/src/endpoints/searchMemory.ts +132 -0
  108. package/src/endpoints/stateSchema.ts +106 -0
  109. package/src/endpoints/stopGraph.ts +85 -0
  110. package/src/endpoints/storeMemory.ts +98 -0
  111. package/src/endpoints/stream.ts +440 -0
  112. package/src/endpoints/threadDetails.ts +78 -0
  113. package/src/endpoints/threadMessage.ts +76 -0
  114. package/src/endpoints/threadMessages.ts +97 -0
  115. package/src/endpoints/threadState.ts +74 -0
  116. package/src/endpoints/threads.ts +112 -0
  117. package/src/endpoints/updateMemory.ts +90 -0
  118. package/src/endpoints/updateThreadState.ts +82 -0
  119. package/src/endpoints/wsStream.ts +251 -0
  120. package/src/errors.ts +553 -0
  121. package/src/index.ts +108 -0
  122. package/src/message.ts +436 -0
  123. package/src/request.ts +168 -0
  124. package/src/tools.ts +225 -0
  125. package/src/ws.ts +100 -0
package/src/tools.ts ADDED
@@ -0,0 +1,225 @@
1
+ import { Message, RemoteToolCallBlock, ToolResultBlock } from './message.js';
2
+
3
+ // TOOL HANDLER
4
+ export interface ToolHandler {
5
+ (args: any): Promise<any>;
6
+ }
7
+
8
+ /**
9
+ * JSON Schema describing a tool's arguments.
10
+ *
11
+ * `properties` and `required` are optional, matching JSON Schema itself: a tool
12
+ * whose arguments are all optional needs neither, and a tool that takes no
13
+ * arguments can be declared as `{ type: 'object' }`. Additional JSON Schema
14
+ * keywords (`additionalProperties`, `$defs`, ...) are passed through untouched.
15
+ */
16
+ export interface ToolParameter {
17
+ type: string;
18
+ properties?: Record<string, any>;
19
+ required?: string[];
20
+ [key: string]: unknown;
21
+ }
22
+
23
+ /**
24
+ * Fill in the JSON Schema defaults a tool declaration may leave out, so the
25
+ * wire format sent to the server is always a complete object schema.
26
+ */
27
+ export function normalizeToolParameters(parameters?: ToolParameter): ToolParameter {
28
+ const source: Partial<ToolParameter> = parameters ?? {};
29
+ const { type, properties, required, ...rest } = source;
30
+
31
+ return {
32
+ ...rest,
33
+ type: type ?? 'object',
34
+ properties: properties ?? {},
35
+ required: required ?? [],
36
+ };
37
+ }
38
+
39
+ export interface Tool {
40
+ type: string;
41
+ function: {
42
+ name: string;
43
+ description: string;
44
+ parameters: ToolParameter;
45
+ };
46
+ }
47
+
48
+ // Tool Registration - what users provide when registering tools
49
+ export interface ToolRegistration {
50
+ node?: string;
51
+ name: string;
52
+ description?: string;
53
+ parameters?: ToolParameter;
54
+ handler: ToolHandler;
55
+ }
56
+
57
+ // Internal tool definition (extends handler)
58
+ export interface ToolDefinition extends ToolHandler {
59
+ name: string;
60
+ description?: string;
61
+ parameters?: ToolParameter;
62
+ node?: string;
63
+ }
64
+
65
+ export class ToolExecutor {
66
+ private tools: Map<string, ToolDefinition>;
67
+ private toolsByNode: Map<string, Map<string, ToolDefinition>>;
68
+
69
+ constructor(tools: ToolDefinition[] = []) {
70
+ this.tools = new Map<string, ToolDefinition>();
71
+ this.toolsByNode = new Map<string, Map<string, ToolDefinition>>();
72
+
73
+ for (const func of tools) {
74
+ this.tools.set(func.name, func);
75
+
76
+ // Also organize by node if specified
77
+ if (func.node) {
78
+ if (!this.toolsByNode.has(func.node)) {
79
+ this.toolsByNode.set(func.node, new Map());
80
+ }
81
+ this.toolsByNode.get(func.node)!.set(func.name, func);
82
+ }
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Register a new tool
88
+ */
89
+ registerTool(registration: ToolRegistration): void {
90
+ // Create a proper ToolDefinition by wrapping the handler
91
+ const toolDef: ToolDefinition = async (args: any) => {
92
+ return registration.handler(args);
93
+ };
94
+
95
+ // Use Object.defineProperty to add properties to the function
96
+ Object.defineProperty(toolDef, 'name', {
97
+ value: registration.name,
98
+ writable: true,
99
+ configurable: true,
100
+ });
101
+ Object.defineProperty(toolDef, 'description', {
102
+ value: registration.description,
103
+ writable: true,
104
+ configurable: true,
105
+ });
106
+ Object.defineProperty(toolDef, 'parameters', {
107
+ value: registration.parameters,
108
+ writable: true,
109
+ configurable: true,
110
+ });
111
+ Object.defineProperty(toolDef, 'node', {
112
+ value: registration.node,
113
+ writable: true,
114
+ configurable: true,
115
+ });
116
+
117
+ this.tools.set(registration.name, toolDef);
118
+
119
+ // Organize by node
120
+ if (registration.node) {
121
+ if (!this.toolsByNode.has(registration.node)) {
122
+ this.toolsByNode.set(registration.node, new Map());
123
+ }
124
+ this.toolsByNode.get(registration.node)!.set(registration.name, toolDef);
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Get tools for a specific node
130
+ */
131
+ getToolsForNode(node: string): ToolDefinition[] {
132
+ const nodeTools = this.toolsByNode.get(node);
133
+ return nodeTools ? Array.from(nodeTools.values()) : [];
134
+ }
135
+
136
+ /**
137
+ * Get all tools in OpenAI-compatible format
138
+ */
139
+ all_tools(): Tool[] {
140
+ const openaiTools: Tool[] = [];
141
+
142
+ for (const [name, func] of this.tools) {
143
+ const tool: Tool = {
144
+ type: 'function',
145
+ function: {
146
+ name: name,
147
+ description: func.description || `Execute ${name}`,
148
+ parameters: normalizeToolParameters(func.parameters),
149
+ },
150
+ };
151
+ openaiTools.push(tool);
152
+ }
153
+
154
+ return openaiTools;
155
+ }
156
+
157
+ /**
158
+ * Extract and execute all tool calls from the response
159
+ * Returns an array of tool result messages
160
+ */
161
+ async executeToolCalls(messages: Message[]): Promise<Message[]> {
162
+ const toolCalls: RemoteToolCallBlock[] = [];
163
+
164
+ // Extract all remote_tool_call blocks from messages
165
+ for (const msg of messages) {
166
+ if (msg.content) {
167
+ for (const block of msg.content) {
168
+ if (block.type === 'remote_tool_call') {
169
+ toolCalls.push(block as RemoteToolCallBlock);
170
+ }
171
+ }
172
+ }
173
+ }
174
+
175
+ const results: Message[] = [];
176
+
177
+ // Execute each tool call
178
+ for (const call of toolCalls) {
179
+ const toolName = call.name;
180
+
181
+ if (this.tools.has(toolName)) {
182
+ const tool = this.tools.get(toolName)!;
183
+
184
+ try {
185
+ // Execute the tool
186
+ const result = await tool(call.args);
187
+
188
+ // Create a tool result message
189
+ const toolResultBlock = new ToolResultBlock({
190
+ call_id: call.id,
191
+ output: result,
192
+ status: 'completed',
193
+ is_error: false,
194
+ });
195
+
196
+ results.push(Message.tool_message([toolResultBlock]));
197
+ } catch (error) {
198
+ // Handle errors
199
+ const errorMessage = error instanceof Error ? error.message : String(error);
200
+
201
+ const toolResultBlock = new ToolResultBlock({
202
+ call_id: call.id,
203
+ output: { error: errorMessage },
204
+ status: 'failed',
205
+ is_error: true,
206
+ });
207
+
208
+ results.push(Message.tool_message([toolResultBlock]));
209
+ }
210
+ } else {
211
+ // Tool not found error
212
+ const toolResultBlock = new ToolResultBlock({
213
+ call_id: call.id,
214
+ output: { error: `Tool '${toolName}' not found` },
215
+ status: 'failed',
216
+ is_error: true,
217
+ });
218
+
219
+ results.push(Message.tool_message([toolResultBlock]));
220
+ }
221
+ }
222
+
223
+ return results;
224
+ }
225
+ }
package/src/ws.ts ADDED
@@ -0,0 +1,100 @@
1
+ import { TenxGraphAuth, buildHeaders } from './request.js';
2
+
3
+ /**
4
+ * Sec-WebSocket-Protocol token the server recognizes for browser-safe bearer auth.
5
+ * The client opens the socket with `[WS_BEARER_SUBPROTOCOL, "<jwt>"]`; the server
6
+ * extracts the second protocol entry as the token. This works in browsers (which
7
+ * cannot set request headers on a WebSocket) and avoids leaking the token in the URL.
8
+ */
9
+ export const WS_BEARER_SUBPROTOCOL = '10xgraph-bearer';
10
+
11
+ /** Minimal constructor shape shared by the browser `WebSocket` and the Node `ws` package. */
12
+ export type WebSocketImpl = new (
13
+ url: string,
14
+ protocols?: string | string[],
15
+ options?: unknown
16
+ ) => WebSocket;
17
+
18
+ /** The auth/transport fields the WS helpers read from a request context. */
19
+ export interface WsAuthContext {
20
+ baseUrl: string;
21
+ authToken?: string | null;
22
+ auth?: TenxGraphAuth | null;
23
+ headers?: HeadersInit;
24
+ credentials?: RequestCredentials;
25
+ debug?: boolean;
26
+ /** Optional WebSocket implementation for runtimes without a global (Node < 21). */
27
+ webSocketImpl?: WebSocketImpl;
28
+ }
29
+
30
+ /**
31
+ * Resolve the bearer token with the same priority as `buildHeaders`.
32
+ *
33
+ * `auth` takes precedence over `authToken`, matching the HTTP path. When `auth`
34
+ * is set to a non-bearer scheme (basic/header) there is no bearer token to send,
35
+ * so this returns `null` rather than silently falling back to `authToken` — the
36
+ * HTTP path would not send a bearer in that case either.
37
+ */
38
+ export function resolveBearerToken(
39
+ context: Pick<WsAuthContext, 'authToken' | 'auth'>
40
+ ): string | null {
41
+ if (context.auth) {
42
+ return context.auth.type === 'bearer' ? context.auth.token : null;
43
+ }
44
+ if (context.authToken) {
45
+ return context.authToken;
46
+ }
47
+ return null;
48
+ }
49
+
50
+ /**
51
+ * Convert the HTTP base URL to a WebSocket URL and append `path`.
52
+ * The token is never placed in the URL — it travels via the `10xgraph-bearer`
53
+ * subprotocol (browser-safe) and, in Node, the Authorization header.
54
+ */
55
+ export function buildWsUrl(context: Pick<WsAuthContext, 'baseUrl'>, path: string): string {
56
+ return (
57
+ context.baseUrl
58
+ .replace(/^https:/, 'wss:')
59
+ .replace(/^http:/, 'ws:')
60
+ .replace(/\/$/, '') + path
61
+ );
62
+ }
63
+
64
+ /**
65
+ * Open a WebSocket with bearer auth.
66
+ *
67
+ * - If a token is present it is sent as the `10xgraph-bearer` subprotocol (works
68
+ * in browsers and Node `ws`).
69
+ * - In Node-style implementations that accept a third `options` argument, the
70
+ * Authorization header is also passed (ignored by browsers).
71
+ * - The implementation is taken from `context.webSocketImpl`, falling back to the
72
+ * global `WebSocket`. If neither exists a descriptive error is thrown.
73
+ */
74
+ export function openWebSocket(url: string, context: WsAuthContext): WebSocket {
75
+ const Impl: WebSocketImpl | undefined =
76
+ context.webSocketImpl ?? (globalThis as { WebSocket?: WebSocketImpl }).WebSocket;
77
+
78
+ if (!Impl) {
79
+ throw new Error(
80
+ 'No WebSocket implementation available. In Node < 21 pass `webSocketImpl` ' +
81
+ 'in the client config (e.g. the `ws` package: `new TenxGraphClient({ ..., webSocketImpl: WebSocket })`).'
82
+ );
83
+ }
84
+
85
+ const token = resolveBearerToken(context);
86
+ const protocols = token ? [WS_BEARER_SUBPROTOCOL, token] : undefined;
87
+
88
+ const headers = buildHeaders(context);
89
+ const authHeader = headers['Authorization'] ?? headers['authorization'];
90
+
91
+ if (authHeader) {
92
+ try {
93
+ return new Impl(url, protocols, { headers: { Authorization: authHeader } });
94
+ } catch {
95
+ // Fall through: browser constructors reject the 3rd arg shape — retry plain.
96
+ }
97
+ }
98
+
99
+ return new Impl(url, protocols);
100
+ }