@namzu/zen 2.3.0 → 2.5.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 +30 -0
- package/README.md +36 -15
- package/dist/catalogue/catalogue.d.ts +106 -0
- package/dist/catalogue/catalogue.d.ts.map +1 -0
- package/dist/catalogue/catalogue.js +325 -0
- package/dist/catalogue/catalogue.js.map +1 -0
- package/dist/catalogue/derive.d.ts +203 -0
- package/dist/catalogue/derive.d.ts.map +1 -0
- package/dist/catalogue/derive.js +485 -0
- package/dist/catalogue/derive.js.map +1 -0
- package/dist/catalogue/fetch.d.ts +63 -0
- package/dist/catalogue/fetch.d.ts.map +1 -0
- package/dist/catalogue/fetch.js +180 -0
- package/dist/catalogue/fetch.js.map +1 -0
- package/dist/catalogue/index.d.ts +17 -0
- package/dist/catalogue/index.d.ts.map +1 -0
- package/dist/catalogue/index.js +17 -0
- package/dist/catalogue/index.js.map +1 -0
- package/dist/client.d.ts +5 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +39 -8
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +6 -0
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +63 -10
- package/dist/models.js.map +1 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +4 -1
- package/dist/options.js.map +1 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +46 -0
- package/dist/prompt.js.map +1 -1
- package/dist/types.d.ts +11 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/src/catalogue/catalogue.ts +462 -0
- package/src/catalogue/derive.ts +638 -0
- package/src/catalogue/fetch.ts +229 -0
- package/src/catalogue/index.ts +37 -0
- package/src/client.ts +47 -9
- package/src/index.ts +2 -1
- package/src/models.review.json +4 -0
- package/src/models.ts +64 -10
- package/src/options.ts +4 -1
- package/src/prompt.ts +51 -0
- package/src/types.ts +11 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The derivation rules that turn Zen's and Go's upstream documents into a
|
|
3
|
+
* model roster.
|
|
4
|
+
*
|
|
5
|
+
* Pure: no network, no file system, no logger. `fetch.ts` reads the sources and
|
|
6
|
+
* `catalogue.ts` assembles a catalogue from them; the maintainer's generator
|
|
7
|
+
* (`scripts/generate-zen-models.mjs`) imports these same functions to render
|
|
8
|
+
* the bundled snapshot in `models.ts`, so the runtime refresh and the snapshot
|
|
9
|
+
* can never parse the same page two different ways.
|
|
10
|
+
*
|
|
11
|
+
* ## Where each field comes from
|
|
12
|
+
*
|
|
13
|
+
* Routes come from the service's own documentation page, as the pair
|
|
14
|
+
* (endpoint, AI SDK package) that page states per model. Both halves are read
|
|
15
|
+
* and required to agree, because a page that changed shape must stop the run
|
|
16
|
+
* rather than have one half guessed: the wire a model is served on is a routing
|
|
17
|
+
* fact, and the wrong one is a request to the wrong endpoint rather than a
|
|
18
|
+
* clean failure. A row may state its endpoint and no package, with the `-` the
|
|
19
|
+
* page's own tables use for a cell that has no value: that row is read and
|
|
20
|
+
* recorded with no wire, and `deriveService` reports it as a model it will not
|
|
21
|
+
* carry. Losing a column, or carrying a marker that is not `-`, is the page
|
|
22
|
+
* moving and stops the run.
|
|
23
|
+
*
|
|
24
|
+
* Prices come from the same page's per-1M-token table, at the base tier: the
|
|
25
|
+
* unqualified row when a model has one, the "(Off-Peak)" row for the Go
|
|
26
|
+
* DeepSeek entries that publish both, and the "(≤ n tokens)" row when a model
|
|
27
|
+
* is only published as a tier pair. A model with no price row at all must
|
|
28
|
+
* appear in that page's free-model list and is then zero — "no row" is never
|
|
29
|
+
* quietly read as free.
|
|
30
|
+
*
|
|
31
|
+
* Limits, modalities, tool support and effort levels come from the matching
|
|
32
|
+
* provider entry in models.dev. Its `npm` is deliberately NOT used as a route,
|
|
33
|
+
* in either place models.dev states one: the provider-level field names a
|
|
34
|
+
* single Chat-Completions package for both services, which would send the Go
|
|
35
|
+
* Qwen rows — documented on `/messages` — to `/chat/completions`, and the
|
|
36
|
+
* per-model `provider.npm` is stated for fewer than half the documented
|
|
37
|
+
* models, so it cannot route the rest.
|
|
38
|
+
*
|
|
39
|
+
* The two services' own `/models` answers carry `id`, `object`, `created` and
|
|
40
|
+
* `owned_by` and nothing else: they say a model EXISTS and nothing about how to
|
|
41
|
+
* call it. An id served there and documented nowhere cannot be carried, only
|
|
42
|
+
* reported.
|
|
43
|
+
*/
|
|
44
|
+
import type { ModelInputModality, ReasoningEffort } from '@namzu/sdk';
|
|
45
|
+
import type { ZenProtocol, ZenService } from '../models.js';
|
|
46
|
+
/**
|
|
47
|
+
* A source that could not be read, or no longer has the shape these rules
|
|
48
|
+
* parse. Never a curation decision: nothing a caller does to the catalogue
|
|
49
|
+
* clears it, and a refresh that meets one must keep whatever it had before.
|
|
50
|
+
*/
|
|
51
|
+
export declare class ZenCatalogueSourceError extends Error {
|
|
52
|
+
readonly name = "ZenCatalogueSourceError";
|
|
53
|
+
}
|
|
54
|
+
/** Whether `name` is safe to print as it is: no control, format or separator character. */
|
|
55
|
+
export declare function isDisplayableName(name: string): boolean;
|
|
56
|
+
/** A service, its documentation page, and the models.dev provider holding its limits. */
|
|
57
|
+
export declare const ZEN_SERVICES: readonly {
|
|
58
|
+
readonly service: ZenService;
|
|
59
|
+
readonly page: string;
|
|
60
|
+
readonly provider: string;
|
|
61
|
+
}[];
|
|
62
|
+
/**
|
|
63
|
+
* Every (AI SDK package, endpoint) pair a page may state, and the protocol
|
|
64
|
+
* each is. `kind` says how the endpoint names the model: the first three put
|
|
65
|
+
* it in the body of a fixed path, Google puts it in the path itself.
|
|
66
|
+
*/
|
|
67
|
+
export declare const ROUTES: readonly {
|
|
68
|
+
readonly npm: string;
|
|
69
|
+
readonly path: string;
|
|
70
|
+
readonly protocol: ZenProtocol;
|
|
71
|
+
readonly kind: 'path' | 'model';
|
|
72
|
+
}[];
|
|
73
|
+
/** The SDK's input modalities, and the models.dev names that map onto them. */
|
|
74
|
+
export declare const MODALITIES: Readonly<Record<string, ModelInputModality>>;
|
|
75
|
+
/** The service each base host serves, by the path prefix its endpoints carry. */
|
|
76
|
+
export declare const SERVICE_PREFIX: Readonly<Record<ZenService, string>>;
|
|
77
|
+
/** One route-table row. `npm` is undefined when the page states no wire. */
|
|
78
|
+
export interface ZenRouteRow {
|
|
79
|
+
readonly name: string;
|
|
80
|
+
readonly id: string;
|
|
81
|
+
readonly endpoint: string;
|
|
82
|
+
readonly npm: string | undefined;
|
|
83
|
+
}
|
|
84
|
+
/** One price-table row, in USD per million tokens. */
|
|
85
|
+
export interface ZenPriceRow {
|
|
86
|
+
readonly name: string;
|
|
87
|
+
readonly input: number;
|
|
88
|
+
readonly output: number;
|
|
89
|
+
}
|
|
90
|
+
/** A documentation page, split into the three tables the rules read. */
|
|
91
|
+
export interface ZenParsedPage {
|
|
92
|
+
readonly routes: readonly ZenRouteRow[];
|
|
93
|
+
readonly prices: readonly ZenPriceRow[];
|
|
94
|
+
readonly freeNames: readonly string[];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* One `/models` answer, as the set of ids it says the service serves.
|
|
98
|
+
*
|
|
99
|
+
* The shape is asserted rather than assumed, and an answer with no ids in it is
|
|
100
|
+
* refused: a service that returns nothing is a source that moved, and reading
|
|
101
|
+
* it as "nothing is served" would turn an outage into an empty roster.
|
|
102
|
+
*/
|
|
103
|
+
export declare function parseServed(service: string, text: string): Set<string>;
|
|
104
|
+
/**
|
|
105
|
+
* Whether a line looks like a row of the route table.
|
|
106
|
+
*
|
|
107
|
+
* The account has to CLOSE, not merely to be attempted: a line shaped like a
|
|
108
|
+
* route row that the route pattern did not capture is a page these rules no
|
|
109
|
+
* longer read correctly, and dropping it silently is the defect the whole
|
|
110
|
+
* arrangement exists to remove. Two shapes count, both measured against the
|
|
111
|
+
* live pages:
|
|
112
|
+
*
|
|
113
|
+
* - two or more backticked cells, which is a row carrying both its endpoint
|
|
114
|
+
* and its package;
|
|
115
|
+
* - three or more cells with at least one backticked cell, which is a row that
|
|
116
|
+
* kept a value and lost a column: an empty package cell leaves four cells,
|
|
117
|
+
* and a row whose package COLUMN is gone leaves three.
|
|
118
|
+
*
|
|
119
|
+
* The backtick guard keeps the wider rule off table separators
|
|
120
|
+
* (`| --- | --- | --- | --- |` carries no code span), and a prose row that
|
|
121
|
+
* quotes a code span has two cells.
|
|
122
|
+
*/
|
|
123
|
+
export declare function isRouteRowShaped(line: string): boolean;
|
|
124
|
+
/** A documentation page, split into the three tables the rules read. */
|
|
125
|
+
export declare function parsePage(text: string, { page, service }: {
|
|
126
|
+
readonly page: string;
|
|
127
|
+
readonly service: string;
|
|
128
|
+
}): ZenParsedPage;
|
|
129
|
+
/**
|
|
130
|
+
* A price cell, or undefined when the cell is not a price.
|
|
131
|
+
*
|
|
132
|
+
* Go states its free models' rate as the word "Free" rather than as `$0.00`,
|
|
133
|
+
* which is a statement about the price and not a missing one, so it is read as
|
|
134
|
+
* zero.
|
|
135
|
+
*/
|
|
136
|
+
export declare function priceCell(cell: string): number | undefined;
|
|
137
|
+
/** Model names are matched across tables by their letters, digits and dots. */
|
|
138
|
+
export declare function nameKey(name: string): string;
|
|
139
|
+
/**
|
|
140
|
+
* The base-tier price row for a model: the unqualified row, the "(≤ …)" row of
|
|
141
|
+
* a tier pair, or the "(Off-Peak)" row of a peak/off-peak pair.
|
|
142
|
+
*/
|
|
143
|
+
export declare function priceRowFor(rows: readonly ZenPriceRow[], name: string): ZenPriceRow | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* The protocol a (package, endpoint) pair is, refusing anything unrecognised.
|
|
146
|
+
*
|
|
147
|
+
* The pair is checked against the URL's own parts rather than by substring: a
|
|
148
|
+
* cell reading `https://evil.example/messages` contains the path a Messages
|
|
149
|
+
* route has, and a routing decision that accepts it is a routing decision made
|
|
150
|
+
* on the wrong string. Host, service prefix, path and package must all agree.
|
|
151
|
+
*/
|
|
152
|
+
export declare function protocolFor({ id, endpoint, npm }: Pick<ZenRouteRow, 'id' | 'endpoint' | 'npm'>, service: string): ZenProtocol;
|
|
153
|
+
/** A models.dev provider entry: its models, keyed by id. */
|
|
154
|
+
export interface ModelsDevProvider {
|
|
155
|
+
readonly models: Readonly<Record<string, unknown>>;
|
|
156
|
+
}
|
|
157
|
+
/** One model a service's derivation carries, before it becomes a `ZenModel`. */
|
|
158
|
+
export interface DerivedZenModel {
|
|
159
|
+
readonly id: string;
|
|
160
|
+
readonly name: string;
|
|
161
|
+
readonly protocol: ZenProtocol;
|
|
162
|
+
readonly contextWindow: number;
|
|
163
|
+
readonly maxOutputTokens: number;
|
|
164
|
+
readonly inputModalities: ModelInputModality[];
|
|
165
|
+
readonly inputPrice: number;
|
|
166
|
+
readonly outputPrice: number;
|
|
167
|
+
readonly supportsToolUse: boolean;
|
|
168
|
+
readonly effortLevels: ReasoningEffort[];
|
|
169
|
+
readonly supportsAnonymousAccess: boolean;
|
|
170
|
+
}
|
|
171
|
+
/** Everything one service's derivation produced, carried and not. */
|
|
172
|
+
export interface DerivedZenService {
|
|
173
|
+
readonly models: DerivedZenModel[];
|
|
174
|
+
/** `[service/id, why]`: documented models it did not carry and nothing omits. */
|
|
175
|
+
readonly undecided: [string, string][];
|
|
176
|
+
/** Omitted ids upstream neither documents nor serves any more. */
|
|
177
|
+
readonly stale: string[];
|
|
178
|
+
/** Price rows no route row names. */
|
|
179
|
+
readonly orphanPrices: string[];
|
|
180
|
+
/** Ids the service serves that its page does not document and nothing omits. */
|
|
181
|
+
readonly servedUncurried: string[];
|
|
182
|
+
}
|
|
183
|
+
/** Omission decisions, as the review file's record or as a set of `service/id` keys. */
|
|
184
|
+
export type ZenOmissions = Readonly<Record<string, string>> | ReadonlySet<string>;
|
|
185
|
+
/**
|
|
186
|
+
* One service's carried models, plus everything either source names and the
|
|
187
|
+
* catalogue does not carry.
|
|
188
|
+
*
|
|
189
|
+
* `served` is the set of ids the service's own `/models` answer carries, and it
|
|
190
|
+
* is required rather than defaulted: a caller that forgot it would turn the
|
|
191
|
+
* served dimension off silently.
|
|
192
|
+
*/
|
|
193
|
+
export declare function derive(service: string, parsed: ZenParsedPage, providerKey: string, provider: ModelsDevProvider, omissions: ZenOmissions, served: ReadonlySet<string>): DerivedZenService;
|
|
194
|
+
/**
|
|
195
|
+
* Refuse a roster that collapsed.
|
|
196
|
+
*
|
|
197
|
+
* A roster that came out empty, or that lost a fifth of what the baseline
|
|
198
|
+
* carries, is a source that moved far more often than a decision anybody made,
|
|
199
|
+
* and both look identical to a successful run from the inside.
|
|
200
|
+
*/
|
|
201
|
+
export declare const ROSTER_FLOOR = 0.8;
|
|
202
|
+
export declare function checkRosterFloor(built: Readonly<Record<ZenService, readonly unknown[]>>, committed: Readonly<Record<ZenService, readonly unknown[]>>): void;
|
|
203
|
+
//# sourceMappingURL=derive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../src/catalogue/derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAErE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE3D;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,SAAkB,IAAI,6BAA4B;CAClD;AAkBD,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAYD,yFAAyF;AACzF,eAAO,MAAM,YAAY,EAAE,SAAS;IACnC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACzB,EAGC,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,SAAS;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC/B,EAKC,CAAA;AAKF,+EAA+E;AAC/E,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAIlE,CAAA;AAEF,iFAAiF;AACjF,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAG9D,CAAA;AAEF,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAChC;AAED,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACvB;AAED,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;IACvC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAgCtE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAItD;AAED,wEAAwE;AACxE,wBAAgB,SAAS,CACxB,IAAI,EAAE,MAAM,EACZ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpE,aAAa,CA4Ff;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM1D;AAED,+EAA+E;AAC/E,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAQ/F;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAC1B,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,UAAU,GAAG,KAAK,CAAC,EACnE,OAAO,EAAE,MAAM,GACb,WAAW,CA8Bb;AAUD,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAClD;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,eAAe,EAAE,kBAAkB,EAAE,CAAA;IAC9C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,YAAY,EAAE,eAAe,EAAE,CAAA;IACxC,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAA;CACzC;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAA;IAClC,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;IACtC,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;IACxB,qCAAqC;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAA;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAA;CAClC;AAED,wFAAwF;AACxF,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;AAMjF;;;;;;;GAOG;AACH,wBAAgB,MAAM,CACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,YAAY,EACvB,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,GACzB,iBAAiB,CAwHnB;AA8BD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,MAAM,CAAA;AAE/B,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,EACvD,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,GACzD,IAAI,CAeN"}
|