sitelooper 0.3.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 +625 -0
- package/bin/sitelooper.js +6 -0
- package/dist/agent/llm.js +460 -0
- package/dist/agent/llm.js.map +1 -0
- package/dist/agent/loop.js +870 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/prompt.js +40 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/report.js +545 -0
- package/dist/agent/report.js.map +1 -0
- package/dist/agent/tools.js +1147 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/cli.js +1692 -0
- package/dist/cli.js.map +1 -0
- package/dist/daemon/browser.js +218 -0
- package/dist/daemon/browser.js.map +1 -0
- package/dist/daemon/codegen.js +241 -0
- package/dist/daemon/codegen.js.map +1 -0
- package/dist/daemon/dialogs.js +57 -0
- package/dist/daemon/dialogs.js.map +1 -0
- package/dist/daemon/diff.js +198 -0
- package/dist/daemon/diff.js.map +1 -0
- package/dist/daemon/fingerprint.js +98 -0
- package/dist/daemon/fingerprint.js.map +1 -0
- package/dist/daemon/inputs.js +134 -0
- package/dist/daemon/inputs.js.map +1 -0
- package/dist/daemon/recorder.js +1232 -0
- package/dist/daemon/recorder.js.map +1 -0
- package/dist/daemon/refs.js +194 -0
- package/dist/daemon/refs.js.map +1 -0
- package/dist/daemon/server.js +1724 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/state.js +239 -0
- package/dist/daemon/state.js.map +1 -0
- package/dist/doctor.js +90 -0
- package/dist/doctor.js.map +1 -0
- package/dist/shared/paths.js +80 -0
- package/dist/shared/paths.js.map +1 -0
- package/dist/shared/protocol.js +28 -0
- package/dist/shared/protocol.js.map +1 -0
- package/dist/shared/secrets.js +92 -0
- package/dist/shared/secrets.js.map +1 -0
- package/dist/shared/text.js +39 -0
- package/dist/shared/text.js.map +1 -0
- package/dist/skills/compile.js +1420 -0
- package/dist/skills/compile.js.map +1 -0
- package/dist/skills/components.js +456 -0
- package/dist/skills/components.js.map +1 -0
- package/dist/skills/flow.js +1041 -0
- package/dist/skills/flow.js.map +1 -0
- package/dist/skills/learn.js +406 -0
- package/dist/skills/learn.js.map +1 -0
- package/dist/skills/ledger.js +304 -0
- package/dist/skills/ledger.js.map +1 -0
- package/dist/skills/relabel.js +206 -0
- package/dist/skills/relabel.js.map +1 -0
- package/dist/skills/repair.js +570 -0
- package/dist/skills/repair.js.map +1 -0
- package/dist/skills/replay.js +1281 -0
- package/dist/skills/replay.js.map +1 -0
- package/dist/skills/store.js +147 -0
- package/dist/skills/store.js.map +1 -0
- package/dist/spec/check.js +428 -0
- package/dist/spec/check.js.map +1 -0
- package/dist/spec/diagnostics.js +58 -0
- package/dist/spec/diagnostics.js.map +1 -0
- package/dist/spec/emit.js +2084 -0
- package/dist/spec/emit.js.map +1 -0
- package/dist/spec/index.js +62 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/spec/ir.js +216 -0
- package/dist/spec/ir.js.map +1 -0
- package/dist/spec/lift.js +162 -0
- package/dist/spec/lift.js.map +1 -0
- package/dist/spec/locators.js +270 -0
- package/dist/spec/locators.js.map +1 -0
- package/dist/spec/lower.js +124 -0
- package/dist/spec/lower.js.map +1 -0
- package/dist/spec/repair.js +657 -0
- package/dist/spec/repair.js.map +1 -0
- package/dist/spec/rerecord.js +169 -0
- package/dist/spec/rerecord.js.map +1 -0
- package/dist/spec/rethread.js +120 -0
- package/dist/spec/rethread.js.map +1 -0
- package/package.json +50 -0
- package/skills/sitelooper/SKILL.md +228 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider adapter (thin, swappable). One implementation — OpenAI-compatible
|
|
3
|
+
* chat completions — parameterised by named presets (zhipu, novita, openai,
|
|
4
|
+
* openrouter) or a fully custom base URL. Endpoint/model ids drift; every
|
|
5
|
+
* preset value is overridable by config file, env, or flag, so doc drift is
|
|
6
|
+
* a config change, not a code change.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { rootDir } from '../shared/paths.js';
|
|
11
|
+
export const PROVIDER_PRESETS = {
|
|
12
|
+
// Z.ai international endpoint; mainland alternative: https://open.bigmodel.cn/api/paas/v4
|
|
13
|
+
// (Coding Plan subscriptions use /api/coding/paas/v4 instead.)
|
|
14
|
+
zhipu: {
|
|
15
|
+
baseUrl: 'https://api.z.ai/api/paas/v4',
|
|
16
|
+
defaultModel: 'glm-5.2',
|
|
17
|
+
keyEnvVars: ['GLM_API_KEY', 'ZHIPU_API_KEY'],
|
|
18
|
+
},
|
|
19
|
+
// Model picks are benchmarked, not guessed: deepseek-v4-flash drove the real
|
|
20
|
+
// agent loop ~2x faster and ~12x cheaper than glm-5.2 at the same pass rate,
|
|
21
|
+
// and glm-5.3 solved the hardest probe in the fewest turns of anything tried
|
|
22
|
+
// (at glm-5.2's list price), which is what you want on the escalation path.
|
|
23
|
+
novita: {
|
|
24
|
+
baseUrl: 'https://api.novita.ai/openai',
|
|
25
|
+
defaultModel: 'deepseek/deepseek-v4-flash',
|
|
26
|
+
fallbackModel: 'zai-org/glm-5.3',
|
|
27
|
+
keyEnvVars: ['NOVITA_API_KEY'],
|
|
28
|
+
},
|
|
29
|
+
openrouter: {
|
|
30
|
+
baseUrl: 'https://openrouter.ai/api/v1',
|
|
31
|
+
defaultModel: 'z-ai/glm-5.2',
|
|
32
|
+
keyEnvVars: ['OPENROUTER_API_KEY'],
|
|
33
|
+
},
|
|
34
|
+
openai: {
|
|
35
|
+
baseUrl: 'https://api.openai.com/v1',
|
|
36
|
+
defaultModel: 'gpt-5-mini',
|
|
37
|
+
keyEnvVars: ['OPENAI_API_KEY'],
|
|
38
|
+
},
|
|
39
|
+
// Not OpenAI-compatible — see AnthropicProvider. A stronger, pricier fallback
|
|
40
|
+
// tier: useful for escalating specific instructions that a cheaper model
|
|
41
|
+
// couldn't complete, without paying Anthropic prices for the whole session.
|
|
42
|
+
anthropic: {
|
|
43
|
+
baseUrl: 'https://api.anthropic.com',
|
|
44
|
+
defaultModel: 'claude-sonnet-5',
|
|
45
|
+
keyEnvVars: ['ANTHROPIC_API_KEY'],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
export const DEFAULT_PROVIDER = 'zhipu';
|
|
49
|
+
const CONFIG_KEYS = ['provider', 'model', 'fallbackModel', 'baseUrl', 'apiKey'];
|
|
50
|
+
export function globalConfigPath() {
|
|
51
|
+
return path.join(rootDir(), 'config.json');
|
|
52
|
+
}
|
|
53
|
+
export function readGlobalConfig() {
|
|
54
|
+
try {
|
|
55
|
+
const raw = JSON.parse(fs.readFileSync(globalConfigPath(), 'utf8'));
|
|
56
|
+
const out = {};
|
|
57
|
+
for (const key of CONFIG_KEYS) {
|
|
58
|
+
if (typeof raw[key] === 'string' && raw[key])
|
|
59
|
+
out[key] = raw[key];
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function writeGlobalConfig(updates) {
|
|
68
|
+
for (const key of Object.keys(updates)) {
|
|
69
|
+
if (!CONFIG_KEYS.includes(key)) {
|
|
70
|
+
throw new Error(`unknown config key "${key}" (allowed: ${CONFIG_KEYS.join(', ')})`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const merged = { ...readGlobalConfig(), ...updates };
|
|
74
|
+
for (const key of CONFIG_KEYS) {
|
|
75
|
+
if (merged[key] === '')
|
|
76
|
+
delete merged[key]; // setting to "" clears a key
|
|
77
|
+
}
|
|
78
|
+
fs.mkdirSync(rootDir(), { recursive: true });
|
|
79
|
+
fs.writeFileSync(globalConfigPath(), JSON.stringify(merged, null, 2));
|
|
80
|
+
return merged;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Precedence per field: explicit override (flag) > env > global config file >
|
|
84
|
+
* provider preset. The preset is chosen the same way, then supplies defaults
|
|
85
|
+
* for whatever remains unset.
|
|
86
|
+
*/
|
|
87
|
+
export function resolveProviderConfig(overrides = {}) {
|
|
88
|
+
const file = readGlobalConfig();
|
|
89
|
+
const provider = overrides.provider || process.env.SITELOOPER_PROVIDER || file.provider || DEFAULT_PROVIDER;
|
|
90
|
+
const preset = PROVIDER_PRESETS[provider];
|
|
91
|
+
if (!preset) {
|
|
92
|
+
throw new Error(`unknown provider "${provider}" (available: ${Object.keys(PROVIDER_PRESETS).join(', ')}; ` +
|
|
93
|
+
`or use any OpenAI-compatible endpoint via SITELOOPER_BASE_URL / config set baseUrl)`);
|
|
94
|
+
}
|
|
95
|
+
const keyEnvVars = [...preset.keyEnvVars, 'SITELOOPER_API_KEY'];
|
|
96
|
+
const apiKey = overrides.apiKey ||
|
|
97
|
+
keyEnvVars.map((v) => process.env[v]).find(Boolean) ||
|
|
98
|
+
file.apiKey ||
|
|
99
|
+
'';
|
|
100
|
+
return {
|
|
101
|
+
provider,
|
|
102
|
+
baseUrl: overrides.baseUrl || process.env.SITELOOPER_BASE_URL || file.baseUrl || preset.baseUrl,
|
|
103
|
+
model: overrides.model || process.env.SITELOOPER_MODEL || file.model || preset.defaultModel,
|
|
104
|
+
// "none"/"off" is how a caller disables a preset's escalation tier without
|
|
105
|
+
// having to clear a config key it never set.
|
|
106
|
+
fallbackModel: normalizeFallback(overrides.fallbackModel ||
|
|
107
|
+
process.env.SITELOOPER_FALLBACK_MODEL ||
|
|
108
|
+
file.fallbackModel ||
|
|
109
|
+
preset.fallbackModel),
|
|
110
|
+
apiKey,
|
|
111
|
+
temperature: overrides.temperature ?? 0,
|
|
112
|
+
extraBody: parseExtraBody(process.env.SITELOOPER_EXTRA_BODY, 'SITELOOPER_EXTRA_BODY'),
|
|
113
|
+
fallbackExtraBody: parseExtraBody(process.env.SITELOOPER_FALLBACK_EXTRA_BODY, 'SITELOOPER_FALLBACK_EXTRA_BODY'),
|
|
114
|
+
keyEnvVars,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function parseExtraBody(raw, envVar) {
|
|
118
|
+
if (!raw || !raw.trim())
|
|
119
|
+
return undefined;
|
|
120
|
+
try {
|
|
121
|
+
const parsed = JSON.parse(raw);
|
|
122
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
123
|
+
return parsed;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// fall through to the throw below
|
|
128
|
+
}
|
|
129
|
+
// A malformed value silently ignored would defeat the point of setting it:
|
|
130
|
+
// the caller believes a routing pin is in force when it is not.
|
|
131
|
+
throw new Error(`${envVar} must be a JSON object`);
|
|
132
|
+
}
|
|
133
|
+
function normalizeFallback(value) {
|
|
134
|
+
if (!value)
|
|
135
|
+
return undefined;
|
|
136
|
+
const trimmed = value.trim();
|
|
137
|
+
if (!trimmed || /^(none|off|false)$/i.test(trimmed))
|
|
138
|
+
return undefined;
|
|
139
|
+
return trimmed;
|
|
140
|
+
}
|
|
141
|
+
export class OpenAICompatProvider {
|
|
142
|
+
config;
|
|
143
|
+
model;
|
|
144
|
+
constructor(config) {
|
|
145
|
+
this.config = config;
|
|
146
|
+
this.model = config.model;
|
|
147
|
+
}
|
|
148
|
+
async complete(messages, tools, opts = {}) {
|
|
149
|
+
if (!this.config.apiKey) {
|
|
150
|
+
throw new Error(`no API key for provider "${this.config.provider}": set ${this.config.keyEnvVars.join(' or ')} ` +
|
|
151
|
+
`(or \`sitelooper config set apiKey <key>\`)`);
|
|
152
|
+
}
|
|
153
|
+
const body = {
|
|
154
|
+
model: this.config.model,
|
|
155
|
+
temperature: this.config.temperature,
|
|
156
|
+
messages,
|
|
157
|
+
tools: tools.map((t) => ({
|
|
158
|
+
type: 'function',
|
|
159
|
+
function: { name: t.name, description: t.description, parameters: t.parameters },
|
|
160
|
+
})),
|
|
161
|
+
tool_choice: 'auto',
|
|
162
|
+
// See CompleteOptions.effort — openrouter-only by design.
|
|
163
|
+
...(opts.effort && this.config.provider === 'openrouter' ? { reasoning: { effort: opts.effort } } : {}),
|
|
164
|
+
// Spread last on purpose: extraBody is the caller's explicit override
|
|
165
|
+
// channel (see ProviderConfig.extraBody) and must win over defaults.
|
|
166
|
+
...this.config.extraBody,
|
|
167
|
+
};
|
|
168
|
+
const url = this.config.baseUrl.replace(/\/$/, '') + '/chat/completions';
|
|
169
|
+
let lastErr = null;
|
|
170
|
+
for (let attempt = 0; attempt < MAX_LLM_ATTEMPTS; attempt++) {
|
|
171
|
+
if (opts.signal?.aborted)
|
|
172
|
+
throw new Error('LLM request aborted');
|
|
173
|
+
try {
|
|
174
|
+
const res = await fetch(url, {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
headers: {
|
|
177
|
+
'content-type': 'application/json',
|
|
178
|
+
authorization: `Bearer ${this.config.apiKey}`,
|
|
179
|
+
},
|
|
180
|
+
body: JSON.stringify(body),
|
|
181
|
+
signal: opts.signal,
|
|
182
|
+
});
|
|
183
|
+
if (res.status === 429 || res.status >= 500) {
|
|
184
|
+
lastErr = new Error(`LLM HTTP ${res.status}: ${(await res.text()).slice(0, 300)}`);
|
|
185
|
+
// A 429 against a per-minute cap needs minute-scale patience, not
|
|
186
|
+
// seconds: flow-replay recovery fires requests far faster than the
|
|
187
|
+
// interactive loop and killed whole flowruns on OpenRouter's
|
|
188
|
+
// 20 rpm tier (fwgr2-n2/n3). Honor the server's own hint first.
|
|
189
|
+
await sleep(retryDelayMs(res, attempt), opts.signal);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (!res.ok) {
|
|
193
|
+
throw new Error(`LLM HTTP ${res.status}: ${(await res.text()).slice(0, 500)}`);
|
|
194
|
+
}
|
|
195
|
+
return parseCompletion((await res.json()));
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
// An abort is a decision, not a transport failure — never retry it.
|
|
199
|
+
if (opts.signal?.aborted)
|
|
200
|
+
throw new Error('LLM request aborted');
|
|
201
|
+
if (err instanceof Error && err.message.startsWith('LLM HTTP 4'))
|
|
202
|
+
throw err;
|
|
203
|
+
lastErr = err;
|
|
204
|
+
await sleep(1000 * (attempt + 1), opts.signal);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
throw lastErr ?? new Error('LLM request failed');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function parseCompletion(json) {
|
|
211
|
+
const choice = json.choices?.[0];
|
|
212
|
+
const msg = choice?.message;
|
|
213
|
+
if (!msg)
|
|
214
|
+
throw new Error(`LLM returned no choices: ${JSON.stringify(json).slice(0, 300)}`);
|
|
215
|
+
const rawCalls = (msg.tool_calls ?? []).filter((c) => c?.function?.name);
|
|
216
|
+
const toolCalls = rawCalls.map((c, i) => {
|
|
217
|
+
let args = null;
|
|
218
|
+
try {
|
|
219
|
+
args = c.function.arguments ? JSON.parse(c.function.arguments) : {};
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
args = null;
|
|
223
|
+
}
|
|
224
|
+
return { id: c.id || `call_${i}`, name: c.function.name, args, rawArgs: c.function.arguments ?? '' };
|
|
225
|
+
});
|
|
226
|
+
const assistantMessage = {
|
|
227
|
+
role: 'assistant',
|
|
228
|
+
content: msg.content ?? null,
|
|
229
|
+
...(rawCalls.length
|
|
230
|
+
? {
|
|
231
|
+
tool_calls: rawCalls.map((c, i) => ({
|
|
232
|
+
id: c.id || `call_${i}`,
|
|
233
|
+
type: 'function',
|
|
234
|
+
function: { name: c.function.name, arguments: c.function.arguments ?? '' },
|
|
235
|
+
})),
|
|
236
|
+
}
|
|
237
|
+
: {}),
|
|
238
|
+
};
|
|
239
|
+
return {
|
|
240
|
+
text: msg.content ?? null,
|
|
241
|
+
toolCalls,
|
|
242
|
+
assistantMessage,
|
|
243
|
+
usage: {
|
|
244
|
+
promptTokens: json.usage?.prompt_tokens ?? 0,
|
|
245
|
+
completionTokens: json.usage?.completion_tokens ?? 0,
|
|
246
|
+
// Both OpenAI and z.ai/novita nest the cache hit here; absent → 0.
|
|
247
|
+
cachedTokens: json.usage?.prompt_tokens_details?.cached_tokens ?? 0,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Anthropic Messages API adapter. A genuinely different wire format from the
|
|
253
|
+
* OpenAI-compatible providers above (system is a top-level field, not a
|
|
254
|
+
* message; tool calls/results are typed content blocks, not a role:'tool'
|
|
255
|
+
* message; usage splits fresh vs. cache-write vs. cache-read tokens instead
|
|
256
|
+
* of reporting one total with a cached subset) — so this translates rather
|
|
257
|
+
* than reusing OpenAICompatProvider. No SDK dependency: same thin-fetch style
|
|
258
|
+
* as the rest of this file.
|
|
259
|
+
*/
|
|
260
|
+
export class AnthropicProvider {
|
|
261
|
+
config;
|
|
262
|
+
model;
|
|
263
|
+
baseUrl;
|
|
264
|
+
constructor(config) {
|
|
265
|
+
this.config = config;
|
|
266
|
+
this.model = config.model;
|
|
267
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, '');
|
|
268
|
+
}
|
|
269
|
+
async complete(messages, tools, opts = {}) {
|
|
270
|
+
if (!this.config.apiKey) {
|
|
271
|
+
throw new Error(`no API key for provider "${this.config.provider}": set ${this.config.keyEnvVars.join(' or ')} ` +
|
|
272
|
+
`(or \`sitelooper config set apiKey <key>\`)`);
|
|
273
|
+
}
|
|
274
|
+
const system = messages
|
|
275
|
+
.filter((m) => m.role === 'system')
|
|
276
|
+
.map((m) => m.content)
|
|
277
|
+
.join('\n\n');
|
|
278
|
+
const anthMessages = toAnthropicMessages(messages.filter((m) => m.role !== 'system'));
|
|
279
|
+
// Prompt caching: unlike the OpenAI-compatible providers above (which cache
|
|
280
|
+
// automatically server-side), Anthropic only caches up to an explicit
|
|
281
|
+
// cache_control breakpoint. Without one, every turn re-bills the entire
|
|
282
|
+
// growing conversation at full price. Two breakpoints: the system prompt
|
|
283
|
+
// (large, stable across the whole session) and the last content block of
|
|
284
|
+
// the latest message (so each turn's identical prefix — everything before
|
|
285
|
+
// this turn's new content — hits cache on the next call).
|
|
286
|
+
const lastMsg = anthMessages[anthMessages.length - 1];
|
|
287
|
+
const lastBlock = lastMsg?.content[lastMsg.content.length - 1];
|
|
288
|
+
if (lastBlock)
|
|
289
|
+
lastBlock.cache_control = { type: 'ephemeral' };
|
|
290
|
+
const body = {
|
|
291
|
+
model: this.config.model,
|
|
292
|
+
max_tokens: 8192,
|
|
293
|
+
...(system ? { system: [{ type: 'text', text: system, cache_control: { type: 'ephemeral' } }] } : {}),
|
|
294
|
+
messages: anthMessages,
|
|
295
|
+
tools: tools.map((t) => ({ name: t.name, description: t.description, input_schema: t.parameters })),
|
|
296
|
+
tool_choice: { type: 'auto' },
|
|
297
|
+
};
|
|
298
|
+
let lastErr = null;
|
|
299
|
+
for (let attempt = 0; attempt < MAX_LLM_ATTEMPTS; attempt++) {
|
|
300
|
+
if (opts.signal?.aborted)
|
|
301
|
+
throw new Error('LLM request aborted');
|
|
302
|
+
try {
|
|
303
|
+
const res = await fetch(`${this.baseUrl}/v1/messages`, {
|
|
304
|
+
method: 'POST',
|
|
305
|
+
headers: {
|
|
306
|
+
'content-type': 'application/json',
|
|
307
|
+
'x-api-key': this.config.apiKey,
|
|
308
|
+
'anthropic-version': '2023-06-01',
|
|
309
|
+
},
|
|
310
|
+
body: JSON.stringify(body),
|
|
311
|
+
signal: opts.signal,
|
|
312
|
+
});
|
|
313
|
+
if (res.status === 429 || res.status >= 500) {
|
|
314
|
+
lastErr = new Error(`LLM HTTP ${res.status}: ${(await res.text()).slice(0, 300)}`);
|
|
315
|
+
await sleep(retryDelayMs(res, attempt), opts.signal);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
if (!res.ok) {
|
|
319
|
+
throw new Error(`LLM HTTP ${res.status}: ${(await res.text()).slice(0, 500)}`);
|
|
320
|
+
}
|
|
321
|
+
return parseAnthropicCompletion((await res.json()));
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
if (opts.signal?.aborted)
|
|
325
|
+
throw new Error('LLM request aborted');
|
|
326
|
+
if (err instanceof Error && err.message.startsWith('LLM HTTP 4'))
|
|
327
|
+
throw err;
|
|
328
|
+
lastErr = err;
|
|
329
|
+
await sleep(1000 * (attempt + 1), opts.signal);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
throw lastErr ?? new Error('LLM request failed');
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Our internal history is OpenAI-shaped (role:'tool' per call, tool_calls on
|
|
337
|
+
* the assistant message). Anthropic instead wants tool_use/tool_result as
|
|
338
|
+
* typed content blocks, with all of one assistant turn's tool_results merged
|
|
339
|
+
* into a single following user message — so consecutive role:'tool' entries
|
|
340
|
+
* (one per call in that turn) are collapsed here rather than sent as
|
|
341
|
+
* separate messages.
|
|
342
|
+
*/
|
|
343
|
+
function toAnthropicMessages(messages) {
|
|
344
|
+
const out = [];
|
|
345
|
+
for (const m of messages) {
|
|
346
|
+
if (m.role === 'tool') {
|
|
347
|
+
const block = { type: 'tool_result', tool_use_id: m.tool_call_id, content: m.content };
|
|
348
|
+
const prev = out[out.length - 1];
|
|
349
|
+
if (prev && prev.role === 'user' && prev.content.every((b) => b.type === 'tool_result')) {
|
|
350
|
+
prev.content.push(block);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
out.push({ role: 'user', content: [block] });
|
|
354
|
+
}
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (m.role === 'user') {
|
|
358
|
+
out.push({ role: 'user', content: [{ type: 'text', text: m.content }] });
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (m.role !== 'assistant')
|
|
362
|
+
continue; // 'system' — caller already strips these; defensive only
|
|
363
|
+
const content = [];
|
|
364
|
+
if (m.content)
|
|
365
|
+
content.push({ type: 'text', text: m.content });
|
|
366
|
+
for (const tc of m.tool_calls ?? []) {
|
|
367
|
+
let input = {};
|
|
368
|
+
try {
|
|
369
|
+
input = tc.function.arguments ? JSON.parse(tc.function.arguments) : {};
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
/* malformed args — send empty input rather than fail the whole request */
|
|
373
|
+
}
|
|
374
|
+
content.push({ type: 'tool_use', id: tc.id, name: tc.function.name, input });
|
|
375
|
+
}
|
|
376
|
+
// An empty assistant turn (a reasoning model that emitted only reasoning)
|
|
377
|
+
// is a 400 on this API; keep the turn so the tool/user pairing holds.
|
|
378
|
+
if (!content.length)
|
|
379
|
+
content.push({ type: 'text', text: '(no output)' });
|
|
380
|
+
out.push({ role: 'assistant', content });
|
|
381
|
+
}
|
|
382
|
+
return out;
|
|
383
|
+
}
|
|
384
|
+
function parseAnthropicCompletion(json) {
|
|
385
|
+
const blocks = json.content ?? [];
|
|
386
|
+
if (!blocks.length && !json.usage) {
|
|
387
|
+
throw new Error(`LLM returned no content: ${JSON.stringify(json).slice(0, 300)}`);
|
|
388
|
+
}
|
|
389
|
+
const textBlocks = blocks.filter((b) => b.type === 'text');
|
|
390
|
+
const toolUseBlocks = blocks.filter((b) => b.type === 'tool_use');
|
|
391
|
+
const text = textBlocks.length ? textBlocks.map((b) => b.text).join('\n') : null;
|
|
392
|
+
const toolCalls = toolUseBlocks.map((b) => ({
|
|
393
|
+
id: b.id,
|
|
394
|
+
name: b.name,
|
|
395
|
+
args: (b.input ?? {}),
|
|
396
|
+
rawArgs: JSON.stringify(b.input ?? {}),
|
|
397
|
+
}));
|
|
398
|
+
const assistantMessage = {
|
|
399
|
+
role: 'assistant',
|
|
400
|
+
content: text,
|
|
401
|
+
...(toolUseBlocks.length
|
|
402
|
+
? {
|
|
403
|
+
tool_calls: toolUseBlocks.map((b) => ({
|
|
404
|
+
id: b.id,
|
|
405
|
+
type: 'function',
|
|
406
|
+
function: { name: b.name, arguments: JSON.stringify(b.input ?? {}) },
|
|
407
|
+
})),
|
|
408
|
+
}
|
|
409
|
+
: {}),
|
|
410
|
+
};
|
|
411
|
+
const u = json.usage ?? {};
|
|
412
|
+
return {
|
|
413
|
+
text,
|
|
414
|
+
toolCalls,
|
|
415
|
+
assistantMessage,
|
|
416
|
+
usage: {
|
|
417
|
+
// Our Usage.promptTokens is documented as the TOTAL prompt (OpenAI
|
|
418
|
+
// convention); Anthropic's input_tokens is only the fresh portion, so
|
|
419
|
+
// fold cache writes/reads back in to keep that contract, and surface
|
|
420
|
+
// reads (the cheap-billed subset) as cachedTokens same as the other
|
|
421
|
+
// providers.
|
|
422
|
+
promptTokens: (u.input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0),
|
|
423
|
+
completionTokens: u.output_tokens ?? 0,
|
|
424
|
+
cachedTokens: u.cache_read_input_tokens ?? 0,
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
/** Backoff sleep that gives up early if the request is aborted mid-wait. */
|
|
429
|
+
const MAX_LLM_ATTEMPTS = 5;
|
|
430
|
+
/**
|
|
431
|
+
* How long to wait before retrying a 429/5xx. The server's own hint wins
|
|
432
|
+
* (Retry-After seconds, or an X-RateLimit-Reset epoch-ms as OpenRouter
|
|
433
|
+
* sends); otherwise escalate on a scale that can outlast a per-MINUTE rate
|
|
434
|
+
* cap rather than a transient blip. Capped so a bad header cannot wedge a
|
|
435
|
+
* turn for longer than the caller's own deadlines.
|
|
436
|
+
*/
|
|
437
|
+
function retryDelayMs(res, attempt) {
|
|
438
|
+
const cap = 65_000;
|
|
439
|
+
const retryAfter = Number(res.headers.get('retry-after'));
|
|
440
|
+
if (Number.isFinite(retryAfter) && retryAfter > 0)
|
|
441
|
+
return Math.min(retryAfter * 1000, cap);
|
|
442
|
+
const reset = Number(res.headers.get('x-ratelimit-reset'));
|
|
443
|
+
if (Number.isFinite(reset) && reset > Date.now())
|
|
444
|
+
return Math.min(reset - Date.now() + 500, cap);
|
|
445
|
+
if (res.status === 429)
|
|
446
|
+
return Math.min(5_000 * 2 ** attempt, cap);
|
|
447
|
+
return 1_000 * (attempt + 1);
|
|
448
|
+
}
|
|
449
|
+
function sleep(ms, signal) {
|
|
450
|
+
return new Promise((resolve) => {
|
|
451
|
+
const timer = setTimeout(done, ms);
|
|
452
|
+
function done() {
|
|
453
|
+
clearTimeout(timer);
|
|
454
|
+
signal?.removeEventListener('abort', done);
|
|
455
|
+
resolve();
|
|
456
|
+
}
|
|
457
|
+
signal?.addEventListener('abort', done, { once: true });
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/agent/llm.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAwH7C,MAAM,CAAC,MAAM,gBAAgB,GAAmC;IAC9D,0FAA0F;IAC1F,+DAA+D;IAC/D,KAAK,EAAE;QACL,OAAO,EAAE,8BAA8B;QACvC,YAAY,EAAE,SAAS;QACvB,UAAU,EAAE,CAAC,aAAa,EAAE,eAAe,CAAC;KAC7C;IACD,6EAA6E;IAC7E,6EAA6E;IAC7E,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,EAAE;QACN,OAAO,EAAE,8BAA8B;QACvC,YAAY,EAAE,4BAA4B;QAC1C,aAAa,EAAE,iBAAiB;QAChC,UAAU,EAAE,CAAC,gBAAgB,CAAC;KAC/B;IACD,UAAU,EAAE;QACV,OAAO,EAAE,8BAA8B;QACvC,YAAY,EAAE,cAAc;QAC5B,UAAU,EAAE,CAAC,oBAAoB,CAAC;KACnC;IACD,MAAM,EAAE;QACN,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,YAAY;QAC1B,UAAU,EAAE,CAAC,gBAAgB,CAAC;KAC/B;IACD,8EAA8E;IAC9E,yEAAyE;IACzE,4EAA4E;IAC5E,SAAS,EAAE;QACT,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,iBAAiB;QAC/B,UAAU,EAAE,CAAC,mBAAmB,CAAC;KAClC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAUxC,MAAM,WAAW,GAA2B,CAAC,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAExG,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACpE,MAAM,GAAG,GAAiB,EAAE,CAAC;QAC7B,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAqB;IACrD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAyB,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,eAAe,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,EAAE,GAAG,gBAAgB,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC;IACrD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;YAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,6BAA6B;IAC3E,CAAC;IACD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAA+B,EAAE;IACrE,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;IAChC,MAAM,QAAQ,GACZ,SAAS,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,QAAQ,IAAI,gBAAgB,CAAC;IAC7F,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,qBAAqB,QAAQ,iBAAiB,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YACxF,qFAAqF,CACxF,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;IAChE,MAAM,MAAM,GACV,SAAS,CAAC,MAAM;QAChB,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QACnD,IAAI,CAAC,MAAM;QACX,EAAE,CAAC;IACL,OAAO;QACL,QAAQ;QACR,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO;QAC/F,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,YAAY;QAC3F,2EAA2E;QAC3E,6CAA6C;QAC7C,aAAa,EAAE,iBAAiB,CAC9B,SAAS,CAAC,aAAa;YACrB,OAAO,CAAC,GAAG,CAAC,yBAAyB;YACrC,IAAI,CAAC,aAAa;YAClB,MAAM,CAAC,aAAa,CACvB;QACD,MAAM;QACN,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,CAAC;QACvC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;QACrF,iBAAiB,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,gCAAgC,CAAC;QAC/G,UAAU;KACX,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,GAAuB,EAAE,MAAc;IAC7D,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,OAAO,MAAiC,CAAC;QAC3C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;IACD,2EAA2E;IAC3E,gEAAgE;IAChE,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,wBAAwB,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAyB;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IACtE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,OAAO,oBAAoB;IAGX;IAFX,KAAK,CAAS;IAEvB,YAAoB,MAAsB;QAAtB,WAAM,GAAN,MAAM,CAAgB;QACxC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAuB,EAAE,KAAgB,EAAE,OAAwB,EAAE;QAClF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,CAAC,MAAM,CAAC,QAAQ,UAAU,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG;gBAC9F,6CAA6C,CAChD,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG;YACX,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;YACxB,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW;YACpC,QAAQ;YACR,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvB,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE;aACjF,CAAC,CAAC;YACH,WAAW,EAAE,MAAM;YACnB,0DAA0D;YAC1D,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvG,sEAAsE;YACtE,qEAAqE;YACrE,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS;SACzB,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,mBAAmB,CAAC;QACzE,IAAI,OAAO,GAAiB,IAAI,CAAC;QACjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5D,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;oBAC3B,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;qBAC9C;oBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC,CAAC;gBACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBAC5C,OAAO,GAAG,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;oBACnF,kEAAkE;oBAClE,mEAAmE;oBACnE,6DAA6D;oBAC7D,gEAAgE;oBAChE,MAAM,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;oBACrD,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBACjF,CAAC;gBACD,OAAO,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC,CAAC;YACpE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,oEAAoE;gBACpE,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBACjE,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;oBAAE,MAAM,GAAG,CAAC;gBAC5E,OAAO,GAAG,GAAY,CAAC;gBACvB,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QACD,MAAM,OAAO,IAAI,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC;CACF;AAED,SAAS,eAAe,CAAC,IAAyB;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,MAAM,EAAE,OAAO,CAAC;IAC5B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAkB,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7F,MAAM,SAAS,GAAe,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClD,IAAI,IAAI,GAAmC,IAAI,CAAC;QAChD,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;IACvG,CAAC,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAgB;QACpC,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;QAC5B,GAAG,CAAC,QAAQ,CAAC,MAAM;YACjB,CAAC,CAAC;gBACE,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;oBAClC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,QAAQ,CAAC,EAAE;oBACvB,IAAI,EAAE,UAAmB;oBACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE,EAAE;iBAC3E,CAAC,CAAC;aACJ;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;QACzB,SAAS;QACT,gBAAgB;QAChB,KAAK,EAAE;YACL,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;YAC5C,gBAAgB,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB,IAAI,CAAC;YACpD,mEAAmE;YACnE,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,qBAAqB,EAAE,aAAa,IAAI,CAAC;SACpE;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,iBAAiB;IAIR;IAHX,KAAK,CAAS;IACf,OAAO,CAAS;IAExB,YAAoB,MAAsB;QAAtB,WAAM,GAAN,MAAM,CAAgB;QACxC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAuB,EAAE,KAAgB,EAAE,OAAwB,EAAE;QAClF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,CAAC,MAAM,CAAC,QAAQ,UAAU,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG;gBAC9F,6CAA6C,CAChD,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;aACrB,IAAI,CAAC,MAAM,CAAC,CAAC;QAChB,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC;QACtF,4EAA4E;QAC5E,sEAAsE;QACtE,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,0EAA0E;QAC1E,0DAA0D;QAC1D,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/D,IAAI,SAAS;YAAE,SAAS,CAAC,aAAa,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAE/D,MAAM,IAAI,GAAG;YACX,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;YACxB,UAAU,EAAE,IAAI;YAChB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrG,QAAQ,EAAE,YAAY;YACtB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;YACnG,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;SAC9B,CAAC;QAEF,IAAI,OAAO,GAAiB,IAAI,CAAC;QACjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5D,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,cAAc,EAAE;oBACrD,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;wBAC/B,mBAAmB,EAAE,YAAY;qBAClC;oBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;oBAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC,CAAC;gBACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBAC5C,OAAO,GAAG,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;oBACnF,MAAM,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;oBACrD,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBACjF,CAAC;gBACD,OAAO,wBAAwB,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC,CAAC;YAC7E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBACjE,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;oBAAE,MAAM,GAAG,CAAC;gBAC5E,OAAO,GAAG,GAAY,CAAC;gBACvB,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QACD,MAAM,OAAO,IAAI,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC;CACF;AAED;;;;;;;GAOG;AACH,SAAS,mBAAmB,CAAC,QAAuB;IAClD,MAAM,GAAG,GAA0D,EAAE,CAAC;IACtE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACvF,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjC,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,EAAE,CAAC;gBACxF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACtB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;YACzE,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS,CAAC,yDAAyD;QAC/F,MAAM,OAAO,GAAU,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;YACpC,IAAI,KAAK,GAA4B,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,CAAC;YAAC,MAAM,CAAC;gBACP,0EAA0E;YAC5E,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,0EAA0E;QAC1E,sEAAsE;QACtE,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QACzE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAyB;IACzD,MAAM,MAAM,GAAU,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEjF,MAAM,SAAS,GAAe,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtD,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAA4B;QAChD,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;KACvC,CAAC,CAAC,CAAC;IAEJ,MAAM,gBAAgB,GAAgB;QACpC,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,IAAI;QACb,GAAG,CAAC,aAAa,CAAC,MAAM;YACtB,CAAC,CAAC;gBACE,UAAU,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACpC,EAAE,EAAE,CAAC,CAAC,EAAE;oBACR,IAAI,EAAE,UAAmB;oBACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE;iBACrE,CAAC,CAAC;aACJ;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IAEF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IAC3B,OAAO;QACL,IAAI;QACJ,SAAS;QACT,gBAAgB;QAChB,KAAK,EAAE;YACL,mEAAmE;YACnE,sEAAsE;YACtE,qEAAqE;YACrE,oEAAoE;YACpE,aAAa;YACb,YAAY,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,uBAAuB,IAAI,CAAC,CAAC;YAC7G,gBAAgB,EAAE,CAAC,CAAC,aAAa,IAAI,CAAC;YACtC,YAAY,EAAE,CAAC,CAAC,uBAAuB,IAAI,CAAC;SAC7C;KACF,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,GAAsE,EAAE,OAAe;IAC3G,MAAM,GAAG,GAAG,MAAM,CAAC;IACnB,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1D,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3F,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC3D,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;IACjG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,OAAO,EAAE,GAAG,CAAC,CAAC;IACnE,OAAO,KAAK,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,KAAK,CAAC,EAAU,EAAE,MAAoB;IAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnC,SAAS,IAAI;YACX,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC3C,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC"}
|