@tidblink/server 0.3.0-rc.0 → 0.4.0-rc.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/README.md +565 -368
- package/dist/audio.d.ts +9 -0
- package/dist/audio.d.ts.map +1 -1
- package/dist/audio.js +6 -1
- package/dist/audio.js.map +1 -1
- package/dist/backend-connection.d.ts +91 -0
- package/dist/backend-connection.d.ts.map +1 -0
- package/dist/backend-connection.js +314 -0
- package/dist/backend-connection.js.map +1 -0
- package/dist/backend-pool.d.ts +104 -0
- package/dist/backend-pool.d.ts.map +1 -0
- package/dist/backend-pool.js +483 -0
- package/dist/backend-pool.js.map +1 -0
- package/dist/client-tool-executor.d.ts +31 -0
- package/dist/client-tool-executor.d.ts.map +1 -0
- package/dist/client-tool-executor.js +190 -0
- package/dist/client-tool-executor.js.map +1 -0
- package/dist/client-tools.d.ts +0 -25
- package/dist/client-tools.d.ts.map +1 -1
- package/dist/client-tools.js +1 -67
- package/dist/client-tools.js.map +1 -1
- package/dist/connector-callback.d.ts +92 -0
- package/dist/connector-callback.d.ts.map +1 -0
- package/dist/connector-callback.js +155 -0
- package/dist/connector-callback.js.map +1 -0
- package/dist/connectors.d.ts +66 -0
- package/dist/connectors.d.ts.map +1 -0
- package/dist/connectors.js +71 -0
- package/dist/connectors.js.map +1 -0
- package/dist/control.js +1 -1
- package/dist/control.js.map +1 -1
- package/dist/errors.d.ts +34 -11
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +36 -8
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +158 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +110 -0
- package/dist/events.js.map +1 -0
- package/dist/files.js +9 -9
- package/dist/files.js.map +1 -1
- package/dist/history.d.ts +38 -1
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +1 -1
- package/dist/history.js.map +1 -1
- package/dist/http.d.ts +28 -4
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +44 -24
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +26 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/organization.d.ts +45 -28
- package/dist/organization.d.ts.map +1 -1
- package/dist/organization.js +67 -73
- package/dist/organization.js.map +1 -1
- package/dist/realtime.d.ts +0 -1
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +0 -1
- package/dist/realtime.js.map +1 -1
- package/dist/session-connection.d.ts +155 -0
- package/dist/session-connection.d.ts.map +1 -0
- package/dist/session-connection.js +394 -0
- package/dist/session-connection.js.map +1 -0
- package/dist/session-send.d.ts +49 -0
- package/dist/session-send.d.ts.map +1 -0
- package/dist/session-send.js +179 -0
- package/dist/session-send.js.map +1 -0
- package/dist/session.d.ts +37 -8
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +56 -29
- package/dist/session.js.map +1 -1
- package/dist/skills.d.ts +103 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +98 -0
- package/dist/skills.js.map +1 -0
- package/dist/sse.d.ts +5 -2
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +7 -2
- package/dist/sse.js.map +1 -1
- package/dist/template-switch.d.ts +51 -0
- package/dist/template-switch.d.ts.map +1 -0
- package/dist/template-switch.js +81 -0
- package/dist/template-switch.js.map +1 -0
- package/dist/templates.d.ts +129 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +92 -0
- package/dist/templates.js.map +1 -0
- package/dist/turn.d.ts +4 -0
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +17 -13
- package/dist/turn.js.map +1 -1
- package/dist/usage.d.ts +13 -197
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +5 -3
- package/dist/usage.js.map +1 -1
- package/dist/user.d.ts +10 -51
- package/dist/user.d.ts.map +1 -1
- package/dist/user.js +18 -105
- package/dist/user.js.map +1 -1
- package/examples/control-turn.mjs +9 -4
- package/examples/create-session.mjs +37 -24
- package/examples/http-connector.mjs +127 -0
- package/examples/lamp-backend.mjs +175 -0
- package/examples/prepare-realtime-connection.mjs +18 -7
- package/examples/read-usage.mjs +7 -25
- package/examples/send-message.mjs +9 -4
- package/examples/submit-audio.mjs +9 -4
- package/examples/upload-file.mjs +9 -4
- package/package.json +7 -13
- package/dist/progress.d.ts +0 -34
- package/dist/progress.d.ts.map +0 -1
- package/dist/progress.js +0 -154
- package/dist/progress.js.map +0 -1
- package/dist/schedulers.d.ts +0 -129
- package/dist/schedulers.d.ts.map +0 -1
- package/dist/schedulers.js +0 -91
- package/dist/schedulers.js.map +0 -1
- package/examples/answer-client-tool.mjs +0 -69
- package/examples/observe-message.mjs +0 -44
- package/examples/organization-session.mjs +0 -66
- package/examples/provision-user.mjs +0 -83
- package/examples/schedule-task.mjs +0 -67
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { BackendConnectionClosedError, BackendRequestError, TiDBLinkError, } from "./errors.js";
|
|
2
|
+
const OUTPUT_MAX = 65_536;
|
|
3
|
+
const ERROR_MAX = 4_096;
|
|
4
|
+
/** How long a settled callId is remembered to ignore late duplicates. */
|
|
5
|
+
const SETTLED_MEMORY_MS = 60_000;
|
|
6
|
+
/**
|
|
7
|
+
* Raised through `onError` when the core did not accept a Client Tool
|
|
8
|
+
* result. `reason` is the core's: `call_settled` (the call already had an
|
|
9
|
+
* outcome, for example its deadline passed), `not_claimed` or
|
|
10
|
+
* `call_not_found`.
|
|
11
|
+
*/
|
|
12
|
+
export class ClientToolResultRefusedError extends TiDBLinkError {
|
|
13
|
+
callId;
|
|
14
|
+
reason;
|
|
15
|
+
constructor(callId, reason) {
|
|
16
|
+
super(`The core did not accept the result of Client Tool call ${callId}: ${reason}`);
|
|
17
|
+
this.callId = callId;
|
|
18
|
+
this.reason = reason;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const isString = (value) => typeof value === "string" && value !== "";
|
|
22
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
+
const parseCall = (params) => isString(params.callId) &&
|
|
24
|
+
isString(params.sessionId) &&
|
|
25
|
+
isString(params.userId) &&
|
|
26
|
+
isString(params.turnId) &&
|
|
27
|
+
isString(params.name) &&
|
|
28
|
+
isObject(params.arguments) &&
|
|
29
|
+
isString(params.claimBy) &&
|
|
30
|
+
isString(params.deadlineAt) &&
|
|
31
|
+
Number.isFinite(Date.parse(params.deadlineAt))
|
|
32
|
+
? params
|
|
33
|
+
: undefined;
|
|
34
|
+
const truncate = (text, max) => text.length <= max ? text : `${text.slice(0, max - 1)}…`;
|
|
35
|
+
/** The text the model receives for a handler's return value. */
|
|
36
|
+
const outputOf = (value) => {
|
|
37
|
+
let output;
|
|
38
|
+
try {
|
|
39
|
+
output = typeof value === "string" ? value : value === undefined ? "" : JSON.stringify(value);
|
|
40
|
+
}
|
|
41
|
+
catch (cause) {
|
|
42
|
+
return { error: { message: `The tool returned a value that is not JSON: ${String(cause)}` } };
|
|
43
|
+
}
|
|
44
|
+
if (output === undefined)
|
|
45
|
+
return { error: { message: "The tool returned a value that is not JSON" } };
|
|
46
|
+
if (output.length > OUTPUT_MAX)
|
|
47
|
+
return {
|
|
48
|
+
error: { message: `The tool output exceeds ${OUTPUT_MAX} characters` },
|
|
49
|
+
};
|
|
50
|
+
return { output };
|
|
51
|
+
};
|
|
52
|
+
const errorOf = (error) => {
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
return { error: { message: truncate(message || "The tool failed", ERROR_MAX) } };
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Executes the Client Tool calls an executing Session connection receives:
|
|
58
|
+
* claim first, run only after `claimed: true`, then submit the result over any
|
|
59
|
+
* Backend Connection until the call's deadline. Each callId runs at most once.
|
|
60
|
+
*/
|
|
61
|
+
export class ClientToolExecutor {
|
|
62
|
+
#pool;
|
|
63
|
+
#sessionId;
|
|
64
|
+
#handlers;
|
|
65
|
+
#report;
|
|
66
|
+
#calls = new Map();
|
|
67
|
+
constructor(input) {
|
|
68
|
+
this.#pool = input.pool;
|
|
69
|
+
this.#sessionId = input.sessionId;
|
|
70
|
+
this.#handlers = input.handlers;
|
|
71
|
+
this.#report = input.report;
|
|
72
|
+
}
|
|
73
|
+
/** Handle one `tool.call` from the connection that delivered it. */
|
|
74
|
+
receive(params, link) {
|
|
75
|
+
const call = parseCall(params);
|
|
76
|
+
if (!call || call.sessionId !== this.#sessionId) {
|
|
77
|
+
this.#report(new TiDBLinkError("Received an invalid Client Tool call"));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// The core may send a call again after a reconnect; it runs once.
|
|
81
|
+
if (this.#calls.has(call.callId))
|
|
82
|
+
return;
|
|
83
|
+
// Never sent: the core sends it again to the next attachment while unclaimed.
|
|
84
|
+
if (!link.open)
|
|
85
|
+
return;
|
|
86
|
+
this.#calls.set(call.callId, "claiming");
|
|
87
|
+
void this.#claimAndRun(call, link);
|
|
88
|
+
}
|
|
89
|
+
async #claimAndRun(call, link) {
|
|
90
|
+
let answer;
|
|
91
|
+
try {
|
|
92
|
+
answer = await link.request("tool.claim", { callId: call.callId });
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof BackendConnectionClosedError ||
|
|
96
|
+
(error instanceof BackendRequestError && error.code === -32603)) {
|
|
97
|
+
// The claim may have been granted; the call must not run, so close it as failed.
|
|
98
|
+
await this.#submit(call, {
|
|
99
|
+
error: {
|
|
100
|
+
message: "The Application Server lost the claim's answer and did not execute the call",
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.#calls.set(call.callId, "settled");
|
|
106
|
+
this.#forget(call);
|
|
107
|
+
this.#report(error);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (!answer || answer.claimed !== true) {
|
|
111
|
+
if (answer?.reason === "superseded") {
|
|
112
|
+
// Another generation holds the Session; this process may receive it again there.
|
|
113
|
+
this.#calls.delete(call.callId);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
this.#calls.set(call.callId, "settled");
|
|
117
|
+
this.#forget(call);
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.#calls.set(call.callId, "running");
|
|
122
|
+
await this.#submit(call, await this.#execute(call));
|
|
123
|
+
}
|
|
124
|
+
async #execute(call) {
|
|
125
|
+
const handler = Object.hasOwn(this.#handlers, call.name)
|
|
126
|
+
? this.#handlers[call.name]
|
|
127
|
+
: undefined;
|
|
128
|
+
if (!handler)
|
|
129
|
+
return {
|
|
130
|
+
error: {
|
|
131
|
+
message: `Client Tool ${call.name} has no handler in this Application Server`,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
const deadlineAt = new Date(call.deadlineAt);
|
|
135
|
+
const controller = new AbortController();
|
|
136
|
+
let timer;
|
|
137
|
+
const expired = new Promise((resolve) => {
|
|
138
|
+
timer = setTimeout(() => {
|
|
139
|
+
controller.abort(new TiDBLinkError("The Client Tool call reached its deadline"));
|
|
140
|
+
resolve({ error: { message: "The tool did not finish before its deadline" } });
|
|
141
|
+
}, Math.max(0, deadlineAt.getTime() - Date.now()));
|
|
142
|
+
});
|
|
143
|
+
const context = {
|
|
144
|
+
callId: call.callId,
|
|
145
|
+
sessionId: call.sessionId,
|
|
146
|
+
userId: call.userId,
|
|
147
|
+
turnId: call.turnId,
|
|
148
|
+
name: call.name,
|
|
149
|
+
deadlineAt,
|
|
150
|
+
signal: controller.signal,
|
|
151
|
+
};
|
|
152
|
+
const run = (async () => {
|
|
153
|
+
try {
|
|
154
|
+
return outputOf(await handler.run(call.arguments, context));
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
return errorOf(error);
|
|
158
|
+
}
|
|
159
|
+
})();
|
|
160
|
+
try {
|
|
161
|
+
return await Promise.race([run, expired]);
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
clearTimeout(timer);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async #submit(call, result) {
|
|
168
|
+
try {
|
|
169
|
+
const answer = await this.#pool.request("tool.result", { callId: call.callId, ...result }, { retryUntil: Date.parse(call.deadlineAt) });
|
|
170
|
+
if (answer?.accepted !== true) {
|
|
171
|
+
if (answer?.reason === "not_claimed") {
|
|
172
|
+
// The lost claim never took effect: the call may arrive again and run then.
|
|
173
|
+
this.#calls.delete(call.callId);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
this.#report(new ClientToolResultRefusedError(call.callId, answer?.reason ?? "unknown"));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
this.#report(error);
|
|
181
|
+
}
|
|
182
|
+
this.#calls.set(call.callId, "settled");
|
|
183
|
+
this.#forget(call);
|
|
184
|
+
}
|
|
185
|
+
#forget(call) {
|
|
186
|
+
const timer = setTimeout(() => this.#calls.delete(call.callId), Math.max(0, Date.parse(call.deadlineAt) - Date.now()) + SETTLED_MEMORY_MS);
|
|
187
|
+
timer.unref?.();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=client-tool-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-tool-executor.js","sourceRoot":"","sources":["../src/client-tool-executor.ts"],"names":[],"mappings":"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"}
|
package/dist/client-tools.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type SessionInteraction } from "./history.js";
|
|
2
1
|
import { HttpClient } from "./http.js";
|
|
3
2
|
import type { RequestOptions } from "./organization.js";
|
|
4
3
|
export interface ClientToolDeclaration {
|
|
@@ -19,28 +18,4 @@ export interface ReplaceClientToolsOptions extends RequestOptions {
|
|
|
19
18
|
export declare function validateClientTools(tools: readonly ClientToolDeclaration[]): void;
|
|
20
19
|
export declare function getClientTools(http: HttpClient, sessionId: string, options?: RequestOptions): Promise<ClientToolSet>;
|
|
21
20
|
export declare function replaceClientTools(http: HttpClient, sessionId: string, tools: readonly ClientToolDeclaration[], options: ReplaceClientToolsOptions): Promise<ClientToolSet>;
|
|
22
|
-
export interface PendingClientToolCall {
|
|
23
|
-
callId: string;
|
|
24
|
-
turnId: string;
|
|
25
|
-
name: string;
|
|
26
|
-
arguments: Record<string, unknown>;
|
|
27
|
-
publishedAt: string;
|
|
28
|
-
deadlineAt: string;
|
|
29
|
-
}
|
|
30
|
-
export type ClientToolOutputInput = RequestOptions & {
|
|
31
|
-
/** Persist a separate command identity; callId identifies the call, not this submission. */
|
|
32
|
-
clientEventId: string;
|
|
33
|
-
turnId: string;
|
|
34
|
-
callId: string;
|
|
35
|
-
} & ({
|
|
36
|
-
output: string;
|
|
37
|
-
error?: never;
|
|
38
|
-
} | {
|
|
39
|
-
error: {
|
|
40
|
-
message: string;
|
|
41
|
-
};
|
|
42
|
-
output?: never;
|
|
43
|
-
});
|
|
44
|
-
export declare function listPendingClientToolCalls(http: HttpClient, sessionId: string, options?: RequestOptions): Promise<PendingClientToolCall[]>;
|
|
45
|
-
export declare function submitClientToolOutput(http: HttpClient, sessionId: string, input: ClientToolOutputInput): Promise<SessionInteraction>;
|
|
46
21
|
//# sourceMappingURL=client-tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-tools.d.ts","sourceRoot":"","sources":["../src/client-tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client-tools.d.ts","sourceRoot":"","sources":["../src/client-tools.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EAKX,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,yBAA0B,SAAQ,cAAc;IAC/D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,qBAAqB,EAAE,GACtC,IAAI,CAuBN;AAkBD,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,aAAa,CAAC,CAQxB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,qBAAqB,EAAE,EACvC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,aAAa,CAAC,CAqBxB"}
|
package/dist/client-tools.js
CHANGED
|
@@ -26,7 +26,7 @@ const toolSet = (result) => {
|
|
|
26
26
|
});
|
|
27
27
|
return { ...result.data, etag: requireEtag(result) };
|
|
28
28
|
};
|
|
29
|
-
const toolsPath = (sessionId) => `/
|
|
29
|
+
const toolsPath = (sessionId) => `/sessions/${encodeURIComponent(sessionId)}/tools`;
|
|
30
30
|
export async function getClientTools(http, sessionId, options) {
|
|
31
31
|
if (options)
|
|
32
32
|
requireKnownKeys(options, ["signal", "requestId"], "Client Tool read options");
|
|
@@ -45,70 +45,4 @@ export async function replaceClientTools(http, sessionId, tools, options) {
|
|
|
45
45
|
throw new OutcomeUnknownError("Client Tool replacement returned no usable receipt; read the current set before retrying", { sessionId, requestId: result.requestId, cause });
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
export async function listPendingClientToolCalls(http, sessionId, options) {
|
|
49
|
-
if (options)
|
|
50
|
-
requireKnownKeys(options, ["signal", "requestId"], "Pending Client Tool call options");
|
|
51
|
-
const result = await http.get(`/api/v1/user/sessions/${encodeURIComponent(sessionId)}/client-tool-calls`, options);
|
|
52
|
-
return result.calls;
|
|
53
|
-
}
|
|
54
|
-
export async function submitClientToolOutput(http, sessionId, input) {
|
|
55
|
-
requireKnownKeys(input, [
|
|
56
|
-
"clientEventId",
|
|
57
|
-
"turnId",
|
|
58
|
-
"callId",
|
|
59
|
-
"output",
|
|
60
|
-
"error",
|
|
61
|
-
"signal",
|
|
62
|
-
"requestId",
|
|
63
|
-
], "Client Tool output");
|
|
64
|
-
requireCreationKey(input.clientEventId);
|
|
65
|
-
for (const id of [input.turnId, input.callId])
|
|
66
|
-
if (typeof id !== "string" || !id || id.length > 64)
|
|
67
|
-
throw new TypeError("Client Tool output requires turnId and callId containing 1-64 characters");
|
|
68
|
-
if (Object.hasOwn(input, "output") === Object.hasOwn(input, "error"))
|
|
69
|
-
throw new TypeError("Provide exactly one Client Tool output or error");
|
|
70
|
-
if ("output" in input) {
|
|
71
|
-
if (typeof input.output !== "string" || input.output.length > 65536)
|
|
72
|
-
throw new TypeError("Client Tool output must be a string of at most 65536 characters");
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
requireKnownKeys(input.error, ["message"], "Client Tool error");
|
|
76
|
-
if (typeof input.error.message !== "string" ||
|
|
77
|
-
!input.error.message ||
|
|
78
|
-
input.error.message.length > 4096)
|
|
79
|
-
throw new TypeError("Client Tool error.message must contain 1-4096 characters");
|
|
80
|
-
}
|
|
81
|
-
const { clientEventId, signal, requestId, ...data } = input;
|
|
82
|
-
const turnId = data.turnId;
|
|
83
|
-
signal?.throwIfAborted();
|
|
84
|
-
try {
|
|
85
|
-
const result = await http.postResponse(`/api/v1/user/sessions/${encodeURIComponent(sessionId)}/events`, { type: "agent.session.input.client_tool_output", clientEventId, data }, {
|
|
86
|
-
outcomeUnknown: true,
|
|
87
|
-
...(signal ? { signal } : {}),
|
|
88
|
-
...(requestId ? { requestId } : {}),
|
|
89
|
-
});
|
|
90
|
-
try {
|
|
91
|
-
const receipt = requireInteraction(result.data?.interaction, clientEventId, result.requestId);
|
|
92
|
-
if (receipt.kind !== "client_tool_output" ||
|
|
93
|
-
receipt.turnId !== turnId ||
|
|
94
|
-
receipt.message !== null)
|
|
95
|
-
throw new TiDBLinkError("Client Tool output receipt identifies a different command");
|
|
96
|
-
return receipt;
|
|
97
|
-
}
|
|
98
|
-
catch (cause) {
|
|
99
|
-
throw new OutcomeUnknownError("Client Tool output returned no usable receipt; query the original input", { requestId: result.requestId, cause });
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch (cause) {
|
|
103
|
-
if (!(cause instanceof OutcomeUnknownError))
|
|
104
|
-
throw cause;
|
|
105
|
-
throw new OutcomeUnknownError(cause.message, {
|
|
106
|
-
sessionId,
|
|
107
|
-
inputId: clientEventId,
|
|
108
|
-
turnId,
|
|
109
|
-
...(cause.requestId ? { requestId: cause.requestId } : {}),
|
|
110
|
-
cause,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
48
|
//# sourceMappingURL=client-tools.js.map
|
package/dist/client-tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-tools.js","sourceRoot":"","sources":["../src/client-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GAEnB,MAAM,WAAW,CAAC;AAqBnB,MAAM,UAAU,mBAAmB,CACjC,KAAuC;IAEvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAC5C,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;IAC3E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,gBAAgB,CACd,IAAI,EACJ,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,CAAC,EAC7C,yBAAyB,CAC1B,CAAC;QACF,IACE,IAAI,CAAC,IAAI,KAAK,UAAU;YACxB,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAC7B,CAAC,IAAI,CAAC,IAAI;YACV,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ;YACpC,CAAC,IAAI,CAAC,WAAW;YACjB,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;YACnC,IAAI,CAAC,UAAU,KAAK,IAAI;YACxB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;YAE9B,MAAM,IAAI,SAAS,CACjB,8EAA8E,CAC/E,CAAC;IACN,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,CACd,MAA+C,EAChC,EAAE;IACjB,IACE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC;QACxB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAEjC,MAAM,IAAI,aAAa,CAAC,+CAA+C,EAAE;YACvE,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC,CAAC;IACL,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC;AACF,MAAM,SAAS,GAAG,CAAC,SAAiB,EAAE,EAAE,CACtC,
|
|
1
|
+
{"version":3,"file":"client-tools.js","sourceRoot":"","sources":["../src/client-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,kBAAkB,GAEnB,MAAM,WAAW,CAAC;AAqBnB,MAAM,UAAU,mBAAmB,CACjC,KAAuC;IAEvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAC5C,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;IAC3E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,gBAAgB,CACd,IAAI,EACJ,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,CAAC,EAC7C,yBAAyB,CAC1B,CAAC;QACF,IACE,IAAI,CAAC,IAAI,KAAK,UAAU;YACxB,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAC7B,CAAC,IAAI,CAAC,IAAI;YACV,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ;YACpC,CAAC,IAAI,CAAC,WAAW;YACjB,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;YACnC,IAAI,CAAC,UAAU,KAAK,IAAI;YACxB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;YAE9B,MAAM,IAAI,SAAS,CACjB,8EAA8E,CAC/E,CAAC;IACN,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,CACd,MAA+C,EAChC,EAAE;IACjB,IACE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC;QACxB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAEjC,MAAM,IAAI,aAAa,CAAC,+CAA+C,EAAE;YACvE,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC,CAAC;IACL,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC;AACF,MAAM,SAAS,GAAG,CAAC,SAAiB,EAAE,EAAE,CACtC,aAAa,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAgB,EAChB,SAAiB,EACjB,OAAwB;IAExB,IAAI,OAAO;QACT,gBAAgB,CACd,OAAO,EACP,CAAC,QAAQ,EAAE,WAAW,CAAC,EACvB,0BAA0B,CAC3B,CAAC;IACJ,OAAO,OAAO,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAgB,EAChB,SAAiB,EACjB,KAAuC,EACvC,OAAkC;IAElC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC3B,gBAAgB,CACd,OAAO,EACP,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,EAClC,iCAAiC,CAClC,CAAC;IACF,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,OAAO;QACzD,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAChC,SAAS,CAAC,SAAS,CAAC,EACpB,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CACrE,CAAC;IACF,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,mBAAmB,CAC3B,0FAA0F,EAC1F,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,CAClD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { TiDBLinkError } from "./errors.js";
|
|
2
|
+
import type { FetchFunction } from "./http.js";
|
|
3
|
+
export declare const CONNECTOR_CALLBACK_ISSUER = "tidb-link/connector-callback/v1";
|
|
4
|
+
export declare const CONNECTOR_CALLBACK_AUDIENCE = "tidb-link/connector";
|
|
5
|
+
/** The `params._meta` key of the Call Context on every Connector `tools/call`. */
|
|
6
|
+
export declare const CONNECTOR_CALL_CONTEXT_KEY = "tidb-link/context";
|
|
7
|
+
/** A public Ed25519 key that signs Connector callback tokens. */
|
|
8
|
+
export interface ConnectorVerificationKey {
|
|
9
|
+
kty: "OKP";
|
|
10
|
+
crv: "Ed25519";
|
|
11
|
+
x: string;
|
|
12
|
+
kid: string;
|
|
13
|
+
alg: "EdDSA";
|
|
14
|
+
use: "sig";
|
|
15
|
+
}
|
|
16
|
+
/** The verified claims of a Connector callback token. */
|
|
17
|
+
export interface ConnectorCallbackClaims {
|
|
18
|
+
iss: typeof CONNECTOR_CALLBACK_ISSUER;
|
|
19
|
+
aud: typeof CONNECTOR_CALLBACK_AUDIENCE;
|
|
20
|
+
organizationId: string;
|
|
21
|
+
connectorId: string;
|
|
22
|
+
iat: number;
|
|
23
|
+
exp: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Who a Connector tool call is for, written by the platform from the
|
|
27
|
+
* Session's persisted owner. Model arguments cannot override it.
|
|
28
|
+
*/
|
|
29
|
+
export interface ConnectorCallContext {
|
|
30
|
+
/** Globally unique; deduplicate side effects by it. */
|
|
31
|
+
callId: string;
|
|
32
|
+
sessionId: string;
|
|
33
|
+
organizationId: string;
|
|
34
|
+
/** The Session owner's End User ID. Map it to your own account. */
|
|
35
|
+
userId: string;
|
|
36
|
+
/** When the platform stops waiting. Abandon the work after it. */
|
|
37
|
+
deadline: string;
|
|
38
|
+
/** Always 1: the platform never retries a call. */
|
|
39
|
+
attempt: 1;
|
|
40
|
+
}
|
|
41
|
+
/** A Connector callback was refused: bad signature, wrong scope or expired. */
|
|
42
|
+
export declare class ConnectorAuthError extends TiDBLinkError {
|
|
43
|
+
}
|
|
44
|
+
export interface ConnectorKeySetOptions {
|
|
45
|
+
/** Your trusted TiDB Link deployment, for example `https://api.example.com`. */
|
|
46
|
+
baseUrl: string;
|
|
47
|
+
fetch?: FetchFunction;
|
|
48
|
+
/** How long fetched keys are reused. Default 10 minutes. */
|
|
49
|
+
maxAgeMs?: number;
|
|
50
|
+
/** Minimum time between refreshes for an unknown key ID. Default 30 seconds. */
|
|
51
|
+
minRefreshIntervalMs?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Caches the deployment's public verification keys from
|
|
55
|
+
* `GET /api/v1/connectors/jwks`. Fetch keys only from your trusted deployment
|
|
56
|
+
* URL, never from a URL a token names.
|
|
57
|
+
*/
|
|
58
|
+
export declare class ConnectorKeySet {
|
|
59
|
+
#private;
|
|
60
|
+
constructor(options: ConnectorKeySetOptions);
|
|
61
|
+
/** The key for `kid`, refreshing the cache when it is stale or the key is new. */
|
|
62
|
+
key(kid: string): Promise<CryptoKey | undefined>;
|
|
63
|
+
/** Fetch the keys now. Concurrent callers share one request. */
|
|
64
|
+
refresh(): Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
export interface VerifyConnectorCallbackOptions {
|
|
67
|
+
keys: ConnectorKeySet;
|
|
68
|
+
/** Your Organization; tokens for another are refused. */
|
|
69
|
+
organizationId: string;
|
|
70
|
+
/** This Connector; tokens for another are refused. */
|
|
71
|
+
connectorId: string;
|
|
72
|
+
/** Allowed clock difference with the platform. Default 5 seconds. */
|
|
73
|
+
clockToleranceSec?: number;
|
|
74
|
+
/** Override the current time, in milliseconds since the epoch. */
|
|
75
|
+
now?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Verify the `Authorization` header of a request the platform sends to your
|
|
79
|
+
* HTTP Connector (initialization, tool discovery and tool calls). Returns the
|
|
80
|
+
* claims, or throws ConnectorAuthError. A token may be reused within its
|
|
81
|
+
* scope until it expires, so verification needs no per-request state.
|
|
82
|
+
*/
|
|
83
|
+
export declare function verifyConnectorCallback(authorization: string | null | undefined, options: VerifyConnectorCallbackOptions): Promise<ConnectorCallbackClaims>;
|
|
84
|
+
/**
|
|
85
|
+
* Read the Call Context from a `tools/call` request's `params._meta`. Throws
|
|
86
|
+
* ConnectorAuthError when it is missing, malformed or for another
|
|
87
|
+
* Organization. Initialization and tool discovery carry no Call Context.
|
|
88
|
+
*/
|
|
89
|
+
export declare function readConnectorCallContext(meta: unknown, options: {
|
|
90
|
+
organizationId: string;
|
|
91
|
+
}): ConnectorCallContext;
|
|
92
|
+
//# sourceMappingURL=connector-callback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector-callback.d.ts","sourceRoot":"","sources":["../src/connector-callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,eAAO,MAAM,yBAAyB,oCAAoC,CAAC;AAC3E,eAAO,MAAM,2BAA2B,wBAAwB,CAAC;AACjE,kFAAkF;AAClF,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAE9D,iEAAiE;AACjE,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,KAAK,CAAC;IACX,GAAG,EAAE,SAAS,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,KAAK,CAAC;CACZ;AAED,yDAAyD;AACzD,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,OAAO,yBAAyB,CAAC;IACtC,GAAG,EAAE,OAAO,2BAA2B,CAAC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,+EAA+E;AAC/E,qBAAa,kBAAmB,SAAQ,aAAa;CAAG;AAExD,MAAM,WAAW,sBAAsB;IACrC,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,qBAAa,eAAe;;gBASd,OAAO,EAAE,sBAAsB;IAU3C,kFAAkF;IAC5E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAUtD,gEAAgE;IAChE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAmDzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,IAAI,EAAE,eAAe,CAAC;IACtB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAaD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,uBAAuB,CAAC,CAuDlC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,OAAO,EACb,OAAO,EAAE;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,GAClC,oBAAoB,CAkBtB"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { TiDBLinkError } from "./errors.js";
|
|
2
|
+
export const CONNECTOR_CALLBACK_ISSUER = "tidb-link/connector-callback/v1";
|
|
3
|
+
export const CONNECTOR_CALLBACK_AUDIENCE = "tidb-link/connector";
|
|
4
|
+
/** The `params._meta` key of the Call Context on every Connector `tools/call`. */
|
|
5
|
+
export const CONNECTOR_CALL_CONTEXT_KEY = "tidb-link/context";
|
|
6
|
+
/** A Connector callback was refused: bad signature, wrong scope or expired. */
|
|
7
|
+
export class ConnectorAuthError extends TiDBLinkError {
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Caches the deployment's public verification keys from
|
|
11
|
+
* `GET /api/v1/connectors/jwks`. Fetch keys only from your trusted deployment
|
|
12
|
+
* URL, never from a URL a token names.
|
|
13
|
+
*/
|
|
14
|
+
export class ConnectorKeySet {
|
|
15
|
+
#url;
|
|
16
|
+
#fetch;
|
|
17
|
+
#maxAgeMs;
|
|
18
|
+
#minRefreshIntervalMs;
|
|
19
|
+
#keys = new Map();
|
|
20
|
+
#fetchedAt = -Infinity;
|
|
21
|
+
#loading;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
const base = new URL(options.baseUrl);
|
|
24
|
+
if (base.protocol !== "https:" && base.protocol !== "http:")
|
|
25
|
+
throw new TypeError("baseUrl must be an HTTP(S) URL");
|
|
26
|
+
this.#url = new URL("/api/v1/connectors/jwks", base);
|
|
27
|
+
this.#fetch = options.fetch ?? ((url, init) => fetch(url, init));
|
|
28
|
+
this.#maxAgeMs = options.maxAgeMs ?? 600_000;
|
|
29
|
+
this.#minRefreshIntervalMs = options.minRefreshIntervalMs ?? 30_000;
|
|
30
|
+
}
|
|
31
|
+
/** The key for `kid`, refreshing the cache when it is stale or the key is new. */
|
|
32
|
+
async key(kid) {
|
|
33
|
+
const age = Date.now() - this.#fetchedAt;
|
|
34
|
+
if (age > this.#maxAgeMs ||
|
|
35
|
+
(!this.#keys.has(kid) && age > this.#minRefreshIntervalMs))
|
|
36
|
+
await this.refresh();
|
|
37
|
+
return this.#keys.get(kid);
|
|
38
|
+
}
|
|
39
|
+
/** Fetch the keys now. Concurrent callers share one request. */
|
|
40
|
+
refresh() {
|
|
41
|
+
this.#loading ??= this.#load().finally(() => {
|
|
42
|
+
this.#loading = undefined;
|
|
43
|
+
});
|
|
44
|
+
return this.#loading;
|
|
45
|
+
}
|
|
46
|
+
async #load() {
|
|
47
|
+
let response;
|
|
48
|
+
try {
|
|
49
|
+
response = await this.#fetch(this.#url, {
|
|
50
|
+
headers: { accept: "application/json" },
|
|
51
|
+
redirect: "error",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (cause) {
|
|
55
|
+
throw new TiDBLinkError("Connector verification keys are unreachable", { cause });
|
|
56
|
+
}
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
await response.body?.cancel();
|
|
59
|
+
throw new TiDBLinkError(`Connector verification keys are unavailable (status ${response.status})`);
|
|
60
|
+
}
|
|
61
|
+
const body = (await response.json());
|
|
62
|
+
if (!Array.isArray(body?.keys))
|
|
63
|
+
throw new TiDBLinkError("Connector verification keys are malformed");
|
|
64
|
+
const keys = new Map();
|
|
65
|
+
for (const key of body.keys) {
|
|
66
|
+
if (key?.kty !== "OKP" ||
|
|
67
|
+
key.crv !== "Ed25519" ||
|
|
68
|
+
key.alg !== "EdDSA" ||
|
|
69
|
+
key.use !== "sig" ||
|
|
70
|
+
typeof key.kid !== "string" ||
|
|
71
|
+
typeof key.x !== "string")
|
|
72
|
+
continue;
|
|
73
|
+
keys.set(key.kid, await crypto.subtle.importKey("jwk", { kty: "OKP", crv: "Ed25519", x: key.x }, { name: "Ed25519" }, false, ["verify"]));
|
|
74
|
+
}
|
|
75
|
+
this.#keys = keys;
|
|
76
|
+
this.#fetchedAt = Date.now();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const base64UrlBytes = (part) => Uint8Array.from(atob(part.replace(/-/g, "+").replace(/_/g, "/")), (c) => c.charCodeAt(0));
|
|
80
|
+
const decodeJson = (part) => {
|
|
81
|
+
const value = JSON.parse(new TextDecoder().decode(base64UrlBytes(part)));
|
|
82
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
83
|
+
throw new Error("not an object");
|
|
84
|
+
return value;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Verify the `Authorization` header of a request the platform sends to your
|
|
88
|
+
* HTTP Connector (initialization, tool discovery and tool calls). Returns the
|
|
89
|
+
* claims, or throws ConnectorAuthError. A token may be reused within its
|
|
90
|
+
* scope until it expires, so verification needs no per-request state.
|
|
91
|
+
*/
|
|
92
|
+
export async function verifyConnectorCallback(authorization, options) {
|
|
93
|
+
const refuse = (reason) => {
|
|
94
|
+
throw new ConnectorAuthError(`Connector callback refused: ${reason}`);
|
|
95
|
+
};
|
|
96
|
+
const bearer = /^Bearer ([A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)$/i.exec(authorization ?? "");
|
|
97
|
+
if (!bearer)
|
|
98
|
+
return refuse("missing or malformed bearer token");
|
|
99
|
+
const [headerPart, payloadPart, signaturePart] = bearer[1].split(".");
|
|
100
|
+
let header;
|
|
101
|
+
let claims;
|
|
102
|
+
try {
|
|
103
|
+
header = decodeJson(headerPart);
|
|
104
|
+
claims = decodeJson(payloadPart);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return refuse("undecodable token");
|
|
108
|
+
}
|
|
109
|
+
if (header.alg !== "EdDSA" || typeof header.kid !== "string")
|
|
110
|
+
return refuse("unsupported algorithm");
|
|
111
|
+
const key = await options.keys.key(header.kid);
|
|
112
|
+
if (!key)
|
|
113
|
+
return refuse("unknown signing key");
|
|
114
|
+
const valid = await crypto.subtle.verify({ name: "Ed25519" }, key, base64UrlBytes(signaturePart), new TextEncoder().encode(`${headerPart}.${payloadPart}`));
|
|
115
|
+
if (!valid)
|
|
116
|
+
return refuse("invalid signature");
|
|
117
|
+
const now = (options.now ?? Date.now()) / 1000;
|
|
118
|
+
const tolerance = options.clockToleranceSec ?? 5;
|
|
119
|
+
const { iat, exp } = claims;
|
|
120
|
+
if (claims.iss !== CONNECTOR_CALLBACK_ISSUER ||
|
|
121
|
+
claims.aud !== CONNECTOR_CALLBACK_AUDIENCE)
|
|
122
|
+
return refuse("wrong issuer or audience");
|
|
123
|
+
if (claims.organizationId !== options.organizationId ||
|
|
124
|
+
claims.connectorId !== options.connectorId)
|
|
125
|
+
return refuse("issued for another Organization or Connector");
|
|
126
|
+
if (!Number.isSafeInteger(iat) ||
|
|
127
|
+
!Number.isSafeInteger(exp) ||
|
|
128
|
+
exp <= iat ||
|
|
129
|
+
exp - iat > 60 ||
|
|
130
|
+
iat > now + tolerance ||
|
|
131
|
+
exp <= now - tolerance)
|
|
132
|
+
return refuse("expired or not yet valid");
|
|
133
|
+
return claims;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Read the Call Context from a `tools/call` request's `params._meta`. Throws
|
|
137
|
+
* ConnectorAuthError when it is missing, malformed or for another
|
|
138
|
+
* Organization. Initialization and tool discovery carry no Call Context.
|
|
139
|
+
*/
|
|
140
|
+
export function readConnectorCallContext(meta, options) {
|
|
141
|
+
const context = meta?.[CONNECTOR_CALL_CONTEXT_KEY];
|
|
142
|
+
const text = (value) => typeof value === "string" && value.length > 0;
|
|
143
|
+
if (!context ||
|
|
144
|
+
!text(context.callId) ||
|
|
145
|
+
!text(context.sessionId) ||
|
|
146
|
+
!text(context.userId) ||
|
|
147
|
+
!text(context.deadline) ||
|
|
148
|
+
!Number.isFinite(Date.parse(context.deadline)) ||
|
|
149
|
+
context.attempt !== 1)
|
|
150
|
+
throw new ConnectorAuthError("Connector call has no valid Call Context");
|
|
151
|
+
if (context.organizationId !== options.organizationId)
|
|
152
|
+
throw new ConnectorAuthError("Connector call is for another Organization");
|
|
153
|
+
return context;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=connector-callback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector-callback.js","sourceRoot":"","sources":["../src/connector-callback.ts"],"names":[],"mappings":"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"}
|