@nathapp/nax-ai 0.1.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/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/auth/oauth-policy.d.ts +42 -0
- package/dist/auth/oauth-policy.d.ts.map +1 -0
- package/dist/auth/oauth-policy.js +61 -0
- package/dist/auth/oauth-policy.js.map +1 -0
- package/dist/auth/pi-auth.d.ts +12 -0
- package/dist/auth/pi-auth.d.ts.map +1 -0
- package/dist/auth/pi-auth.js +84 -0
- package/dist/auth/pi-auth.js.map +1 -0
- package/dist/auth/resolver.d.ts +30 -0
- package/dist/auth/resolver.d.ts.map +1 -0
- package/dist/auth/resolver.js +10 -0
- package/dist/auth/resolver.js.map +1 -0
- package/dist/client.d.ts +33 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +68 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/protocols/collect.d.ts +15 -0
- package/dist/protocols/collect.d.ts.map +1 -0
- package/dist/protocols/collect.js +65 -0
- package/dist/protocols/collect.js.map +1 -0
- package/dist/protocols/errors.d.ts +30 -0
- package/dist/protocols/errors.d.ts.map +1 -0
- package/dist/protocols/errors.js +59 -0
- package/dist/protocols/errors.js.map +1 -0
- package/dist/protocols/pi-client.d.ts +36 -0
- package/dist/protocols/pi-client.d.ts.map +1 -0
- package/dist/protocols/pi-client.js +348 -0
- package/dist/protocols/pi-client.js.map +1 -0
- package/dist/protocols/pi-protocols.d.ts +21 -0
- package/dist/protocols/pi-protocols.d.ts.map +1 -0
- package/dist/protocols/pi-protocols.js +29 -0
- package/dist/protocols/pi-protocols.js.map +1 -0
- package/dist/protocols/registry.d.ts +36 -0
- package/dist/protocols/registry.d.ts.map +1 -0
- package/dist/protocols/registry.js +85 -0
- package/dist/protocols/registry.js.map +1 -0
- package/dist/protocols/retry.d.ts +37 -0
- package/dist/protocols/retry.d.ts.map +1 -0
- package/dist/protocols/retry.js +96 -0
- package/dist/protocols/retry.js.map +1 -0
- package/dist/protocols/thinking.d.ts +11 -0
- package/dist/protocols/thinking.d.ts.map +1 -0
- package/dist/protocols/thinking.js +35 -0
- package/dist/protocols/thinking.js.map +1 -0
- package/dist/protocols/tool-args.d.ts +27 -0
- package/dist/protocols/tool-args.d.ts.map +1 -0
- package/dist/protocols/tool-args.js +38 -0
- package/dist/protocols/tool-args.js.map +1 -0
- package/dist/protocols/types.d.ts +142 -0
- package/dist/protocols/types.d.ts.map +1 -0
- package/dist/protocols/types.js +33 -0
- package/dist/protocols/types.js.map +1 -0
- package/dist/providers/catalog.d.ts +37 -0
- package/dist/providers/catalog.d.ts.map +1 -0
- package/dist/providers/catalog.js +72 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/pi-catalog.d.ts +14 -0
- package/dist/providers/pi-catalog.d.ts.map +1 -0
- package/dist/providers/pi-catalog.js +91 -0
- package/dist/providers/pi-catalog.js.map +1 -0
- package/dist/providers/types.d.ts +79 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +10 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/types.d.ts +94 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/usage.d.ts +39 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +40 -0
- package/dist/usage.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP-shaped error classification.
|
|
3
|
+
*
|
|
4
|
+
* Kept as pure functions, separate from any call path, for the same reason
|
|
5
|
+
* `usage.ts` is: a hand-written backend classifies the same statuses from a
|
|
6
|
+
* different source and should not carry a second copy of this table.
|
|
7
|
+
*/
|
|
8
|
+
import type { ProtocolError, ProtocolErrorKind } from "./types.ts";
|
|
9
|
+
export declare function classifyHttpError(status: number | undefined): ProtocolErrorKind;
|
|
10
|
+
/**
|
|
11
|
+
* Reads `retry-after` as a delay in seconds.
|
|
12
|
+
*
|
|
13
|
+
* The header may also carry an HTTP-date. That form is deliberately not
|
|
14
|
+
* converted: the conversion depends on clock skew between us and the provider,
|
|
15
|
+
* and a wrong number here would be worse than an absent one, because the
|
|
16
|
+
* consumer owns the retry loop and would sleep on it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseRetryAfter(headers: Readonly<Record<string, string>> | undefined): number | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Normalises an arbitrary thrown value (connection reset, DNS failure, an
|
|
21
|
+
* immediate socket error) into a `ProtocolError`.
|
|
22
|
+
*
|
|
23
|
+
* Always classified as "transport": `classifyHttpError(undefined)` would
|
|
24
|
+
* return "unknown", but a throw with no HTTP response is exactly the class
|
|
25
|
+
* of fault §10.1 assigns to nax-ai's own bounded retry, not the consumer's
|
|
26
|
+
* rate-limit/overload policy. `cause` is preserved so the original value is
|
|
27
|
+
* never lost.
|
|
28
|
+
*/
|
|
29
|
+
export declare function classifyThrown(cause: unknown): ProtocolError;
|
|
30
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/protocols/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAQ/E;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASzG;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAM5D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP-shaped error classification.
|
|
3
|
+
*
|
|
4
|
+
* Kept as pure functions, separate from any call path, for the same reason
|
|
5
|
+
* `usage.ts` is: a hand-written backend classifies the same statuses from a
|
|
6
|
+
* different source and should not carry a second copy of this table.
|
|
7
|
+
*/
|
|
8
|
+
export function classifyHttpError(status) {
|
|
9
|
+
if (status === undefined)
|
|
10
|
+
return "unknown";
|
|
11
|
+
if (status === 401 || status === 403)
|
|
12
|
+
return "auth";
|
|
13
|
+
if (status === 429)
|
|
14
|
+
return "rate-limit";
|
|
15
|
+
if (status === 529 || status === 503)
|
|
16
|
+
return "overloaded";
|
|
17
|
+
if (status >= 400 && status < 500)
|
|
18
|
+
return "bad-request";
|
|
19
|
+
if (status >= 500)
|
|
20
|
+
return "transport";
|
|
21
|
+
return "unknown";
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Reads `retry-after` as a delay in seconds.
|
|
25
|
+
*
|
|
26
|
+
* The header may also carry an HTTP-date. That form is deliberately not
|
|
27
|
+
* converted: the conversion depends on clock skew between us and the provider,
|
|
28
|
+
* and a wrong number here would be worse than an absent one, because the
|
|
29
|
+
* consumer owns the retry loop and would sleep on it.
|
|
30
|
+
*/
|
|
31
|
+
export function parseRetryAfter(headers) {
|
|
32
|
+
if (headers === undefined)
|
|
33
|
+
return undefined;
|
|
34
|
+
const entry = Object.entries(headers).find(([name]) => name.toLowerCase() === "retry-after");
|
|
35
|
+
if (entry === undefined)
|
|
36
|
+
return undefined;
|
|
37
|
+
const seconds = Number(entry[1]);
|
|
38
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
39
|
+
return undefined;
|
|
40
|
+
return seconds;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Normalises an arbitrary thrown value (connection reset, DNS failure, an
|
|
44
|
+
* immediate socket error) into a `ProtocolError`.
|
|
45
|
+
*
|
|
46
|
+
* Always classified as "transport": `classifyHttpError(undefined)` would
|
|
47
|
+
* return "unknown", but a throw with no HTTP response is exactly the class
|
|
48
|
+
* of fault §10.1 assigns to nax-ai's own bounded retry, not the consumer's
|
|
49
|
+
* rate-limit/overload policy. `cause` is preserved so the original value is
|
|
50
|
+
* never lost.
|
|
51
|
+
*/
|
|
52
|
+
export function classifyThrown(cause) {
|
|
53
|
+
return {
|
|
54
|
+
kind: "transport",
|
|
55
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
56
|
+
cause,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/protocols/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,MAAM,CAAC;IACpD,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,YAAY,CAAC;IACxC,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,YAAY,CAAC;IAC1D,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;QAAE,OAAO,aAAa,CAAC;IACxD,IAAI,MAAM,IAAI,GAAG;QAAE,OAAO,WAAW,CAAC;IACtC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,OAAqD;IACnF,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE5C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,aAAa,CAAC,CAAC;IAC7F,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE1C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QAC/D,KAAK;KACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pi-ai-backed protocol.
|
|
3
|
+
*
|
|
4
|
+
* This file and the two other files on the ALLOWED list in
|
|
5
|
+
* scripts/check-pi-ai-imports.ts are the only places pi-ai may be imported.
|
|
6
|
+
* Nothing exported here may expose a pi-ai type in a shape a consumer sees.
|
|
7
|
+
*
|
|
8
|
+
* One implementation serves all four protocols. They differ only in where a
|
|
9
|
+
* system prompt sits in the wire request, and pi-ai's Context carries it in a
|
|
10
|
+
* dedicated field, so on this path the difference does not exist. The protocol
|
|
11
|
+
* name is still a parameter because a per-api quirk would branch on it.
|
|
12
|
+
*/
|
|
13
|
+
import type { Api, AssistantMessageEvent, Context, Model, SimpleStreamOptions } from "@earendil-works/pi-ai";
|
|
14
|
+
import type { PiProtocolOptions } from "./pi-protocols.ts";
|
|
15
|
+
import type { Protocol, ProtocolRequest } from "./types.ts";
|
|
16
|
+
export interface PiResponse {
|
|
17
|
+
readonly status: number;
|
|
18
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
19
|
+
}
|
|
20
|
+
export type PiStreamFn = (model: Model<Api>, context: Context, options: SimpleStreamOptions,
|
|
21
|
+
/**
|
|
22
|
+
* Called once, before the body is consumed. pi-ai's error event carries no
|
|
23
|
+
* status and no retry-after, so without this the classifier would return
|
|
24
|
+
* "unknown" for every failure and the consumer's retry policy — which M1
|
|
25
|
+
* section 10.1 deliberately assigns to the consumer — would be blind.
|
|
26
|
+
*/
|
|
27
|
+
onResponse: (response: PiResponse) => void) => AsyncIterable<AssistantMessageEvent>;
|
|
28
|
+
export interface PiDeps {
|
|
29
|
+
readonly resolveModel: (modelId: string, provider?: string) => Promise<Model<Api>>;
|
|
30
|
+
readonly stream: PiStreamFn;
|
|
31
|
+
}
|
|
32
|
+
export declare function toPiContext(req: ProtocolRequest, model: Model<Api>): Context;
|
|
33
|
+
export declare function toPiOptions(req: ProtocolRequest): SimpleStreamOptions;
|
|
34
|
+
export declare function createPiProtocol(name: string, deps: PiDeps): Protocol;
|
|
35
|
+
export declare function createPiDeps(options?: PiProtocolOptions): PiDeps;
|
|
36
|
+
//# sourceMappingURL=pi-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-client.d.ts","sourceRoot":"","sources":["../../src/protocols/pi-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,GAAG,EACH,qBAAqB,EACrB,OAAO,EACP,KAAK,EAKL,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAM/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,KAAK,EAAuB,QAAQ,EAAiB,eAAe,EAAiB,MAAM,YAAY,CAAC;AAE/G,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,UAAU,GAAG,CACvB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,mBAAmB;AAC5B;;;;;GAKG;AACH,UAAU,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,IAAI,KACvC,aAAa,CAAC,qBAAqB,CAAC,CAAC;AAE1C,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACnF,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AA6GD,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAM5E;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,mBAAmB,CAWrE;AAkDD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CA+HrE;AAYD,wBAAgB,YAAY,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CA6CpE"}
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pi-ai-backed protocol.
|
|
3
|
+
*
|
|
4
|
+
* This file and the two other files on the ALLOWED list in
|
|
5
|
+
* scripts/check-pi-ai-imports.ts are the only places pi-ai may be imported.
|
|
6
|
+
* Nothing exported here may expose a pi-ai type in a shape a consumer sees.
|
|
7
|
+
*
|
|
8
|
+
* One implementation serves all four protocols. They differ only in where a
|
|
9
|
+
* system prompt sits in the wire request, and pi-ai's Context carries it in a
|
|
10
|
+
* dedicated field, so on this path the difference does not exist. The protocol
|
|
11
|
+
* name is still a parameter because a per-api quirk would branch on it.
|
|
12
|
+
*/
|
|
13
|
+
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
|
|
14
|
+
import { createPiAuthResolver, toPiCredentialStore } from "../auth/pi-auth.js";
|
|
15
|
+
import { toTokenUsage, totalTokens } from "../usage.js";
|
|
16
|
+
import { classifyHttpError, classifyThrown, parseRetryAfter } from "./errors.js";
|
|
17
|
+
import { createToolArgAccumulator, parseToolArgs } from "./tool-args.js";
|
|
18
|
+
/**
|
|
19
|
+
* pi-ai's Message requires a timestamp, but no wire module under its api/
|
|
20
|
+
* directory reads one. A constant keeps translation deterministic; Date.now()
|
|
21
|
+
* would make tests flap over a field that is never sent.
|
|
22
|
+
*/
|
|
23
|
+
const NO_TIMESTAMP = 0;
|
|
24
|
+
/** Placeholder accounting for a replayed assistant turn. Never sent upstream. */
|
|
25
|
+
const NO_USAGE = {
|
|
26
|
+
input: 0,
|
|
27
|
+
output: 0,
|
|
28
|
+
cacheRead: 0,
|
|
29
|
+
cacheWrite: 0,
|
|
30
|
+
totalTokens: 0,
|
|
31
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
32
|
+
};
|
|
33
|
+
function toPiTool(tool) {
|
|
34
|
+
return {
|
|
35
|
+
name: tool.name,
|
|
36
|
+
description: tool.description,
|
|
37
|
+
// pi-ai types this as a TypeBox TSchema, which is a JSON Schema object at
|
|
38
|
+
// runtime. nax-ai does not validate schemas; it forwards what it was given.
|
|
39
|
+
parameters: tool.inputSchema,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* pi's ThinkingContent, from our ThinkingBlock. `thinkingSignature` is left
|
|
44
|
+
* unset rather than "" when absent, because pi's own request-side handling
|
|
45
|
+
* (dist/api/anthropic-messages.js:923-957) treats "no signature" and "empty
|
|
46
|
+
* signature" differently — a synthesised "" would pick the wrong branch.
|
|
47
|
+
*/
|
|
48
|
+
function toPiThinking(block) {
|
|
49
|
+
return {
|
|
50
|
+
type: "thinking",
|
|
51
|
+
thinking: block.text,
|
|
52
|
+
...(block.signature !== undefined ? { thinkingSignature: block.signature } : {}),
|
|
53
|
+
...(block.redacted !== undefined ? { redacted: block.redacted } : {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function toPiMessages(messages, model) {
|
|
57
|
+
const toolNames = new Map();
|
|
58
|
+
const out = [];
|
|
59
|
+
for (const message of messages) {
|
|
60
|
+
if (message.role === "user") {
|
|
61
|
+
out.push({ role: "user", content: message.content, timestamp: NO_TIMESTAMP });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (message.role === "assistant") {
|
|
65
|
+
for (const call of message.toolCalls ?? [])
|
|
66
|
+
toolNames.set(call.id, call.name);
|
|
67
|
+
out.push({
|
|
68
|
+
role: "assistant",
|
|
69
|
+
content: [
|
|
70
|
+
// Anthropic requires thinking blocks to lead the assistant
|
|
71
|
+
// message when present — this is a wire ordering requirement, not
|
|
72
|
+
// a style choice, so it goes first unconditionally.
|
|
73
|
+
...(message.thinking ?? []).map(toPiThinking),
|
|
74
|
+
...(message.content === "" ? [] : [{ type: "text", text: message.content }]),
|
|
75
|
+
...(message.toolCalls ?? []).map((call) => ({
|
|
76
|
+
type: "toolCall",
|
|
77
|
+
id: call.id,
|
|
78
|
+
name: call.name,
|
|
79
|
+
arguments: (call.input ?? {}),
|
|
80
|
+
})),
|
|
81
|
+
],
|
|
82
|
+
api: model.api,
|
|
83
|
+
provider: model.provider,
|
|
84
|
+
model: model.id,
|
|
85
|
+
usage: NO_USAGE,
|
|
86
|
+
stopReason: "stop",
|
|
87
|
+
timestamp: NO_TIMESTAMP,
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// toolName is not on our ConversationMessage but is read on the wire by
|
|
92
|
+
// several providers, so it is recovered from the call that produced this
|
|
93
|
+
// result. No match means the caller assembled an impossible conversation.
|
|
94
|
+
const toolName = toolNames.get(message.toolCallId);
|
|
95
|
+
if (toolName === undefined) {
|
|
96
|
+
throw new Error(`Tool result references tool call "${message.toolCallId}", which no earlier assistant message made.`);
|
|
97
|
+
}
|
|
98
|
+
out.push({
|
|
99
|
+
role: "toolResult",
|
|
100
|
+
toolCallId: message.toolCallId,
|
|
101
|
+
toolName,
|
|
102
|
+
content: [{ type: "text", text: message.content }],
|
|
103
|
+
isError: message.isError ?? false,
|
|
104
|
+
timestamp: NO_TIMESTAMP,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
export function toPiContext(req, model) {
|
|
110
|
+
return {
|
|
111
|
+
...(req.system !== undefined ? { systemPrompt: req.system } : {}),
|
|
112
|
+
messages: toPiMessages(req.messages, model),
|
|
113
|
+
...(req.tools !== undefined ? { tools: req.tools.map(toPiTool) } : {}),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export function toPiOptions(req) {
|
|
117
|
+
return {
|
|
118
|
+
...(req.toolChoice !== undefined ? { toolChoice: req.toolChoice } : {}),
|
|
119
|
+
...(req.maxTokens !== undefined ? { maxTokens: req.maxTokens } : {}),
|
|
120
|
+
...(req.temperature !== undefined ? { temperature: req.temperature } : {}),
|
|
121
|
+
...(req.cacheRetention !== undefined ? { cacheRetention: req.cacheRetention } : {}),
|
|
122
|
+
...(req.signal !== undefined ? { signal: req.signal } : {}),
|
|
123
|
+
// pi-ai's scale has no "off": the absence of the field is how thinking is
|
|
124
|
+
// disabled, so mapping "off" to a value would silently enable it.
|
|
125
|
+
...(req.thinking !== undefined && req.thinking !== "off" ? { reasoning: req.thinking } : {}),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* pi-ai's terminal reasons, narrowed to ours.
|
|
130
|
+
*
|
|
131
|
+
* "deferred" is absent by design: we never request a deferred response, so
|
|
132
|
+
* receiving one means an assumption broke and it must surface rather than be
|
|
133
|
+
* folded into "stop". "content_filter" has no pi-ai equivalent and is
|
|
134
|
+
* unreachable here; it exists for a hand-written backend.
|
|
135
|
+
*/
|
|
136
|
+
const STOP_REASONS = {
|
|
137
|
+
stop: "stop",
|
|
138
|
+
length: "length",
|
|
139
|
+
toolUse: "tool_use",
|
|
140
|
+
};
|
|
141
|
+
/** The in-progress tool call at a content index, when there is one. */
|
|
142
|
+
function toolCallAt(partial, index) {
|
|
143
|
+
const block = partial.content[index];
|
|
144
|
+
if (typeof block !== "object" || block === null)
|
|
145
|
+
return undefined;
|
|
146
|
+
const candidate = block;
|
|
147
|
+
if (candidate.type !== "toolCall" || typeof candidate.id !== "string" || typeof candidate.name !== "string") {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
return { id: candidate.id, name: candidate.name };
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The signature and redacted flag for the thinking block at a content index,
|
|
154
|
+
* when the block at that index has that shape. `thinking_end`'s own event
|
|
155
|
+
* carries no signature — pi accumulates it onto the block in `partial`
|
|
156
|
+
* during the stream (signature_delta, dist/api/anthropic-messages.js:501-502)
|
|
157
|
+
* so by the time the block ends it is complete there. Same trap as
|
|
158
|
+
* `toolCallAt` above: the terminal event is missing fields only the partial
|
|
159
|
+
* carries.
|
|
160
|
+
*/
|
|
161
|
+
function thinkingBlockAt(partial, index) {
|
|
162
|
+
const block = partial.content[index];
|
|
163
|
+
if (typeof block !== "object" || block === null)
|
|
164
|
+
return {};
|
|
165
|
+
const candidate = block;
|
|
166
|
+
if (candidate.type !== "thinking")
|
|
167
|
+
return {};
|
|
168
|
+
return {
|
|
169
|
+
...(typeof candidate.thinkingSignature === "string" ? { signature: candidate.thinkingSignature } : {}),
|
|
170
|
+
...(typeof candidate.redacted === "boolean" ? { redacted: candidate.redacted } : {}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
export function createPiProtocol(name, deps) {
|
|
174
|
+
return {
|
|
175
|
+
name,
|
|
176
|
+
async *stream(req) {
|
|
177
|
+
const model = await deps.resolveModel(req.model, req.provider);
|
|
178
|
+
let observed;
|
|
179
|
+
const events = deps.stream(model, toPiContext(req, model), toPiOptions(req), (response) => {
|
|
180
|
+
observed = response;
|
|
181
|
+
});
|
|
182
|
+
const toolArgs = createToolArgAccumulator();
|
|
183
|
+
try {
|
|
184
|
+
for await (const event of events) {
|
|
185
|
+
switch (event.type) {
|
|
186
|
+
case "text_delta":
|
|
187
|
+
yield { type: "text-delta", text: event.delta };
|
|
188
|
+
break;
|
|
189
|
+
case "thinking_delta":
|
|
190
|
+
yield { type: "thinking-delta", text: event.delta };
|
|
191
|
+
break;
|
|
192
|
+
case "thinking_end": {
|
|
193
|
+
// Losing thinking text is worse than losing a signature: even
|
|
194
|
+
// when the block at this content index is not the shape we
|
|
195
|
+
// expect, still emit the text `thinking_end` itself carries.
|
|
196
|
+
const { signature, redacted } = thinkingBlockAt(event.partial, event.contentIndex);
|
|
197
|
+
yield {
|
|
198
|
+
type: "thinking",
|
|
199
|
+
block: {
|
|
200
|
+
text: event.content,
|
|
201
|
+
...(signature !== undefined ? { signature } : {}),
|
|
202
|
+
...(redacted !== undefined ? { redacted } : {}),
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
case "toolcall_delta": {
|
|
208
|
+
// The delta carries neither id nor name; both are only on the
|
|
209
|
+
// in-progress call block that partial.content holds at this index.
|
|
210
|
+
const call = toolCallAt(event.partial, event.contentIndex);
|
|
211
|
+
if (call === undefined)
|
|
212
|
+
break;
|
|
213
|
+
const rawInput = toolArgs.append(call.id, call.name, event.delta);
|
|
214
|
+
yield { type: "tool-call-partial", id: call.id, name: call.name, rawInput };
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
case "toolcall_end": {
|
|
218
|
+
const pending = toolArgs.take(event.toolCall.id);
|
|
219
|
+
let input;
|
|
220
|
+
try {
|
|
221
|
+
input = parseToolArgs(pending?.raw ?? "");
|
|
222
|
+
}
|
|
223
|
+
catch (cause) {
|
|
224
|
+
// An error event, not a throw: text and usage already yielded
|
|
225
|
+
// must survive.
|
|
226
|
+
yield {
|
|
227
|
+
type: "error",
|
|
228
|
+
error: {
|
|
229
|
+
kind: "bad-request",
|
|
230
|
+
message: `Tool "${event.toolCall.name}" returned unparseable arguments.`,
|
|
231
|
+
cause,
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
yield { type: "tool-call", call: { id: event.toolCall.id, name: event.toolCall.name, input } };
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case "done": {
|
|
240
|
+
const stopReason = STOP_REASONS[event.reason];
|
|
241
|
+
yield { type: "usage", usage: toTokenUsage(event.message.usage) };
|
|
242
|
+
if (stopReason === undefined) {
|
|
243
|
+
yield {
|
|
244
|
+
type: "error",
|
|
245
|
+
error: {
|
|
246
|
+
kind: "unknown",
|
|
247
|
+
message: `Upstream reported stop reason "${event.reason}", which nax-ai never requests.`,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
yield { type: "done", stopReason };
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
case "error": {
|
|
256
|
+
const status = observed?.status;
|
|
257
|
+
const retryAfter = parseRetryAfter(observed?.headers);
|
|
258
|
+
const usage = toTokenUsage(event.error.usage);
|
|
259
|
+
// A failed request that consumed tokens still bills for them.
|
|
260
|
+
if (totalTokens(usage) > 0)
|
|
261
|
+
yield { type: "usage", usage };
|
|
262
|
+
yield {
|
|
263
|
+
type: "error",
|
|
264
|
+
error: {
|
|
265
|
+
kind: classifyHttpError(status),
|
|
266
|
+
message: event.error.errorMessage ?? `Upstream stream ended: ${event.reason}.`,
|
|
267
|
+
...(status !== undefined ? { status } : {}),
|
|
268
|
+
...(retryAfter !== undefined ? { retryAfter } : {}),
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
default:
|
|
274
|
+
// start, text_start, text_end, thinking_start and toolcall_start
|
|
275
|
+
// carry nothing our vocabulary expresses: content is already
|
|
276
|
+
// delivered by the deltas (and, for thinking, by "thinking_end"
|
|
277
|
+
// above).
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (cause) {
|
|
283
|
+
// A stream failure with no HTTP response (connection reset, DNS
|
|
284
|
+
// failure, an immediate socket error) propagates as a raw throw
|
|
285
|
+
// rather than pi-ai's own "error" event — there was never a response
|
|
286
|
+
// to build one from, which is why classifyHttpError(undefined) would
|
|
287
|
+
// otherwise return "unknown" here. The caller's own abort must not be
|
|
288
|
+
// relabelled as a transport fault: retryTransportFaults, and any
|
|
289
|
+
// consumer-level abort handling, both need to see abort as abort.
|
|
290
|
+
if (req.signal?.aborted)
|
|
291
|
+
throw cause;
|
|
292
|
+
yield { type: "error", error: classifyThrown(cause) };
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
let shared;
|
|
298
|
+
/**
|
|
299
|
+
* The credential-backed twin of `shared`, keyed by the store itself. Each of
|
|
300
|
+
* the four protocol entries resolves lazily through `createPiDeps`, so without
|
|
301
|
+
* this memo a consumer with credentials would construct one Models per entry
|
|
302
|
+
* instead of the single instance pi-protocols.ts promises.
|
|
303
|
+
*/
|
|
304
|
+
const credentialed = new WeakMap();
|
|
305
|
+
export function createPiDeps(options = {}) {
|
|
306
|
+
const store = options.credentials;
|
|
307
|
+
let models;
|
|
308
|
+
if (store === undefined) {
|
|
309
|
+
models = shared ??= builtinModels();
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
models = credentialed.get(store) ?? builtinModels({ credentials: toPiCredentialStore(store) });
|
|
313
|
+
credentialed.set(store, models);
|
|
314
|
+
}
|
|
315
|
+
const resolver = createPiAuthResolver(models);
|
|
316
|
+
return {
|
|
317
|
+
resolveModel: async (modelId, provider) => {
|
|
318
|
+
// pi-ai serves one model id from many providers (e.g. gpt-5.4 under
|
|
319
|
+
// azure-openai-responses, openai and openai-codex), so when the client
|
|
320
|
+
// supplies the owning provider the search is scoped to it. Without a
|
|
321
|
+
// provider — protocol-direct callers and existing tests — the global
|
|
322
|
+
// catalog's first match stays as the documented fallback.
|
|
323
|
+
const found = provider !== undefined
|
|
324
|
+
? models.getModels(provider).find((candidate) => candidate.id === modelId)
|
|
325
|
+
: models.getModels().find((candidate) => candidate.id === modelId);
|
|
326
|
+
if (found === undefined) {
|
|
327
|
+
if (provider !== undefined) {
|
|
328
|
+
throw new Error(`Unknown model "${modelId}" for provider "${provider}" in the pi-ai catalog.`);
|
|
329
|
+
}
|
|
330
|
+
throw new Error(`Unknown model "${modelId}" in the pi-ai catalog.`);
|
|
331
|
+
}
|
|
332
|
+
return found;
|
|
333
|
+
},
|
|
334
|
+
stream: async function* (model, context, options_, onResponse) {
|
|
335
|
+
// Resolve through nax-ai's own port, not through Models' internal path,
|
|
336
|
+
// so the seam a native backend will use is exercised in production
|
|
337
|
+
// rather than merely exported.
|
|
338
|
+
const auth = await resolver.resolve({ provider: model.provider, model: model.id });
|
|
339
|
+
yield* models.streamSimple(model, context, {
|
|
340
|
+
...options_,
|
|
341
|
+
...(auth.apiKey !== undefined ? { apiKey: auth.apiKey } : {}),
|
|
342
|
+
...(auth.headers !== undefined ? { headers: { ...auth.headers } } : {}),
|
|
343
|
+
onResponse: (response) => onResponse({ status: response.status, headers: response.headers }),
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=pi-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-client.js","sourceRoot":"","sources":["../../src/protocols/pi-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The registration surface for the pi-backed protocols.
|
|
3
|
+
*
|
|
4
|
+
* A consumer cannot assemble these entries itself: the four protocols must
|
|
5
|
+
* share one pi-ai Models instance, and therefore one credential store and one
|
|
6
|
+
* catalog, rather than constructing four. That is why this is exported rather
|
|
7
|
+
* than documented.
|
|
8
|
+
*
|
|
9
|
+
* pi-ai is not imported here. The factory is lazy, so the import cost is paid
|
|
10
|
+
* on first resolve of a protocol and not before.
|
|
11
|
+
*/
|
|
12
|
+
import type { CredentialStore } from "../types.ts";
|
|
13
|
+
import type { ProtocolEntries } from "./registry.ts";
|
|
14
|
+
export declare const PI_PROTOCOL_NAMES: readonly ["anthropic-messages", "openai-completions", "openai-responses", "openai-codex-responses"];
|
|
15
|
+
export type PiProtocolName = (typeof PI_PROTOCOL_NAMES)[number];
|
|
16
|
+
export interface PiProtocolOptions {
|
|
17
|
+
/** Where OAuth and api-key credentials live. Omitted means ambient only. */
|
|
18
|
+
readonly credentials?: CredentialStore;
|
|
19
|
+
}
|
|
20
|
+
export declare function piProtocols(options?: PiProtocolOptions): ProtocolEntries;
|
|
21
|
+
//# sourceMappingURL=pi-protocols.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-protocols.d.ts","sourceRoot":"","sources":["../../src/protocols/pi-protocols.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,eAAO,MAAM,iBAAiB,YAC5B,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,CAChB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;CACxC;AAED,wBAAgB,WAAW,CAAC,OAAO,GAAE,iBAAsB,GAAG,eAAe,CAY5E"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The registration surface for the pi-backed protocols.
|
|
3
|
+
*
|
|
4
|
+
* A consumer cannot assemble these entries itself: the four protocols must
|
|
5
|
+
* share one pi-ai Models instance, and therefore one credential store and one
|
|
6
|
+
* catalog, rather than constructing four. That is why this is exported rather
|
|
7
|
+
* than documented.
|
|
8
|
+
*
|
|
9
|
+
* pi-ai is not imported here. The factory is lazy, so the import cost is paid
|
|
10
|
+
* on first resolve of a protocol and not before.
|
|
11
|
+
*/
|
|
12
|
+
export const PI_PROTOCOL_NAMES = [
|
|
13
|
+
"anthropic-messages",
|
|
14
|
+
"openai-completions",
|
|
15
|
+
"openai-responses",
|
|
16
|
+
"openai-codex-responses",
|
|
17
|
+
];
|
|
18
|
+
export function piProtocols(options = {}) {
|
|
19
|
+
return Object.fromEntries(PI_PROTOCOL_NAMES.map((name) => [
|
|
20
|
+
name,
|
|
21
|
+
{
|
|
22
|
+
pi: async () => {
|
|
23
|
+
const { createPiDeps, createPiProtocol } = await import("./pi-client.js");
|
|
24
|
+
return createPiProtocol(name, createPiDeps(options));
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
]));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=pi-protocols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-protocols.js","sourceRoot":"","sources":["../../src/protocols/pi-protocols.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,oBAAoB;IACpB,oBAAoB;IACpB,kBAAkB;IAClB,wBAAwB;CAChB,CAAC;AASX,MAAM,UAAU,WAAW,CAAC,OAAO,GAAsB,EAAE;IACzD,OAAO,MAAM,CAAC,WAAW,CACvB,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,IAAI;QACJ;YACE,EAAE,EAAE,KAAK,IAAI,EAAE;gBACb,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;gBAC1E,OAAO,gBAAgB,CAAC,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;YACvD,CAAC;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol backend registration and selection.
|
|
3
|
+
*
|
|
4
|
+
* A protocol may have more than one backend — `pi` today, `native` when a wire
|
|
5
|
+
* format is hand-written later. Both can be registered at once so a native
|
|
6
|
+
* implementation can be run against the pi-backed one on real traffic before
|
|
7
|
+
* becoming the default. That comparison is the reason selection happens at
|
|
8
|
+
* runtime rather than by swapping a module at build time.
|
|
9
|
+
*/
|
|
10
|
+
import type { Protocol } from "./types.ts";
|
|
11
|
+
export type BackendId = "pi" | "native";
|
|
12
|
+
/** Lazy factories keyed by backend id. Laziness preserves pi-ai's deferred SDK loading. */
|
|
13
|
+
export type ProtocolBackends = Partial<Record<BackendId, () => Promise<Protocol>>>;
|
|
14
|
+
export type ProtocolEntries = Readonly<Record<string, ProtocolBackends>>;
|
|
15
|
+
export interface BackendSelection {
|
|
16
|
+
/** Applied to protocols not named in `byProtocol`. Defaults to "pi". */
|
|
17
|
+
readonly default?: BackendId;
|
|
18
|
+
readonly byProtocol?: Readonly<Record<string, BackendId>>;
|
|
19
|
+
}
|
|
20
|
+
export declare class UnknownProtocolError extends Error {
|
|
21
|
+
readonly protocolName: string;
|
|
22
|
+
constructor(protocolName: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class UnregisteredBackendError extends Error {
|
|
25
|
+
readonly protocolName: string;
|
|
26
|
+
readonly backendId: BackendId;
|
|
27
|
+
constructor(protocolName: string, backendId: BackendId, available: readonly BackendId[]);
|
|
28
|
+
}
|
|
29
|
+
export interface ProtocolRegistry {
|
|
30
|
+
available(): ReadonlyMap<string, readonly BackendId[]>;
|
|
31
|
+
resolve(protocolName: string): Promise<Protocol>;
|
|
32
|
+
/** Throws if any configured selection names an unknown protocol or unregistered backend. */
|
|
33
|
+
validate(): void;
|
|
34
|
+
}
|
|
35
|
+
export declare function createRegistry(entries: ProtocolEntries, selection?: BackendSelection): ProtocolRegistry;
|
|
36
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/protocols/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,QAAQ,CAAC;AAExC,2FAA2F;AAC3F,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEnF,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CAC3D;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM;IAAzC,YAAqB,YAAY,EAAE,MAAM,EAGxC;CACF;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IAE/C,QAAQ,CAAC,YAAY,EAAE,MAAM;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS;IAF/B,YACW,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,SAAS,EAC7B,SAAS,EAAE,SAAS,SAAS,EAAE,EAQhC;CACF;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,4FAA4F;IAC5F,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,SAAS,GAAE,gBAAqB,GAAG,gBAAgB,CA8D3G"}
|