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.
- package/CHANGELOG.md +276 -0
- package/LICENSE +21 -0
- package/README.md +400 -2
- package/dist/agent.d.ts +22 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/client.d.ts +479 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/compat.d.ts +28 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/endpoints/addThreadMessages.d.ts +22 -0
- package/dist/endpoints/addThreadMessages.d.ts.map +1 -0
- package/dist/endpoints/clearThreadState.d.ts +15 -0
- package/dist/endpoints/clearThreadState.d.ts.map +1 -0
- package/dist/endpoints/deleteMemory.d.ts +19 -0
- package/dist/endpoints/deleteMemory.d.ts.map +1 -0
- package/dist/endpoints/deleteThread.d.ts +19 -0
- package/dist/endpoints/deleteThread.d.ts.map +1 -0
- package/dist/endpoints/deleteThreadMessage.d.ts +20 -0
- package/dist/endpoints/deleteThreadMessage.d.ts.map +1 -0
- package/dist/endpoints/files.d.ts +83 -0
- package/dist/endpoints/files.d.ts.map +1 -0
- package/dist/endpoints/fixGraph.d.ts +29 -0
- package/dist/endpoints/fixGraph.d.ts.map +1 -0
- package/dist/endpoints/forgetMemories.d.ts +22 -0
- package/dist/endpoints/forgetMemories.d.ts.map +1 -0
- package/dist/endpoints/getMemory.d.ts +19 -0
- package/dist/endpoints/getMemory.d.ts.map +1 -0
- package/dist/endpoints/graph.d.ts +39 -0
- package/dist/endpoints/graph.d.ts.map +1 -0
- package/dist/endpoints/graphTools.d.ts +32 -0
- package/dist/endpoints/graphTools.d.ts.map +1 -0
- package/dist/endpoints/invoke.d.ts +59 -0
- package/dist/endpoints/invoke.d.ts.map +1 -0
- package/dist/endpoints/listMemories.d.ts +19 -0
- package/dist/endpoints/listMemories.d.ts.map +1 -0
- package/dist/endpoints/metadata.d.ts +6 -0
- package/dist/endpoints/metadata.d.ts.map +1 -0
- package/dist/endpoints/observability.d.ts +58 -0
- package/dist/endpoints/observability.d.ts.map +1 -0
- package/dist/endpoints/ping.d.ts +10 -0
- package/dist/endpoints/ping.d.ts.map +1 -0
- package/dist/endpoints/realtime.d.ts +134 -0
- package/dist/endpoints/realtime.d.ts.map +1 -0
- package/dist/endpoints/searchMemory.d.ts +57 -0
- package/dist/endpoints/searchMemory.d.ts.map +1 -0
- package/dist/endpoints/stateSchema.d.ts +50 -0
- package/dist/endpoints/stateSchema.d.ts.map +1 -0
- package/dist/endpoints/stopGraph.d.ts +26 -0
- package/dist/endpoints/stopGraph.d.ts.map +1 -0
- package/dist/endpoints/storeMemory.d.ts +33 -0
- package/dist/endpoints/storeMemory.d.ts.map +1 -0
- package/dist/endpoints/stream.d.ts +60 -0
- package/dist/endpoints/stream.d.ts.map +1 -0
- package/dist/endpoints/threadDetails.d.ts +19 -0
- package/dist/endpoints/threadDetails.d.ts.map +1 -0
- package/dist/endpoints/threadMessage.d.ts +17 -0
- package/dist/endpoints/threadMessage.d.ts.map +1 -0
- package/dist/endpoints/threadMessages.d.ts +23 -0
- package/dist/endpoints/threadMessages.d.ts.map +1 -0
- package/dist/endpoints/threadState.d.ts +14 -0
- package/dist/endpoints/threadState.d.ts.map +1 -0
- package/dist/endpoints/threads.d.ts +30 -0
- package/dist/endpoints/threads.d.ts.map +1 -0
- package/dist/endpoints/updateMemory.d.ts +21 -0
- package/dist/endpoints/updateMemory.d.ts.map +1 -0
- package/dist/endpoints/updateThreadState.d.ts +18 -0
- package/dist/endpoints/updateThreadState.d.ts.map +1 -0
- package/dist/endpoints/wsStream.d.ts +33 -0
- package/dist/endpoints/wsStream.d.ts.map +1 -0
- package/dist/errors.d.ts +155 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2664 -0
- package/dist/index.js.map +1 -0
- package/dist/message.d.ts +174 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/request.d.ts +33 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/tools.d.ts +67 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/ws.d.ts +48 -0
- package/dist/ws.d.ts.map +1 -0
- package/package.json +99 -4
- package/src/agent.ts +43 -0
- package/src/client.ts +1044 -0
- package/src/compat.ts +35 -0
- package/src/endpoints/addThreadMessages.ts +83 -0
- package/src/endpoints/clearThreadState.ts +75 -0
- package/src/endpoints/deleteMemory.ts +91 -0
- package/src/endpoints/deleteThread.ts +78 -0
- package/src/endpoints/deleteThreadMessage.ts +83 -0
- package/src/endpoints/files.ts +274 -0
- package/src/endpoints/fixGraph.ts +91 -0
- package/src/endpoints/forgetMemories.ts +95 -0
- package/src/endpoints/getMemory.ts +82 -0
- package/src/endpoints/graph.ts +97 -0
- package/src/endpoints/graphTools.ts +90 -0
- package/src/endpoints/invoke.ts +318 -0
- package/src/endpoints/listMemories.ts +97 -0
- package/src/endpoints/metadata.ts +6 -0
- package/src/endpoints/observability.ts +107 -0
- package/src/endpoints/ping.ts +58 -0
- package/src/endpoints/realtime.ts +326 -0
- package/src/endpoints/searchMemory.ts +132 -0
- package/src/endpoints/stateSchema.ts +106 -0
- package/src/endpoints/stopGraph.ts +85 -0
- package/src/endpoints/storeMemory.ts +98 -0
- package/src/endpoints/stream.ts +440 -0
- package/src/endpoints/threadDetails.ts +78 -0
- package/src/endpoints/threadMessage.ts +76 -0
- package/src/endpoints/threadMessages.ts +97 -0
- package/src/endpoints/threadState.ts +74 -0
- package/src/endpoints/threads.ts +112 -0
- package/src/endpoints/updateMemory.ts +90 -0
- package/src/endpoints/updateThreadState.ts +82 -0
- package/src/endpoints/wsStream.ts +251 -0
- package/src/errors.ts +553 -0
- package/src/index.ts +108 -0
- package/src/message.ts +436 -0
- package/src/request.ts +168 -0
- package/src/tools.ts +225 -0
- 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
|
+
}
|